ROS:机器人描述--URDF和XACRO

本文深入解析URDF和XACRO文件在机器人描述中的应用,涵盖link、joint、位置、形状、碰撞检测及关节限制等内容,并介绍XACRO如何简化描述过程,提升效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1 URDF 文件

1.1 link和joint

图中机器人的描述方式

复制代码

<robot name="test_robot">
  <link name="link1" />
  <link name="link2" />
  <link name="link3" />
  <link name="link4" />

  <joint name="joint1" type="continuous">
    <parent link="link1"/>
    <child link="link2"/>
  </joint>

  <joint name="joint2" type="continuous">
    <parent link="link1"/>
    <child link="link3"/>
  </joint>

  <joint name="joint3" type="continuous">
    <parent link="link3"/>
    <child link="link4"/>
  </joint>
</robot>

复制代码

以上描述只能够描述机器人的大致样子,不能够确定link的位置关系和具体形状。

 

1.2 位置

在定义好了机器人的骨架后, 进一步我们可以使用origin子标签进行定义link所应该在的位置. 但是有一点应该注意到, link和link之间是使用joint进行连接, 那么link的位置, 就由连接他的joint确定. 所以, 该子标签是定义在joint内. 在三维空间中, 要精确描述一个刚性体的姿态, 仅仅使用他的xyz坐标是不够的, 还需要使用rpy. rpy角是描述船舶在海中航行时姿态的一种方法. 将船的行驶方向取为z轴, 绕z轴旋转称为滚动(Roll), 绕y轴旋转称为俯仰(Pitch), 绕x轴旋转称为偏转(Yaw). 这种描述方式大量运用于各个领域. 依稀记得, kinect2关于脸部模型匹配的DEMO程序里面, 对脸部的描述就用到了这种描述方式来描述姿态. 在机器人中, 当然运用就更多了. 现在对之前的内容进行扩充. 其中rpy代表的是角度, 用弧度表示.

复制代码

<robot name="test_robot">
  <link name="link1" />
  <link name="link2" />
  <link name="link3" />
  <link name="link4" />


  <joint name="joint1" type="continuous">
    <parent link="link1"/>
    <child link="link2"/>
    <origin xyz=".5 .3 0.7" rpy="0 0 0" />
  </joint>

  <joint name="joint2" type="continuous">
    <parent link="link1"/>
    <child link="link3"/>
    <origin xyz="-.2 .5 -0.3" rpy="0 0 1.57" />
  </joint>

  <joint name="joint3" type="continuous">
    <parent link="link3"/>
    <child link="link4"/>
    <origin xyz=".5 0 0.2" rpy="0 0 -1.57" />
  </joint>
</robot>

复制代码

上述位置关系定义如下图所示. xyz就如同一个平移向量, 将下一个link的原点坐标移动到下一个位置(起点是父link的原点). 同时, 你也可以多尝试几次rpy, 体会下一个坐标系是如何进行变换的. 虽然现在还没有任何东西出来, 但每个link的空间位置以及姿态已经被我们所指定了.

 

1.3 形状

复制代码

<?xml version="1.0"?>
<robot name="test_robot">
  <link name="link1">
    <visual>
      <geometry>
        <cylinder length="0.6" radius="0.2" />
      </geometry>
    </visual>
  </link>

  <link name="link2">
    <visual>
      <geometry>
        <box size="0.6 0.2 .1" />
      </geometry>
    </visual>
  </link>

  <link name="link3" >
    <visual>
      <geometry>
        <sphere radius="0.2"/>
      </geometry>
    </visual>
  </link>

  <link name="link4" >
    <visual>
      <origin rpy="0 -1.57 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://urdf_csdn/urdf/mesh/knife.stl"/>
      </geometry>
    </visual>
  </link>


  <joint name="joint1" type="fixed">
    <parent link="link1"/>
    <child link="link2"/>
    <origin xyz="0.22 0 0.6" rpy="0 1.57 0" />
  </joint>

  <joint name="joint2" type="continuous">
    <parent link="link1"/>
    <child link="link3"/>
    <origin xyz="-0.1 0.5 0" />
  </joint>

  <joint name="joint3" type="fixed">
    <parent link="link3"/>
    <child link="link4"/>
    <origin xyz=".5 0 0" rpy="0 0 -1.57" />
  </joint>
</robot>

复制代码

 

1.4 Collision和joint limit

当然, 每个link一般是不会产生重合的, 在运动规划的时候, 也会去避免碰撞到自己, 所以针对于每一个link, 还有一个collision标签, 和visual标签内容完全一样.

