当前位置: 首页 > news >正文

机器人操作系统:ROS2 仿真入门

塞巴斯蒂安

·

一、说明

在机器人项目中,仿真是一个具有多种用途的重要方面。首先,您可以测试希望机器人执行的行为代码。其次,您可以使用仿真来测试不同类型的硬件,例如距离传感器、相机或 3D 点云传感器,看看哪种效果最好。第三,可视化模拟的相同软件可以与真正的机器人实时使用,在机器人扫描和导航环境的同时查看环境。

        在我的机器人项目中,我从 ROS1 开始,并提供了一个可以使用 RVIZ 可视化的基本机器人模型。然后,我构建了一个实用的原型,完全基于Arduino,不涉及ROS。在项目的当前阶段,我致力于构建一个与视觉传感器兼容的 Gazebo 模型。

        本文继续该系列,使用 Gazebo 快速启动 ROS2 模拟。我们将了解创建模拟的基本工具 - ROS启动文件和Gazebo - 并学习应用基本步骤 - 选择3D模型,将它们放置在世界上。

        本文的技术背景是 Ubuntu 20.04、ROS2 Foxy、Gazebo11,但它也应该适用于较新的版本。

二、基本机器人仿真术语

        本段简要列出了理解物理仿真方面所必需的所有术语。如果您对词汇量很坚定,请跳过本节。

  • 运动学:运动学是物理学的一个分支,它控制着身体在时间、位置、速度和加速度方面的运动方式,而不考虑身体的重量或向外力,如重力
  • 动力学:物理学的另一个分支,它考虑当物体有质量并受到力影响时物体的位置、速度和加速度如何变化。(在机器人中,这也称为机器人动力学)
  • 里程计:一种通过连续记录运动数据来估计物体位置并计算物体移动的距离和轨迹的方法
  • 惯性:这种力是运动物体对任何其他会改变其方向、速度或加速度的力的阻力
  • 摩擦力:当两个物体靠近另一个物体移动并抵抗该移动时施加的力
  • 关节:关节是连接两个物体的机械元件。关节有不同的类型来描述连接的物体如何移动。

来源:ROS机器人编程书

  • RPY 值:此首字母缩略词代表横滚、俯仰、偏航,用于描述物体在 3D 空间中的运动。对象可以根据下图在这三个轴上移动:

来源: wikipedia.org

三、循序渐进:如何创建模拟世界

Gazebo是在ROS之外开始的,但后来完全整合了。它更侧重于机器人和世界的完整物理模拟。特别是,世界通过物理引擎提供正确的物理模拟:机器人可以撞到物体,这些物体会移动,最终甚至撞到你的机器人身上。Gazebo 带有预定义的世界模型,您甚至可以定义自己的模型。

在本教程中,我们将启动一个带有空世界的凉亭模拟,然后在里面生成一个机器人。简而言之,基本步骤是:

  • 创建新的 ROS 包并设置目录结构
  • 创建一个空的坐标定位文件
  • 创建启动文件
  • 在机器人 URDF 模型中添加其他物理属性
  • 参数化机器人 URDF 模型以使用 Gazebo 或 RVIZ 运行。
  • 用启动文件开始空的世界

以下各节详细介绍了这些任务。

3.1 第 1 步:包创建和目录结构

        我们将创建一个如下所示的包结构:

radu_gazebo/
├── config
│   └── rviz.config
├── launch
│   └── launch.py
├── radu_bot
│   └── __init__.py
├── resource
├── scripts
├── test
├── urdf
│   └── core.xacro
└── worlds
│   └── room.world
├── package.xml
├── setup.cfg
├── setup.py

为方便起见,只需运行以下命令:

ros2 pkg create  --build-type python radu_gazebo
mkdir radu_gazebo/launch radu_gazebo/world
mkdir radu_gazebo/launch radu_gazebo/world/room.world
touch radu_gazebo/launch/room.launch

3.2 第 2 步:清空坐标定位文件

        该文件是一个SDF文件,将包含我们想要模拟的所有内容的标签:墙壁,窗户和家具等对象。我们将从一个简单的空白世界开始,并逐步添加新对象。room.world<model>

<!-- FILE: world/room.world -->
<?xml version='1.0'?>
<sdf version="1.6">
<world name="room"><include><uri>model://sun</uri></include><include><uri>model://ground_plane</uri></include>
</world>
</sdf>

您可以手动将此文件加载到凉亭中。但是由于我们最终也将在这个模型中生成一个机器人,因此最好继续直接启动文件。

