ROS学习笔记(十三)—— URDF 模型文件学习

一、 URDF简介

1.1 初步认识URDF

RDF全称(United Robotics Description Format)统一机器人描述格式,是一个XML语法框架下用来描述机器人的语言格式,URDF在ROS界很流行。我们可以通过URDF对机器人建模然后放到ROS里面进行仿真与分析把一个URDF文件转换成simscape模型,在Simulink里面进行仿真分析或者控制器设计。把simscape模型转化成urdf格式

1.2 机器人物理构件属性的定义

URDF文件里面有着与XML语言格式,一个机器人主要由连杆(link)和关节(joint)组成, URDF具有类似XML树状结构的,比如下面的例子:

<robot>
    <link>
        ...
    link>
    <link>
        ...
    link>
    <joint>
        ...
    joint>
robot>

上面的 link 与 joint 是 robot 下面的子分量(应该有比‘子分量’更好的描述),换句话说 joint 和 link 隶属于 robot 。知道了机器人的基本构成之后还不够,还需要知道基本组成部分的一些物理信息,例如连杆的质量属性,惯量属性,颜色,以及关节的种类,这到底是转动关节还是平动关节。因此 link 和 joint 也要有自己的子分量,比如 inertial 和 visual , visual 下面还可以再次细分子分量 geometry 和 material ,然后 material 下面还可以有自己的子分量,由此往复我们就可以用URDF来充分定义好一个机器人的各个信息。所以一个增加了这些额外信息的URDF文件内容例子如下

<robot>
    <link>
        <inertial>
            ...
        inertial>
        <visual>
            <geometry>
                ...
            geometry>
            <material>
                <color />
            material>
        visual>
    link>
    ...
robot>

我们定义好了机器人的组成部分以及各个部分所具有的信息,接着还需要有属性描述这些量。比如 robot,link,joint 都有 name属性,一个用来辨识模块的字符串。 color 有 rgba 属性,用来定义连杆的外表颜色。添加了相关信息的URDF文件长这个样子:

<robot name = "linkage">
    <link name = "root link">
        <inertial>
            ...
        inertial>
        <visual>
            <geometry>
                ...
            geometry>
            <material>
                <color rgba = "1 0 0 1" />
            material>
        visual>
    link>
    ...
robot>

把这些属性附上对应的数值之后,一个机器人的 urdf 模型中各个模块的外表和物理属性就建立好了。
接下来我们来描述关节连杆之间的关系。

1.3 层次结构以及动力学树的定义

URDF文件里,就像XML一样,link 通过 joint 按一定的层次一个个联系在一起。 joint 通过 parent-child 关系把上下 link 联系起来,parent link可以同时作为其他 link 的child link,而child link也可以同时作为其他link的parent link,举例:

<parent> and <child> Joint Elements
<robot name = "linkage">
    <joint name = "joint A ... >
        "link A" />
        <child link = "link B" />
    joint>
    <joint name = "joint B ... >
        "link A" />
        <child link = "link C" />
    joint>
    <joint name = "joint C ... >
        "link C" />
        <child link = "link D" />
    joint>
robot>

上述URDF语法建立了一个这样的连杆模型:

连杆A通过关节A连接着连杆B,连杆A是父连杆
连杆C通过关节B连接着连杆A,连杆A是父连杆
连杆D通过关节C连接着连杆C,连杆C是父连杆
我们可以通过connectivity graph来展示 link 之间的从属和连接关系,用圆代表link,箭头代表joint,joint 从 parent link流出,指向child link,于是上述URDF文件可以用图表示为:

描述好关系之后,一个加上上面所说的物理和外表属性,一个完整的机器人 URDF 模型就建立好了。
但是在URDF里面,模型的拓扑结构也受到着一定的限制:那就是URDF不能定义一个闭环的连杆模型。翻译成URDF说法就是:

一个child 只能有一个parent link
只有root link(也就是connectivity graph的起源)可以有多个分支
一个模型只能由一个root link
举例:

Kinematic Loop URDF Example

<robot name = "linkage">
    <joint name = "joint A ... >
        "link A" />
        <child link = "link B" />
    joint>
    <joint name = "joint B ... >
        "link A" />
        <child link = "link C" />
    joint>
    <joint name = "joint C ... >
        "link C" />
        <child link = "link D" />
    joint>
    <joint name = "joint D ... >
        "link B" />
        <child link = "link D" />
    joint>
robot>

1.4 连接图显示

上述URDF的连线图如下所示:
ROS学习笔记(十三)—— URDF 模型文件学习_第1张图片

它有一个child link D具有两个parent link, 因此该模型不能用URDF来建模

1.5 其他可选部分定义

URDF里面并不是所有的信息都需要定义,一些信息比如 link 下面的 inertial 信息就是可选的,可以定义也可以不定义。下面的例子中绿色代表可选的信息,可填可不填:

二 、URDF定义机器人模型实践

学习古月老师的创建简单的机器人模型smartcar, 调试urdf 代码,需要的可以直接下载,github

smartcar.urdf.xacro


<robot name="smartcar"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:gazebo="http://playerstage.sourceforge.net/gazebo/xmlschema/#gz"
    xmlns:model="http://playerstage.sourceforge.net/gazebo/xmlschema/#model"
    xmlns:sensor="http://playerstage.sourceforge.net/gazebo/xmlschema/#sensor"
    xmlns:body="http://playerstage.sourceforge.net/gazebo/xmlschema/#body"
    xmlns:geom="http://playerstage.sourceforge.net/gazebo/xmlschema/#geom"
    xmlns:joint="http://playerstage.sourceforge.net/gazebo/xmlschema/#joint"
    xmlns:controller="http://playerstage.sourceforge.net/gazebo/xmlschema/#controller"
    xmlns:interface="http://playerstage.sourceforge.net/gazebo/xmlschema/#interface"
    xmlns:rendering="http://playerstage.sourceforge.net/gazebo/xmlschema/#rendering"
    xmlns:renderable="http://playerstage.sourceforge.net/gazebo/xmlschema/#renderable"
    xmlns:physics="http://playerstage.sourceforge.net/gazebo/xmlschema/#physics"
    xmlns:xacro="http://ros.org/wiki/xacro">

    <xacro:include filename="$(find smartcar_description)/urdf/smartcar_body.urdf.xacro" />
    
    
    <xacro:smartcar_body/>
robot>

gazebo.urdf.xacro


<robot name="smartcar"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:gazebo="http://playerstage.sourceforge.net/gazebo/xmlschema/#gz"
    xmlns:model="http://playerstage.sourceforge.net/gazebo/xmlschema/#model"
    xmlns:sensor="http://playerstage.sourceforge.net/gazebo/xmlschema/#sensor"
    xmlns:body="http://playerstage.sourceforge.net/gazebo/xmlschema/#body"
    xmlns:geom="http://playerstage.sourceforge.net/gazebo/xmlschema/#geom"
    xmlns:joint="http://playerstage.sourceforge.net/gazebo/xmlschema/#joint"
    xmlns:controller="http://playerstage.sourceforge.net/gazebo/xmlschema/#controller"
    xmlns:interface="http://playerstage.sourceforge.net/gazebo/xmlschema/#interface"
    xmlns:rendering="http://playerstage.sourceforge.net/gazebo/xmlschema/#rendering"
    xmlns:renderable="http://playerstage.sourceforge.net/gazebo/xmlschema/#renderable"
    xmlns:physics="http://playerstage.sourceforge.net/gazebo/xmlschema/#physics"
    xmlns:xacro="http://ros.org/wiki/xacro">

    <xacro:include filename="$(find smartcar_description)/urdf/smartcar_body.urdf.xacro" />
    
    
    <xacro:smartcar_body/>
  
robot>

smartcar_body.urdf.xacro


