连接到 ROS 2


预计完成时间:14 分钟

3.8   差速驱动插件

现在你的机器人已经具备移动能力了!下一步就是把它接入 ROS2,这样你就可以通过向 ROS2 话题发布消息来控制机器人运动。这个功能可以通过一个插件实现,并且可以借助 Gazebo 标签把它写入 URDF 模型中。具体做法如下:

把下面这段包含 Differential Drive Plugin 的代码复制到你的 URDF 文件底部,也就是放在结束的 </robot> XML 标签之前。

  复制并粘贴

In [ ]:
<!-- Differential Drive Plugin -->
<gazebo>
    <plugin
        filename="libignition-gazebo-diff-drive-system.so"
        name="ignition::gazebo::systems::DiffDrive">
        <left_joint>joint_chassis_left_wheel</left_joint>
        <right_joint>joint_chassis_right_wheel</right_joint>
        <wheel_separation>1.66</wheel_separation>
        <wheel_radius>0.4</wheel_radius>
        <odom_publish_frequency>20</odom_publish_frequency>
        <topic>cmd_vel</topic>
        <odom_topic>odom</odom_topic>
        <tf_topic>tf</tf_topic>
        <frame_id>odom</frame_id>
        <child_frame_id>link_chassis</child_frame_id>
    </plugin>
</gazebo>
- 注释 -

对应的新 Gazebo Sim 写法:

In [ ]:
<gazebo>
    <plugin
        filename="libgz-sim-diff-drive-system.so"
        name="gz::sim::systems::DiffDrive">
        ...
    </plugin>
</gazebo>
- 注释结束 -

粘贴完成后,保存你的 URDF 文件。接下来需要重新构建 ROS2 功能包,并重新生成机器人。

  在 Web Shell 1 中执行

In [ ]:
cd /workspace/gazebo_sim_ros2
In [ ]:
rm -rf ./build ./install ./log
In [ ]:
colcon build --packages-select robot_description && source install/setup.bash
In [ ]:
ros2 launch robot_description empty_world.launch.py

  在 Web Shell 2 中执行

In [ ]:
cd /workspace/gazebo_sim_ros2
In [ ]:
source install/setup.bash
In [ ]:
ros2 launch robot_description spawn.launch.py

你已经添加了 diff_drive 插件。现在是不是就应该可以直接控制机器人运动了呢?

先检查一下在 ros2 topic list 中是否能看到 cmd_vel 话题。

你找到 cmd_vel 了吗?我可以肯定,它现在还没有出现。

之所以现在还不能移动机器人,是因为你还没有可用于发布速度消息的 cmd_vel 话题。因此,接下来需要创建一个双向的 ros_gz_bridge,用来在 ROS2 和 IGN Gazebo Sim 之间传递速度指令。

请打开一个新的 web shell,为 cmd_vel 话题启动双向桥接。你可以先尝试根据前一节学到的内容自己写命令;如果暂时写不出来,也可以直接参考下面给出的命令。

桥接启动之后,需要让它持续保持运行。

  在 Web Shell 3 中执行

In [ ]:
ros2 run ros_gz_bridge parameter_bridge /cmd_vel@geometry_msgs/msg/Twist@ignition.msgs.Twist
- 注释 -

对应的新 Gazebo Sim 写法:

In [ ]:
ros2 run ros_gz_bridge parameter_bridge /cmd_vel@geometry_msgs/msg/Twist@gz.msgs.Twist
- 注释结束 -

桥接激活之后,你现在应该就能在 ros2 topic list 中看到 cmd_vel 话题了。

最后,向 cmd_vel 话题发送速度指令来控制机器人运动。这里我们使用键盘遥操作程序来完成这项任务。

  在 Web Shell 4 中执行

In [ ]:
ros2 run teleop_twist_keyboard teleop_twist_keyboard

现在,按照 teleop 程序所在 web shell 中显示的按键说明,你就可以在 Gazebo Sim 中移动机器人了!

现在你已经可以在 Gazebo Sim 中自由操控并测试这台机器人了。

**注意:** 如果你停止了 ros_gz_bridge,机器人会保持执行你在 teleop 程序中最后一次发送的动作。因此,如果你在关闭桥接之前先把机器人停下来,它就会保持静止;反之,如果它在桥接关闭时还在移动,那么它会继续移动。你可以自己试试看!

按照当前的配置,你可以通过向 /cmd_vel 发布消息来控制机器人运动。角速度会考虑左右车轮之间的间距,线速度则会考虑你配置的车轮半径。这也正是为什么你需要在 diff_drive 插件中显式填写这两个参数。

此外,你还会得到一个 /odom 话题,它接收来自该 Gazebo 插件的消息,其中包含机器人的位置信息。不过,你还没有为这个话题配置桥接,接下来的练习中就会处理它。

"Gazebo Diff Drive Plugin"

- 练习 3.7.1 -

编写一个简单的 Python 脚本,根据两个参数来控制机器人运动:线速度角速度

在机器人运动过程中,程序还需要显示机器人在 XY 轴上的位置

提示: 你需要同时为 /cmd_vel/odom 这两个话题创建桥接。你已经知道 /cmd_vel 需要使用双向桥接;而 /odom 则应使用单向桥接,也就是 IGN 到 ROS 的桥接。可用命令如下:

In [ ]:
ros2 run ros_gz_bridge parameter_bridge /cmd_vel@geometry_msgs/msg/Twist@ignition.msgs.Twist /odom@nav_msgs/msg/Odometry[ignition.msgs.Odometry
- 注释 -

对应的新 Gazebo Sim 写法:

In [ ]:
ros2 run ros_gz_bridge parameter_bridge /cmd_vel@geometry_msgs/msg/Twist@gz.msgs.Twist /odom@nav_msgs/msg/Odometry[gz.msgs.Odometry
- 注释结束 -

注意: 别忘了更新你的 setup.py 文件,这样你才能通过 ros2 run 命令运行自己的程序。

预期结果:

"Display Odom Result"

- 练习 3.7.1 结束 -
- 练习 3.7.1 参考答案 -

在你自己尝试完成练习之前,不要先看答案。完成后再回头查看参考答案,会更方便你对比自己的实现。

如果你在完成练习时遇到问题,可以到论坛寻求支持。

display_odom.py

- 练习 3.7.1 参考答案结束 -