3.3 步骤 3:启动文件

        正如我们在上一篇文章中了解到的,ROS2 不再支持 XML 启动文件,而是使用 Python 文件。

        我们使用的启动文件包装包中的启动命令,并提供一个世界参数。gazebo_ros

#!/usr/bin/python3
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
package_name = 'radu_bot'
world_file = 'room.world'
def generate_launch_description():pkg_gazebo_ros = get_package_share_directory('gazebo_ros')pkg_radu_simulation = get_package_share_directory(package_name)# launch Gazebo by including its definitiongazebo = IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(pkg_gazebo_ros, 'launch', 'gazebo.launch.py'),))# load the world fileworld_arg = DeclareLaunchArgument('world',default_value=[os.path.join(pkg_radu_simulation, 'worlds', world_file), ''],description='SDF world file')return LaunchDescription([gazebo,world_arg])

3.4 第 4 步:使用 Gazebo 标签扩展机器人模型

        为了在凉亭中使用RViz的URDF模型,我们需要对模型进行一些更改。

        首先,我们需要为机器人提供额外的物理方面,以便它在模拟中正确运行。其次,机器人的视觉外观不同。RVIZ 模型的颜色和文本定义不适用。如果使用网格,也需要更改它们。第三,我们还需要额外的插件,以便 Gazebo 工具正常工作

        让我们逐步查看这些更改。

3.5 物理模拟属性

惯性

物体的惯性是当其当前运动受到另一个物体影响时施加的反作用力。在凉亭模型中,标签用于表示这一方面。<inertial>

下面是一个示例:

<link name="base_link"><inertial><origin xyz="0 0 0" rpy="0 0 0"/><mass value="0.25" /><inertia ixx="0.000486" ixy="0.0" ixz="0.0" iyy="0.000486" iyz="0.0" izz="0.000729"/></inertial><visual><origin rpy="0 0 0" xyz="0 0 0"/><geometry><cylinder radius="0.09" length="0.09"/></geometry></visual>
</link>

        标签相对于其父链接定位链接,在这里您可以更改值以移动估计的质量中心。通过您指定此链接质量(以千克为单位)。最后,该元素是 x、y 和 z 上的力如何影响链接的矩阵。您可以在维基百科上阅读物理文章,或使用这个方便的python脚本。<origin>xyz<mass><inertial>

摩擦

        另一组变量控制机器人中链接的摩擦。你用四个值来表达这一点。首先,提供静态和动态接触刚度。在这里,我们使用值和,这是许多ROS项目中使用的默认值。其次,值和是静态和动态摩擦系数,您可以根据链接的材料在维基百科上查找。<kp><kd>1000001.0<mu1><mu2>

<gazebo reference="base_link"><kp>100000.0</kp><kd>1.0</kd><mu1>10.0</mu1><mu2>10.0</mu2>  
</gazebo>

碰撞

        这定义了机器人的硬材料边界——它会影响在模拟中将重力和其他力施加到机器人上的方式。这些属性由链接中的标记表示。它的属性非常简单:只需复制原始链接和值,如下所示。<collision><geometry><origin>

<link name="base_link"><inertial><origin xyz="0 0 0" rpy="0 0 0"/><mass value="0.25" /><inertia ixx="0.000486" ixy="0.0" ixz="0.0" iyy="0.000486" iyz="0.0" izz="0.000729"/></inertial><visual><origin rpy="0 0 0" xyz="0 0 0"/><geometry><cylinder radius="0.09" length="0.09"/></geometry></visual><collision><origin rpy="0 0 0" xyz="0 0 0"/><geometry><cylinder radius="0.09" length="0.09"/></geometry></collision>
</link>

关节特性

机器人中的关节应进一步建模,以表达其真实世界的行为。

  • 对于所有非静态、非连续接头,集合和值<upper><lower>
  • 对于所有连续接头,添加和限制<effort><velocity>
<joint name="camera_joint"><limit upper="0.5" lower="-0.5"/>
</joint>
<joint name="left_wheel_joint"><limit effort="0.1" velocity="0.005"/>
</joint>

3.6 可视化模拟属性

要更改机器人的视觉效果,您有以下选项:

简单的颜色

这与 RViz 中的工作方式相同:在链接标签中,您可以引用一个元素。<visual><color>

<material name="blue"><color rgba="0 0 0.8 1"/>
</material>
<link name="camera"><visuals><material name="blue"></visuals>
</link>

预定义网格

        Gazebo 提供了一组内置网格,这些网格在此源代码文件中列出。应用它们,在标签内添加标签,如下所示。<material><gazebo>

