建立两轮机器人 URDF 文件,通过两轮机器人来熟悉 ROS 工具 (包括可视化工具 Rviz 和 Gazebo 模拟器)的使用。

这里主要参考的书籍是 “ROS Robotics By Example, Second Edition”,其中书中的代码都在书本的 GitHub 页面 可以下载到。书本代码针对 ROS Kinetic 版本,我使用的是 Ubuntu 20.04 对应 Noetic 版本,有的细节处有所不同我在这里也有注明。


准备工作

对 .bashrc 文件进行配置

根据前面第一篇和第二篇文章说到的,应该已经配置过 .bashrc 文件了,运行以下命令确认源文件加载成功:


$ echo $ROS_PACKAGE_PATH

输出应该为:

/home/ubuntu/catkin_ws/src:/opt/ros/noetic/share

如果这两个路径中有一个路径没有的话,应该运行对应的命令:

$ echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
$ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc

哪个路径没有就运行哪个就行了,然后运行:

source ~/.bashrc

$ rosrun rviz rviz

安装和启动 Rviz

如果在前面和我一样安装了 ros-noetic-desktop-full 版本,那么应该同时安装了 Rviz.

可以通过以下方式确认:

先打开一个终端,通过以下命令启动 ROS 终端:

$ roscore

然后打开第二个终端,运行:

$ rosrun rviz rviz

会启动以下 ROS 界面:


如果系统没有安装 Rviz,应该运行如下指令安装:

$ sudo apt-get update
$ sudo apt-get install ros-noetic-rviz

安装并启动 Gazebo


和 Rviz类似,如果已经安装了完整版本的 ROS: ros-noetic-desktop-full,那么应该已经安装了 Gazebo,检查 Gazebo 是否安装成功的方法为:打开一个终端窗口 (不需要有 roscore 在运行)并输入如下命令:


$ gazebo

执行后会出现类似下图的界面:


请添加图片描述


终结 Gazebo:在关闭 Gazebo 的图形化界面之后,可以用 Ctrl+C 关闭终端窗口进程。

如果没有安装 Gazebo,应该按照如下步骤安装:


$ sudo apt-get update
$ sudo apt-get -y install gazebo

生成并构建 ROS 功能包

首先切换到 catkin 工作空间(文件夹)目录下:

$ cd ~/catkin_ws/src

然后生成功能包 ros_robotics:


$ catkin_create_pkg ros_robotics

功能包生成之后还需要 make ,由于现在在 /catkin_ws/src 目录下,而构建功能包需要在 catkin 工作空间下构建:


cd ~/catkin_ws #或者在 /catkin_ws/src目录下: cd ..
catkin_make

构建两轮机器人 URDF


如上所说,所有代码都在书本的 GitHub 页面可以下载到,如果直接下载的话就用链接里 Chapter 2 的文件夹直接覆盖掉刚刚创建的 ~catkin_ws/src/ros_robotics 就可以了。如果自己生成或者是想看着代码一步一步走的话,需要线生成一个 urdf目录:

$ cd ~/catkin_ws/src/ros_robotics
$ mkdir urdf

创建机器人底座

然后在 urdf 文件夹下创建一个文件 dd_robot.urdf:

<?xml version='1.0'?>
<robot name="dd_robot">

  <!-- Base Link -->
  <link name="base_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry>
          <box size="0.5 0.5 0.25"/>
      </geometry>
    </visual>
  </link>

</robot>

这里创建的 baselink 就是机器人的底座。地作为一个长和宽为 0.5 m,高为 0.25 m 的矩形盒子。盒子的中心在原点 (origin xyz=“0 0 0”), 盒子在 roll, pitch and yaw 三个方向都不存在旋转 (rpy =“0 0 0”)。


使用 roslaunch

roslaunch 可以简化启动多个 ROS 节点的过程,之前我们每次都需要通过 roscore 来启动 ROS 节点管理器,有了 肉丝launch 文件就不需要了。

同样可以下载这个 ddrobot_rviz.launch 到目录 ~/catkin_ws/src/ros_robotics/launch 目录下 (如果没有launch目录需要新建一个)。

最后下载 urdf.rviz 文件在 ~/catkin_ws/src/ros_robotics 目录下。至此该目录下应该有:

  • launch文件夹
  • urdf 文件夹
  • CMakeLists.txt
  • package.xml
  • urdf.rviz

然后运行如下命令在 Rviz 中查看机器人模型:

$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot.urdf

这里有一个地方按照代码运行会报错,在这里先贴一下原本的 ddrobot_rviz.launch 文件:

<launch>
   <!-- values passed by command line input -->     
   <arg name="model" />
   <arg name="gui" default="False" />

   <!-- set these parameters on Parameter Server -->
   <param name="robot_description" textfile="$(find ros_robotics)/urdf/$(arg model)" />
   <param name="use_gui" value="$(arg gui)"/>

   <!-- Start 3 nodes: joint_state_publisher, robot_state_publisher and rviz -->
   <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />

   <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />

   <node name="rviz" pkg="rviz" type="rviz" args="-d $(find ros_robotics)/urdf.rviz" required="true" />
   <!-- (required = "true") if rviz dies, entire roslaunch will be killed -->
</launch>

如果直接运行,会报错如下:

ERROR: cannot launch node of type [robot_state_publisher/state_publisher]: Cannot locate node of type [state_publisher] in package [robot_state_publisher]. Make sure file exists in package path and permission is set to executable (chmod +x)

这里需要注意,在 Noetic 里,需要把上面 ddrobot_rviz.launch 文件里第13行的:

<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />

改为:

<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />

注意 type =“state_publisher” 需要改成 type=“robot_state_pubisher”。(之后的所有 rviz.launch 都需要进行这个修改)然后再运行:


$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot.urdf

应该得到一个如图所示的界面:


在这里插入图片描述


如果是第一次使用,可能界面上没有显示盒子,并且在 Displays 面板也没有 RobotModel 或者 TF 选项,可以按照如下方法添加(无顺序要求):


  • 选择 Displays 面板下的 Add 按钮,添加 RobotModel
  • 选择 Displays 面板下的 Add 按钮,添加 TF
  • 选择靠近 Fixed Frame 的区域 (位于 Global Options 下面),可能这个区域我截图里面显示的是 base_link,你需要将显示的 map 改成 base_link (手动输入即可)

即可得到如上图显示的界面


添加轮子、颜色和碰撞属性

在这里原书通过创建了4个 urdf(都是在 dd_robot.urdf 的基础上进行添加)来进行演示,因为只是在 urdf 添加代码,读者可以自行学习原书代码。在添加玩这些属性之后,得到了一个 dd_robot5.urdf, 这里再运行 roslaunch命令:

$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot5.urdf

Rviz界面应当如图所示:


在这里插入图片描述


移动轮子

到现在我们已经定义了这个两轮机器人,下面希望可以通过 GUI 弹窗来控制两个轮子,在 launch 文件里,我们启动了 joint_state_publisher 这个节点,它找到苏油的非固定关节组件并将定义了的关节组件通过 JointState 消息发布。到目前为止, JointState 消息中的值一直保持不变,以防止轮子旋转。我们现在可以启动一个 GUI 结构来改变 JointSate 消息中的值。

首先需要安装一个包: (在 Noetic 中才需要,之前的版本好像不需要)

$ sudo apt-get install joint_state_publisher_gui

然后将launch文件中所有的 joint_state_publisher 改成 joint_state_publisher_gui,这个在 Noetic 中非常重要,不然不能显示这个 GUI。


也就是说对于 Noetic来说,应该要将:

<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" &gt;="" <param="" name="use_gui" value="True"/> </node>

改成:

 <node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" &gt;="" <param="" name="use_gui" value="True"/> </node>

最后的 ddrobot_rviz.launch 如下所示:

<launch>
   <!-- values passed by command line input -->     
   <arg name="model" />
   <arg name="gui" default="False" />

   <!-- set these parameters on Parameter Server -->
   <param name="robot_description" textfile="$(find ros_robotics)/urdf/$(arg model)" />
   <param name="use_gui" value="$(arg gui)"/>

   <!-- Start 3 nodes: joint_state_publisher, robot_state_publisher and rviz -->
   <node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" />

   <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" /> 

   <node name="rviz" pkg="rviz" type="rviz" args="-d $(find ros_robotics)/urdf.rviz" required="true" />
   <!-- (required = "true") if rviz dies, entire roslaunch will be killed -->
</launch>

然后运行:

$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot5.urdf

注意如果是 Noetic 之前的版本,好像应该是:

$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot5.urdf gui:=True

在 Noetic里面由于启动了 joint_state_publisher_gui 节点,就不需要这个 argument了。


启动后如图:

可以通过这个滑条或者 Random 来改变小轮的角度。


添加物理学属性

添加物理学属性是为了让机器人可以在 Gazebo模拟器中启动。需要将要模拟的 元素都添加一个 标签,该标签包含了质量和转动惯量矩阵两个子元素。在网站上的 dd_robot6.urdf 中,包含了之前全部定义的元素和这里的物理学属性。下载 dd_robot6.urdf 之后,可以:

$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot6.urdf

这里直接运行这个会出现一个警告:

[ WARN] [1661329049.295041222]: The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia.  As a workaround, you can add an extra dummy link to your URDF.

解决这个问题的方法是按照提示增加一个 dummy link。一个简单的例子如下:

<link name="dummy">
   </link>
