用urdf给自己的ROS小车编写模型

注:本人大部分为转载别人的内容,但注明了出处,且程序自己跑过一遍,进行相关的验证;也有自己添加的 miiboo 机器人的信息;转载是为了分享,更是为了学习

 

使用urdf编写自己的ROS小车模型

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

下面就是常见的ROS小车,相信在大家的脑海里已经有了自己小车的样子,下面我和大家一起使用urdf对ros小车建模。

image-20200901075813068

这里只对urdf进行简单介绍,然后就带大家使用urdf最基础的标签,建立机器人的urdf机器人模型。关于更多细节,请参看官网:http://wiki.ros.org/urdf/Tutorials

一、什么是urdf?建模的原因?

什么是urdf?

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

建模的原因?

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

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

 

讲例一:简单模型

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

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

image-20200903220127848

假设在机器人运行过程中,激光雷达可以采集到距离前方障碍物的数据,这些数据当然是以激光雷达为原点的测量值,换句话说,也就是  base_laser 参考系下的测量值。现在,如果我们想使用这些数据帮助机器人完成避障功能,当然,由于激光雷达在机器人之上,直接使用这些数据不会产生太大的问题,但是激光雷达并不在机器人的中心之上,在极度要求较高的系统中,会始终存在一个雷达与机器人中心的偏差值。这个时候,如果我们采用一种坐标变换,将及  激光数据从base_laser参考系变换到base_link 参考下,问题不就解决了么。于是我们就需要定义这两个坐标系之间的变换关系。

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

image-20200903220846457

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

讲例二:复杂模型

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

描述如图所示的机器人的手臂位置时,可以将其描述为每个关节(joint)的相对坐标变换。下面举一个人形机器人的手的例子。手连接到手腕,再连接到肘部,而肘部又连接到肩膀。以此逆推,在机器人行走和移动时,利用相对坐标关系,可以将肘部的状态表示为肩部关节状态的函数,继而可以表示为腰部状态的函数,再可以表示为各腿关节状态的函数,最终可以表示为机器人双脚的中心状态的函数。换句话说,当机器人步行移动时,机器人手的坐标会根据各个相关关节的相对坐标变换而移动。另外,除了机器人以外,假设有一个机器人要抓取的物体,那么机器人的原点会相对的位于特定的地图上,而 这个物体也是在这个地图上。机器人为了抓取这个物体,需要以自己在地图上的相对位置 计算出物体对自己的相对位置,最终抓取物体。在机器人编程中,经过坐标变换的机器人的关节(或带有旋转轴的车轮)和物体的位置是非常重要的,在ROS中将它以坐标变换(Transform)43来表达。

ROS中的坐标转换TF在描述组成机器人的每个部分、障碍物和外部物体时是最有用的概念之一。这些可以被描述为位置(position)和方向(direction),统称为姿态(pose)。在此,位置由x、y、z这3个矢量表示,而方向是用四元数(quaternion)x、y、z、w表示。四元数并不直观,因为它们没有使用我们在日常生活中使用的三元数的角度表达方式:滚动角(roll)、俯仰角(pitch)和偏航角(yaw)。但这种四元数方式不存在滚动、俯仰和偏航矢量的欧拉(Euler)方式具有的万向节死锁(gimbal lock)问题或速度问题,因此在机器人工程中人们更喜欢用四元数(quaternion)的形式。因为同样的原因,ROS中也大量使用四元数 。当然,考虑到方便,它也提供将欧拉值转换成四元数的功能。 类似消息( message ),TF使用以下格式 44 。Header用于记录转换的时间,并使用名为child_frame_id的消息来表示下位的坐标。并且为了表达坐标的转换 值,使用 transformTranslation.x / transform.translation.y / transform.translation.z / transform.rotation.x / transform.rotation.y / transform.rotation.z / transform.rotation.w 的数据形式描述对方的位置和方向
 

二、介绍urdf部分细节

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

robot

image-20200903224032351

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

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

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

image-20200902081549987

如下面所示,描述了一个链接 父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轴的箭头方向看过去,顺时针为正,逆时针为负

image-20200903225150005

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

具体事例分析:miiboo.urdf 机器人对应 urdf