前面内容可以看到, 每个link可以看作是一个刚体, 刚体和刚体之间是通过joint进行连接, 那么, 问题就来了. 这个joint是固定的? 还是可以任意的动? 如果可以动, 那么, 问题又来了, 极限位置是多少? 等等等等…

比如, 我们限定joint2只能沿着y轴旋转, 则需要添加 <axis xyz="0 1 0"/> , 类似的, 可以指定其他关节的转动轴, 例如 <axis xyz="-0.2 0.1 1"/> .

比如, 我们要限定joint2的移动范围, 则需要添加<limit lower="-3.14" upper="3.14" effort="150.0" velocity="3.15"/>, 从标签中可以看到, 上下限以及速度, 力矩等都是可以指定的.

复制代码

<?xml version="1.0"?>
<robot name="test_robot">
  <link name="link1">
    <visual>
      <geometry>
        <cylinder length="0.6" radius="0.2" />
      </geometry>
    </visual>

    <collision>
      <origin xyz="0.0 0 0.0" rpy="0 0 0" />
      <geometry>
        <cylinder length="0.6" radius="0.2" />
      </geometry>
    </collision>
  </link>

  <link name="link2">
    <visual>
      <geometry>
        <box size="0.6 0.2 .1" />
      </geometry>
    </visual>
  </link>

  <link name="link3" >
    <visual>
      <geometry>
        <sphere radius="0.2"/>
      </geometry>
    </visual>
  </link>

  <link name="link4" >
    <visual>
      <origin rpy="0 -1.57 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://urdf_csdn/urdf/mesh/knife.stl"/>
      </geometry>
    </visual>
  </link>


  <joint name="joint1" type="fixed">
    <parent link="link1"/>
    <child link="link2"/>
    <origin xyz="0.22 0 0.6" rpy="0 1.57 0" />
  </joint>

  <joint name="joint2" type="continuous">
    <parent link="link1"/>
    <child link="link3"/>
    <origin xyz="-0.1 0.5 0" />
    <axis xyz="0 1 0"/>
    <limit lower="-3.14" upper="3.14" effort="150.0" velocity="3.15"/>
  </joint>

  <joint name="joint3" type="fixed">
    <parent link="link3"/>
    <child link="link4"/>
    <origin xyz=".5 0 0" rpy="0 0 -1.57" />
  </joint>
</robot>

复制代码

 

1.5 可视化

查看urdf文件, 可以使用urdf_tutorial包, 命令格式roslaunch urdf_tutorial display.launch model:=path/to/your/xxx.urdf, 会使用Rviz进行显示, 如上述内容, 进行显示之后, 可以得到下图所示内容. 坐标系图示, 需要添加TF条目进行显示. 值得注意的地方, 将Global Options中的fixed frame设定为link1. 如果你设定了可移动的关节, 想查看以下关节移动的效果以及设定等, 使用roslaunch urdf_tutorial display.launch model:=path/to/your/xxx.urdf gui:=true, 你会看到弹出一个控制面板(如果没找到, 再好好找一找, 或许真的很小).

通过上述方式, 在rviz中正确显示模型之后, 新打开一个命令行, 输入rostopic list命令, 可以查看到类似如下的输出. 可以看到, 开启了/joint_states话题(Topic), 使用rostopic echo /joint_states可以看到话题数据

 

2 XACRO文件

前面也提到了, XACRO文件和URDF实质上是等价的. XACRO格式提供了一些更高级的方式来组织编辑机器人描述. 主要提供了三种方式来使得整个描述文件变得简单. 借用在教程中一句话来形容xacro的优势: “Fortunately, you can use the xacro package to make your life simpler”.

2.1 Constants

Usage:  <xacro:property name="WIDTH" value="2.0"/> 

类似于C语言中的宏定义, 在头部定义, 如 <xacro:property name="WIDTH" value="2.0"/> , 以 ${WIDTH} 的方式进行使用. 经常会看到的一个常量定义,  <property name="PI" value="3.14159265" /> . 还有定义一个前缀, 这样后面关节名都可以方便的进行修改. 比如 <property name="prefix" value="my_"/> , 后面关节名字就可以类似的进行更新.  <joint name="${prefix}joint1" type="revolute"/>. 

在有了上面的常量定义之后, 类似于宏定义, 完成字符串替换, 同时还可以进行一些简单的数学运算.

Usage:  ${1/2} ,  ${PI*(WIDTH*0.5)} 

 

2.2 Macros

这个才是xacro文件中最重要的部分. 就像宏函数一样, 完成一些最小模块的定义, 方便重用, 以及可以使用参数来标识不同的部分.

