news 2026/7/12 0:47:34

ROS2之URDF建模

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ROS2之URDF建模

ROS是机器人操作系统,当然要给机器人使用啦,不过在使用之前,还得让ROS认识下我们使用的机器人,如何把一个机器人介绍给ROS呢?

为此,ROS专门提供了一种机器人建模方法——URDF,用来描述机器人外观、性能等各方面属性。

一、URDF语法

1.1 机器人的组成

建模描述机器人的过程中,我们自己需要先熟悉机器人的组成和参数,比如机器人一般是由硬件结构、驱动系统、传感器系统、控制系统四大部分组成,市面上一些常见的机器人,无论是移动机器人还是机械臂,我们都可以按照这四大组成部分进行分解。

其中:

  • 硬件结构就是底盘、外壳、电机等实打实可以看到的设备;
  • 驱动系统就是可以驱使这些设备正常使用的装置,比如电机的驱动器,电源管理系统等;
  • 传感系统包括电机上的编码器、板载的IMU、安装的摄像头、雷达等等,便于机器人感知自己的状态和外部的环境;
  • 控制系统就是我们开发过程的主要载体了,一般是树莓派、电脑等计算平台,以及里边的操作系统和应用软件。

机器人建模的过程,其实就是按照类似的思路,通过建模语言,把机器人每一个部分都描述清楚,再组合起来的过程。

1.2 什么是URDF

URDF(Unified Robot Description Format,统一机器人描述格式)是一种XML格式的文件,用于从物理和逻辑上描述一个机器人模型。

你可以把它理解为机器人的数字说明书或三维装配图,它告诉计算机:

  • 机器人由哪些零件(连杆、关节)组成;
  • 这些零件长什么样(形状、尺寸、颜色);
  • 零件之间如何连接(位置、旋转、运动类型);
  • 零件的物理属性(质量、惯性);
1.3URDF组成

URDF主要描述两大核心元素:

  • 连杆(Link):代表机器人的刚性部件,如机械臂的每一节臂杆、底盘、轮子、传感器支架等,包括:
    • 视觉属性:形状(立方体、圆柱体、网格模型)、尺寸、颜色、纹理;
    • 碰撞属性:用于物理仿真的简化几何形状;
    • 惯性属性:质量、转动惯量(对仿真至关重要)。
  • 关节(Joint):定义连杆之间的连接方式和运动关系,主要类型:
    • 固定关节(fixed):完全固定连接;
    • 旋转关节(revolute):绕单轴旋转,有角度限制(如机械臂关节);
    • 连续关节(continuous):无限旋转(如轮子);
    • 平移关节(prismatic):线性滑动;
    • 平面关节(planar):在平面内运动;
    • 浮动关节(floating):完全自由(6自由度)。

机器人描述由一组连杆元素和一组将连杆连接起来的关节元素组成;

因此,典型的机器人描述大致如下所示:

<?xml version="1.0"?> <?xml-model href="https://raw.githubusercontent.com/ros/urdfdom/master/xsd/urdf.xsd" ?> <robot name="pr2" xmlns="http://www.ros.org"> <link> ... </link> <link> ... </link> <link> ... </link> <joint> .... </joint> <joint> .... </joint> <joint> .... </joint> </robot>

可以看到,URDF格式的根元素是一个<robot>元素。

1.3.1link元素

link元素描述了一个具有惯性、视觉特征和碰撞属性的刚体。以下是一个link元素的示例:

<link name="my_link"> <inertial> <origin xyz="0 0 0.5" rpy="0 0 0"/> <mass value="1"/> <inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /> </inertial> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <box size="1 1 1" /> </geometry> <material name="Cyan"> <color rgba="0 1.0 1.0 1.0"/> </material> </visual> <collision> <origin xyz="0 0 0" rpy="0 0 0"/> <geometry> <cylinder radius="1" length="0.5"/> </geometry> </collision> </link>

link元素有一个属性,即name(必选):用来描述连杆本身的名称.。此外,link包含若干部元素,接下来我们一一介绍。

1.3.1.1 惯性属性inertial

inertial(可选):用于描述连杆的质量、其质心的位置以及其中心惯性属性。

