ROS理论与实践——三、机器人系统设计


前言

本文是我在18年深蓝学院上课的第二讲内容,过去两年了,我重新整理了下,并结合当时课程布置的作业,在文中给出。本文主要介绍简单的机器人URDF模型的建模。


一、机器人的定义与组成

1 机器人的定义

人们印象中的机器人形象是类似《变形精钢》、《钢铁侠》影片中出现的机器人,类似人形,但十分智能。而现实生活中,我们常见到的机器人形象却是这样的,它们也是机器人。
在这里插入图片描述

图中从左到右分别是PR2、TurtleBot2、TurtleBot3(右侧三种)。
当然,除了上述的机器人外,在其他领域也有各种机器人,比如:

  • 机械手臂
  • 移动机器人
  • 自动驾驶汽车
  • 人形机器人
  • 无人驾驶飞机
  • 无人潜艇
  • 无人水面艇
    在之后的实践中,主要是以TurtleBot2 作为实体,进行演示。

2 机器人的组成

从控制的角度分析机器人的组成,主要由4部分组成:

  • 控制系统:控制系统类似人的大脑,除了要进行各种算法计算,还要实现关节控制、人机交互、系统监督等功能,因此要求根据相应的功能需求配置相应的处理器。
  • 驱动系统:动力源,分这样几种,电驱动、液压驱动、气压驱动
  • 传感器系统:实时获取自身位姿和外部环境,分为内部传感器系统和外部传感器系统,内部传感器包含里程计、陀螺仪、加速度计等,外部传感器包括摄像头、红外摄像、激光雷达、麦克风等。
  • 执行机构:控制系统发出的控制信号要最终传递给执行机构去执行操作,分为电机、伺服、传动机构等。
    在这里插入图片描述

二、URDF机器人建模

1 URDF是什么?

Unified Robot Description Format 统一机器人描述格式的缩写形式

之后的机器人模型文件都使用的是XML格式来进行描述,一种优势是可以很方便的使用标签、属性来描述机器人的很多相关的属性,另一个好处就是看起来直观一点。
URDF模型中按组成,主要分成两大类:link和joint

1.1 URDF模型中的link标签

< link >:连杆,用来描述机器人某刚体部分的外观和物理属性,它的子属性,包括了尺寸、颜色、形状、惯性矩阵、碰撞检测参数等。用相应的子标签来描述。
< visual >:描述机器人link部分的外观参数
< inertial > :描述link的惯性参数
< collision >:描述link的碰撞属性

相应的格式为:

在这里插入图片描述

1.2 URDF模型中的joint标签

< joint >:用来连接两个连杆,关节标签,用于描述关节的运动学和动力学属性,内容包括关节运动的位置和速度限制,其中根据关节的运动形式,分成了六种类型。
重点理解和把握两种关节的类型:
(1)continuous:旋转关节,可以围绕单轴无限旋转;
(2)revolute:旋转关节,但是有旋转的角度极限。
注意的是在连接两个link时,需要标明parent link和child link,相应的格式如下:

在这里插入图片描述
图中子标签的描述的含义如下:
< calibration >:描述关节的参考位置,用来校准关节的绝对位置;
< dynamic >:描述关节的物理属性,在动力学仿真中会用到

< limit >:描述运动的一些极限值,包括关节运动的上下限位置、速度限制、力矩限制

1.3 URDF模型中的根标签

< robot >:是根标签,也是顶层标签,以上两个标签< link >和< joint >标签都必须包含在< robot >标签内。
相应的形式为:
在这里插入图片描述

2 URDF建模

在上次新建的catkin_ws工作空间的目录下,在src文件夹下,新建一个机器人建模的功能包。

catkin_create_pkg mbot_description urdf xacro

生成功能包后,需要在其路径下,创建几个文件夹:

  • urdf:存放机器人模型的URDF或xacro文件
  • meshes:放置URDF中引用的模型渲染文件
  • launch:用于保存相关启动文件
  • config:保存rviz的配置文件

2.1 launch启动文件的编写

在launch文件夹下,编写launch启动文件display_mbot_base_urdf.launch