<gazebo reference="base_link"><material>Gazebo/Grey</material>  
</gazebo>

自定义网格

        使用自定义网格表示链接时,只需在链接的标记中引用它们,如下所示:<geometry>

<link name="camera"><mesh filename:"package://radu_bot/model/meshes/camera.dae" />
</link>

        重要提示:建议不要在标签中使用自定义网格文件,因为这会影响仿真性能。相反,请根据可用的盒子、圆柱体和球体类型定义值。<collision><geometry>

3.7 第 5 步:参数化机器人 URDF 模型以使用 Gazebo 或 RViz 跑步

        如您所见,所需的更改是根本性的。而且它们不向后兼容:Gazebo 所需的所有更改都无法被 RVIZ 解析。

        由于这些原因,复杂的机器人项目将URDF方面分成不同的XACRO文件。经过一些实验,我想出了以下层次结构。

  • core- 包含用于渲染机器人链接和关节的核心宏
  • rviz- RVIZ主文件,它定义参数并导入其他文件
  • rviz_viusals- 定义机器人在RViz中的可视化方式
  • gazebo- 凉亭核心文件,就像定义参数和导入其他文件一样
  • gazebo_visuals- 定义如何在凉亭中可视化机器人
  • gazebo_physics- 计算链接和标签的附加宏<inertial><collision>
  • gazebo_sensor- 添加传感器数据
  • gazebo_controll- 添加了 ROS 控制插件并定义用于渲染标签的宏<transmission>

让我们看看这种方法在实践中是如何工作的。运行 Xacro 渲染模型时,将使用命令 -o radu_rviz_compiled.urdf'。此文件将...xacro rviz.xacro

  1. 导入其他必需的文件
<xacro:include filename="$(find radu_bot)/urdf2/core.xacro"/>
<xacro:include filename="$(find radu_bot)/urdf2/visuals.xacro"/>

2. 定义控制宏执行的基本参数

<xacro:property name="gazebo_build" value="false" />
<xacro:property name="rviz_build" value="true" />

3. 执行宏以创建 URDF 模型

<xacro:box_link name="base_link" size="0.6 0.3 0.05" color="${torso_color_name}" color_rgb="${torso_color_rgb}" />
<xacro:wheel_link name="right_wheel_frontside" />
<xacro:wheel_joint name="base_link_right_wheel_frontside" parent="base_link" child="right_wheel_frontside" xyz="0.2 -0.2 -0.05" />
<xacro:wheel_link name="right_wheel_backside" />
<xacro:wheel_joint name="base_link_right_wheel_backside" parent="base_link" child="right_wheel_backside" xyz="-0.2 -0.2 -0.05" />
<xacro:wheel_link name="left_wheel_frontside" /> 
<xacro:wheel_joint name="base_link_left_wheel_frontside" parent="base_link" child="left_wheel_frontside" xyz="0.2 0.2 -0.05" />
<xacro:wheel_link name="left_wheel_backside" /> 
<xacro:wheel_joint name="base_link_left_wheel_backside" parent="base_link" child="left_wheel_backside" xyz="-0.2 0.2 -0.05" />

        在使用这种方法一段时间后,我意识到处理可变性的核心逻辑在文件内部:用于呈现链接和关节的宏具有将由主文件触发的不同块。请参阅以下定义。在第 3 行中,评估条件以添加特定于 RViz 的视觉对象。在第 14 行中,另一个条件检查凉亭物理属性并将其应用于模型。core.xacro<link><xacro:if>

<xacro:macro name="box_link" params="name size color color_rgb" ><link name="${name}"><xacro:if value="${rviz_build}"><visual><origin xyz="0 0 0" rpy="0 0 0"/><geometry><box size="${size}"/></geometry><material name="${color}"><color rgba="${color_rgb}"/></material></visual></xacro:if><xacro:if value="${gazebo_build}"><pose>0 0 0 0 0 0</pose><xacro:box_inertia m="0.6" x="0.7" y="0.4" z="0.2"/><collision name="collision_${name}"><origin xyz="0 0 0" rpy="0 0 0"/><geometry><box size="${size}"/></geometry></collision></xacro:if>  </link>
</xacro:macro>

3.8 第 6 步:生成机器人

        Gazebo 节点通过启动文件启动,但机器人需要生成到节点中。感谢博客文章如何在 ROS2 中生成机器人,我创建了以下启动文件。