2.2.1 Simple Macro

Usage

<xacro:macro name="default_origin">
    <origin xyz="0 0 0" rpy="0 0 0"/>
</xacro:macro>
<xacro:default_origin />

前面三行对宏进行定义, 第四行是使用.

 

2.2.2 Paramiterized Macro

Usage

<xacro:macro name="default_link" params="prefix">
    <link name="${prefix}_link1" />
</xacro:macro>
<xacro:default_link prefix="my" />

类似, 前三行定义, 第四行是进行使用. 当然, 不单由这样简单的参数, 还可以使用块参数. 

Usage

复制代码

<xacro:macro name="default_link" params="prefix *origin">
    <link name="${prefix}_link1" >
        <xacro:insert_block name="prigin" />
    </link>
</xacro:macro>
<xacro:default_link prefix="my">
    <origin xyz="0 0 0" rpy="0 0 0" />
</xacro:default_link>

复制代码

一般情况下, 很多已有的机器人模型, 都是以xacro格式提供描述, 而在xacro文件中, 整个机器人定义为一个很大的宏. 例如, barrett hand, 想进一步了解的朋友可以点击前面的链接, 查看以下barrett hand是如何进行描述的

 

2.2.3 Include

很多模型都是已宏的形式进行定义, 并以最小集团分成很多个文件. 而最终的机器人描述就变得非常简单了. 下面摘录一个ur5的描述文件. 从中可以看出来xacro的强大优势. 在最后的示例中我们还能够看到, urdf文件也是能够直接导入进来的.

复制代码

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

  <!-- common stuff -->
  <xacro:include filename="$(find ur_description)/urdf/ur5/common.gazebo.xacro" />

  <!-- ur5 -->
  <xacro:include filename="$(find ur_description)/urdf/ur5/ur5.urdf.xacro" />

  <!-- arm -->
  <xacro:ur5_robot prefix="" joint_limited="false"/>

  <link name="world" />

  <joint name="world_joint" type="fixed">
    <parent link="world" />
    <child link = "base_link" />
    <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
  </joint>

</robot>

复制代码

当然, 此时的简单是建立在之前的复杂的基础上的. 从上述内容中可以看到, 首先是在ur_description包中找到另外几个xacro文件, 将其包含进来. 当然应该注意到, include类似于C语言中的include, 先将该文件扩展到包含的位置. 但包含进来的文件很有可能只是一个参数宏的定义. 并没有被调用. 所以, 示例中调用了一个宏(<xacro:ur5_robot prefix="" joint_limited="false"/>), 产生一个ur5机器人

 

2.3 可视化

urdf_tutorial包也是可以查看xacro文件的. 使用

roslaunch urdf_tutorial xacrodisplay.launch model:=path/to/your/xxx.urdf.xacro.

 

3 关于urdf_tutorial

前面提到的可视化都是使用urdf_tutorial包进行的. 分别调用了两个launch文件. 在上面的示例中我们还看到了不但会使用rviz进行可视化, 还会发起一些话题等. 其实这些我们能够从他的launch文件中一窥究竟.

打开命令行, 输入: rosed urdf_tutorial dispaly.launch. 会使用vim打开该文件. 可以看到下述内容

复制代码

<launch>
  <arg name="model" />
  <arg name="gui" default="False" />
  <param name="robot_description" textfile="$(arg model)" />
  <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" />
  <node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" required="true" />
</launch>

复制代码

由上可以看到, 参数model是没有默认值的, 所以调用该launch文件必须指定model参数. 其他都比较易懂, 主要解释以下robot_description, 可以看到, 其前面是param. 这个是指定ros 参数服务器中的参数值. 而打开rviz之后, rviz就是直接从参数服务器中读取机器人描述文件, 也就是这个参数. 然后进行显示. use_gui也是如此对显示产生的影响. 另外, 还发起了两个发布者节点, 分别发布joint_states和robot_state. 这也就是会由joint_states话题的原因. xacrodispaly.launch文件和上面类似, 但在处理文件时, 使用的是:  <param name="robot_description" command="(findxacro)/xacro.py

(arg model)" /> . 在launch中将xacro文件解析为urdf.

至于其中启动的两个节点, joint_state_publisher 和 robot_state_publisher, 可以查看ROS Answer上相关的解释. 另外, 在robot_state_publisher概述中提到, robot_state_publisher从 /joint_states 话题中获取机器人joint角度作为输入, 使用机器人的运动学树模型计算出机器人link的3D姿态, 然后将其发布到话题 /tf 和  /tf_static . joint_state_publisher从ROS参数服务器中读取robot_description参数, 找到所有non-fixed joint, 发布他们的 JointState 消息到 /joint_states 话题