<launch>
	<param name="robot_description" textfile="$(find mbot_description)/urdf/mbot_base.urdf" />

	<!-- 设置GUI参数,显示关节控制插件 -->
	<param name="use_gui" value="true"/>
	
	<!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
	
	<!-- 运行robot_state_publisher节点,发布tf  -->
	<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
	
	<!-- 运行rviz可视化界面 -->
	<node name="rviz" pkg="rviz" type="rviz" args="-d $(find mbot_description)/config/mbot_urdf.rviz" required="true" />
</launch>

2.2 URDF模型文件的编写

1.使用圆柱体创建一个车体模型

<?xml version="1.0" ?>
<robot name="mbot">

    <link name="base_link">
        <visual>
            <origin xyz=" 0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder length="0.16" radius="0.20"/>
            </geometry>
            <material name="yellow">
                <color rgba="1 0.4 0 1"/>
            </material>
        </visual>
    </link>

2.使用圆柱体创建左侧车轮

<?xml version="1.0" ?>
<robot name="mbot">

    <link name="base_link">
        <visual>
            <origin xyz=" 0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder length="0.16" radius="0.20"/>
            </geometry>
            <material name="yellow">
                <color rgba="1 0.4 0 1"/>
            </material>
        </visual>
    </link>

    <joint name="left_wheel_joint" type="continuous">
        <origin xyz="0 0.19 -0.05" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="left_wheel_link"/>
        <axis xyz="0 1 0"/>
    </joint>

    <link name="left_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="1.5707 0 0" />
            <geometry>
                <cylinder radius="0.06" length = "0.025"/>
            </geometry>
            <material name="white">
                <color rgba="1 1 1 0.9"/>
            </material>
        </visual>
    </link>

3.使用圆柱体创建右侧车轮

<?xml version="1.0" ?>
<robot name="mbot">

    <link name="base_link">
        <visual>
            <origin xyz=" 0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder length="0.16" radius="0.20"/>
            </geometry>
            <material name="yellow">
                <color rgba="1 0.4 0 1"/>
            </material>
        </visual>
    </link>

    <joint name="left_wheel_joint" type="continuous">
        <origin xyz="0 0.19 -0.05" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="left_wheel_link"/>
        <axis xyz="0 1 0"/>
    </joint>

    <link name="left_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="1.5707 0 0" />
            <geometry>
                <cylinder radius="0.06" length = "0.025"/>
            </geometry>
            <material name="white">
                <color rgba="1 1 1 0.9"/>
            </material>
        </visual>
    </link>

    <joint name="right_wheel_joint" type="continuous">
        <origin xyz="0 -0.19 -0.05" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="right_wheel_link"/>
        <axis xyz="0 1 0"/>
    </joint>

    <link name="right_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="1.5707 0 0" />
            <geometry>
                <cylinder radius="0.06" length = "0.025"/>
            </geometry>
            <material name="white">
                <color rgba="1 1 1 0.9"/>
            </material>
        </visual>
    </link>

4.使用球体创建前后支撑轮

 <joint name="front_caster_joint" type="continuous">
        <origin xyz="0.18 0 -0.095" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="front_caster_link"/>
        <axis xyz="0 1 0"/>
    </joint>

    <link name="front_caster_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <sphere radius="0.015" />
            </geometry>
            <material name="black">
                <color rgba="0 0 0 0.95"/>
            </material>
        </visual>
    </link>

    <joint name="back_caster_joint" type="continuous">
        <origin xyz="-0.18 0 -0.095" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="back_caster_link"/>
        <axis xyz="0 1 0"/>
    </joint>

    <link name="back_caster_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <sphere radius="0.015" />
            </geometry>
            <material name="black">
                <color rgba="0 0 0 0.95"/>
            </material>
        </visual>
    </link>

创建完成后的模型如图所示:
在这里插入图片描述

5.创建摄像头

<link name="camera_link">
        <visual>
            <origin xyz=" 0 0 0 " rpy="0 0 0" />
            <geometry>
                <box size="0.03 0.04 0.04" />
            </geometry>
            <material name="black">
                <color rgba="0 0 0 0.95"/>
            </material>
        </visual>
    </link>

    <joint name="camera_joint" type="fixed">
        <origin xyz="0.17 0 0.10" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="camera_link"/>
    </joint>