<robot name="miiboo">
  <material name="orange">
    <color rgba="1.0 0.5 0.2 1" />
  </material>
  <material name="gray">
    <color rgba="0.2 0.2 0.2 1" />
  </material>

  <link name="base_footprint"/>

  <!-- base_link -->
  <link name="base_link"/>
  <joint name="base_link_joint" type="fixed">
    <parent link="base_footprint" />
    <child link="base_link" />
    <origin xyz="0 0 0.065" rpy="0 0 0.0" />
  </joint>

  <!-- laser -->
  <link name="base_laser_link"/>
  <joint name="base_laser_link_joint" type="fixed">
    <origin xyz="0.08 0.00 0.065" rpy="0 0 0.0" />
    <parent link="base_footprint" />
    <child link="base_laser_link" />
  </joint>

  <!-- imu of hi219 -->
  <link name="imu_link"/>
  <joint name="imu_link_joint" type="fixed">
    <origin xyz="-0.035 0.00 0.065" rpy="0 0 0" />
    <parent link="base_footprint" />
    <child link="imu_link" />
  </joint>
</robot>

按照前面的讲解,对应分析一下,机器人实物模型如下:

 

三、使用urdf建立自己的ROS小车模型

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

//第一步:进入自己设定的文件夹,建立包

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如下图。

image-20200904004620960

 

//第 五 步:写显示模型的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>

或者  miiboo_description.launch

<launch>
    <arg name="model" />      
    <arg name="gui" default="False" />     
    <param name="robot_description" textfile="$(find miiboo_description)/urdf/miiboo.urdf" />      
    <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" />      
</launch>
  • //第 六 步:运行luanch文件

cd ~/catkin_test_ws                          // 进入对应的文件夹
catkin_make
source devel/setup.bash
rospack    profile
roslaunch robot_description dispaly_robot_with_laser.launch 

 

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

image-20200904001051051

解决方法:

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

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

image-20200904001821018

 

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

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

image-20200904002130944

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

image-20200904002501975

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

image-20200904003005097

 

 总结

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

urdf的缺点:

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

 

 

  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
ROS小车的URDF模型可以根据具体的小车类型和设计进行创建,下面是一个简单的示例: ```xml <?xml version="1.0"?> <robot name="ros_car"> <!-- 定义小车的基座 --> <link name="base_link"> <visual> <geometry> <box size="0.5 0.3 0.2"/> </geometry> <origin rpy="0 0 0" xyz="0 0 0"/> <material name="blue"> <color rgba="0.2 0.2 0.8 1"/> </material> </visual> <collision> <geometry> <box size="0.5 0.3 0.2"/> </geometry> <origin rpy="0 0 0" xyz="0 0 0"/> </collision> <inertial> <mass value="1.0"/> <origin rpy="0 0 0" xyz="0 0 0"/> <inertia ixx="0.1" ixy="0.0" ixz="0.0" iyy="0.1" iyz="0.0" izz="0.1"/> </inertial> </link> <!-- 定义小车的轮子 --> <link name="wheel_link"> <visual> <geometry> <cylinder length="0.1" radius="0.05"/> </geometry> <origin rpy="0 1.5708 0" xyz="0 0 0"/> <material name="black"> <color rgba="0 0 0 1"/> </material> </visual> <collision> <geometry> <cylinder length="0.1" radius="0.05"/> </geometry> <origin rpy="0 1.5708 0" xyz="0 0 0"/> </collision> <inertial> <mass value="0.1"/> <origin rpy="0 0 0" xyz="0 0 0"/> <inertia ixx="0.0005" ixy="0.0" ixz="0.0" iyy="0.0005" iyz="0.0" izz="0.0005"/> </inertial> </link> <!-- 定义小车的轮子连接 --> <joint name="wheel_joint" type="continuous"> <parent link="base_link"/> <child link="wheel_link"/> <origin xyz="0.25 0 -0.1" rpy="0 0 0"/> <axis xyz="0 1 0"/> </joint> <!-- 定义小车的传感器 --> <link name="sensor_link"> <visual> <geometry> <cylinder length="0.05" radius="0.02"/> </geometry> <origin rpy="0 0 0" xyz="0.2 0 0"/> <material name="red"> <color rgba="1 0 0 1"/> </material> </visual> <collision> <geometry> <cylinder length="0.05" radius="0.02"/> </geometry> <origin rpy="0 0 0" xyz="0.2 0 0"/> </collision> <inertial> <mass value="0.05"/> <origin rpy="0 0 0" xyz="0 0 0"/> <inertia ixx="0.00005" ixy="0.0" ixz="0.0" iyy="0.00005" iyz="0.0" izz="0.00005"/> </inertial> </link> <!-- 定义小车的传感器连接 --> <joint name="sensor_joint" type="fixed"> <parent link="base_link"/> <child link="sensor_link"/> <origin xyz="0.25 0 0.1" rpy="0 0 0"/> </joint> </robot> ``` 在这个示例中,我们定义了一个名为"ros_car"的机器人,它由基座、轮子和传感器组成。基座由一个长方体表示,轮子由一个圆柱体表示,传感器由一个较小的圆柱体表示。连接由各自的关节表示。您可以根据您的小车类型和设计进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值