版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ROS2机器人操作系统与Gazebo机器人仿真
第7章Gazebo与ROS2联合仿真提纲7.1简介7.2ros_gz_sim功能包 7.2.1启动仿真环境 7.2.2添加模型7.3ros_gz_bridge功能包7.3.1bridge_parameter节点7.3.2案例:桥接单个话题7.3.3案例:桥接多个话题7.4其他注意事项7.4.1实体的控制7.4.2话题消息类型7.4.3相机话题7.4.4RViz2可视化SDF模型7.5案例:视觉巡线移动轮式机器人7.6本章小结 Gazebo作为一款先进的物理仿真工具,提供了高度逼真的三维仿真环境,能够有效替代ROS2中自带的TurtleSim二维仿真环境,从而实现功能更为强大的机器人仿真。而在与真实环境高度相似的仿真环境进行的实验和研究,能够为部署到真实机器人提供重要参考,即可以在不更改或稍许微调后就可将算法部署到真实的机器人。建立以Gazebo为仿真工具的ROS2项目对于研究机器人是必要的,本章将详细介绍Gazebo和ROS2进行机器人联合仿真的方法和流程。7.1简介7.1简介目前经过多年的发展Gazebo与ROS2间已经形成了一套非常完整的仿真规范和流程。在联合仿真中,Gazebo作为仿真环境的提供者,具有两个功能,既作为命令的执行器,接收和执行来自ROS2的命令,又作为数据的生成器,向ROS2提供仿真环境的各种状态信息。对于联合仿真的总体流程是用ROS2编写机器人程序从Gazebo中获得各种传感器数据,然后在分析和处理这些数据后又将执行命令发送回Gazebo完成机器人的控制。7.1简介Gazebo与ROS2间进行联合仿真的关键是两者间的通信。下图展示了Gazebo与ROS2间进行联合仿真的原理,Gazebo和ROS2程序间的通信主要通过多个ROS2的功能包提供,其中ros_gz_sim和ros_gz_bridge是两个最主要的功能包。ros_gz_sim功能包主要提供了启动Gazebo仿真环境和在Gazebo中创建机器人两个功能,而ros_gz_bridge功能包主要提供了Gazebo和ROS2间的通信机制,建立了以话题为主的Gazebo到ROS2和ROS2到Gazebo间的通信。7.1简介此外,还有ros_gz_image,ros-jazzy-sdformat-urdf等功能包用于Gazebo和ROS2的联合仿真。通过以上的ROS2功能包,就能够在ROS2建立与Gazebo之间信息和命令的交互,从而能够实现Gazebo与ROS2的联合仿真。7.2ros_gz_sim功能包7.2ros_gz_sim功能包在Gazebo和ROS2的联合仿真中,ROS2的功能包ros_gz_sim主要提供了启动Gazebo仿真环境和向仿真环境添加模型(机器人)两个功能。以上两个功能主要由ros_gz_sim功能包内相关的Launch文件和节点所提供。功能包ros_gz_sim的Launch文件有:(1)gz_server.launch.py:对节点gzserver进行了封装,用于只启动Gazebo的仿真服务器,但不启动GazeboGUI,在提高仿真效率时十分有用。(2)gz_sim.launch.py:启动Gazebo的仿真服务和GUI,是Gazebo和ROS2联合仿真时最常使用的Launch文件。(3)gz_spawn_model.launch.py:向Gazebo仿真场景中添加模型,是对create节点的简单封装。7.2ros_gz_sim功能包(4)ros_gz_sim.launch.py:将启动GazeboServer的gz_server.launch.py和ros_gz_bridge功能包中的Launch文件ros_gz_bridge.launch.py进行了综合,可以同时启动Gazebo的仿真服务器和消息的传递,常用于Gazebo和ROS2进行后台联合仿真。(5)ros_gz_spawn_model.launch.py:将添加模型的gz_spawn_model.launch.py和ros_gz_bridge中的Launch文件ros_gz_bridge.launch.py进行了综合,将创建模型和建立模型话题的通信进行了整合。功能包ros_gz_sim的节点有:(1)create:用于向Gazebo的仿真环境中添加模型。(2)gzserver:用于启动Gazebo的仿真服务器。7.2ros_gz_sim功能包7.2.1启动仿真环境ros_gz_sim功能包中的Launch文件gz_sim.launch.py和ros_gz_sim.launch.py都提供了启动Gazebo仿真的功能。其中gz_sim.launch.py只有启动仿真环境一个功能,而ros_gz_sim.launch.py提供了同时启动Gazebo服务器和ros_gz_bridge进行话题中继两个功能。在一般情况下,使用gz_sim.launch.py进行Gazebo仿真环境的启动。通过gz_sim.launch.py启动Gazebo仿真有两种用法,一种是通过命令行的方式,另一种是在另一个自定义的Launch文件中调用gz_sim.launch.py文件。下面介绍利用ROS2启动Gazebo仿真的两种方法:7.2ros_gz_sim功能包7.2.1启动仿真环境(1)通过命令行启动。gz_sim.launch.py本质上是一个ros_gz_sim功能包中的Launch文件,通过gz_args参数来设置要启动的Gazebo仿真文件SDF。例如,启动Gazebo内置的仿真环境diff_drive.sdf,命令如下:ros2launchros_gz_simgz_sim.launch.pygz_args:=diff_drive.sdf上述ROS2的launch命令在行后,会启动Gazebo并加载仿真环境diff_drive.sdf,从而完成在ROS2中启动Gazebo。(2)在自定义的Launch文件中调用gz_sim.launch.py。通过在自定义的Launch文件将gz_sim.launch.py作为一个功能进行调用,从而构成一个更为复杂的,具有多个功能的新Launch文件。下面的代码展示了在自定义中Launch文件open_world.launch.py内调用gz_sim.launch.py启动Gazebo仿真的方法:7.2ros_gz_sim功能包importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcedefgenerate_launch_description():gazebo_node=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('ros_gz_sim'),'launch','gz_sim.launch.py')),launch_arguments=[('gz_args','diff_drive.sdf-r-v4')])returnLaunchDescription([gazebo_node,])7.2ros_gz_sim功能包7.2.1启动仿真环境在上述代码中,在generate_launch_description()函数中通过gazebo_node变量进行仿真环境的启动,该变量代码的含义是:IncludeLaunchDescription()用于创建一个Launch文件对象,第一个参数是经过封装后的一个Launch文件源,参数launch_arguments用于设置传入被引入的Launch文件的参数,是一个列表,列表中的元素是由参数名和参数值构成的元组,上述代码中的[('gz_args','diff_drive.sdf-r-v4')],表示只包含一个组参数,该参数的名称为gz_args,值为'diff_drive.sdf-r-v4'。从上述参数的形式可以看出,gz_args参数的值就是Gazebo的命令gzsim后的参数构成的字符串。PythonLaunchDescriptionSource()用于加载指定路径的使用Python编写的Launch文件,参数为被引入的Launch文件的路径。7.2ros_gz_sim功能包7.2.1启动仿真环境get_package_share_directory()函数用于获得ROS2功能包的安装路径,在上述代码中获得了ros_gz_sim功能包的安装路径,并且通过功能包的安装路径构造了gz_sim.launch.py文件的实际路径。当需要只启动仿真服务器而不打开GUI时,可以通过gzserver节点完成,命令如下:ros2runros_gz_simgzserver--ros-args-pworld_sdf_file:=diff_drive.sdf上述命令在运行后,Gazebo的服务器会启动,但不会打开Gazebo的GUI,这可以降低GUI带来的额外负荷,从而提升仿真效率。此外,上述命令也可以添加到Launch文件中实现在后台运行Gazebo仿真。7.2ros_gz_sim功能包7.2.2添加模型Gazebo的仿真环境在启动和运行后,可以动态的向仿真场景中添加模型,其中机器人可以看作是一种特殊的模型。ros_gz_sim功能包提供了添加模型的三种方法,一是通过create节点,二是通过Luanch文件gz_spwan_model.launch.py,三是通过Launch文件ros_gz_spawn_model.launch.py。其中第三种方法通过引用第二种方法的Launch文件提供添加模型的功能,而第二种方法的Launch文件中实际上使用了第一种方法,调用了create节点实现添加模型。此外,第三种方法还包括了ros_gz_bridge功能包中的话题中继功能。以下介绍前两种向Gazebo仿真中添加模型的方法。7.2ros_gz_sim功能包7.2.2添加模型(1)通过create节点添加模型。ros_gz_sim功能包提供了向Gazebo的仿真环境中添加模型的create节点,并且create节点提供了丰富的配置参数。通过以下命令可以查看create节点的使用方法。ros2runros_gz_simcreate-help输出:create:Usage:create-world[arg][-fileFILE][-paramPARAM][-topicTOPIC][-stringSTRING][-nameNAME][-allow_renamingRENAMING][-xX][-yY][-zZ][-RROLL][-PPITCH][-YYAW]其中,create节点各参数的含义如下:-world:世界名称,模型添加到指定名称的世界,类型是字符串,默认值为空字符串。7.2ros_gz_sim功能包7.2.2添加模型-file:从指定模型文件中获得模型,类型是表示文件路径的字符串,默认值为空字符串,模型文件的格式既可以是URDF,也可以是SDF。-param:从指定的ROS2参数中获得模型的内容,类型是表示参数名的字符串,默认值为空字符串。-topic:从指定的ROS2话题获得模型并加载,类型是表示话题名称的字符串,默认值是空字符串。-string:加载用字符串表示的模型,类型是字符串,支持URDF和SDF格式表示的模型,默认值为空字符串。-name:重新设置模型的名称,默认值为空字符串,使用模型中设置的模型名称。7.2ros_gz_sim功能包7.2.2添加模型-x:设置模型在仿真场景中的x坐标,默认值是0.0,单位是米。-y:设置模型在仿真场景中的y坐标,默认值是0.0,单位是米。-z:设置模型在仿真场景中的z坐标,默认值是0.0,单位是米。-R:设置模型在仿真场景中旋转的欧拉角Roll,默认值是0.0,单位是弧度。-P:设置模型在仿真场景中旋转的欧拉角Pitch,默认值是0.0,单位是弧度。-Y:设置模型在仿真场景中旋转的欧拉角Yaw,默认值是0.0,单位是弧度。7.2ros_gz_sim功能包7.2.2添加模型以下通示例介绍使用create节点向仿真场景中添加模型的方法。首先,进入工作空间ros2_ws7,启动一个空的仿真环境,执行命令:ros2launchros_gz_simgz_sim.launch.pygz_args:=empty.sdf其次,通过create向仿真场景中分别添加SDF和URDF模型,命令如下:ros2runros_gz_simcreate-filemodel.sdf-namecar-z0.3ros2runros_gz_simcreate-filerobot.urdf-namearm-x0.7在上述命令中,使用create节点向仿真场景中添加了一个SDF格式文件的模型model.sdf,并将其重命名为car后将其放置到z=0.3米处,最后使用create节点向仿真场景中添加了一个URDF格式文件的模型robot.urdf,并将其重新命名为arm后,将其放置到x=0.7米处。7.2ros_gz_sim功能包7.2.2添加模型运行后效果如图所示。7.2ros_gz_sim功能包7.2.2添加模型对于上述的操作,可通过Launch文件将上述启动仿真环境和加载模型的create节点命令进行整合,生成一个新的Launch文件add_model.launch.py,代码如下:importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNode
defgenerate_launch_description():gazebo_node=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('ros_gz_sim'),'launch','gz_sim.launch.py')),launch_arguments=[('gz_args','empty.sdf-v4')])7.2ros_gz_sim功能包robot_to_gazebo=Node(package='ros_gz_sim',executable='create',arguments=['-file','model.sdf','-z','0.3','-name','car'])
robot_to_gazebo2=Node(package='ros_gz_sim',executable='create',arguments=['-file','robot.urdf','-x','0.7','-name','arm'])returnLaunchDescription([gazebo_node,robot_to_gazebo,robot_to_gazebo2])7.2ros_gz_sim功能包7.2.2添加模型在上述Launch文件的代码中,先创建了一个启动仿真环境的节点,然后通过两个Node对象创建了调用create节点分别向仿真场景中添加SDF格式和URDF格式的模型(机器人)。运行上述Luanch文件,在终端里执行命令:ros2launchadd_model.launch.py以上命令的运行效果与执行依次执行上述三条命令的效果相同。(2)通过Launch文件gz_spawn_model.launch.py添加模型。gz_spawn_model.launch.py文件实质是对create节点的一个简单封装,提供了一组与create节点相同的参数,但是在参数命名上稍有不同。7.2ros_gz_sim功能包7.2.2添加模型下表列出了gz_spawn_model.launch.py与create节点参数的映射关系。create参数gz_spawn_model.launch.py参数create参数gz_spawn_model.launch.py参数worldworldxxfilefileyystringmodel_stringzztopictopicRRnameentity_namePP
YY7.2ros_gz_sim功能包7.2.2添加模型在命令行中通过gz_spawn_model.launch.py向仿真场景中添加模型的命令如下:ros2launchros_gz_simgz_sim.launch.pygz_args:=empty.sdfros2launchros_gz_simgz_spawn_model.launch.pyentity_name:=carfile:=model.sdfz:=0.3ros2launchros_gz_simgz_spawn_model.launch.pyentity_name:=armfile:=robot.urdfx:=0.7在上述三条命令中,首先启动了一个空的仿真环境,随后使用gz_spawn_model.launch.py分别向仿真场景中加载了SDF格式和URDF格式的模型。此外,还可以将gz_spawn_model.launch.py引入到另一个Launch文件中,从而与其它节点配合完成更复杂的启动。下面的代码add2_model.launch.py展示了将上述三条命令进行整合为一个Launch文件的效果,代码如下:7.2ros_gz_sim功能包importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNode
defgenerate_launch_description():gazebo_node=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('ros_gz_sim'),'launch','gz_sim.launch.py')),launch_arguments=[('gz_args','empty.sdf-v4')])robot_to_gazebo=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('ros_gz_sim'),'launch','gz_spawn_model.launch.py')),launch_arguments=[('world','empty'),('file','model.sdf'),('name','car'),('z','0.3')])7.2ros_gz_sim功能包robot_to_gazebo2=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('ros_gz_sim'),'launch','gz_spawn_model.launch.py')),launch_arguments=[('world','empty'),('file','robot.urdf'),('name','arm'),('x','0.7')])returnLaunchDescription([gazebo_node,robot_to_gazebo,robot_to_gazebo2])7.2ros_gz_sim功能包7.2.2添加模型上述代码中,创建了三个IncludeLaunchDescription()对象,分别用于启动Gazebo仿真环境,加载SDF模型和加载URDF模型。执行上述Launch文件的命令如下:ros2launchadd2_model.launch.py上述命令在运行后,会启动Gazebo仿真,并加载两个模型到仿真场景中,效果与单独执行三条命令相同。注意:在上述Launch文件的编写中并没有将其放置在一个ROS2的功能包内,然而并不会影响功能的执行,但在一个项目中Launch文件一般要放入到ROS2功能包内,在本章的案例中会详细介绍完整流程。7.3ros_gz_bridge功能包7.3ros_gz_bridge功能包由于ROS2和Gazebo分别定义了自己的通信标准,二者不能直接进行通信,需要一个工具将二者的信息进行转换。ros_gz_bridge功能包就是这样的工具,提供了Gazebo与ROS2间的通信转换的功能,用于进行二者间信息和命令的传输。简单来说,ros_gz_bridge功能包主要提供了Gazebo和ROS2间的话题通信的“桥接”,如图所示。7.3ros_gz_bridge功能包7.3.1bridge_parameter节点Gazebo和ROS2间的话题间的通信的桥接主要是通过ros_gz_bridge功能包中的parameter_bridge节点完成的。查看parameter_bridge节点的使用方法的命令如下:ros2runros_gz_bridgeparameter_bridge-h上述命令的运行效果如图所示,在终端里会显示parameter_bridge的使用方法。7.3ros_gz_bridge功能包7.3.1bridge_parameter节点parameter_bridge节点进行话题桥接时需要提供一个参数,该参数包含三个部分,用于设置桥接的话题、以及该话题在ROS2和Gazebo里消息类型。该参数的格式为:topic@ROS2_type@gz_type上述参数的各部分含义为:①topic为进行桥接的话题名称,设置为话题发布者定义的名称,会在接收者创建一个同名的话题;②第一个@符号为分割符,用于分割话题名称和ROS2消息类型;③ROS2_type为进行桥接的话题对应的ROS2消息类型;7.3ros_gz_bridge功能包7.3.1bridge_parameter节点④第二个@占位符,该位置处可以是“@”,“[”,或“]”符号之一,其中“@”符号表示对话题进行双向的桥接;“[”符号表示将话题由发布者Gazebo桥接到ROS2,如仿真中的图像和里程计等传感器数据由Gazebo生成并发送给ROS2;“]”符号表示将话题由发布者ROS2桥接到Gazebo,如仿真中ROS2发送控制车辆速度指令到Gazebo;⑤gz_type为进行桥接的话题对应的Gazebo消息类型。在上述参数中,桥接话题的消息类型在ROS2和Gazebo间的映射关系十分重要,只有正确的设置才能实现话题的桥接。下表列出了ROS2和Gazebo间的映射关系,在进行话题桥接时查询该表即可获得ROS2和Gazebo话题在消息类型上的映射关系。7.3ros_gz_bridge功能包7.3.1bridge_parameter节点ROS话题消息类型Gazebo话题消息类型actuator_msgs/msg/Actuatorsgz.msgs.Actuatorsbuiltin_interfaces/msg/Timegz.msgs.Timegeometry_msgs/msg/Pointgz.msgs.Vector3dgeometry_msgs/msg/Posegz.msgs.Posegeometry_msgs/msg/PoseArraygz.msgs.Pose_Vgeometry_msgs/msg/PoseStampedgz.msgs.Posegeometry_msgs/msg/PoseWithCovariancegz.msgs.PoseWithCovariancegeometry_msgs/msg/PoseWithCovarianceStampedgz.msgs.PoseWithCovariancegeometry_msgs/msg/Quaterniongz.msgs.Quaterniongeometry_msgs/msg/Transformgz.msgs.Posegeometry_msgs/msg/TransformStampedgz.msgs.Posegeometry_msgs/msg/Twistgz.msgs.Twistgeometry_msgs/msg/TwistStampedgz.msgs.Twistgeometry_msgs/msg/TwistWithCovariancegz.msgs.TwistWithCovariancegeometry_msgs/msg/TwistWithCovarianceStampedgz.msgs.TwistWithCovariancegeometry_msgs/msg/Vector3gz.msgs.Vector3dgeometry_msgs/msg/Wrenchgz.msgs.Wrenchgeometry_msgs/msg/WrenchStampedgz.msgs.Wrenchgps_msgs/msg/GPSFixgz.msgs.NavSatnav_msgs/msg/Odometrygz.msgs.Odometrynav_msgs/msg/Odometrygz.msgs.OdometryWithCovariance7.3ros_gz_bridge功能包7.3.1bridge_parameter节点rcl_interfaces/msg/ParameterValuegz.msgs.Anyros_gz_interfaces/msg/Altimetergz.msgs.Altimeterros_gz_interfaces/msg/Contactgz.msgs.Contactros_gz_interfaces/msg/Contactsgz.msgs.Contactsros_gz_interfaces/msg/Dataframegz.msgs.Dataframeros_gz_interfaces/msg/Entitygz.msgs.Entityros_gz_interfaces/msg/EntityWrenchgz.msgs.EntityWrenchros_gz_interfaces/msg/Float32Arraygz.msgs.Float_Vros_gz_interfaces/msg/GuiCameragz.msgs.GUICameraros_gz_interfaces/msg/JointWrenchgz.msgs.JointWrenchros_gz_interfaces/msg/Lightgz.msgs.Lightros_gz_interfaces/msg/ParamVecgz.msgs.Paramros_gz_interfaces/msg/ParamVecgz.msgs.Param_Vros_gz_interfaces/msg/SensorNoisegz.msgs.SensorNoiseros_gz_interfaces/msg/StringVecgz.msgs.StringMsg_Vros_gz_interfaces/msg/TrackVisualgz.msgs.TrackVisualros_gz_interfaces/msg/VideoRecordgz.msgs.VideoRecordrosgraph_msgs/msg/Clockgz.msgs.Clocksensor_msgs/msg/BatteryStategz.msgs.BatteryStatesensor_msgs/msg/CameraInfogz.msgs.CameraInfosensor_msgs/msg/FluidPressuregz.msgs.FluidPressuresensor_msgs/msg/Imagegz.msgs.Imagesensor_msgs/msg/Imugz.msgs.IMU7.3ros_gz_bridge功能包7.3.1bridge_parameter节点sensor_msgs/msg/JointStategz.msgs.Modelsensor_msgs/msg/Joygz.msgs.Joysensor_msgs/msg/LaserScangz.msgs.LaserScansensor_msgs/msg/MagneticFieldgz.msgs.Magnetometersensor_msgs/msg/NavSatFixgz.msgs.NavSatsensor_msgs/msg/PointCloud2gz.msgs.PointCloudPackedstd_msgs/msg/Boolgz.msgs.Booleanstd_msgs/msg/ColorRGBAgz.msgs.Colorstd_msgs/msg/Emptygz.msgs.Emptystd_msgs/msg/Float32gz.msgs.Floatstd_msgs/msg/Float64gz.msgs.Doublestd_msgs/msg/Headergz.msgs.Headerstd_msgs/msg/Int32gz.msgs.Int32std_msgs/msg/Stringgz.msgs.StringMsgstd_msgs/msg/UInt32gz.msgs.UInt32tf2_msgs/msg/TFMessagegz.msgs.Pose_Vtrajectory_msgs/msg/JointTrajectorygz.msgs.JointTrajectoryvision_msgs/msg/Detection2Dgz.msgs.AnnotatedAxisAligned2DBoxvision_msgs/msg/Detection2DArraygz.msgs.AnnotatedAxisAligned2DBox_Vvision_msgs/msg/Detection3Dgz::msgs::AnnotatedOriented3DBoxvision_msgs/msg/Detection3DArraygz::msgs::AnnotatedOriented3DBox_V7.3ros_gz_bridge功能包7.3.1bridge_parameter节点在一个复杂的仿真中,通常需要桥接多个话题,每次只桥接一个话题将十分繁琐,bridge_parameter节点提供了通过YAML配置文件一次性桥接多个话题的功能。只需要将桥接的所有话题的配置写入到YAML配置文件中,随后在运行bridge_parameter节点时设置config_file参数即可。加载YAML文件启动多个话题桥接的命令格式如下:ros2runros_gz_bridgeparameter_bridge--ros-args-pconfig_file:=config.yaml其中config.yaml就为配置文件,其内定义了话题桥接的配置信息。7.3ros_gz_bridge功能包7.3.1bridge_parameter节点下面的代码展示了config.yaml配置文件示例:-topic_name:"chatter"ros_type_name:"std_msgs/msg/String"gz_type_name:"gz.msgs.StringMsg"#只设置ROS2话题名,并应用到Gazebo-ros_topic_name:"chatter_ros"ros_type_name:"std_msgs/msg/String"gz_type_name:"gz.msgs.StringMsg"#只设置Gazebo的话题名,并应用于ROS2-gz_topic_name:"chatter_gz"ros_type_name:"std_msgs/msg/String"gz_type_name:"gz.msgs.StringMsg"7.3ros_gz_bridge功能包7.3.1bridge_parameter节点-ros_topic_name:"chatter_both_ros"gz_topic_name:"chatter_both_gz"ros_type_name:"std_msgs/msg/String"gz_type_name:"gz.msgs.StringMsg"-ros_topic_name:"ros_chatter"gz_topic_name:"gz_chatter"ros_type_name:"std_msgs/msg/String"gz_type_name:"gz.msgs.StringMsg"subscriber_queue:5#Default10publisher_queue:6#Default10lazy:true#Default"false"direction:BIDIRECTIONAL#Default"BIDIRECTIONAL"-Bridgebothdirections#"GZ_TO_ROS"-BridgeGztopictoROS#"ROS_TO_GZ"-BridgeROStopictoGz7.3ros_gz_bridge功能包7.3.2案例:桥接单个话题本案例将介绍使用bridge_parameter节点进行Gazebo和ROS2间单个话题的桥接方法。以下将实现ROS2发布速度控制话题实现Gazebo中车辆的控制,实现Gazebo中车辆的里程记话题发布到ROS2,以及实现Gazebo中的图像话题发布ROS2三个例子。首先,启动上一节中添加了模型的仿真环境,执行命令:ros2launchadd_model.launch.py在上述命令执行后,打开Gazebo仿真环境,然后点击Gazebo中的启动仿真按钮,启动仿真。7.3ros_gz_bridge功能包7.3.2案例:桥接单个话题其次,建立ROS2速度控制话题/cmd_vel到Gazebo车辆控制话题的桥接,执行命令:ros2runros_gz_bridgeparameter_bridge/cmd_vel@geometry_msgs/msg/Twist]gz.msgs.Twist在上述命令中,通过设置parameter_bridge节点的参数,建立了将ROS2中表示速度控制话题的/cmd_vel桥接到Gazebo中车辆的Diff_Drive差速控制器的话题。命令的运行效果如图所示。7.3ros_gz_bridge功能包7.3.2案例:桥接单个话题随后在一个新的终端里向话题/cmd_vel发布控制速度的命令,代码如下:ros2topicpub/cmd_velgeometry_msgs/msg/Twist"{linear:{x:1.0,y:0.0,z:0.0},angular:{x:0.0,y:0.0,z:0.3}}"上述命令的执行效果如图所示,命令行运行后ROS2会不断的向话题/cmd_vel发布线速度为1.0,角速度为0.3的控制信息,仿真环境中的车辆开始运动。7.3ros_gz_bridge功能包7.3.2案例:桥接单个话题以上通过速度控制话题介绍了将ROS2中话题的消息桥接到Gazebo中的方法。再次,将Gazebo中车辆的里程计话题桥接到ROS2中并在RViz2中显示接收到的里程计信息,执行命令:ros2runros_gz_bridgeparameter_bridge/model/car/odometry@nav_msgs/msg/Odometry[gz.msgs.Odometry随后打开Rviz2,添加一个里程计Odometry的数据可视化功能,将话题名设置为/model/car/odometry,然后设置FixedFrame参数为car/odom,随后即可在RViz中看到车辆实时的里程计数据,如图所示。7.3ros_gz_bridge功能包7.3.2案例:桥接单个话题7.3ros_gz_bridge功能包7.3.2案例:桥接单个话题最后,将Gazebo中相机的图像桥接到ROS2中,执行命令:ros2runros_gz_bridgeparameter_bridge/camera@sensor_msgs/msg/Image[gz.msgs.Image上述命令运行后,将Gazebo中的发布图像的/camera话题桥接到ROS2中,随后在Rviz2中添加Image的可视化,并设置话题为/camera后,即可在显示图像的Image窗体中显示图像,如图所示。7.3ros_gz_bridge功能包7.3.2案例:桥接单个话题以上通过里程计和图像两个话题介绍了将Gazebo采集数据的话题桥接到ROS2中的方法。上述案例通过三个话题的桥接例子介绍了ros_gz_bridge功能包parameter_bridge在桥接一个话题上的使用方法,展示了ROS2到Gazebo和Gazebo到ROS2话题的桥接,以及不同消息类型数据的桥接效果。7.3ros_gz_bridge功能包7.3.3案例:桥接多个话题对于一个真实的仿真通常需要桥接多个话题,此时就需要使用YAML文件存储所有需要桥接话题的配置信息,然后通过ROS2参数config_file设置YAML文件,由parameter_bridge运行时从YAML文件中加载和桥接相应的话题。与命令行进行话题的桥接时不能更改话题名称相比,使用YAML文件可以完成更改话题名称,以及设置更多的配置项信息。在以下的案例中,将用YAML文件对上一个案例中的三个话题进行配置,并使用命令行和Launch文件两种方式完成话题的桥接。7.3ros_gz_bridge功能包7.3.3案例:桥接多个话题首先,编辑进行话题桥接的YAML文件。创建一个名为car_bridge.yaml的文件,输入以下配置信息:#将ROS2发布的cmd_vel话题桥接到Gazebo车辆-ros_topic_name:"/cmd_vel"gz_topic_name:"/cmd_vel"ros_type_name:"geometry_msgs/msg/Twist"gz_type_name:"gz.msgs.Twist"direction:"ROS_TO_GZ"#将Gazebo发布的里程计话题桥接到ROS2,话题名重命名为odom-ros_topic_name:"/odom"gz_topic_name:"/model/car/odometry"ros_type_name:"nav_msgs/msg/Odometry"gz_type_name:"gz.msgs.Odometry"direction:"GZ_TO_ROS"7.3ros_gz_bridge功能包7.3.3案例:桥接多个话题#将Gazebo发布的camera话题桥接到ROS2-ros_topic_name:"/camera"gz_topic_name:"/camera"ros_type_name:"sensor_msgs/msg/Image"gz_type_name:"gz.msgs.Image"direction:"GZ_TO_ROS"7.3ros_gz_bridge功能包7.3.3案例:桥接多个话题第一种方法,通过命令行的方式桥接以上YAML配置。(1)启动上一节中添加了模型的仿真环境,执行命令:ros2launchadd_model.launch.py在上述命令执行后,Gazebo仿真环境打开,然后点击启动仿真。(2)启动parameter_bridge节点并加载话题桥接配置文件car_bridge.yaml,命令如下:ros2runros_gz_bridgeparameter_bridge--ros-args-pconfig_file:=car_bridge.yaml第二种方法,将启动方法一中的parameter_bridge节点启动也添加到Launch文件中,使用一个Launch文件完成仿真环境,加载模型和话题桥接三个功能。创建一个名为add_model_and_bridge.launch.py的文件,代码如下:7.3ros_gz_bridge功能包7.3.3案例:桥接多个话题importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNodedefgenerate_launch_description():gazebo_node=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('ros_gz_sim'),'launch','gz_sim.launch.py')),launch_arguments=[('gz_args','empty.sdf-r-v4‘)])robot_to_gazebo=Node(package='ros_gz_sim',executable='create',arguments=['-file','model.sdf','-z','0.3','-name','car‘])7.3ros_gz_bridge功能包7.3.3案例:桥接多个话题robot_to_gazebo2=Node(package='ros_gz_sim',executable='create',arguments=['-file','robot.urdf','-x','0.7','-name','arm'])car_bridge_node=Node(package='ros_gz_bridge',executable='parameter_bridge',parameters=[{"config_file":"car_bridge.yaml"},])returnLaunchDescription([gazebo_node,robot_to_gazebo,robot_to_gazebo2,car_bridge_node])7.3ros_gz_bridge功能包7.3.3案例:桥接多个话题在上述代码中加入了一个启动节点,用于启动具有话题桥接配置文件的parameter_bridge节点。在终端里执行命令:ros2launchadd_model_and_bridge.launch.py上述命令执行后,就会一次性完成启动仿真、加载模型和创建话题桥接等多个任务。对于实际的应用只需要将所有需要启动的节点加入到Launch文件中即可。注意:进行话题桥接的配置文件car_bridge.yaml和Launch文件add_model_and_bridge.launch.py需要在相同的文件夹下。如果不在相同的文件夹下,需要在Launch文件设置配置文件的相对路径或绝对路径。7.4其他注意事项7.4其他注意事项除了启动仿真环境、添加模型和进行话题桥接外,在进行Gazebo和ROS2联合仿真时还需要注意其他的一些事项以更顺利地进行二者间的仿真。7.4.1实体的控制Gazebo将整个仿真场景内容以实体进行组织,因此,可将整个仿真环境看作是一个由若干个实体构成的数据库。数据库一般需要具有对数据(实体)的增、删、改和查功能。对于仿真环境,就是向仿真场景添加实体,ros_gz_sim功能包的create节点提供了添加模型(模型可以看作是实体的一个子集)的功能,而删、改和查等三个功能ROS2并没有直接提供相关的操作。7.4其他注意事项7.4.1实体的控制当前Gazebo一方面成为ROS2在仿真环境的一部分,另一方面Gazebo本身也是一个独立的物理仿真工具,提供了类似于ROS2命令行和编程接口,通过Gazebo的话题和服务等可实现对仿真环境中实体的增、删、改和查全部四个功能。这样在联合仿真时,借助GazeboTransport库的相关方法就可以实现对仿真环境中实体的控制。例如,在机械臂智能抓取的强化学习中,当机械臂将抓取物品移动后,就可以直接“修改”物品的位置,将物品移动回原位置,继续进行学习直到成功。7.4其他注意事项7.4.2话题消息类型由于Gazebo和ROS2都定义了自身的消息类型,在桥接话题进行配置时要查到话题在Gazebo和ROS2上的消息类型后才能进行正确设置。话题消息类型的查询可以分为ROS2作为发布者和Gazebo作为话题发布者两种情况。(1)ROS2作为话题发者时,首先利用ROS2的topic命令查询话题的消息类型,然后再根据表7.2中的消息类型对应关系查得相应的Gazebo消息类型。例如,在桥接ROS2的速度控制话题/cmd_vel到Gazebo时,在终端里查询话题的消息类型,执行命令:ros2topicinfo/cmd_vel终端输出的结果如下:Type:geometry_msgs/msg/Twist7.4其他注意事项7.4.2话题消息类型从以上的输出可以看到话题的/cmd_vel的消息类型geometry_msgs/msg/Twist,通过查表7.2可知与其对应的Gazebo消息类型为gz.msgs.Twist。(2)Gazebo作为话题发布者时,首先利用Gazebo的topic命令查询话题的消息类型,然后再根据表7.2中的消息类型对应关系查得相应的ROS2消息类型。例如,在桥接Gazebo的相机话题/camera到ROS2时,在终端里查询话题的消息类型,执行命令:gztopic-i-t/camera终端输出的内容如下:Publishers[Address,MessageType]:tcp://5:38257,gz.msgs.Image7.4其他注意事项7.4.2话题消息类型从以上输出可以看出,相机话题/camera的消息类型为gz.msgs.Image,通过查表可知与其对应的ROS2消息类型为sensor_msgs/msg/Image。此外,在进行复杂的Gazebo和ROS2联合仿真时,可能会出现需要桥接ros_gz_bridge提供的标准消息类型以外的数据。此时,如果采取在Gazebo和ROS2分别定义消息类型,再定义桥接方法的方式就十分复杂。针对该种情况,可以在发送两端使用数据序列化和反序化方法,例如将数据封装为JSON字符串的形式,使用标准的字符串类型进行桥接即可。7.4其他注意事项7.4.3相机话题相较于其他传感器,相机采集的是图像,数据量较大,虽然可以直接使用ros_gz_bridge功能包进行桥接,但是效率较低。针对上述情况,ROS2专门提供了一个功能包ros_gz_image进行话题的桥接,利用该功能包的image_bridge节点完成图像的桥接。使用image_bridge节点桥接相机的命令如下:ros2runros_gz_imageimage_bridge/camera以上命令中,/camera为待桥接的话题名称。7.4其他注意事项7.4.3相机话题在Launch文件中可通过创建相应的启动节点调用image_bridge完成图像数据的桥接,相关代码如下:image_bridge_node=Node(package='ros_gz_image',executable='image_bridge',arguments=['/camera'])#/camera为待桥接的相机话题名7.4其他注意事项7.4.4RViz2可视化SDF模型在进行机器人的联合仿真时,机器人模型通常使用ROS2的URDF格式,从而在RViz中进行显示。在ROS2Jazzy中提供了功能包ros-jazzy-sdformat-urdf,其内部将SDF格式的机器人转化为URDF格式,从而使得在ROS2开发上支持原生的SDF格式的机器人,将SDF格式的机器人在RViz2中进行可视化。RViz2中可视化SDF模型(机器人)主要包括以下几个步骤:(1)安装功能包ros-jazzy-sdformat-urdf,执行命令:sudoaptinstallros-jazzy-sdformat-urdf-y7.4其他注意事项7.4.4RViz2可视化SDF模型(2)在Launch文件中使用robot_state_publisher功能包发布模型。相关代码如下:robot_desc=open('model.sdf').read()#打开SDF格式的机器人模型并读取模型为字符串robot_desc_node=Node(package='robot_state_publisher',executable='robot_state_publisher',name='robot_state_publisher',output='both',parameters=[{'use_sim_time':True},{'robot_description':robot_desc},])7.4其他注意事项7.4.4RViz2可视化SDF模型(3)配置模型的坐标信息/tf话题和关节状态/joint_state话题的桥接,并在Launch文件中使用ros_gz_bridge进行桥接。话题桥接配置的vis_bridge.yaml的代码如下:-ros_topic_name:"/tf"gz_topic_name:"/tf"ros_type_name:"tf2_msgs/msg/TFMessage"gz_type_name:"gz.msgs.Pose_V"direction:GZ_TO_ROS-ros_topic_name:"/joint_states"gz_topic_name:"/joint_states"ros_type_name:"sensor_msgs/msg/JointState"gz_type_name:"gz.msgs.Model"direction:GZ_TO_ROS7.4其他注意事项7.4.4RViz2可视化SDF模型在Launch文件进行话题的桥接,相关代码如下:car_bridge_node=Node(package='ros_gz_bridge',executable='parameter_bridge',parameters=[{"config_file":"vis_bridge.yaml"},])7.4其他注意事项7.4.4RViz2可视化SDF模型(4)运行Launch文件add_and_vis_model.launch.py,然后打开RViz2。在RViz2中添加RobotModel可视化功能,选择话题为/robot_description,并设置FixedFrame为body。下图展示了RViz2可视化SDF模型的效果。注意:目前ros-jazzy-sdformat-urdf功能包在将SDF转化为URDF时,模型的关节只支持基本的几何体,如圆柱、长方体等类型,以及STL格式或DAE格式的三维格网。对于其他类型的三维数据并不支持,在可视化SDF模型时需要注意。7.5案例:视觉巡线移动轮式机器人7.5案例:视觉巡线移动轮式机器人以下将以一个视觉巡线移动轮式机器人的例子来介绍Gazebo和ROS2进行联合仿真的完整过程和详细步骤。本案例的任务是使一台具有图像采集功能的差速车辆,其相机采集地面图像,然后识别图像中的引导线,最后根据识别结果控制车辆在仿真场景中沿着引导线移动。要完成该任务,首先要创建一个功能包,其次制作包含地面和车辆的仿真场景,再次创建Launch文件启动仿真环境,以及进行速度控制话题和图像话题的桥接,最后,编辑和添加车辆控制节点控制车辆进行巡线。以下对整个视觉巡线移动轮式机器人的仿真流程进行介绍。(1)创建一个功能包,用于放置整个任务的相关文件和代码。执行命令:ros2pkgcreate--build-typeament_python--node-nametrackroad--licenseMITtrackroad在上述命令中创建了一个名为trackroad的Python功能包,此外,还创建了一个用于实现巡线功能的trackroad节点。7.5案例:视觉巡线移动轮式机器人(2)创建一个包含地面和车辆的仿真场景,效果如图所示。仿真场景在建模时先利用Gazebo的SDF分别进行地面的建模和车辆的建模,然后再将地面和车辆加载到仿真场景中进行调整和测试车辆的控制和图像采集功能,最后利用Gazebo导出整个仿真场景为名称raceworldallinone.sdf的SDF文件。7.5案例:视觉巡线移动轮式机器人(3)添加仿真场景到功能包。首先,在功能包trackroad内创建一个名为models的文件夹,将仿真场景SDF文件和地面贴图放置在该文件夹内;其次,编辑功能包的setup.py文件,在文件头导入glob函数,代码如下:fromglobimportglob此外,将models文件夹中的文件添加到功能包trackroad,方法是向data_files变量添加models文件夹,代码如下:('share/'+package_name+'/models',glob('models/*.*'))7.5案例:视觉巡线移动轮式机器人(4)创建Launch文件启动仿真环境。在功能包trackroad内创建一个名为launch的文件夹,在该文件夹内创建名为trackroad.launch.py的Launch文件,代码如下:importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNode
packagepath=get_package_share_directory('trackroad')worldsdf=packagepath+'/models/raceworldallinone.sdf'7.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 四省八校2025届高三化学第一学期期中复习检测模拟试题含解析
- 2026辅导员调研面试题及答案
- 2026高校旅游管理教师面试题及答案
- 2026工程检测面试题库及答案
- 释普度古诗词全集大全
- 苏教版科学小学五年级上册期末测试卷附答案
- 2026国企文化面试题目及答案
- 数控工艺试题
- 2026护卫面试题及回答模板及答案
- 工会安全会议主题讲解
- 眼镜制造工程师考试试卷及答案
- 铸造考核细则培训课件
- 河道挡墙钢板桩围堰施工方案
- 前列腺癌诊疗指南(2026版)
- 医院临床路径管理实施及考核评价细则
- 2026 酒店客房布置实训课件
- 2025福州市鼓西街道社区工作者招聘考试真题及答案
- 钢结构施工工期压缩方案
- TGDACM 0174-2026 中医技术操作规范 温通拨筋罐疗法
- 监委留置工作培训课件
- 矿井供电设计毕业论文
评论
0/150
提交评论