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

    科技2024-07-16  78

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

     

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

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

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

    这里只对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参考系。

    假设在机器人运行过程中,激光雷达可以采集到距离前方障碍物的数据,这些数据当然是以激光雷达为原点的测量值,换句话说,也就是  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) 的变换即可。

    如上图所示,每两个相邻的坐标系之间都有变换关系,也就是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

    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

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

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

    如下面所示,描述了一个链接 父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度

    具体事例分析: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如下图。

     

    //第 五 步:写显示模型的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功能包默认没有安装。

    解决方法:

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

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

     

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

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

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

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

     

     总结

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

    urdf的缺点:

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

     

     

    Processed: 0.008, SQL: 8