#!/usr/bin/python3
import os
import sys
import rclpy
from gazebo_msgs.srv import SpawnEntity
from ament_index_python.packages import get_package_share_directory
package_name = 'radu_bot'
def main(args=None):rclpy.init(args=args)node = rclpy.create_node('minimal_client')cli = node.create_client(SpawnEntity, '/spawn_entity')sdf_file_path = (os.path.join(get_package_share_directory(package_name), 'urdf', 'radu_gazebo_compiled.urdf')),model = open(sdf_file_path[0], 'r').read()print("MODEL %s" %model)req = SpawnEntity.Request(name = "radu_bot",xml = model,robot_namespace = "radu",reference_frame = "world",)while not cli.wait_for_service(timeout_sec=1.0):node.get_logger().info('service not available, waiting again...')future = cli.call_async(req)rclpy.spin_until_future_complete(node, future)if future.result() is not None:node.get_logger().info('Result ' + str(future.result().success) + " " + future.result().status_message)else:node.get_logger().info('Service call failed %r' % (future.exception(),))node.destroy_node()rclpy.shutdown()
if __name__ == '__main__':main()

启动文件还可以在启动期间转换 Xacro 文件,如diff_bot示例中所示。例如,要加载 Gazebo 配置,您需要执行以下命令:

import xacro
def generate_launch_description():pkg_radu_simulation = get_package_share_directory(package_name)robot_description_path =  os.path.join(pkg_radu_simulation,"urdf","gazebo.xacro",)robot_description = {"robot_description": xacro.process_file(robot_description_path).toxml()}

四、启动机器人

首先,我们构建当前工作区。

$> colcon build --symlink-install --cmake-clean-first --event-handlers console_direct+ --packages-up-to radu_bot

然后我们推出凉亭。

$> ros2 launch radu_bot gazebo.launch.py 
[INFO] [launch]: All log files can be found below /home/devcon/.ros/log/2021-05-30-09-07-30-541933-giga-36879
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [gzserver-1]: process started with pid [36886]
[INFO] [gzclient   -2]: process started with pid [36889]

然后生成机器人。

$> ros2 run radu_bot spawn_radu
[INFO] [1622358479.722919377] [minimal_client]: Result True SpawnEntity: Successfully spawned entity [radu_bot]

最后,渲染机器人:

五、结论

        本文向您展示了如何从头开始在 ROS2 中创建与 Gazebo 兼容的模拟。事实证明,这是一个漫长的 过程,您需要 (1) 创建一个包,(2) 创建坐标定位文件,(3) 创建启动文件,(4) 将 Gazebo 特定标签添加到我们的机器人模型中,(5) 参数化您的机器人模型以与 Gazebo 和 RVIZ 兼容,以及 (6) 在模拟中生成机器人实体。形成所有这些步骤。添加 Gazebo 物理是学习和应用的时间密集型,我希望您也能获得宝贵的见解。最后,我们可以使用自定义启动脚本文件在 Gazebo 和 RViz 中生成 RADU。从这里,我们可以在模拟中移动机器人。

相关文章:

机器人操作系统:ROS2 仿真入门

塞巴斯蒂安 一、说明 在机器人项目中&#xff0c;仿真是一个具有多种用途的重要方面。首先&#xff0c;您可以测试希望机器人执行的行为代码。其次&#xff0c;您可以使用仿真来测试不同类型的硬件&#xff0c;例如距离传感器、相机或 3D 点云传感器&#xff0c;看看哪种效果最…...

面试题:线程池的底层工作原理

线程池的几个重要的参数&#xff1a; 1、corePoolSize&#xff1a;线程池的核心线程数&#xff08;也是默认线程数&#xff09; 2、maximumPoolSize&#xff1a;最大线程数 3、keepAliveTime&#xff1a;允许的线程最大空闲时间&#xff08;单位/秒&#xff09; 线程池内部是…...

Excel/PowerPoint条形图改变顺序

条形图是从下往上排的&#xff0c;很多时候不是我们想要的效果 解决方案 选择坐标轴&#xff0c;双击&#xff0c;按下图顺序点击 效果...

【操作系统】虚拟内存相关分段分页页面置换算法

虚拟内存是什么&#xff1f; 【进程地址空间虚拟地址空间C/C程序地址空间就是那个4G的空间】 虚拟内存是操作系统内核为了对进程地址空间进行管理&#xff0c;而设计的一个逻辑意义上的内存空间概念。在程序运行过程中&#xff0c;虚拟内存中需要被访问的部分会被映射到物理内…...

Unrecognized Hadoop major version number: 3.0.0-cdh6.3.2