<robot name="smartcar" xmlns:xacro="http://ros.org/wiki/xacro">
  <property name="M_PI" value="3.14159"/>

  
  <include filename="$(find smartcar_description)/urdf/gazebo.urdf.xacro"/>

  <property name="base_x" value="0.33" />
  <property name="base_y" value="0.33" />

  <xacro:macro name="smartcar_body">
  <link name="base_link">
    <inertial>
      <origin xyz="0 0 0.055"/>
      <mass value="100.0" />
      <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    inertial>
    <visual>
      <geometry>
        <box size="0.25 .16 .05"/>
      geometry>
	  <origin rpy="0 0 0" xyz="0 0 0.055"/>
      <material name="blue">
	  <color rgba="0 0 .8 1"/>
      material>
   visual>
   <collision>
      <origin rpy="0 0 0" xyz="0 0 0.055"/>
      <geometry>
        <box size="0.25 .16 .05" />
      geometry>
    collision>
  link>


 <link name="left_front_wheel">
	<inertial>
      <origin  xyz="0.08 0.08 0.025"/>
      <mass value="1" />
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    inertial>
    <visual>
      <geometry>
        <cylinder length=".02" radius="0.025"/>
      geometry>
      <material name="black">
        <color rgba="0 0 0 1"/>
      material>
    visual>
    <collision>
      <origin rpy="0 1.57075 1.57075" xyz="0.08 0.08 0.025"/>
      <geometry>
         <cylinder length=".02" radius="0.025"/>
      geometry>
    collision>
  link>

  <joint name="left_front_wheel_joint" type="continuous">
    <axis xyz="0 0 1"/>
    <parent link="base_link"/>
    <child link="left_front_wheel"/>
    <origin rpy="0 1.57075 1.57075" xyz="0.08 0.08 0.025"/>
    <limit effort="100" velocity="100"/>
    <joint_properties damping="0.0" friction="0.0"/>
  joint>

  <link name="right_front_wheel">
	<inertial>
      <origin xyz="0.08 -0.08 0.025"/>
      <mass value="1" />
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    inertial>
    <visual>
      <geometry>
        <cylinder length=".02" radius="0.025"/>
      geometry>
      <material name="black">
        <color rgba="0 0 0 1"/>
      material>
    visual>
    <collision>
      <origin rpy="0 1.57075 1.57075" xyz="0.08 -0.08 0.025"/>
      <geometry>
         <cylinder length=".02" radius="0.025"/>
      geometry>
    collision>
  link>

  <joint name="right_front_wheel_joint" type="continuous">
    <axis xyz="0 0 1"/>
    <parent link="base_link"/>
    <child link="right_front_wheel"/>
    <origin rpy="0 1.57075 1.57075" xyz="0.08 -0.08 0.025"/>
    <limit effort="100" velocity="100"/>
    <joint_properties damping="0.0" friction="0.0"/>
 joint>

 <link name="left_back_wheel">
    <inertial>
      <origin xyz="-0.08 0.08 0.025"/>
      <mass value="1" />
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    inertial>
    <visual>
      <geometry>
        <cylinder length=".02" radius="0.025"/>
      geometry>
      <material name="black">
        <color rgba="0 0 0 1"/>
      material>
   visual>
   <collision>
       <origin rpy="0 1.57075 1.57075" xyz="-0.08 0.08 0.025"/>
      <geometry>
         <cylinder length=".02" radius="0.025"/>
      geometry>
    collision>
  link>

  <joint name="left_back_wheel_joint" type="continuous">
    <axis xyz="0 0 1"/>
    <parent link="base_link"/>
    <child link="left_back_wheel"/>
    <origin rpy="0 1.57075 1.57075" xyz="-0.08 0.08 0.025"/>
    <limit effort="100" velocity="100"/>
    <joint_properties damping="0.0" friction="0.0"/>
  joint>

  <link name="right_back_wheel">
	<inertial>
       <origin xyz="-0.08 -0.08 0.025"/>
       <mass value="1" />
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    inertial>
    <visual>
      <geometry>
        <cylinder length=".02" radius="0.025"/>
      geometry>
      <material name="black">
        <color rgba="0 0 0 1"/>
      material>
   visual>
   <collision>
      <origin rpy="0 1.57075 1.57075" xyz="-0.08 -0.08 0.025"/>
      <geometry>
         <cylinder length=".02" radius="0.025"/>
      geometry>
    collision>
  link>


  <joint name="right_back_wheel_joint" type="continuous">
    <axis xyz="0 0 1"/>
    <parent link="base_link"/>
    <child link="right_back_wheel"/>
    <origin rpy="0 1.57075 1.57075" xyz="-0.08 -0.08 0.025"/>
    <limit effort="100" velocity="100"/>
    <joint_properties damping="0.0" friction="0.0"/>
  joint>

  <link name="head">
	<inertial>
      <origin xyz="0.08 0 0.08"/>
      <mass value="1" />
      <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    inertial>
    <visual>
      <geometry>
        <box size=".02 .03 .03"/>
      geometry>
	  <material name="white">
		<color rgba="1 1 1 1"/>
	  material>
     visual>
     <collision>
      <origin xyz="0.08 0 0.08"/>
      <geometry>
         <cylinder length=".02" radius="0.025"/>
      geometry>
    collision>
  link>

  <joint name="tobox" type="fixed">
    <parent link="base_link"/>
    <child link="head"/>
    <origin xyz="0.08 0 0.08"/>
  joint>
 
  xacro:macro>

