my_gmapping_slam来龙去脉(二)

本节主要记录如何使用urdf和xacro编写小车模型。

目录

1、使用urdf编写自己的ros小车模型

1.1 常见的ROS小车结构有哪些?

1.2 什么是urdf?建模的原因

1.2.1 什么是urdf?

1.2.2 建模的原因

1.2.3 介绍urdf部分细节

1.2.4 介绍urdf部分细节

1.2.5 总结

1.2.6 urdf的缺点        

2、使用xacro编写自己的ros小车模型

2.1 urdf建模存在的问题

2.2 使用xacro建模的优势

2.3 xacro模型文件常用语法介绍

2.4 xacro建模实例

 2.5 总结


1、使用urdf编写自己的ros小车模型

        

1.1 常见的ROS小车结构有哪些?

        下面就是常见ROS小车,下面是几种小车的样子:

         这里对urdf进行简单介绍,然后使用urdf最基础的标签,建立机器人的urdf机器人模型。关于更多细节,请参考官网:urdf/Tutorials - ROS Wiki

1.2 什么是urdf?建模的原因

1.2.1 什么是urdf?

        URDF(Unified Robot Description Format),统一机器人描述格式。在ROS中,大家通常使用urdf对机器人模型进行描述,主要的作用就是维护机器人关节的tf树以及使用机器人模型3D可视化的作用,关于其他的作用,这里并没有使用到。

1.2.2 建模的原因

        关于机器TF树,这里要对它进行详细说明,为的是让大家清楚建立机器人模型的一个主要原因。

        ROS中的很多软件包都需要机器人发布TF变换树,那么什么是TF变换树呢?

        抽象的来讲,一颗TF变换树定义了不同坐标系之间的平移与旋转变换关系。

        具体来说,我们假设有一个机器人,包括一个机器人移动平台和一个安装在平台之上的激光雷达,以这两个机器人为例,定义两个坐标系,一个坐标系以机器人移动平台的中心为原点,称为base_link参考系,另一个坐标系以激光雷达的中心为原点,称为base_laser参考系。

        为了定义这个变换关系,假设我们已知激光雷达安装的位置在机器人的中心点上方20cm,前方10cm处。这就根据这些数据,就足以定义这两个参考系之间的变换关系;当我们获取激光数据后,采用(x:0.1m,y:0.0m,z:0.2m)的坐标变换,就可以将数据从base_laser参考系变换到base_link参考系了。当然,如果方向变化,采用(x:-0.1m,y:0.0m,z:-0.50m)即可。

        从上边的示例来看,参考系之间的坐标变换好像并不复杂,但是在复杂的系统中,存在的参考系可能远远大于两个,如果我们都使用这种手动的方式进行变换,估计很快你就会被繁杂的坐标关系搞懵了。ROS提供的TF变换就是为解决这个问题的,TF功能包提供了存储、计算不同数据的在不同參考系之的变换公式即可,这棵TF树就可以用树的数据结构管理我们所需要的参考系变换。

        如上图所示,每两个相邻的坐标系之间都有变换关系,也就是TF变换。我们需要通过机器人的urdf模型文件,向TF树发布机器人相关TF和关节状态,这也是建立机器人urdf模型的主要原因之一。

1.2.3 介绍urdf部分细节

        大家都知道,几乎所有机器人都可以用连杆和关节组成;对于不同形状的机器人,连杆大小和关节的分布不同。urdf就是采用这种方式,使用连杆link和关节joint共同组建机器人结构。

robot 

link 

        描述机器人某个刚体部分的外观和物理属性。

        包括大小(size)、颜色(color)、形状(shape)、惯性参数(inertial matrix)、碰撞参数(collision properties)等。

        如下面所示,描述一个原点origin设置为零,坐标系无任何旋转,几何形状geometry为半径=0.075m,长度为0.104m的圆柱,物理属性material颜色为黄色,可设置三基色rgb和透明度a。