一.环境描述 spark提交job到yarn报错&#xff0c;业务代码比较简单&#xff0c;通过接口调用获取数据&#xff0c;将数据通过sparksql将数据写入hive中&#xff0c;尝试各种替换hadoop版本&#xff0c;最后拿下 1.hadoop环境 2.项目 pom.xml spark-submit \ --name GridCorr…...

机器学习分类,损失函数中为什么要用Log,机器学习的应用

目录 损失函数中为什么要用Log 为什么对数可以将乘法转化为加法&#xff1f; 机器学习&#xff08;Machine Learning&#xff09; 机器学习的分类 监督学习 无监督学习 强化学习 机器学习的应用 应用举例&#xff1a;猫狗分类 1. 现实问题抽象为数学问题 2. 数据准备…...

PySpark安装及WordCount实现(基于Ubuntu)

先盘点一下要安装哪些东西&#xff1a; VMwareubuntu 14.04&#xff08;64位&#xff09;Java环境&#xff08;JDK 1.8&#xff09;Hadoop 2.7.1Spark 2.4.0&#xff08;Local模式&#xff09;Pycharm &#xff08;一&#xff09;Ubuntu VMware 和 ubuntu 14.04&#xff08;…...

SpringBoot 模板模式实现优惠券逻辑

一、计算逻辑的类结构图 在这张图里&#xff0c;顶层接口 RuleTemplate 定义了 calculate 方法&#xff0c;抽象模板类 AbstractRuleTemplate 将通用的模板计算逻辑在 calculate 方法中实现&#xff0c;同时它还定义了一个抽象方法 calculateNewPrice 作为子类的扩展点。各个具…...

并查集 rank 的优化(Java 实例代码)

目录 并查集 rank 的优化 Java 实例代码 UnionFind3.java 文件代码&#xff1a; 并查集 rank 的优化 上一小节介绍了并查集基于 size 的优化&#xff0c;但是某些场景下&#xff0c;也会存在某些问题&#xff0c;如下图所示&#xff0c;操作 union(4,2)。 根据上一小节&…...

TDA4超级玩家浮出水面,行泊一体功能、成本刷到极致

2023年以来&#xff0c;智能驾驶市场进入L2普及、高阶ADAS功能&#xff08;NOA&#xff09;大规模量产的新周期&#xff0c;降本增效&#xff0c;打造极致性价比、提升用户体验等&#xff0c;成为了竞争的焦点。 其中&#xff0c;替换更具性价比的硬件平台、传感器复用、系统优…...

3分钟了解Android中稳定性测试

一、什么是Monkey Monkey在英文里的含义是猴子&#xff0c;在测试行业的学名叫“猴子测试”&#xff0c;指的是没有测试经验的人甚至是根本不懂计算机的人&#xff08;就像一只猴子&#xff09;&#xff0c;不需要知道程序的任何用户交互方面的知识&#xff0c;给他一个程序&a…...

LVS-DR+keepalived实现高可用负载群集

VRRP 通信原理&#xff1a; VRRP就是虚拟路由冗余协议&#xff0c;它的出现就是为了解决静态路由的单点故障。 VRRP是通过一种竞选的一种协议机制&#xff0c;来将路由交给某台VRRP路由。 VRRP用IP多播的方式&#xff08;多播地址224.0.0.18&#xff09;来实现高可用的通信&…...

阿里云国际版注册教程

什么是阿里云国际版&#xff1f; 阿里云国际版是阿里云专为海外客户供给的服务器及核算资源&#xff0c;涵盖了云主机、弹性裸金属服务器、容器服务、数据库及安全和监控等一系列云核算解决方案。 与其他云核算服务供给商不同&#xff0c;阿里云国际版在安全性、稳定性、性能方…...

基于百度文心大模型创作的实践与谈论

文心概念 百度文心大模型源于产业、服务于产业&#xff0c;是产业级知识增强大模型。百度通过大模型与国产深度学习框架融合发展&#xff0c;打造了自主创新的AI底座&#xff0c;大幅降低了AI开发和应用的门槛&#xff0c;满足真实场景中的应用需求&#xff0c;真正发挥大模型…...

Java基础知识题(五)

系列文章目录 Java基础知识题(一) Java基础知识题(二) Java基础知识题(三) Java基础知识题(四) Java基础知识题(五) 文章目录 系列文章目录 前言 一 Java的数据连接——JDBC 1. 简述什么是JDBC&#xff1f;重点 2. JDBC PreparedStatement比Statement有什么优势&…...

攻防世界-fileinclude

原题 解题思路 题目已经告诉了&#xff0c;flag在flag.php中&#xff0c;先查看网页源代码&#xff08;快捷键CTRLU&#xff09;。 通过抓包修改&#xff0c;可以把lan变量赋值flag。在cookie处修改。新打开的网页没有cookie&#xff0c;直接添加“Cookie: languagephp://filte…...