其下可以包含如下元素:

  • origin(可选):此位姿(平移、旋转)描述了连杆质心坐标系C相对于连杆坐标系L的位置和方向。
    • xyz(可选):表示从Lo(连杆坐标系原点)到Co(连杆质心)的位置向量,形式为x L̂x + y L̂y + z L̂z,其中L̂xL̂yL̂z是连杆坐标系L的正交单位向量;
    • rpy(可选):表示C的单位向量ĈxĈyĈz相对于连杆坐标系L的方向,以欧拉旋转(横滚roll、俯仰pitch、偏航yaw)序列表示,单位为弧度。注意:ĈxĈyĈz不需要与连杆的惯性主轴对齐;
  • mass:连杆的质量由该元素的value属性表示;
  • inertia:此连杆关于Co(连杆质心)的惯性矩ixxiyyizz和惯性积ixyixziyz,这些值对应于固定在质心坐标系C中的单位向量ĈxĈyĈz。注意:ĈxĈyĈz相对于L̂xL̂yL̂z的方向由<origin>标签中的rpy值指定。
1.3.1.2 视觉属性visual

visual(可选):连杆的视觉属性,此元素指定了用于可视化目的的对象形状(长方体、圆柱体等)。

注意:同一个连杆可以存在多个<visual>标签实例。它们定义的几何体的并集形成了该连杆的视觉表示。

其下可以包含如下元素:

  • origin(可选):视觉元素相对于连杆坐标系的参考坐标系;
    • xyz(可选):分别是xyz方向上的平移;
    • py(可选):表示固定轴的横滚、俯仰和偏航角度,单位为弧度;
  • geometry(必选):表示几何形状,可以是以下之一:
    • <box>
      • size属性包含长方体的三个边长,长方体的原点位于其中心;
    • <cylinder>
      • 指定半径和长度。圆柱体的原点位于其中心;
    • <sphere>
      • 指定半径。球体的原点位于其中心;
    • <mesh>
      • 由文件名指定的三角网格元素,以及一个可选的缩放比例,用于缩放网格的轴对齐边界框。任何几何格式都可以接受,但具体应用程序的兼容性取决于实现。对于最佳纹理和颜色支持,推荐的格式是Collada .dae文件。引用同一模型的机器之间不会传输网格文件。它必须是本地文件。在文件名前加上package://<packagename>/<path>可以使网格文件的路径相对于包<packagename>
  • material(可选):视觉元素的材质,其name属性可以用于指定材质的名称;
    • <color>(可选)
      • rgba由一组四个数字(代表红/绿/蓝/透明度alpha)指定的材质颜色,每个数字的范围为 [0,1];
    • <texture>(可选)
      • 材质的纹理由文件名指定。
1.3.1.3 碰撞属性collision

collision用于描述碰撞参数,里边的内容似乎和<visual>一样,也有<geometry><origin>,看似相同,其实区别还是比较大的;

  • origin(可选):碰撞元素相对于连杆坐标系的参考坐标系;
    • xyz(可选):分别是xyz方向上的平移;
    • py(可选):表示固定轴的横滚、俯仰和偏航角度,单位为弧度;
  • geometry:请参见上述视觉元素中的几何描述。
1.3.2joint元素

joint元素描述了关节的运动学和动力学特性,并指定了关节的安全限制。

以下是一个joint元素的示例:

<joint name="my_joint" type="floating"> <origin xyz="0 0 1" rpy="0 0 3.1416"/> <parent link="link1"/> <child link="link2"/> <calibration rising="0.0"/> <dynamics damping="0.0" friction="0.0"/> <limit effort="30" velocity="1.0" lower="-2.2" upper="0.7" /> <safety_controller k_velocity="10" k_position="15" soft_lower_limit="-2.0" soft_upper_limit="0.5" /> </joint>

下面图中,蓝色关节表示出一个运动的轴,蓝色关节是可以围绕蓝色的轴旋转的,也就是child这个link是可以围绕joint上下旋转。

joint连接两个link,需要分一个主次关系,主关节是parent link,子关节是child link, 在xml形式的描述中这个两个link是必须存在的。

joint元素有两个属性:

  • name(必须):指定关节的唯一名称;

  • type(必须):指定关节的类型,类型可以是以下之一;

    • revolute:旋转关节,和continuous类型的区别在于不能无限旋转,而是带有角度限制,比如机械臂的两个连杆,就属于这种运动;

    • continuous:旋转关节,可以围绕单轴无限旋转;比如小车的轮子,就属于这种类型;

    • prismatic:滑动关节,可以沿某一个轴平移,也带有位置的极限,一般直线电机就是这种运动方式;

    • fixed:固定关节,是唯一一种不允许运动的关节,不过使用还是比较频繁的,比如相机这个连杆,安装在机器人上,相对位置是不会变化的,此时使用的连接方式就是fixed

    • floating:浮动关节,允许进行平移、旋转运动;

    • planar:平面关节,允许在平面正交方向上平移或者旋转;

