建立两轮机器人 URDF 文件,通过两轮机器人来熟悉 ROS 工具 (包括可视化工具 Rviz 和 Gazebo 模拟器)的使用。
这里主要参考的书籍是 “ROS Robotics By Example, Second Edition”,其中书中的代码都在书本的 GitHub 页面 可以下载到。书本代码针对 ROS Kinetic 版本,我使用的是 Ubuntu 20.04 对应 Noetic 版本,有的细节处有所不同我在这里也有注明。
根据前面第一篇和第二篇文章说到的,应该已经配置过 .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
如果在前面和我一样安装了 ros-noetic-desktop-full 版本,那么应该同时安装了 Rviz.
可以通过以下方式确认:
先打开一个终端,通过以下命令启动 ROS 终端:
$ roscore
然后打开第二个终端,运行:
$ rosrun rviz rviz
如果系统没有安装 Rviz,应该运行如下指令安装:
$ sudo apt-get update
$ sudo apt-get install ros-noetic-rviz
和 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
首先切换到 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
如上所说,所有代码都在书本的 GitHub 页面可以下载到,如果直接下载的话就用链接里 Chapter 2 的文件夹直接覆盖掉刚刚创建的 ~catkin_ws/src/ros_robotics 就可以了。如果自己生成或者是想看着代码一步一步走的话,需要线生成一个 urdf目录:
$ cd ~/catkin_ws/src/ros_robotics
$ mkdir urdf
然后在 urdf 文件夹下创建一个文件 dd_robot.urdf:
<robot name="dd_robot">
<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 可以简化启动多个 ROS 节点的过程,之前我们每次都需要通过 roscore 来启动 ROS 节点管理器,有了 肉丝launch 文件就不需要了。
同样可以下载这个 ddrobot_rviz.launch 到目录 ~/catkin_ws/src/ros_robotics/launch 目录下 (如果没有launch目录需要新建一个)。
最后下载 urdf.rviz 文件在 ~/catkin_ws/src/ros_robotics 目录下。至此该目录下应该有:
然后运行如下命令在 Rviz 中查看机器人模型:
$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot.urdf
这里有一个地方按照代码运行会报错,在这里先贴一下原本的 ddrobot_rviz.launch 文件:
<launch>
<arg name="model" />
<arg name="gui" default="False" />
<param name="robot_description" textfile="$(find ros_robotics)/urdf/$(arg model)" />
<param name="use_gui" value="$(arg gui)"/>
<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" />
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 选项,可以按照如下方法添加(无顺序要求):
即可得到如上图显示的界面
在这里原书通过创建了4个 urdf(都是在 dd_robot.urdf 的基础上进行添加)来进行演示,因为只是在 urdf 添加代码,读者可以自行学习原书代码。在添加玩这些属性之后,得到了一个 dd_robot5.urdf, 这里再运行 roslaunch命令:
$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot5.urdf
到现在我们已经定义了这个两轮机器人,下面希望可以通过 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" >="" ="" name="use_gui" value="True"/> node>
改成:
<node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" >="" ="" name="use_gui" value="True"/> node>
最后的 ddrobot_rviz.launch 如下所示:
<launch>
<arg name="model" />
<arg name="gui" default="False" />
<param name="robot_description" textfile="$(find ros_robotics)/urdf/$(arg model)" />
<param name="use_gui" value="$(arg gui)"/>
<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" />
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 如下:
<robot name="dd_robot">
<link name="dummy" >
link >
...
<joint name="dummy_joint" type="fixed">
<parent link="dummy"/>
<child link="base_link"/>
joint>
...
保存后再运行:
$ roslaunch ros_robotics ddrobot_rviz.launch model:=dd_robot6.urdf
在 Rviz 中将模型可视化,就不会出现上述警告了。由于物理学属性没有改变可视化信息,所以在 Rviz 中应该显示的是和之前相同的。
首先:
$ 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 环境支持的文件格式是 SDF 格式。因此我们需要通过一些修改,使得 Gazebo 能自动将 URDF 代码转换成 SDF 格式的机器人描述。 主要有三个内容:
更新之后的 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 文件内容输出到屏幕上。
首先下载 ddrobot_gazebo.launch 到 ros_robotics/launch 文件夹下。
然后下载 ddrobot.world 到 ros_robotics/worlds 文件夹下。 (如果没有worlds文件夹,需要创建一个)
在这里下载到的 ddrobot.world. 其中添加了两个 construction cone 的障碍,但是名字都是:
<name>construction_conename>
这里需要将第二个名字修改掉,比如我这边的 ddrobot.world 文件修改后为:
<sdf version="1.4">
<world name="default">
<include>
<uri>model://ground_planeuri>
include>
<include>
<uri>model://sunuri>
include>
<include>
<uri>model://construction_coneuri>
<name>construction_conename>
<pose>-3.0 0 0 0 0 0pose>
include>
<include>
<uri>model://construction_coneuri>
<name>construction_cone1name>
<pose>3.0 0 0 0 0 0pose>
include>
world>
sdf>
注意第 17 行的修改。
然后输入并执行以下命令:
$ roslaunch ros_robotics ddrobot_gazebo.launch
可以通过 Joints 面板来对机器人进行简单的关节组件控制。在上图中,右侧有一个黑边有几个小白点,按住黑边上小白点的左边,往左边拖动,可以拖出 Joints 面板。在 selection 模式下,可以点击 ddrobot 模型,模型周围会显示一个白框, 在 Joints 面板可以看到可以修改的 joint_left_wheel 和 joint_right_wheel 的 Force, Position 和 Velocity 的值 (如下图所示)。可以尝试通过修改这些值来看机器人怎么运动。