创建完成的模型如图所示:
在这里插入图片描述

6.创建Kinect

<link name="kinect_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 1.5708"/>
            <geometry>
                <mesh filename="package://mbot_description/meshes/kinect.dae" />
            </geometry>
        </visual>
    </link>

    <joint name="kinect_link_joint" type="fixed">
        <origin xyz="0.15 0 0.11" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="kinect_link"/>
    </joint>

创建完成的模型如图所示:
在这里插入图片描述

7.创建激光雷达

<link name="laser_link">
		<visual>
			<origin xyz=" 0 0 0 " rpy="0 0 0" />
			<geometry>
				<cylinder length="0.05" radius="0.05"/>
			</geometry>
			<material name="black"/>
		</visual>
    </link>

    <joint name="laser_joint" type="fixed">
        <origin xyz="0 0 0.105" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="laser_link"/>
    </joint>

创建完成的模型,如图所示:
在这里插入图片描述

三、创建自己的机器人模型

1 创建带有Camera的机器人模型

1.创建机器人建模功能包

catkin_create_pkg  smartcar_description  urdf  xacro

2.创建urdf模型
在smartcar_description文件夹下建立urdf文件夹,创建智能车的描述文件smartcar.urdf,描述代码如下:

1.	<?xml version="1.0"?>  
2.	<robot name="smartcar">  
3.	  <link name="base_link">            //基座
4.	    <visual>  
5.	      <geometry>  
6.	        <box size="0.25 .16 .05"/>     //长方体的长、宽、高
7.	    </geometry>  
8.	    <origin rpy="0 0 1.57075" xyz="0 0 0"/>    //z向旋转9
9.	    <material name="blue">          
10.	        <color rgba="0 0 .8 1"/>      //蓝色
11.	    </material>  
12.	    </visual>  
13.	</link>  
14.	 
15.	<link name="right_front_wheel">     //右前轮
16.	    <visual>  
17.	      <geometry>  
18.	        <cylinder length=".02" radius="0.025"/>  //圆柱长0.02m,半径0.025m
19.	      </geometry>  
20.	      <material name="black">  
21.	        <color rgba="0 0 0 1"/>     //黑色
22.	      </material>  
23.	    </visual>  
24.	  </link>  
25.	 
26.	  <joint name="right_front_wheel_joint" type="continuous">  //右前轮关节
27.	    <axis xyz="0 0 1"/>  
28.	    <parent link="base_link"/>  
29.	    <child link="right_front_wheel"/>  
30.	    <origin rpy="0 1.57075 0" xyz="0.08 0.1 -0.03"/>  
31.	    <limit effort="100" velocity="100"/>  
32.	    <joint_properties damping="0.0" friction="0.0"/>  
33.	  </joint>  
34.	 
35.	  <link name="right_back_wheel">    //右后轮
36.	    <visual>  
37.	      <geometry>  
38.	        <cylinder length=".02" radius="0.025"/>  //圆柱长0.02m,半径0.025m
39.	      </geometry>  
40.	      <material name="black">  
41.	        <color rgba="0 0 0 1"/>  
42.	      </material>  
43.	    </visual>  
44.	  </link>  
45.	 
46.	  <joint name="right_back_wheel_joint" type="continuous">  //右后轮关节
47.	    <axis xyz="0 0 1"/>  
48.	    <parent link="base_link"/>  
49.	    <child link="right_back_wheel"/>  
50.	    <origin rpy="0 1.57075 0" xyz="0.08 -0.1 -0.03"/>  
51.	    <limit effort="100" velocity="100"/>  
52.	    <joint_properties damping="0.0" friction="0.0"/>  
53.	</joint>  
54.	 
55.	<link name="left_front_wheel">    //左前轮
56.	    <visual>  
57.	      <geometry>  
58.	        <cylinder length=".02" radius="0.025"/>  
59.	      </geometry>  
60.	      <material name="black">  
61.	        <color rgba="0 0 0 1"/>  
62.	      </material>  
63.	    </visual>  
64.	  </link>  
65.	 
66.	  <joint name="left_front_wheel_joint" type="continuous">  //左前轮关节
67.	    <axis xyz="0 0 1"/>  
68.	    <parent link="base_link"/>  
69.	    <child link="left_front_wheel"/>  
70.	    <origin rpy="0 1.57075 0" xyz="-0.08 0.1 -0.03"/>  
71.	    <limit effort="100" velocity="100"/>  
72.	    <joint_properties damping="0.0" friction="0.0"/>  
73.	  </joint>  
74.	 
75.	  <link name="left_back_wheel">  //左后轮
76.	    <visual>  
77.	      <geometry>  
78.	        <cylinder length=".02" radius="0.025"/>  
79.	      </geometry>  
80.	      <material name="black">  
81.	        <color rgba="0 0 0 1"/>  
82.	      </material>  
83.	    </visual>  
84.	  </link>  
85.	 
86.	  <joint name="left_back_wheel_joint" type="continuous">  //左后轮关节
87.	    <axis xyz="0 0 1"/>  
88.	    <parent link="base_link"/>  
89.	    <child link="left_back_wheel"/>  
90.	    <origin rpy="0 1.57075 0" xyz="-0.08 -0.1 -0.03"/>  
91.	    <limit effort="100" velocity="100"/>  
92.	    <joint_properties damping="0.0" friction="0.0"/>  
93.	  </joint>  
94.	 
95.	  <link name="head">   //摄像头
96.	    <visual>  
97.	      <geometry>  
98.	        <box size=".02 .03 .03"/>  //长0.02m,宽0.03m,高0.03m
99.	      </geometry>  
100.	      <material name="white">  
101.	          <color rgba="1 1 1 1"/>  
102.	      </material>  
103.	    </visual>  
104.	  </link>  
105.	 
106.	  <joint name="tobox" type="fixed">  
107.	    <parent link="base_link"/>  
108.	    <child link="head"/>  
109.	    <origin xyz="0 0.08 0.025"/>  //放在底座的顶面
110.	  </joint>  
111.	</robot>