robot>

三、实验效果

​​​​ 通过rviz展示出搭建的小车模型,
ROS学习笔记(十三)—— URDF 模型文件学习_第2张图片

四、仿真测试

display.rviz.launch

<launch>
    <param name="/use_sim_time" value="false" />
	
	
    <arg name="urdf_file" default="$(find xacro)/xacro.py '$(find smartcar_description)/urdf/smartcar.urdf.xacro'" />
	<arg name="gui" default="true" />

	<param name="robot_description" command="$(arg urdf_file)" />
	<param name="use_gui" value="$(arg gui)"/>

	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" >
	node>

    <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher">
    node>

	<node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" />
launch>

smartcar_display.rviz.launch

<launch>
    <param name="/use_sim_time" value="false" />
	
	
        <arg name="urdf_file" default="$(find xacro)/xacro.py '$(find smartcar_description)/urdf/smartcar.urdf.xacro'" />
	<arg name="gui" default="false" />

	<param name="robot_description" command="$(arg urdf_file)" />
	<param name="use_gui" value="$(arg gui)"/>

	<node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
        <rosparam command="delete" param="/arbotix" />
        <rosparam file="$(find smartcar_description)/config/smartcar_arbotix.yaml" command="load" />
        <param name="sim" value="true"/>    
        node>

	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" >
	node>
	<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher">
              <param name="publish_frequency" type="double" value="20.0" />	  
        node>
	
    <node pkg="tf" type="static_transform_publisher" name="odom_left_wheel_broadcaster"  args="0 0 0 0 0 0 /base_link /left_front_link 100" /> 
    <node pkg="tf" type="static_transform_publisher" name="odom_right_wheel_broadcaster" args="0 0 0 0 0 0 /base_link /right_front_link 100" />
 
    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find smartcar_description)/urdf.rviz" />
launch>

首先运行lanuch,既可以看到rviz中的机器人:

roslaunch smartcar_description smartcar_display.rviz.launch

发布一条动作的消息。

rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.5, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.5}}'

rviz中显示模拟小车运行效果
ROS学习笔记(十三)—— URDF 模型文件学习_第3张图片

​参考1. 「Wo看见常威在打来福
​参考2. 创建简单的机器人模型smartcar

你可能感兴趣的:(ROS,学习,自动驾驶,人工智能)