<think>嗯,用户想了解ROS中功能包的文件夹结构以及如何创建各个部分,比如launch、urdf、meshes、config这些文件夹的作用创建方法。首先,我需要回忆一下ROS功能包的标准结构。ROS1ROS2的结构可能有所不同,但用户提到的例子看起来像ROS1的,比如launch文件urdf文件的使用。 首先,功能包的基本结构通常包括哪些目录呢?常见的应该有src、launch、urdf、meshes、config、scripts等。每个目录的作用需要明确:比如launch存放启动文件,urdf存放机器人模型,meshes放3D模型文件,config放参数配置文件。 然后用户可能想知道如何创建这些文件夹,可能使用命令行工具或者手动创建。记得ROS提供了catkin_create_pkg命令来创建功能包,但具体的目录可能需要手动添加,比如mkdir -p创建launch、urdf等目录。或者是否有其他自动化方法? 另外,用户提供的引用内容中有提到xacro文件的解析参数生成,需要结合这些引用信息。例如,引用[1]中提到了在launch文件中解析xacro文件,转换成URDF,这可能涉及到launch文件中的参数设置命令执行。而引用[2]提到了生成参数库,可能config目录中的配置文件相关,比如yaml文件。 需要确保回答中每个文件夹的作用创建方法都清晰。比如,launch文件夹存放启动文件,可以通过在功能包根目录下创建launch子目录,并在其中编写.launch文件。urdf文件夹存放URDFxacro文件,同样需要手动创建目录,并在其中添加模型文件。meshes可能用于URDF中引用的3D模型文件,比如STL或DAE文件,需要放在meshes目录下,确保路径正确。config文件夹通常存放yaml或其它配置文件,用于参数服务器或节点配置。 此外,可能还需要提到package.xmlCMakeLists.txt的作用,虽然用户没有直接问,但创建功能包时这些文件是必须的,由catkin_create_pkg生成,但用户的问题更关注子目录的结构。 需要检查是否有遗漏的目录,比如scripts用于存放Python脚本,src用于C++代码,但用户的问题中没有提到这些,可能不需要深入。但用户提到生成相关问题,可能需要包括这些内容的问题。 在创建方法方面,是否每个目录都需要手动创建?是的,通常使用mkdir命令或在IDE中手动创建。是否有ROS工具自动生成这些目录?可能没有,需要用户自己组织。 最后,确保回答符合用户要求的格式:使用中文,LaTeX公式正确,行内公式用$...$,独立公式用$$...$$,但在这个问题中可能不需要数学公式,所以主要关注文本结构。生成相关问题部分需要与ROS功能包结构相关,比如不同文件夹的作用,如何组织,常见问题等。</think>### ROS功能包文件夹结构解析 #### 1. 标准功能包结构 ROS功能包通常包含以下核心目录(以`my_package`为例): ``` my_package/ ├── CMakeLists.txt ├── package.xml ├── launch/ ├── urdf/ ├── meshes/ ├── config/ ├── scripts/ └── src/ ``` #### 2. 核心目录作用与创建方法 1. **launch/** - **作用**:存储`.launch`文件,用于批量启动节点、参数服务器功能包[^1] - **创建**: ```bash mkdir -p ~/catkin_ws/src/my_package/launch ``` 2. **urdf/** - **作用**:存放机器人模型描述文件(`.urdf`或`.xacro`),支持参数化建模 - **示例**(在launch文件中解析xacro): ```xml <param name="robot_description" command="$(find xacro)/xacro $(find my_package)/urdf/robot.xacro" /> ``` 3. **meshes/** - **作用**:存储STL/DAE等3D模型文件,供URDF文件引用 - **创建**: ```bash mkdir -p ~/catkin_ws/src/my_package/meshes ``` 4. **config/** - **作用**:存放YAML/JSON配置文件,用于参数服务器配置[^2] - **参数生成**示例: ```python # generate_parameter_library会根据配置文件生成参数接口 ``` 5. **scripts/** - **作用**:存放Python可执行脚本 - **设置权限**: ```bash chmod +x ~/catkin_ws/src/my_package/scripts/my_script.py ``` #### 3. 功能包创建流程 ```bash # 创建工作空间 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src # 创建功能包(依赖项根据实际需要添加) catkin_create_pkg my_package roscpp rospy std_msgs # 创建子目录 cd my_package mkdir launch urdf meshes config scripts ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值