此外,joint包含若干部元素,接下来我们挑选部分介绍介绍。

1.3.2.1origin

origin(可选):表示从父连杆到子连杆的变换,元素属性有:

  • xyz(可选):表示xyz偏移量,所有位置均以米为单位指定;
  • rpy(可选):表示绕固定轴的旋转:先绕x轴横滚(roll),然后绕y轴俯仰(pitch),最后绕z轴偏航(yaw),所有角度均以弧度为单位指定。
1.3.2.2parent

parent描述父连杆名称,元素属性有:

  • link:在机器人树结构中作为此连杆父连杆的连杆名称。
1.3.2.3child

child描述子连杆名称,元素属性有:

  • link:作为子连杆的连杆名称。
1.3.2.4calibration

关节的参考位置,用来校准关节的绝对位置。

1.3.2.5dynamics

描述关节的物理属性,例如阻尼值、物理静摩擦力等,经常在动力学仿真中用到。

1.3.2.6limit

描述运动的一些极限值,包括关节运动的上下限位置、速度限制、力矩限制等。

1.3.2.7mimic

描述该关节与已有关节的关系。

1.3.2.8safety_controller

描述安全控制器参数。保护机器人关节的运动。

二、URDF案例

创建my_learning_urdfPython版本的功能包;

pi@NanoPC-T6:~/dev_ws$ cd src pi@NanoPC-T6:~/dev_ws/src$ ros2 pkg create --build-type ament_python my_learning_urdf

在包中创建如下文件夹:

  • urdf:存放机器人模型的URDFxacro文件;
  • meshes:放置URDF中引用的模型渲染文件;
  • launch:保存相关启动文件;
  • rviz:保存rviz的配置文件。

我们需要修改setup.py文件,添加配置文件:

import os from glob import glob ... data_files=[ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), (os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*.launch.py'))), (os.path.join('share', package_name, 'urdf'), glob(os.path.join('urdf', '*.*'))), (os.path.join('share', package_name, 'urdf/sensors'), glob(os.path.join('urdf/sensors', '*.*'))), (os.path.join('share', package_name, 'meshes'), glob(os.path.join('meshes', '*.*'))), (os.path.join('share', package_name, 'rviz'), glob(os.path.join('rviz', '*.rviz'))), ], ...
2.1 模型文件

urdf下新建文件mbot_base.urdf

<?xml version="1.0" ?> <robot name="mbot"> <link name="base_link"> <visual> <origin xyz=" 0 0 0" rpy="0 0 0" /> <!-- 机器人中心,坐标系原点 --> <geometry> <cylinder length="0.16" radius="0.20"/> <!-- 直径0.4m,高0.16m的圆柱 --> </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"/> <!-- 位置:Y轴+0.19,Z轴-0.05 --> <parent link="base_link"/> <child link="left_wheel_link"/> <axis xyz="0 1 0"/> <!-- 绕Y轴旋转 --> </joint> <link name="left_wheel_link"> <visual> <origin xyz="0 0 0" rpy="1.5707 0 0" /> <!-- 旋转90度(π/2=1.5707) --> <geometry> <cylinder radius="0.06" length = "0.025"/> <!-- 半径0.06m,厚0.025m --> </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> </robot>

这将会创建一个两轮差分驱动机器人的URDF模型,包含若干个部分。

2.1.11个主体base_link

圆柱体(直径0.4米,高0.16米),橙黄色,机器人中心,坐标系原点。

2.1.22个驱动轮(左右轮)

分别为left_wheel_linkright_wheel_link

  • left_wheel_link
    • 圆柱体(半径0.06米,厚度0.025米);
    • 在基座坐标系中(0, 0.19, -0.05)
    • 关节类型:continuous(连续旋转关节,无限旋转);
    • 旋转轴:绕Y(0, 1, 0)
    • 视觉旋转:rpy="1.5707 0 0"将圆柱旋转90度,使其直立(假设原始圆柱是平放的);
  • right_wheel_link:与左轮对称布置,Y坐标为负;
2.1.32个万向轮(前后脚轮,用于支撑)

分别为front_caster_linkback_caster_link

  • front_caster_link
    • 形状:小球体(半径0.015米),模拟万向轮;
    • 在基座坐标系中前方(0.18, 0, -0.095)
    • 颜色:黑色;
  • back_caster_link:与前万向轮对称布置,X坐标为负(-0.18)。
2.2launch文件

launch文件夹下创建display.launch.py文件;

from ament_index_python.packages import get_package_share_path from launch import LaunchDescription from launch.actions import DeclareLaunchArgument from launch.conditions import IfCondition, UnlessCondition from launch.substitutions import Command, LaunchConfiguration from launch_ros.actions import Node from launch_ros.parameter_descriptions import ParameterValue def generate_launch_description(): urdf_tutorial_path = get_package_share_path('my_learning_urdf') # 设置默认的URDF文件和RViz配置文件路径 default_model_path = urdf_tutorial_path / 'urdf/mbot_base.urdf' default_rviz_config_path = urdf_tutorial_path / 'rviz/urdf.rviz' # 命令行参数:--gui true/false,控制是否使用GUI界面发布关节状态 gui_arg = DeclareLaunchArgument(name='gui', default_value='false', choices=['true', 'false'], description='Flag to enable joint_state_publisher_gui') # 命令行参数:--model <路径>,指定URDF文件路径 model_arg = DeclareLaunchArgument(name='model', default_value=str(default_model_path), description='Absolute path to robot urdf file') # 命令行参数:--rvizconfig <路径>,指定RViz配置文件 rviz_arg = DeclareLaunchArgument(name='rvizconfig', default_value=str(default_rviz_config_path), description='Absolute path to rviz config file') # 关键:使用xacro命令解析URDF文件(支持参数化、宏等高级特性) robot_description = ParameterValue(Command(['xacro ', LaunchConfiguration('model')]), value_type=str) # robot_state_publisher 节点 robot_state_publisher_node = Node( package='robot_state_publisher', executable='robot_state_publisher', parameters=[{'robot_description': robot_description}] ) # 关节状态发布器(二选一) # 文本版本(无GUI) joint_state_publisher_node = Node( package='joint_state_publisher', executable='joint_state_publisher', condition=UnlessCondition(LaunchConfiguration('gui')) ) # GUI版本(带滑动条控制) joint_state_publisher_gui_node = Node( package='joint_state_publisher_gui', executable='joint_state_publisher_gui', condition=IfCondition(LaunchConfiguration('gui')) ) # rviz2 可视化节点 rviz_node = Node( package='rviz2', executable='rviz2', name='rviz2', output='screen', arguments=['-d', LaunchConfiguration('rvizconfig')], ) return LaunchDescription([ gui_arg, model_arg, rviz_arg, joint_state_publisher_node, joint_state_publisher_gui_node, robot_state_publisher_node, rviz_node ])

这个Launch文件主要做三件事:

  • 加载机器人URDF模型(支持xacro格式);
  • 发布机器人的状态变换(TF);
  • rviz2中可视化机器人。
2.2.1 节点

脚本运行会创建以下几个节点:

  • joint_state_publisher:发布每个joint(除fixed类型)的状态,一个无界面的、基础版的关节状态发布器;
  • joint_state_publisher_gui:发布每个joint(除fixed类型)的状态,可以通过UI界面对joint进行控制;
  • robot_state_publisher:将机器人各个linksjoints之间的关系,通过TF的形式,整理成三维姿态信息发布。
  • rviz2:在rviz2中可视化机器人;

joint_state_publisher这是一个官方ROS2包,主要功能:

  • 输入:

    • 读取URDF中的关节定义;

    • 接收用户或程序指定的关节角度;

  • 输出:

    • 发布/joint_states话题,消息类型为sensor_msgs/msg/JointState

    • 包含所有关节的名称、位置、速度、力等信息。

2.2.2 数据流与节点关系

数据流与节点关系:

用户通过滑动条/GUI或程序 → joint_state_publisher(_gui) ↓ 发布/joint_states话题 robot_state_publisher ↓ 计算并发布TF变换 rviz2 和其他节点 ↓ 接收TF并可视化
2.3urdf.rviz

rviz目录下新建urdf.rviz文件;

Panels: - Class: rviz_common/Displays Name: Displays - Class: rviz_common/Views Name: Views Visualization Manager: Class: "" Displays: - Class: rviz_default_plugins/Grid Name: Grid Value: true - Alpha: 0.8 Class: rviz_default_plugins/RobotModel Description Source: Topic Description Topic: Value: /robot_description Enabled: true Name: RobotModel Value: true - Class: rviz_default_plugins/TF Name: TF Value: true Global Options: Fixed Frame: base_link Frame Rate: 30 Name: root Tools: - Class: rviz_default_plugins/MoveCamera Value: true Views: Current: Class: rviz_default_plugins/Orbit Distance: 1.7 Name: Current View Pitch: 0.33 Value: Orbit (rviz) Yaw: 5.5 Window Geometry: Height: 800 Width: 1200
2.4 编译运行

编译程序:

pi@NanoPC-T6:~/dev_ws$ colcon build --paths src/my_learning_urdf pi@NanoPC-T6:~/dev_ws$ source install/setup.sh
2.4.1 可视化

启动终端,运行如下命令;

pi@NanoPC-T6:~/dev_ws$ ros2 launch my_learning_urdf display.launch.py

很快就可以看到rviz中显示的机器人模型啦,大家可以使用鼠标拖拽观察;

从可视化的效果来看,这个机器人由5link和4个joint组成。

2.4.2 查看URDF模型结构

我们分析的对不对呢,可以在模型文件的路径下,使用urdf_to_graphviz这个小工具来分析下;

pi@NanoPC-T6:~/dev_ws/src/my_learning_urdf/urdf$ urdf_to_graphviz mbot_base.urdf WARNING: OUTPUT not given. This type of usage is deprecated!Usage: urdf_to_graphviz input.xml [OUTPUT] Will create either $ROBOT_NAME.gv & $ROBOT_NAME.pdf in CWD or OUTPUT.gv & OUTPUT.pdf. Created file mbot.gv Created file mbot.pdf pi@NanoPC-T6:~/dev_ws/src/my_learning_urdf/urdf$ ls mbot_base.urdf mbot.gv mbot.pdf

运行成功后会产生一个pdf文件,打开之后就可以看到URDF模型分析的结果啦,是不是和我们的猜测完全相同呢!

参考文章

[1] 古月居ROS2入门教程学习笔记

[2]ROS中阶笔记(二):机器人系统设计—URDF机器人建模

[3]XML Robot Description Format(URDF)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 2:10:16

Tool Calling 与 Function Call 深度指南

本文档将带你深入理解 AI Agent 的核心机制&#xff1a;如何让大模型连接外部世界。我们将从最基础的概念出发&#xff0c;一步步揭示技术背后的原理。 1. 什么是 Tool Calling (工具调用)&#xff1f; 核心定义&#xff1a; Tool Calling 是指赋予大语言模型&#xff08;LLM&…

作者头像 李华
网站建设 2026/7/11 11:47:31

零门槛上手!AcFunDown:小白也能秒懂的A站视频下载神器

还在为喜欢的AcFun视频无法离线保存而烦恼吗&#xff1f;AcFunDown作为一款完全免费的A站视频下载工具&#xff0c;凭借其简单易用的图形界面和强大的下载功能&#xff0c;让视频收藏变得前所未有的简单。无论你是想保存精彩瞬间还是备份学习资料&#xff0c;这款开源神器都能完…

作者头像 李华
网站建设 2026/7/11 6:34:25

ARM64与x64启动流程对比:系统移植深度剖析

ARM64与x64启动流程对比&#xff1a;从加电到内核的系统移植实战解析你有没有遇到过这样的情况&#xff1a;把一个在 x86_64 上跑得好好的 Linux 系统镜像&#xff0c;直接烧录到一块新的 ARM64 开发板上&#xff0c;结果——黑屏、串口无输出、CPU卡死&#xff1f;别急&#x…

作者头像 李华
网站建设 2026/7/9 18:30:54

Patreon内容备份终极指南:5分钟快速上手教程

Patreon内容备份终极指南&#xff1a;5分钟快速上手教程 【免费下载链接】PatreonDownloader Powerful tool for downloading content posted by creators on patreon.com. Supports content hosted on patreon itself as well as external sites (additional plugins might be…

作者头像 李华
网站建设 2026/7/12 0:39:36

STM32硬件SPI驱动ST7789显示屏:高效图形渲染终极方案

STM32硬件SPI驱动ST7789显示屏&#xff1a;高效图形渲染终极方案 【免费下载链接】ST7789-STM32 using STM32s Hardware SPI to drive a ST7789 based IPS displayer 项目地址: https://gitcode.com/gh_mirrors/st/ST7789-STM32 STM32 ST7789驱动项目通过硬件SPI接口配合…

作者头像 李华
网站建设 2026/7/9 23:16:48

AcFunDown终极指南:2025年最简单快速的A站视频批量下载方案

还在为无法保存AcFun精彩视频而烦恼吗&#xff1f;AcFunDown作为一款专为A站用户设计的免费视频下载工具&#xff0c;能够让你轻松实现视频批量下载、多格式支持和断点续传功能。无论你是想收藏UP主的精彩作品&#xff0c;还是备份学习资料&#xff0c;这款基于Java开发的图形界…

作者头像 李华