3.建立launch文件
在smartcar_description文件夹下建立launch文件夹,创建智能车的描述文件display_smartcar.launch,描述代码如下:

1.	<launch>     
2.	    <param name="robot_description" textfile="$(find smartcar_description)/urdf/smartcar.urdf" />      
3.	    <param name="use_gui" value="true"/>     
4.	    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />     
5.	    <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />      
6.	    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find smartcar_description) / config / smartcar_urdf.rviz" required="true" />  
7.	</launch>

4.运行

roslaunch  smartcar_description smartercar.launch

效果如图所示:
在这里插入图片描述

2 创建带有Kinetic的机器人模型

其余都一样,只是在urdf模型中添加了传感器模型。
创建智能车的描述文件smartcar_with_kinect.urdf,添加代码:

<link name="kinect_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <mesh filename="package://mbot_description/meshes/kinect.dae" />
            </geometry>
        </visual>
    </link>

    <joint name="laser_joint" type="fixed">
        <origin xyz="0 0.04 0.05" rpy="0 0 -3.14"/>
        <parent link="base_link"/>
        <child link="kinect_link"/>
</joint>

同理修改launch文件,效果显示如下:
在这里插入图片描述

3 创建带有laser的机器人模型

创建智能车的描述文件smartcar_with_laser.urdf,添加代码:

<link name="laser_link">
    <visual>
    <origin xyz=" 0 0 0 " rpy="0 0 0" />
    <geometry>
    <cylinder length="0.05" radius="0.05"/>
    </geometry>
    <material name="cyan">   //青色
      <color rgba="0 1 1 1"/>
    </material>
    </visual>
    </link>

    <joint name="laser_joint" type="fixed">
        <origin xyz="0 0.04 0.05" rpy="0 0 3.14"/>
        <parent link="base_link"/>
        <child link="laser_link"/>
</joint>

同理修改launch文件,显示效果如图:
在这里插入图片描述

总结

本篇文章的内容不是很多,主要是讲有关URDF建模的流程,但是其中一些比如坐标计算的细节以及link标签和joint标签的写法都需要注意,以防出现错误。