<link name="base_link">
    <inertial>
      <origin xyz="0.15 0.15 .2" rpy="0 0 0"/>
      <mass value="10"/>
      <inertia ixx="0" ixy="0" ixz="0" iyy="0" iyz="0" izz="0"/>
    </inertial>
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
                   <box size="0.01 0.01 0.01"/>
      </geometry>
    </visual>
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
      <box size="0.01 0.01 0.01"/>
      </geometry>
    </collision>
  </link>
  <joint name="dummy_joint" type="fixed">
     <parent link="dummy"/>
     <child link="base_link"/>
   </joint>

在 dd_robot6.urdf 中: 加入dummy link 和 dummy joint 如下:

<?xml version='1.0'?>
<robot name="dd_robot">
  <link name="dummy" >
  </link >
  <!-- Base Link -->
  ...
  <joint name="dummy_joint" type="fixed">
    <parent link="dummy"/>
    <child link="base_link"/>
  </joint>
  <!-- Right Wheel -->
  ...

保存后再运行:

$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot6.urdf

在 Rviz 中将模型可视化,就不会出现上述警告了。由于物理学属性没有改变可视化信息,所以在 Rviz 中应该显示的是和之前相同的。


使用 URDF 工具

首先:

$ sudo apt-get install liburdfdom-tools

然后一个用得比较多的命令是:

$ check_urdf dd_robot6.urdf

输出为:

robot name is: dd_robot
---------- Successfully Parsed XML ---------------
root Link: dummy has 1 child(ren)
    child(1):  base_link
        child(1):  left_wheel
        child(2):  right_wheel

这里注意这个 dummy link 是上一步骤加了物理属性之后,因为 base link 不能有 inertia 属性而加上的。


这个命令还挺有用的,有时候 urdf 或者后面要用到的 xacro 文件有问题,都可以用这个命令。


Gazebo

URDF 的修改

Gazebo 环境支持的文件格式是 SDF 格式。因此我们需要通过一些修改,使得 Gazebo 能自动将 URDF 代码转换成 SDF 格式的机器人描述。 主要有三个内容:


  • 添加 Gazebo 标签 (可以参考 Gazebo 用户手册
  • 在 Gazebo 中指定颜色
  • Gazebo 中的 visual 和 collision 属性

更新之后的 dd_robot 模型同样在原书网站上,名称为 dd_robot.gazebo,将其下载在 ros_robotics/urdf 文件夹中后,可以通过以下命令来检测模型:

$ check_urdf dd_robot.gazebo

得到的输出为:

robot name is: dd_robot
---------- Successfully Parsed XML ---------------
root Link: base_link has 2 child(ren)
    child(1):  left_wheel
    child(2):  right_wheel

还可以用下面的命令来检测 URDF 文件是否可以被转换为 SDF 格式:

gz sdf -p dd_robot.gazebo

(书上这里写的是 gzsdf 可能是打错了,中间需要有空格)

上述命令会将完整的 SDF 文件内容输出到屏幕上。


在 Gazebo 中查看 URDF

首先下载 ddrobot_gazebo.launch 到 ros_robotics/launch 文件夹下。

然后下载 ddrobot.world 到 ros_robotics/worlds 文件夹下。 (如果没有worlds文件夹,需要创建一个)

在这里下载到的 ddrobot.world. 其中添加了两个 construction cone 的障碍,但是名字都是:

<name>construction_cone</name>

这里需要将第二个名字修改掉,比如我这边的 ddrobot.world 文件修改后为:

<?xml version="1.0" ?>
<sdf version="1.4">
  <world name="default">
    <include>
      <uri>model://ground_plane</uri>
    </include>
    <include>
      <uri>model://sun</uri>
    </include>
    <include>
      <uri>model://construction_cone</uri>
      <name>construction_cone</name>
      <pose>-3.0 0 0 0 0 0</pose>
    </include>
    <include>
      <uri>model://construction_cone</uri>
      <name>construction_cone1</name> 
      <pose>3.0 0 0 0 0 0</pose>
    </include>
  </world>
</sdf>

注意第 17 行的修改。

然后输入并执行以下命令:

$ roslaunch ros_robotics ddrobot_gazebo.launch

Gazebo 的界面如图所示:


移动机器人模型

可以通过 Joints 面板来对机器人进行简单的关节组件控制。在上图中,右侧有一个黑边有几个小白点,按住黑边上小白点的左边,往左边拖动,可以拖出 Joints 面板。在 selection 模式下,可以点击 ddrobot 模型,模型周围会显示一个白框, 在 Joints 面板可以看到可以修改的 joint_left_wheel 和 joint_right_wheel 的 Force, Position 和 Velocity 的值 (如下图所示)。可以尝试通过修改这些值来看机器人怎么运动。