<link name="base_link">                                   <!-- 连杆的名字,自定义,也可以理解为一个三维坐标系 -->
    <visual>                                              <!-- 可视化标签 -->
        <origin xyz=" 0 0 0" rpy="0 0 0" />               <!-- 原点设置标签:原点为集合中心上,欧拉角为零,无任何方向旋转 -->
        <geometry>                                        <!-- 几何形状标签 -->
            <cylinder radius="0.075" length = "0.104"/>   <!-- 此形状圆柱,若为方形 <box size="0.03 0.157 0.03" /> 参数长宽高、若为球体 <sphere radius="0.0125" /> 参数半径  -->
        </geometry>
        <material name="yellow">                          <!-- 物理属性标签,此name的颜色并不起作用,用作示意 -->
            <color rgba="1 0.4 0 1"/>                     <!-- 可设置连杆rgb三基色和a透明度 -->
        </material>
    </visual>
</link>

joint       

        描述机器人关节的运动学和动力学属性;

        包括关节运动的位置和速度限制;根据具体的关节运动形式分为 6 种类型。

         如下面所示,描述了一个连接父link和子link,绕y轴可持续旋转的关节joint。 

<joint name="left_wheel_joint" type="continuous">  <!-- name关节名字、type关节类型-->
    <origin xyz="0.0 0.0785 -0.085" rpy="0 0 0"/>  <!-- 关节无尺寸大小 ,origin原点必须参照parent link设置。这里表示该关节以父link原点为准,设置在向y轴正方向0.0785m,向z轴负方向0.085m的地方 -->
    <parent link="base_link"/>                     <!-- 父link名字 -->
    <child link="left_wheel_link"/>                <!-- 子link名字 -->
    <axis xyz="0 1 0"/>                            <!-- 此节点绕y轴旋转 -->
</joint>

        关于origin xyz=“0 0 0”,rpy=“0 0 0”的参数还是有点说法的,一般连杆的原点坐标xyz都设置为零,但是rpy(欧拉角:弧度制)有时候会变化。一般关节的原点都有坐标,rpy都设置为零。

        欧拉角RPY分别代表Roll(翻滚角)Pitch(俯仰角)、Yaw(偏航角),分别对应绕XYZ轴旋转。旋转的正方向是,从XYZ轴的箭头方向看过去,顺时针为正,逆时针为负。

         比如这里origin xyz=“0 0 0” rpy=“1.5707 0 0”,就表示连杆模型绕X轴顺时针旋转1.5707rad=90度。

1.2.4 介绍urdf部分细节

        在自己的工作空间下建立机器人模型描述功能包:

cd ~/catkin_test_ws/src/
catkin_create_pkg robot_description urdf xacro

        创建urdf、launch、config、meshes文件夹:

cd robot_description/
mkdir urdf launch config meshes

         urdf存放机器人模型文件。

        launch存放相关启动文件。

        config保存rviz的配置文件,可用可不用,使用rviz保存配置的时候用来存放的位置。

        meshes存放urdf引用的模型渲染文件,可用可不用,如果有渲染的模型文件就用,没有也没关系。

编写ROS小车urdf模型文件:

cd urdf/
vim robot_with_laser.urdf

urdf文件内容如下:

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

    <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>

    <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>

    <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>

</robot>

检查urdf模型整体结构:

cd ~/catkin_test_ws/src/robot_description/urdf
urdf_to_graphiz robot_with_laser.urdf

这里生成两个文件,查看pdf如下图:

编写显示模型的launch文件:

cd ..
cd launch
vim dispaly_robot_with_laser.launch

launch的内容如下:

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

	<!-- 运行joint_state_publisher_gui节点,发布机器人的关节状态  -->
	<node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" />
	
	<!-- 运行robot_state_publisher节点,发布tf,将机器人的连杆关节之间的关系,通过TF的形式,整理成三维姿态发布出去  -->
	<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
	
</launch>

 运行launch文件:

cd ~/catkin_test_ws
catkin_make
source devel/setup.bash
rospack	profile
roslaunch robot_description dispaly_robot_with_laser.launch 

        将出现下面这样的错误,原因是,joint_state_publisher_gui功能包默认没有安装:

解决方法:

sudo apt-get install ros-melodic-joint-state-publisher
sudo apt-get install ros-melodic-joint-state-publisher-gui

将出现下面一个这样的gui调试窗口:

使用rviz查看自己的机器人模型:

rviz

按照图中序号添加机器人模型:

 然后将Fixed Frame选择base_link,就出现你想要的小车模型了。

         通过joint_state_publisher_gui可以控制模型,自行尝试。按照上面的方法,还可以将TF添加的rviz中显示,如下图这个样子:

1.2.5 总结

        这里只是给出了,一个最简单的ROS小车urdf文件功能包编写流程,对于新手来说这就是一个参考的流程。过程中需要注意的地方,都在文章中重点说明了。如果需要更加细化地了解urdf,可以参考官网。但是,这里描述的内容,对小车已经绰绰有余了。

1.2.6 urdf的缺点        

  • 模型冗长
  • 参数修改麻烦
  • 没有参数计算能力等等

2、使用xacro编写自己的ros小车模型

        和上一节一样,首先奉上xacro的官网地址xacro - ROS Wiki

        本文章只基于上一篇针对urdf文件的缺点进行优化开发,不做更多的xacro介绍。当然对于ROS机器人平台搭建,这里对xacro的介绍已经足够了。

2.1 urdf建模存在的问题

        urdf的缺点:

  • 模型冗长,重复内容过大,相似的关节都要重复编写
  • 参数修改麻烦,不便于二次开发
  • 没有参数计算能力等等

2.2 使用xacro建模的优势

        首先可以理解xacro是urdf的进化版本。

        xacro里面的模型仍然是urdf模型,但是从整个模型的管理上有很大的改观。

  • 提供编程接口
    • 常量
    • 变量
    • 数学计算
    • 条件语句
  • 精简模型代码
    • 宏定义
    • 文件包含

2.3 xacro模型文件常用语法介绍

1. 常量定义:

<xacro:property name="M_PI" value="3.14159"/>

xacro: property 常量定义标签

name=常量名

value=常量值

2. 常量使用 

<origin xyz="0 0 0" rpy="${M_PI/2} 0 0"/>

通常使用${常量名}使用常量 ,并在{}内还可以进行加减乘除等数学运算。

3. 数学计算 

<origin xyz="0 ${(motor_length+wheel_length)/2} 0" rpy="0 0 0"/>

在括号里使用数学运算,所有数学运算都会转化为浮点数进行计算,保证运算精度。

4. 宏定义 

<xacro:macro name="name" params="A B C">
   ......具体模型定义(类似函数内容)
</xacro:macro>

xacro: macro定义标签

name=宏定义名字,类似C语言函数名字

params=类似C语言函数参数,可以是字符串

5. 宏调用 

<name A="A_value" B="B_value" C="C_value" />

name=宏定义的名字,即函数名

A = 参数A ...

6. 文件包含 

<xacro:include filename="$(find robot_descripiton)/xacro/robot_base.xacro" />

xacro:include文件包含定义标签

filename存放xacro文件绝对地址,含文件名字

使用${find+功能包}=功能包的绝对路径

7. 模型显示 

        方法一:将xacro文件通过命令转化为urdf文件,使用上一章的方式显示(不常用)

rosrun xacro xacro.py robot.xacro>robot.urdf

        方法二:直接使用xacro文件解析器

<arg name="model" default="$(find xacro)/xacro --inorder '$(find robot_description)/xacro/robot.xacro'" />
<arg name="gui" default="true" />

<param name="robot_description" command="$(arg model)" />

根据自己xacro的存放路径,按照上述格式自行更改。

2.4 xacro建模实例

        本次仍然和上一章一样,只构建一个最基础的带激光雷达的机器人模型。该实例在上一章创建的功能包基础之上进行继续开发。

  • 新建存放xacro文件的文件夹
cd ~/catkin_test_ws/src/robot_description/
mkdir xacro
cd xacro
  • 新建robot_base.xacro文件:主要是做出各种基础宏定义函数

vim robot_base.xacro

        下面是robot_base.xacro文件全部内容,可以对比和urdf的不同之处。

        使用robot name="robot" xmlns:xacro="http://www.ros.org/wiki/xacro"表明文件是xacro文件。

        使用xacro: property name="M_PI" value="3.1415926" 定义常量放在一起,便于修改与运算,其他类比。

        使用xacro: name="wheel" params="prefix reflect" 宏定义轮子,以备后面使用。

        使用xacro: name="caster" params="prefix reflect" 宏定义万向轮,以备后面使用。

        使用xacro: name="robot_base" 宏定义机器人主体,以备其他文件使用。