流媒体服务器SRS的搭建及QT下RTMP推流客户端的编写

一、前言 目前市面上有很多开源的流媒体服务器解决方案&#xff0c;常见的有SRS、EasyDarwin、ZLMediaKit和Monibuca。这几种的对比如下&#xff1a; &#xff08;本图来源&#xff1a;https://www.ngui.cc/zz/1781086.html?actiononClick&#xff09; 二、SRS的介绍 SRS&am…...

Effective C++条款11——在operator=中处理“自我赋值”(构造/析构/赋值运算)

“自我赋值”发生在对象被赋值给自己时: class Widget {}; Widget w; // ... w w; // 赋值给自己 这看起来有点愚蠢&#xff0c;但它合法&#xff0c;所以不要认定客户绝不会那么做。此外赋值动作并不总是那么可被一眼辨识出来&#xff0c;例如: a[i] a[j]; …...

可视化绘图技巧100篇基础篇(八)-气泡图(一)

目录 前言 适用场景 图例 绘图工具及代码实现 EXCEL 1、单轴气泡图...

Elasticsearch查询之Disjunction Max Query

前言 Disjunction Max Query 又称最佳 best_fields 匹配策略&#xff0c;用来优化当查询关键词出现在多个字段中&#xff0c;以单个字段的最大评分作为文档的最终评分&#xff0c;从而使得匹配结果更加合理 写入数据 如下的两条例子数据&#xff1a; docId: 1 title: java …...

Lock wait timeout exceeded; try restarting transaction的错误

文章目录 一、异常发现二、异常定位1、锁表语句确认2、实际场景排查三、解决思路1、本次解决方式2、其他场景解决思路扩展1、【治标方法】innodb_lock_wait_timeout 锁定等待时间改大2、【治标方法】事务信息查询3、【治标方法】如果杀掉线程依然不能解决,可以查找执行线程耗时…...

ShardingSphere01-docker环境安装

使用docker安装数据库是一个非常好的选择&#xff0c;后续的读写分离、数据分片等功能的数据库都是由docker创建。 一、安装准备 1、前提条件 Docker可以运行在Windows、Mac、CentOS、Ubuntu等操作系统上 Docker支持以下的CentOS版本&#xff1a; CentOS 7 (64-bit)CentOS …...

Java代码审计13之URLDNS链

文章目录 1、简介urldns链2、hashmap与url类的分析2.1、Hashmap类readObject方法的跟进2.2、URL类hashcode方法的跟进2.3、InetAddress类的getByName方法 3、整个链路的分析3.1、整理上述的思路3.2、一些疑问的测试3.3、hashmap的put方法分析3.4、反射3.5、整个代码 4、补充说明…...

区间预测 | MATLAB实现QRBiGRU双向门控循环单元分位数回归时间序列区间预测

区间预测 | MATLAB实现QRBiGRU双向门控循环单元分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRBiGRU双向门控循环单元分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 MATLAB实现QRBiGRU双向门控循环单元分位数回归时间序列…...

Python面向对象植物大战僵尸

