以下文章翻译自:Gazebo教程-ROS Communication
Gazebo提供了一组ROS API,允许用户修改和获取Gazebo仿真世界中的各方面的信息。在以下各节中,我们将演示一些实用程序,用这些程序来操作Gazebo的仿真世界以及其中的物体【译者:比如一个可乐罐】。有关Gazebo ROS API(消息和服务)的完整列表也可以在这里找到。
先决条件
如果您想按照演示例子进行操作,请确保您已经将RRBot设置好了,如在 Gazebo 中使用 URDF 中所述。在本教程中,我们将使用各种技术让 RRBot “踢”可乐罐。
我们假设您已经使用以下方法启动了Gazebo:
roscore &
rosrun gazebo_ros gazebo
您可能偶尔需要在执行了下面列出的不同命令后重新启动 Gazebo。
术语
在下文中,一个刚性物体的姿态(pose)和扭曲(twist)被称为它的“状态(state)”。物体还具有固有的“属性”,例如质量和摩擦系数。在Gazebo中,“body”是指刚性物体,用URDF描述机器人时“刚性物体(body)”与“连杆(link)”同义。Gazebo的“模型(model)”是由“关节(joint)”连接的“刚性物体(body)”的集合体。
关于gazebo_ros_api_plugin
插件gazebo_ros_api_plugin 包含在软件包gazebo_ros 中,该插件初始化了一个名为“gazebo”的 ROS 节点。它把ROS 回调调度器(callback scheduler)(消息传递)和Gazebo 的内部调度器(internal scheduler)集成在一起,提供下面描述的 ROS API。利用这套ROS API,用户可以操作仿真环境的属性,以及生成和观察环境中模型的状态。
此插件仅在执行gzserver时被加载。
Gazebo发布的参数
参数:
/use_sim_time:Bool-通知ROS时间使用发布的/clock主题时间。
Gazebo使用ROS参数服务器通知其他应用程序是否应通过/use_sim_time参数使用仿真时间,特别是Rviz。当您启动gazebo_ros时,这应该由Gazebo自动设置为true。
如果希望提供与仿真同步的时间,gazebo_ros需要发布ROS /clock主题,则/use_sim_time应设置为true。有关仿真时间的更多信息,请参见ROS C ++ Time。
检查值
要查看参数设置的情况,运行:
rosparam get /use_sim_time
Gazebo订阅的主题
主题:
~/set_link_state : gazebo_msgs/LinkState – 设置一个连杆的状态(pose/twist).
~/set_model_state : gazebo_msgs/ModelState – 设置一个模型的状态 (pose/twist).
在仿真中通过主题设置model的pose和twist
主题可用于快速设置模型的pose和twist,而无需等待pose设置操作完成。为此,可以将所需的模型状态消息发布到/gazebo/set_model_state主题。为了测试一下如何通过设置主题来改变model的pose(姿态),我们需要先在仿真环境中添加一个可乐罐模型:
rosrun gazebo_ros spawn_model -database coke_can -gazebo -model coke_can -y 1
【译者注:由于版本变化原文语句不对了,参考下面
通用格式为:
rosrun gazebo_ros spawn_model -database <model_name> -sdf -model <model_instance_name>
对于coke_can:
rosrun gazebo_ros spawn_model -database coke_can -sdf -model coke_can
这个操作需要等一会儿。code_can模型将被下载到“~/.gazebo/model”目录中,同时显示在gazebo仿真界面中。】
然后,向主题/gazebo/set_model_state发送可乐罐的姿态消息:
rostopic pub -r 20 /gazebo/set_model_state gazebo_msgs/ModelState '{model_name: coke_can, pose: { position: { x: 1, y: 0, z: 2 }, orientation: {x: 0, y: 0.491983115673, z: 0, w: 0.870604813099 } }, twist: { linear: { x: 0, y: 0, z: 0 }, angular: { x: 0, y: 0, z: 0} }, reference_frame: world }'
你应该看到可乐罐在RRBot前面徘徊,在等待被击中(我们下面处理)。
Gazebo 发布的主题
主题:
/clock : rosgraph_msgs/Clock – 发布仿真时间, 与/use_sim_time 参数一起使用。
~/link_states : gazebo_msgs/LinkStates – 发布仿真中的所有连杆的状态。
~/model_states : gazebo_msgs/ModelStates – 发布仿真中的所有模型的状态。
使用主题获取模型和连杆的状态
Gazebo 发布 /gazebo/link_states和/gazebo/model_states主题,包含仿真中的物体相对于Gazebo世界坐标框架的pose和twist信息。您可以通过运行以下命令来查看这些内容:
rostopic echo -n 1 /gazebo/model_states
或者
rostopic echo -n 1 /gazebo/link_states
重申一下,“link”被定义为具有给定惯性、视觉和碰撞属性的刚体。而“model”被定义为link和joint的集合。“model”的状态是其规范(canonical)“link”的状态。在URDF 中是强制执行树结构的,所以model的规范(canonical )连杆由其根连杆定义。
【译者注:The word “canonical” means “according to rule” or “conforming to a general rule or acceptable procedure”. In the context of URDF, the canonical link of a model is defined by its root link.
“canonical”一词的意思是“按照规则”或“符合一般规则或可接受的程序” 。在URDF的上下文中,模型的规范连杆由其根连杆定义。】
服务:在仿真中创建和销毁模型
这些服务允许用户在仿真中动态生成和销毁模型:
~/spawn_urdf_model : gazebo_msgs/SpawnModel - 使用此服务生成通用机器人描述格式(URDF)的模型
~/spawn_sdf_model : gazebo_msgs/SpawnModel - 使用此服务生成用Gazebo仿真描述格式(SDF)编写的模型
~/delete_model : gazebo_msgs/DeleteModel - 此服务允许用户从仿真中删除模型。
生成模型
提供了一个名为spawn_model的辅助脚本,用于调用gazebo_ros提供的模型生成服务。使用服务调用方法生成模型的最实用方法是使用roslaunch文件。有关详细信息,请参见教程“使用roslaunch文件生成模型”。有许多方法可以使用spawn_model将URDF和SDF生成到Gazebo中。以下是一些示例:
根据存储在文件中的URDF生成模型-首先将.xacro文件转换为.xml,然后生成模型:
rosrun xacro xacro `rospack find rrbot_description`/urdf/rrbot.xacro >> `rospack find rrbot_description`/urdf/rrbot.xml
rosrun gazebo_ros spawn_model -file `rospack find rrbot_description`/urdf/rrbot.xml -urdf -y 1 -model rrbot1 -robot_namespace rrbot1
使用 roslaunch 和 xacro根据来自参数服务器的 URDF生成模型的方法请参阅 Using roslaunch Files to Spawn Models。
根据存储在本地模型数据库的 SDF生成模型:
rosrun gazebo_ros spawn_model -file `echo $GAZEBO_MODEL_PATH`/coke_can/model.sdf -sdf -model coke_can1 -y 0.2 -x -0.3
根据存储在在online模型数据库的 SDF:
rosrun gazebo_ros spawn_model -database coke_can -sdf -model coke_can3 -y 2.2 -x -0.3
要查看包含命名空间、trimesh 属性、关节位置和 RPY 方向的所有可用参数,运行:
rosrun gazebo_ros spawn_model -h
删除模型
删除已在 Gazebo 中的模型会更容易,只要您知道您为对象指定的模型名称即可。如果您按照上一节所述生成了名为“rrbot1”的 rrbot,则可以通过以下方式将其删除:
rosservice call gazebo/delete_model '{model_name: rrbot1}'
服务:状态和属性的设置
这些服务允许用户设置有关仿真和仿真中的对象的状态和属性信息:
~/set_link_properties : gazebo_msgs/SetLinkProperties
~/set_physics_properties : gazebo_msgs/SetPhysicsProperties
~/set_model_state : gazebo_msgs/SetModelState
~/set_model_configuration : gazebo_msgs/SetModelConfiguration – 这些服务允许用户在不考虑它的dynamics特性的情况下设置模型的关节位置。
【译者注:In Gazebo, “dynamics” refers to the damping and friction in a joint. It is part of the URDF description. The “mu1” and “mu2” elements are part of a Gazebo description and apply to the material properties of a body。】
~/set_joint_properties : gazebo_msgs/SetJointProperties`
~/set_link_state : gazebo_msgs/SetLinkState
~/set_link_state : gazebo_msgs/LinkState
~/set_model_state : gazebo_msgs/ModelState
设置model状态的例子
让我们玩得开心,让RRBot使用该服务击中可乐罐。/gazebo/set_model_state
如果尚未将可乐罐生成到仿真环境中,运行:
rosrun gazebo_ros spawn_model -database coke_can -gazebo -model coke_can -y 1
这应该是与Gazebo一起预打包的,或者可以通过在线模型数据库获得(需要互联网连接)。在场景中的任何位置放置可乐罐,放置位置不重要。现在,我们将调用服务请求将可乐罐移动到RRBot的位置。
rosservice call /gazebo/set_model_state '{model_state: { model_name: coke_can, pose: { position: { x: 0.3, y: 0.2 ,z: 0 }, orientation: {x: 0, y: 0.491983115673, z: 0, w: 0.870604813099 } }, twist: { linear: {x: 0.0 , y: 0 ,z: 0 } , angular: { x: 0.0 , y: 0 , z: 0.0 } } , reference_frame: world } }'
您应该看到如下所示的设置:
现在使用以下命令让 RRBot 开始旋转:
rosservice call /gazebo/set_model_state '{model_state: { model_name: rrbot, pose: { position: { x: 1, y: 1 ,z: 10 }, orientation: {x: 0, y: 0.491983115673, z: 0, w: 0.870604813099 } }, twist: { linear: {x: 0.0 , y: 0 ,z: 0 } , angular: { x: 0.0 , y: 0 , z: 0.0 } } , reference_frame: world } }'
运气好的话,你会让可乐罐发射到不同的距离:)(笑脸)如果失败了,您可以随时重试,您知道,这是一个教程。
服务:状态和属性的获取
这些服务允许用户检索有关仿真和仿真对象的状态和属性信息:
~/get_model_properties:gazebo_msgs/GetModelProperties-此服务返回仿真中模型的属性。
~/get_model_state:gazebo_msgs/GetModelState-此服务返回仿真中模型的状态。
~/get_world_properties:gazebo_msgs/GetWorldProperties-此服务返回仿真世界的属性。
~/get_joint_properties:gazebo_msgs/GetJointProperties-此服务返回仿真中joint的属性。
~/get_link_properties:gazebo_msgs/GetLinkProperties-此服务返回仿真中link的属性。
~/get_link_state:gazebo_msgs/GetLinkState-此服务返回仿真中link的状态。
~/get_physics_properties:gazebo_msgs/GetPhysicsProperties-此服务返回用于仿真的物理引擎的属性。
~/link_states:gazebo_msgs/LinkStates-在世界框架中发布所有的link状态
/model_states:gazebo_msgs/ModelStates-在世界框架中发布所有的模型状态
注意
link_names采用Gazebo范畴内的名称表示法,[model_name::body_name]
获取模型状态的例子
现在你已经“踢”了可乐罐一段距离,你会想知道它走了多远。在前面的示例(运行相同的仿真)的基础上,我们将使用服务调用查询可乐罐的姿势和扭曲:
rosservice call gazebo/get_model_state '{model_name: coke_can}'
这取决于你的机器人的踢球技巧,你可以得到这样的东西:
pose:
position:
x: -10.3172263825
y: -1.95098702647
z: -0.00413857755159
orientation:
x: -0.0218349987011
y: -0.00515029763403
z: 0.545795377598
w: 0.83761811887
twist:
linear:
x: -0.000385525262354
y: -0.000344915539911
z: -0.00206406538336
angular:
x: -0.104256200218
y: 0.0370371098566
z: 0.0132837766211
success: True
我的机器人把罐子踢了10米,你的呢?
获取世界和物体的属性
运行下面的命令,你可以得到世界中的所有模型:ground_plane, coke cane, rrbot:
rosservice call gazebo/get_world_properties
sim_time: 1013.366
model_names: ['ground_plane', 'rrbot', 'coke_can']
rendering_enabled: True
success: True
status_message: GetWorldProperties: got properties
并可以得到指定模型的详细信息:
rosservice call gazebo/get_model_properties '{model_name: rrbot}'
parent_model_name: ''
canonical_body_name: ''
body_names: ['link1', 'link2', 'link3']
geom_names: ['link1_geom', 'link2_geom', 'link3_geom', 'link3_geom_camera_link', 'link3_geom_hokuyo_link']
joint_names: ['fixed', 'joint1', 'joint2']
child_model_names: []
is_static: False
success: True
status_message: GetModelProperties: got properties
服务:力控制
这些服务允许用户在仿真中对物体和关节施加扭矩和力:
~/apply_body_wrench:gazebo_msgs/ApplyBodyWrench-将扭矩作用于仿真中的物体。作用于同一物体的所有活动扭矩是累积的。
~/apply_joint_effort:gazebo_msgs/ApplyJointEffort-将力作用于仿真中的关节。作用于同一关节的所有活动力是累积的。
~/clear_joint_forces:gazebo_msgs/JointRequest-清除对关节施加的力。
~/clear_body_wrenches:gazebo_msgs/ClearBodyWrenches-清除对物体施加的扭矩。
向连杆施加扭矩
为了演示在Gazebo body上施加扭矩,让我们先生成一个没有重力的物体。确保可乐罐已添加到仿真中:
rosrun gazebo_ros spawn_model -database coke_can -gazebo -model coke_can -y 1
然后,要想把重力拿掉,可以发送服务调用到/gazebo/set_physics_properties ,这样所有轴向(axis)上都没有重力了:
rosservice call /gazebo/set_physics_properties "
time_step: 0.001
max_update_rate: 1000.0
gravity:
x: 0.0
y: 0.0
z: 0.0
ode_config:
auto_disable_bodies: False
sor_pgs_precon_iters: 0
sor_pgs_iters: 50
sor_pgs_w: 1.3
sor_pgs_rms_error_tol: 0.0
contact_surface_layer: 0.001
contact_max_correcting_vel: 100.0
cfm: 0.0
erp: 0.2
max_contacts: 20"
通过调用/gazebo/apply_body_wrench服务,在可乐罐原点施加0.01 Nm扭矩,持续1秒钟,您应该会看到可乐罐沿着正x轴旋转:
rosservice call /gazebo/apply_body_wrench '{body_name: "coke_can::link" , wrench: { torque: { x: 0.01, y: 0 , z: 0 } }, start_time: 10000000000, duration: 1000000000 }'
你可以看到可乐罐在旋转:
在可乐罐原点施加反向-0.01 Nm扭矩,持续1秒钟,可乐罐应该停止旋转:
rosservice call /gazebo/apply_body_wrench '{body_name: "coke_can::link" , wrench: { torque: { x: -0.01, y: 0 , z: 0 } }, start_time: 10000000000, duration: 1000000000 }'
通常,持续时间为负的扭矩会无限期地持续。要清除施加到物体上的任何活动扭矩,可以:
rosservice call /gazebo/clear_body_wrenches '{body_name: "coke_can::link"}'
在仿真时,向关节施加扭矩
调用/gazebo/apply_joint_effort可以向关节施加扭矩:
rosservice call /gazebo/apply_joint_effort "joint_name: 'joint2'
effort: 10.0
start_time:
secs: 0
nsecs: 0
duration:
secs: 10
nsecs: 0"
连杆应该开始旋转。
可以调用以下语句清除在某一个关节上施加的力:
rosservice call /gazebo/clear_joint_forces '{joint_name: joint2}'
服务:仿真控制
这些服务允许用户在仿真中暂停(pause)和取消暂停(unpause)物理引擎:
~/pause_physics:std_srvs/Empty-暂停物理引擎更新。
~/unpause_physics:std_srvs/Empty-恢复物理引擎更新。
~/reset_simulation:std_srvs/Empty-重置整个仿真,包括时间
~/reset_world:std_srvs/Empty-重置模型的姿态
暂停和取消暂停物理引擎
假设您想获得在空中飞行的苏打水罐的屏幕截图。您可以通过调用以下命令暂停物理引擎:
rosservice call gazebo/pause_physics
当仿真暂停时,仿真时间停止,对象变为静态。但是,Gazebo的内部更新循环(例如自定义动态插件更新)仍在运行,但是由于仿真时间不会改变,因此受仿真时间限制的任何内容都不会更新。要恢复仿真,请通过调用取消暂停物理引擎:
rosservice call gazebo/unpause_physics
词汇翻译:
Topic:主题
Pose:姿态
Twist:扭曲
Model:模型
Link:连杆
Joint:关节
Body:物体
Object:对象
Spawn:生成
Force:力
Wrenches :扭矩