<?xml version="1.0"?>
<robot name="robot" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <!-- PROPERTY LIST -->
    <xacro:property name="M_PI" value="3.1415926"/>
    <xacro:property name="base_radius" value="0.20"/>
    <xacro:property name="base_length" value="0.16"/>

    <xacro:property name="wheel_radius" value="0.06"/>
    <xacro:property name="wheel_length" value="0.025"/>
    <xacro:property name="wheel_joint_y" value="0.19"/>
    <xacro:property name="wheel_joint_z" value="0.05"/>

    <xacro:property name="caster_radius" value="0.015"/> <!-- wheel_radius - ( base_length/2 - wheel_joint_z) -->
    <xacro:property name="caster_joint_x" value="0.18"/>

    <!-- Defining the colors used in this robot -->
    <material name="yellow">
        <color rgba="1 0.4 0 1"/>
    </material>
    <material name="black">
        <color rgba="0 0 0 0.95"/>
    </material>
    <material name="gray">
        <color rgba="0.75 0.75 0.75 1"/>
    </material>
    
    <!-- Macro for robot wheel -->
    <xacro:macro name="wheel" params="prefix reflect">
        <joint name="${prefix}_wheel_joint" type="continuous">
            <origin xyz="0 ${reflect*wheel_joint_y} ${-wheel_joint_z}" rpy="0 0 0"/>
            <parent link="base_link"/>
            <child link="${prefix}_wheel_link"/>
            <axis xyz="0 1 0"/>
        </joint>

        <link name="${prefix}_wheel_link">
            <visual>
                <origin xyz="0 0 0" rpy="${M_PI/2} 0 0" />
                <geometry>
                    <cylinder radius="${wheel_radius}" length = "${wheel_length}"/>
                </geometry>
                <material name="gray" />
            </visual>
        </link>
    </xacro:macro>

    <!-- Macro for robot caster -->
    <xacro:macro name="caster" params="prefix reflect">
        <joint name="${prefix}_caster_joint" type="continuous">
            <origin xyz="${reflect*caster_joint_x} 0 ${-(base_length/2 + caster_radius)}" rpy="0 0 0"/>
            <parent link="base_link"/>
            <child link="${prefix}_caster_link"/>
            <axis xyz="0 1 0"/>
        </joint>

        <link name="${prefix}_caster_link">
            <visual>
                <origin xyz="0 0 0" rpy="0 0 0"/>
                <geometry>
                    <sphere radius="${caster_radius}" />
                </geometry>
                <material name="black" />
            </visual>
        </link>
    </xacro:macro>

    <xacro:macro name="robot_base">
        <link name="base_footprint">
            <visual>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <geometry>
                    <box size="0.001 0.001 0.001" />
                </geometry>
            </visual>
        </link>

        <joint name="base_footprint_joint" type="fixed">
            <origin xyz="0 0 ${base_length/2 + caster_radius*2}" rpy="0 0 0" />        
            <parent link="base_footprint"/>
            <child link="base_link" />
        </joint>

        <link name="base_link">
            <visual>
                <origin xyz=" 0 0 0" rpy="0 0 0" />
                <geometry>
                    <cylinder length="${base_length}" radius="${base_radius}"/>
                </geometry>
                <material name="yellow" />
            </visual>
        </link>

        <wheel prefix="left" reflect="-1"/>
        <wheel prefix="right" reflect="1"/>

        <caster prefix="front" reflect="-1"/>
        <caster prefix="back" reflect="1"/>
    </xacro:macro>
</robot>
  • 新建robot.xacro文件
cd xacro
vim robot.xacro

        robot.xacro文件内容如下,主要是引用robot_base.xacro文件,宏调用定义机器人主体模型。

<?xml version="1.0"?>
<robot name="robot" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <xacro:include filename="$(find robot_description)/xacro/robot_base.xacro" />

    <robot_base/>

</robot>
  • 新建显示xacro模型的launch文件
cd ~/catkin_test_ws/src/robot_description/launch
cp dispaly_robot_with_laser.launch dispaly_robot_base_xacro.launch   #上一章新建过,所以这里直接复制其他文件修改即可

修改display_robot_base_xacro.launch文件内容如下:

<launch>
	<arg name="model" default="$(find xacro)/xacro --inorder '$(find robot_description)/xacro/robot.xacro'" />

	<param name="robot_description" command="$(arg model)" />

	<!-- 运行joint_state_publisher_gui节点,发布机器人的关节状态  -->
	<node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" />
	
	<!-- 运行robot_state_publisher节点,发布tf,将机器人的连杆关节之间的关系,通过TF的形式,整理成三维姿态发布出去  -->
	<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
	
</launch>
  • 运行display_robot_base_xacro.launch文件
cd ~/catkin_test_ws
catkin_make
source devel/setup.bash
rospack	profile
roslaunch robot_description dispaly_robot_base_xacro.launch 

        将出现下面这样的错误,原因是,joint_state_publisher_gui功能包默认没有安装。如果上一节错误出现过并且解决了,将不会再出现。

解决方法:

sudo apt-get install ros-melodic-joint-state-publisher
sudo apt-get install ros-melodic-joint-state-publisher-gui

 将出现下面一个这样的gui调试窗口。

  • 使用rviz查看自己的机器人模型
rviz

然后将Fixed Frame选择base_link,就出现你要小车模型了。

  • 新建添加激光雷达的机器人模型的xacro文件
cd ~/catkin_test_ws/src/robot_description/xacro
mkdir sensors                                   #存放传感器的xacro文件,以后添加其他传感器就方便了
cd sensors
vim lidar.xacro

 lidar.xacro的内容如下: 

<?xml version="1.0"?>
<robot name="laser" xmlns:xacro="http://www.ros.org/wiki/xacro" >

	<xacro:macro name="rplidar" params="prefix:=laser">
		<link name="${prefix}_link">
			<visual>
				<origin xyz=" 0 0 0 " rpy="0 0 0" />
				<geometry>
					<cylinder length="0.06" radius="0.035"/>
				</geometry>
				<material name="black"/>
			</visual>
		</link>
	</xacro:macro>

</robot>
  • 新建robot_with_laser.xacro文件
cd ~/catkin_test_ws/src/robot_description/xacro
vim robot_with_laser.xacro

robot_with_laser.xacro文件内容如下:

<?xml version="1.0"?>
<robot name="robot" xmlns:xacro="http://www.ros.org/wiki/xacro">

    <xacro:include filename="$(find robot_description)/xacro/robot_base.xacro" />
    <xacro:include filename="$(find robot_description)/xacro/sensors/lidar.xacro" />

    <xacro:property name="laser_offset_x" value="0.0" />
    <xacro:property name="laser_offset_y" value="0.0" />
    <xacro:property name="laser_offset_z" value="0.082" />

    <robot_base/>

    <!-- laser -->
    <joint name="laser_joint" type="fixed">
        <origin xyz="${laser_offset_x} ${laser_offset_y} ${laser_offset_z}" rpy="0 0 0" />
        <parent link="base_link"/>
        <child link="laser_link"/>
    </joint>

    <xacro:rplidar prefix="laser"/>

</robot>

        关于新建显示xacro模型的launch文件,以及如何显示模型和上面内容一致,对launch文件的model参数引入的文件名稍作修改即可,效果如下。

 2.5 总结

        通过文章内容,我们清楚认识到,xacro文件对于机器人建模的优点,特别是针对复杂模型。易读、容易修改、有编程接口等等,好处多多。

        但是,我们需要思考一个问题,我们的小车复杂吗?如果不复杂,我们可以接受urdf的直白繁琐吗?如果可以接受,本章的内容将毫无意义。因为urdf和xacro模型文件,实现的是同一种功能,既然对于简单的小车使用urdf就足够了,又没有很繁琐,这时使用xacro意义不大。

        下面,我们就要正式进入ros小车ros层的重要部分了。下一章,我们对差分轮式机器人的里程计模型进行说明。

文件关系:

display_robot_base_xacro.launch

<arg name="model" default="$(find xacro)/xacro --inorder '$(find robot_description)/xacro/robot.xacro'" />

robot.xacro ==> robot_base.xacro 

display_robot_base_xacro.launch

<arg name="model" default="$(find xacro)/xacro --inorder '$(find robot_description)/xacro/robot_with_laser.xacro'" />

robot_with_laser.xacro ==> robot_base.xacro + sensors/lidar.xacro 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值