先来一波效果图 来看看如何设计游戏架构 import sysimport pygameclass BaseSprite(pygame.sprite.Sprite):def __init__(self, name):super().__init__()self.image pygame.image.load(name)self.rect self.image.get_rect()class AnimateSprite(BaseSprite):def __init__(…...

大屏模板,增加自适应(包含websocket)

1、简单的Node服务端 const WebSocket require(ws);// 创建 WebSocket 服务器 const wss new WebSocket.Server({ port: 8888 });const getHeader (protocol) > {const protocolArr protocol.split(,)const headers {};for (let i 0; i < protocolArr.length; i …...

电商系统架构设计系列(九):如何规划和设计分库分表?

上篇文章中&#xff0c;我给你留了一个思考题&#xff1a;分库分表该如何设计&#xff1f; 今天这篇文章&#xff0c;我们来聊一下如何规划和设计分库分表&#xff0c;以及要考虑哪些问题。 引言 当要解决海量数据的问题&#xff0c;就必须要用到分布式的存储集群了&#xff…...

从Web 2.0到Web 3.0,互联网有哪些变革?

文章目录 Web 2.0时代&#xff1a;用户参与和社交互动Web 3.0时代&#xff1a;语义化和智能化影响和展望 &#x1f389;欢迎来到Java学习路线专栏~从Web 2.0到Web 3.0&#xff0c;互联网有哪些变革&#xff1f; ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#x…...

QT中资源文件resourcefile的使用,使用API完成页面布局

QT中资源文件resourcefile的使用 之前添加图标的方法使用资源文件的方法创建资源文件资源文件添加前缀资源文件添加资源使用资源文件中的资源 使用API完成布局使用QHBoxLayout完成水平布局使用QVBoxLayout完成垂直布局使用QGridLayout完成网格布局 在Qt中引入资源文件好处在于他…...

2337. 移动片段得到字符串

题目描述&#xff1a; 给你两个字符串 start 和 target &#xff0c;长度均为 n 。每个字符串 仅 由字符 ‘L’、‘R’ 和 ‘_’ 组成&#xff0c;其中&#xff1a; 字符 ‘L’ 和 ‘R’ 表示片段&#xff0c;其中片段 ‘L’ 只有在其左侧直接存在一个 空位 时才能向 左 移动&a…...

Java并发编程第5讲——volatile关键字(万字详解)

volatile关键字大家并不陌生&#xff0c;尤其是在面试的时候&#xff0c;它被称为“轻量级的synchronized”。但是它并不容易完全被正确的理解&#xff0c;以至于很多程序员都不习惯去用它&#xff0c;处理并发问题的时候一律使用“万能”的sychronized来解决&#xff0c;然而如…...

6.小程序api分类

事件监听 以on开头&#xff0c;监听某个事件触发&#xff0c;例如&#xff1a;wx.WindowResize事件 同步 以Sync结尾的是同步&#xff0c;可以通过函数返回值直接获取&#xff0c;例如&#xff1a;wx.setStorageSync 异步 需要通过函数接收调用结果&#xff0c;例如&#…...

什么是PPS和TOD时序?授时防护设备是什么?

介绍 PPS和TOD PPS和TOD是两种用于精确时间同步的技术&#xff0c;它们在许多领域都有广泛的应用&#xff0c;总的来说&#xff0c;PPS和TOD被广泛应用于各种需要高度精确时间同步的领域&#xff0c;包括通信、测量、测试、系统集成和计算机网络等。 一、PPS PPS&#xff08…...

推荐一款好用的开源视频播放器(免费无广告)

mpv是一个自由开源的媒体播放器&#xff0c;它支持多种音频和视频格式&#xff0c;并且具有高度可定制性。mpv的设计理念是简洁、高效和功能强大。 软件特点&#xff1a; 1. 开源、跨平台。可以在Windows\Linux\MacOS\BSD等系统上使用&#xff0c;完全免费无广告。Windows版解压…...

STM32 CubeMX (第三步Freertos中断管理和软件定时)

STM32 CubeMX STM32 CubeMX &#xff08;第三步Freertos中断管理和软件定时&#xff09; STM32 CubeMX一、STM32 CubeMX设置时钟配置HAL时基选择TIM1&#xff08;不要选择滴答定时器&#xff1b;滴答定时器留给OS系统做时基&#xff09;使用STM32 CubeMX 库&#xff0c;配置Fre…...

Java虚拟机(JVM):堆溢出

一、概念 Java堆溢出&#xff08;Java Heap Overflow&#xff09;是指在Java程序中&#xff0c;当创建对象时&#xff0c;无法分配足够的内存空间来存储对象&#xff0c;导致堆内存溢出的情况。 Java堆是Java虚拟机中用于存储对象的一块内存区域。当程序创建对象时&#xff0c…...

C语言,Linux,静态库编写方法,makefile与shell脚本的关系。

静态库编写&#xff1a; 编写.o文件gcc -c(小写) seqlist.c(需要和头文件、main.c文件在同一文件目录下) libs.a->去掉lib与.a剩下的为库的名称‘s’。 -ls是指库名为s。 -L库的路径。 makefile文件编写&#xff1a; CFLAGS-Wall -O2 -g -I ./inc/ LDFLAGS-L./lib/ -l…...

Php“牵手”淘宝商品详情页数据采集方法,淘宝API接口申请指南

淘宝天猫详情接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在电商平台的开发中&#xff0c;详情接口API是非常常用的 API&#xff0c;因此本文将详细介绍详情接口 API 的使用。 一、…...

如何使用CSS实现一个全屏滚动效果(Fullpage Scroll)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 实现全屏滚动效果的CSS和JavaScript示例⭐ HTML 结构⭐ CSS 样式 (styles.css)⭐ JavaScript 代码 (script.js)⭐ 实现说明⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦…...

Docker之Compose

目录 前言 1.1Docker Swarm与Docker Compose 1.1.1Docker Swarm 1.1.2Docker Compose 1.1.2.1 三层容器 ​编辑 二、YAML 2.1YAML概述 2.2注意事项 2.3Docker Compose 环境安装 2.3.1下载 三、Docker-Compose配置常用字段 四、Docker-compose常用命令 五、Docker…...

安装chromedriver 115,对应chrome版本115(经检验,116也可以使用)

目录 1. 查看Chrome浏览器的版本2. 找到对应的chromedriver3. 安装ChromeDriver 1. 查看Chrome浏览器的版本 点进这个网站查看&#xff1a;chrome://settings/help &#xff08;真是的&#xff0c;上一秒还是115版本&#xff0c;更新后就是116版本了&#xff0c;好在chromedi…...

排序算法:插入排序

插入排序的思想非常简单&#xff0c;生活中有一个很常见的场景&#xff1a;在打扑克牌时&#xff0c;我们一边抓牌一边给扑克牌排序&#xff0c;每次摸一张牌&#xff0c;就将它插入手上已有的牌中合适的位置&#xff0c;逐渐完成整个排序。 插入排序有两种写法&#xff1a; 交…...

掌握AI助手的魔法工具:解密Prompt(提示)在AIGC时代的应用「上篇」

在当今的AIGC时代&#xff0c;我们面临着越来越多的人工智能技术和应用。其中一个引人注目的工具就是Prompt&#xff08;提示&#xff09;。它就像是一种魔法&#xff0c;可以让我们与AI助手进行更加互动和有针对性的对话。那么&#xff0c;让我们一起来了解一下Prompt&#xf…...

JMeter - 接口压力测试工具简单使用

【启动前配置】 启动JMeter前可以先配置语言和编码: 修改:E:\JMeter\apache-jmeter-5.5\bin\jmeter.properties文件中: 1.language=en # 指定语言 language=zh_CN 2.sampleresult.default.encoding=ISO-8859-1 # 指定编码 UTF-8 sampleresult.default.encoding=UTF-8 也…...

【C++入门到精通】C++入门 —— priority_queue(STL)优先队列

阅读导航 前言一、priority_queue简介1. 概念2. 特点 二、priority_queue使用1. 基本操作2. 底层结构 三、priority_queue模拟实现⭕ C代码⭕priority_queue中的仿函数 总结温馨提示 前言 ⭕文章绑定了VS平台下std::priority_queue的源码&#xff0c;大家可以下载了解一下&…...

静态代码扫描工具 Sonar 配置及使用

概览 Sonar 是一个用于代码质量管理的开放平台。通过插件机制&#xff0c;Sonar 可以集成不同的测试工具&#xff0c;代码分析工具&#xff0c;以及持续集成工具。与持续集成工具&#xff08;例如 Hudson/Jenkins 等&#xff09;不同&#xff0c;Sonar 并不是简单地把不同的代…...

docker 03(docker 容器的数据卷)

一、数据卷的概念和作用 删除后&#xff0c;数据也没了。 不能 数据卷 是宿主机中的一个目录或文件当容器目录和数据卷目录绑定后&#xff0c;对方的修改会立即同步一个数据卷可以被多个容器同时挂载 作用&#xff1a; 容器数据持久化 外部机器和容器间接通信 容器之间数据交换…...

【04】基础知识:typescript中的类

一、es5 对象 1、定义 类&#xff08;对象&#xff09; 原型链上的属性和方法会被多个实例共享。构造函数中的属性和方法不会。 // 自定义构造函数 function Person(name, age) {this.name namethis.age agethis.getInfo function() {console.log(${this.name} - ${this.…...

CCClippingNode:在游戏中实现遮罩效果、剪切效果,以涂抹糖霜为例,如何更好的实现涂抹效果,提高用户的游戏体验

CCClippingNode&#xff1a;在游戏中实现遮罩效果、剪切效果&#xff0c;以涂抹糖霜为例&#xff0c;如何更好的实现涂抹效果 设备/引擎&#xff1a;Mac&#xff08;11.6&#xff09;/cocos2d-x 开发工具&#xff1a;Xcode&#xff08;13.0&#xff09; 开发需求&#xff1a…...

cuda gdb调试

如果cudaDeviceEnablePeerAccess函数不支持或不起作用&#xff0c;您仍然可以尝试其他方法来实现GPU之间的数据交换和通信。以下是一些替代方法&#xff1a; 通过主机内存进行数据传输&#xff1a; 如果GPU之间的数据交换不是非常频繁&#xff0c;您可以将数据从一个GPU复制到…...