机器人的建模和仿真一般用于实机部署之前进行算法的虚拟测试
机器人建模的核心文件:URDF
URDF 基本组成
-
<link>:刚体部分(如底盘、机械臂连杆) -
<joint>:连接关系(如旋转、滑动) -
<inertial>:惯性参数(质量、质心、转动惯量) -
<visual>:视觉外观(mesh 文件,如.dae、.stl) -
<collision>:碰撞检测模型 -
<transmission>:定义执行器与 joint 的关系
创建一个urdf的功能包无需其余依赖,使用ament_cmake方式进行构建生成可执行文件,在下面新建一个urdf文件夹用于存放urdf文件
<?xml version="1.0"?>
<!-- 声明 XML 文件头,URDF 是一种 XML 格式的描述语言 --><robot name="my_robot">
<!-- 定义一个机器人模型,名字为 "my_robot" --><link name="base_link"><!-- link 是机器人中的刚体(不发生形变的物理部分) --><visual><!-- visual 定义用于可视化(显示)的几何信息 --><origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/><!-- origin 表示几何形状相对于 link 坐标系的位姿(位置+姿态) --><!-- xyz 表示平移(x, y, z),rpy 表示旋转(roll, pitch, yaw) --><geometry><!-- geometry 定义该 link 的形状 --><cylinder radius="0.10" length="0.12"/><!-- 定义一个圆柱体,半径为 0.10m,高度为 0.12m --></geometry></visual><material><!-- material 定义外观颜色或纹理 --><color rgba="1.0 1.0 1.0 0.5"/><!-- rgba: 红、绿、蓝、透明度(0=透明, 1=不透明) --></material></link><link name="imu_link"><visual><origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/><!-- IMU 的外观几何原点在自身坐标系的原点 --><geometry><box size="0.02 0.02 0.02"/><!-- 定义一个 2cm 立方体,用于表示 IMU 模块 --></geometry></visual><material><color rgba="0.0 0.0 0.0 0.5"/><!-- 颜色为半透明黑色 --></material></link><joint name="imu_joint" type="fixed"><!-- joint 定义两个 link 之间的连接关系 --><!-- name 为关节名称,type 为关节类型 --><!-- type="fixed" 表示两个 link 之间无相对运动 --><parent link="base_link"/><!-- 父连杆(主结构体) --><child link="imu_link"/><!-- 子连杆(被附着的模块) --><origin xyz="0.03 0.0 0.0" rpy="0.0 0.0 0.0"/><!-- 表示 imu_link 坐标系相对于 base_link 坐标系的位姿 --></joint></robot>
urdf_to_graphviz:一个 ROS 工具,用于将 URDF 模型的结构(link-joint 关系)可视化为拓扑图,作用为读取 .urdf 文件,分析 link 与 joint 的连接关系,使用 Graphviz 生成 .gv(graphviz 源文件)和 .pdf(图形文件)。
urdf_to_graphviz robot.urdf将会生成两个文件,这两个文件的名字和xml里面name属性的赋值一致


使用rviz2打开可视化工具,读取urdf文件,可视化展示,我们选择从文件中获取同时设置Fixed Frame(固定坐标系)为base_link
安装两个工具包,sudo apt install ros-$ROS_DISTRO-robot-state-publisher和sudo apt install ros-$ROS_DISTRO-joint-state-publisher
| 包名 | 节点名 | 功能作用 | 输入 | 输出 |
|---|---|---|---|---|
robot_state_publisher |
/robot_state_publisher |
根据 URDF 模型和 joint 状态生成 TF 树(坐标变换关系) | /joint_states(joint 角度)/robot_description(URDF) |
/tf、/tf_static |
joint_state_publisher |
/joint_state_publisher |
发布机器人各关节的角度状态,用于驱动 URDF 中的关节 | ——(手动或 GUI 输入) | /joint_states |
这两个包涉及的节点和话题入下图所示

相关节点
| 节点名称 | 角色 | 主要功能 |
|---|---|---|
| /robot_state_publisher | 机器人状态发布节点(核心) | 根据 URDF 模型(robot_description)和关节角度(joint_states)计算各个 link 的坐标变换(TF),并发布到 /tf 和 /tf_static |
| /joint_state_publisher | 关节状态发布节点 | 向话题 /joint_states 发布各关节的角度、速度、位移等信息(一般由 GUI 或真实传感器产生) |
| /transform_listener_impl_... | TF 监听节点(例如 RViz 或 TF 工具) | 订阅 /tf 与 /tf_static,以便获取机器人各个部分的空间位置关系(用于 3D 显示或坐标变换) |
| /robot_description | 参数(非真正节点) | 存储机器人的 URDF 模型(XML 字符串),供 robot_state_publisher 读取 |
相关话题
| 话题名称 | 发布者 | 订阅者 | 作用 |
|---|---|---|---|
/robot_description |
launch 或 parameter server | /robot_state_publisher |
提供 URDF 模型内容(机器人结构) |
/joint_states |
/joint_state_publisher |
/robot_state_publisher |
提供关节角度、速度、位移信息 |
/tf |
/robot_state_publisher |
/transform_listener_impl_xxxxx |
动态 TF(随时间变化的坐标关系) |
/tf_static |
/robot_state_publisher |
/transform_listener_impl_xxxxx |
静态 TF(固定坐标变换,如 base_link→imu_link) |
创建launch文件启动这些节点
from launch import LaunchDescription # ROS2 启动文件的核心类,用于定义要启动的所有节点/动作
from launch.actions import DeclareLaunchArgument # 声明可在命令行传入的启动参数
from launch.substitutions import Command, LaunchConfiguration # Launch 变量替换机制(动态获取参数或命令结果)
from launch_ros.actions import Node # ROS2 节点启动动作
from launch_ros.descriptions import ParameterValue # ROS 参数值类型
from ament_index_python.packages import get_package_share_directory # 获取包路径的工具函数
import osdef generate_launch_description():# 获取 URDF 模型路径urdf_package_path = get_package_share_directory('robot_description')default_urdf_path = os.path.join(urdf_package_path,'urdf','robot.urdf')# 声明 Launch 参数# 区分launch参数和节点参数,launch 参数管 “启动怎么配”(启动阶段、全局控制),节点参数管 “运行怎么算”(运行阶段、节点内部配置)action_declare_arg_mode_path=DeclareLaunchArgument('model',default_value=str(default_urdf_path))# 读取 URDF 文件内容,cat有空格command_result = Command(['cat ',LaunchConfiguration('model')])# 告诉 ROS 这是一个字符串类型的参数值(即 URDF 模型文本)robot_description_value = ParameterValue(command_result,value_type=str)'''启动节点:├─ joint_state_publisher → 发布 JointState├─ robot_state_publisher → 发布 TF 树└─ rviz2 → 显示模型'''robot_state_publisher = Node(package='robot_state_publisher',executable='robot_state_publisher',parameters=[{'robot_description':robot_description_value}],)robot_joint_publisher = Node(package='joint_state_publisher',executable='joint_state_publisher',)robot_rviz_node = Node(package='rviz2',executable='rviz2',)return LaunchDescription([action_declare_arg_mode_path,robot_state_publisher,robot_joint_publisher,robot_rviz_node,])

在robot_description下新建目录config,将配置保存到该目录下得到.rviz文件然后修改代码和cmakelist.txt
# 复制config目录到install
install(DIRECTORY launch urdf configDESTINATION share/${PROJECT_NAME}
)
from launch import LaunchDescription # ROS2 启动文件的核心类,用于定义要启动的所有节点/动作
from launch.actions import DeclareLaunchArgument # 声明可在命令行传入的启动参数
from launch.substitutions import Command, LaunchConfiguration # Launch 变量替换机制(动态获取参数或命令结果)
from launch_ros.actions import Node # ROS2 节点启动动作
from launch_ros.descriptions import ParameterValue # ROS 参数值类型
from ament_index_python.packages import get_package_share_directory # 获取包路径的工具函数
import osdef generate_launch_description():# 获取 URDF 模型路径urdf_package_path = get_package_share_directory('robot_description')default_urdf_path = os.path.join(urdf_package_path,'urdf','robot.urdf')default_rviz_path = os.path.join(urdf_package_path,'config','display_robot.rviz')# 声明 Launch 参数action_declare_arg_mode_path=DeclareLaunchArgument('model',default_value=str(default_urdf_path))# 读取 URDF 文件内容,cat有空格command_result = Command(['cat ',LaunchConfiguration('model')])# 告诉 ROS 这是一个字符串类型的参数值(即 URDF 模型文本robot_description_value = ParameterValue(command_result,value_type=str)'''启动节点:├─ joint_state_publisher → 发布 JointState├─ robot_state_publisher → 发布 TF 树└─ rviz2 → 显示模型'''robot_state_publisher = Node(package='robot_state_publisher',executable='robot_state_publisher',parameters=[{'robot_description':robot_description_value}],)robot_joint_publisher = Node(package='joint_state_publisher',executable='joint_state_publisher',)robot_rviz_node = Node(package='rviz2',executable='rviz2',arguments=['-d',default_rviz_path], )return LaunchDescription([action_declare_arg_mode_path,robot_state_publisher,robot_joint_publisher,robot_rviz_node,])
Xacro
Xacro是 ROS 中定义机器人模型最常用的增强版 URDF 语言,它是 URDF 的宏扩展语言,让 URDF 文件可以使用变量、宏、条件、循环等高级功能。
| 项目 | URDF | Xacro |
|---|---|---|
| 文件后缀 | .urdf |
.xacro |
| 是否支持变量 | ❌ 不支持 | ✅ 支持 |
| 是否支持复用结构(宏) | ❌ 不支持 | ✅ 支持 |
| 是否支持条件语句 | ❌ 不支持 | ✅ 支持 |
| 是否支持数学计算 | ❌ 不支持 | ✅ 支持 |
| 解析方式 | 直接加载 | 必须先转成 URDF 再加载 |
引入xacro的命名空间
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="my_robot">
常见属性
| 标签 | 功能 | 示例 |
|---|---|---|
<xacro:property> |
定义变量 | <xacro:property name="r" value="0.1"/> |
<xacro:macro> |
定义宏 | <xacro:macro name="wheel" params="name r">...</xacro:macro> |
<xacro:include> |
引入文件 | <xacro:include filename="wheel.xacro"/> |
<xacro:arg> |
定义参数 | <xacro:arg name="use_lidar" default="true"/> |
<xacro:if> / <xacro:unless> |
条件判断 | <xacro:if value="$(arg use_lidar)">...</xacro:if> |
<xacro:insert_block> |
插入块 | <xacro:insert_block name="link_content"/> |
${} |
表达式或变量引用 | ${r/2} |
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="my_robot"><!-- ========= 全局颜色属性定义 ========= --><xacro:property name="base_color_rgba" value="0.2 0.2 0.2 1.0"/> <!-- 深灰底座 --><xacro:property name="imu1_color_rgba" value="0.1 0.6 1.0 1.0"/> <!-- 明亮蓝色 IMU1 --><xacro:property name="imu2_color_rgba" value="1.0 0.5 0.0 1.0"/> <!-- 明亮橙色 IMU2 --><xacro:property name="imu3_color_rgba" value="0.2 1.0 0.2 1.0"/> <!-- 明亮绿色 IMU3 --><xacro:property name="imu4_color_rgba" value="1.0 0.2 0.6 1.0"/> <!-- 粉红 IMU4 --><xacro:property name="imu5_color_rgba" value="1.0 1.0 0.1 1.0"/> <!-- 明亮黄色 IMU5 --><!-- ========= 定义底座 link 宏 ========= --><xacro:macro name="base_link" params="base_name xyz rpy radius length rgba"><link name="${base_name}"><!-- 可视部分 --><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><cylinder radius="${radius}" length="${length}"/></geometry><material name="base_color"><color rgba="${rgba}"/></material></visual></link></xacro:macro><!-- ========= 定义 IMU link 宏 ========= --><xacro:macro name="imu_link" params="imu_name xyz rpy size rgba joint_name joint_type parent_name child_name joint_xyz joint_rpy"><link name="${imu_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><box size="${size}"/></geometry><material name="${imu_name}_color"><color rgba="${rgba}"/></material></visual></link><!-- joint: 连接 IMU 与底座 --><joint name="${joint_name}" type="${joint_type}"><parent link="${parent_name}"/><child link="${child_name}"/><origin xyz="${joint_xyz}" rpy="${joint_rpy}"/></joint></xacro:macro><!-- ========= 生成实际模型 ========= --><!-- 底座 --><xacro:base_link base_name="base_link"xyz="0 0 0"rpy="0 0 0"radius="0.1"length="0.12"rgba="${base_color_rgba}"/><!-- IMU 1(蓝色) 正上方中心 --><xacro:imu_link imu_name="imu_link_1"xyz="0 0 0.15"rpy="0 0 0"size="0.02 0.02 0.02"rgba="${imu1_color_rgba}"joint_name="base_to_imu1"joint_type="fixed"parent_name="base_link"child_name="imu_link_1"joint_xyz="0 0 0.15"joint_rpy="0 0 0"/><!-- IMU 2(橙色) 前方 --><xacro:imu_link imu_name="imu_link_2"xyz="0.1 0 0.12"rpy="0 0 0"size="0.02 0.02 0.02"rgba="${imu2_color_rgba}"joint_name="base_to_imu2"joint_type="fixed"parent_name="base_link"child_name="imu_link_2"joint_xyz="0.1 0 0.12"joint_rpy="0 0 0"/><!-- IMU 3(绿色) 后方 --><xacro:imu_link imu_name="imu_link_3"xyz="-0.1 0 0.12"rpy="0 0 0"size="0.02 0.02 0.02"rgba="${imu3_color_rgba}"joint_name="base_to_imu3"joint_type="fixed"parent_name="base_link"child_name="imu_link_3"joint_xyz="-0.1 0 0.12"joint_rpy="0 0 0"/><!-- IMU 4(粉红) 左方 --><xacro:imu_link imu_name="imu_link_4"xyz="0 0.1 0.12"rpy="0 0 0"size="0.02 0.02 0.02"rgba="${imu4_color_rgba}"joint_name="base_to_imu4"joint_type="fixed"parent_name="base_link"child_name="imu_link_4"joint_xyz="0 0.1 0.12"joint_rpy="0 0 0"/><!-- IMU 5(黄色) 右方 --><xacro:imu_link imu_name="imu_link_5"xyz="0 -0.1 0.12"rpy="0 0 0"size="0.02 0.02 0.02"rgba="${imu5_color_rgba}"joint_name="base_to_imu5"joint_type="fixed"parent_name="base_link"child_name="imu_link_5"joint_xyz="0 -0.1 0.12"joint_rpy="0 0 0"/></robot>

from launch import LaunchDescription # ROS2 启动文件的核心类,用于定义要启动的所有节点/动作
from launch.actions import DeclareLaunchArgument # 声明可在命令行传入的启动参数
from launch.substitutions import Command, LaunchConfiguration # Launch 变量替换机制(动态获取参数或命令结果)
from launch_ros.actions import Node # ROS2 节点启动动作
from launch_ros.descriptions import ParameterValue # ROS 参数值类型
from ament_index_python.packages import get_package_share_directory # 获取包路径的工具函数
import osdef generate_launch_description():# 获取 URDF 模型路径urdf_package_path = get_package_share_directory('robot_description')default_urdf_path = os.path.join(urdf_package_path,'urdf','robot.xacro')default_rviz_path = os.path.join(urdf_package_path,'config','display_robot.rviz')# 声明 Launch 参数action_declare_arg_mode_path=DeclareLaunchArgument('model',default_value=str(default_urdf_path))# 读取 xacro 文件内容,xacro有空格,通过命令转换为urdf让rviz工具可以分析command_result = Command(['xacro ',LaunchConfiguration('model')])# 告诉 ROS 这是一个字符串类型的参数值(即 URDF 模型文本robot_description_value = ParameterValue(command_result,value_type=str)'''启动节点:├─ joint_state_publisher → 发布 JointState├─ robot_state_publisher → 发布 TF 树└─ rviz2 → 显示模型'''robot_state_publisher = Node(package='robot_state_publisher',executable='robot_state_publisher',parameters=[{'robot_description':robot_description_value}],)robot_joint_publisher = Node(package='joint_state_publisher',executable='joint_state_publisher',)robot_rviz_node = Node(package='rviz2',executable='rviz2',arguments=['-d',default_rviz_path], )return LaunchDescription([action_declare_arg_mode_path,robot_state_publisher,robot_joint_publisher,robot_rviz_node,])
通过上面的例子可以看到xacro的出现本质上是面向对象的思想运用到urdf文件中,通过定义宏将部件简化为一个模板,对于有相似属性的部件,通过模板可以创建多个极大的简化了代码量,如果是urdf原始写法,上面五个imu部件就要写五给link标签,而xacro就简化为了一个模板,传入不同的值就可以定义多个不同的imu部件。
注意有些名称的定义都是静态的,例如宏的名称是静态的,不能用变量插入,比如 <xacro:macro name="${var}" params="${var}"> ,<xacro:property name="${var}"/> 和 <xacro:${macro_name}/>这些都不能动态变化,而其余的标签里面的属性可以进行动态插入。
创建一个自己的机器人
该机器人以mybot整合,包含底盘,传感器和执行器三大块

底盘部件为机器人的主体几何
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:macro name="base_xacro" params="base_name xyz rpy radius length base_color rgba"><link name="${base_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><cylinder radius="${radius}" length="${length}"/></geometry><material name="${base_color}"><color rgba="${rgba}"/></material></visual></link><!-- 虚拟部件用于贴合地面 --><link name="base_footprint"> </link><joint name="joint_name" type="fixed"><parent link="base_footprint"/><child link="${base_name}"/><origin xyz="0.0 0.0 ${length/2.0+0.032-0.01}" rpy="0.0 0.0 0.0"/></joint></xacro:macro>
</robot>
传感器包括相机,imu和雷达三大传感器
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:macro name="camera_xacro" params="camera_name xyz rpy size camera_color rgba joint_name joint_type parent_name child_name joint_xyz joint_rpy"><link name="${camera_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><box size="${size}"/></geometry><material name="${camera_color}"><color rgba="${rgba}"/></material></visual></link><joint name="${joint_name}" type="${joint_type}"><parent link="${parent_name}"/><child link="${child_name}"/><origin xyz="${joint_xyz}" rpy="${joint_rpy}"/></joint></xacro:macro>
</robot>
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:macro name="imu_xacro" params="imu_name xyz rpy size imu_color rgba joint_name joint_type parent_name child_name joint_xyz joint_rpy"><link name="${imu_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><box size="${size}"/></geometry><material name="${imu_color}"><color rgba="${rgba}"/></material></visual></link><joint name="${joint_name}" type="${joint_type}"><parent link="${parent_name}"/><child link="${child_name}"/><origin xyz="${joint_xyz}" rpy="${joint_rpy}"/></joint></xacro:macro>
</robot>
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><!-- 激光雷达组件宏 --><xacro:macro name="laser_xacro" params="laser_nameparent_namejoint1_name joint1_type joint1_xyz joint1_rpyjoint2_name joint2_type joint2_xyz joint2_rpycylinder_xyz cylinder_rpy cylinder_radius cylinder_length cylinder_color cylinder_rgbasensor_xyz sensor_rpy sensor_radius sensor_length sensor_color sensor_rgba"><!-- 支撑杆 --><link name='${laser_name}_cylinder_link'><visual><origin xyz='${cylinder_xyz}' rpy='${cylinder_rpy}'/><geometry><cylinder radius='${cylinder_radius}' length='${cylinder_length}'/></geometry><material name='${cylinder_color}'><color rgba='${cylinder_rgba}'/></material></visual></link><!-- 激光雷达主体 --><link name='${laser_name}_sensor_link'><visual><origin xyz='${sensor_xyz}' rpy='${sensor_rpy}'/><geometry><cylinder radius='${sensor_radius}' length='${sensor_length}'/></geometry><material name='${sensor_color}'><color rgba='${sensor_rgba}'/></material></visual></link><!-- 关节1:底座连接支撑杆 --><joint name='${joint1_name}' type='${joint1_type}'><parent link='${parent_name}'/><child link='${laser_name}_cylinder_link'/><origin xyz='${joint1_xyz}' rpy='${joint1_rpy}'/></joint><!-- 关节2:支撑杆连接激光雷达 --><joint name='${joint2_name}' type='${joint2_type}'><parent link='${laser_name}_cylinder_link'/><child link='${laser_name}_sensor_link'/><origin xyz='${joint2_xyz}' rpy='${joint2_rpy}'/></joint></xacro:macro></robot>
执行器有左右两个轮子和前后的万向轮
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:macro name="caster_xacro" params="caster_name xyz rpy radius caster_color rgba joint_name joint_type parent_name child_name joint_xyz joint_rpy"><link name="${caster_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><sphere radius="${radius}"/></geometry><material name="${caster_color}"><color rgba="${rgba}"/></material></visual></link><joint name="${joint_name}" type="${joint_type}"><parent link="${parent_name}"/><child link="${child_name}"/><origin xyz="${joint_xyz}" rpy="${joint_rpy}"/><axis xyz="0 1 0"/></joint></xacro:macro>
</robot>
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:macro name="wheel_xacro" params="wheel_name xyz rpy radius length wheel_color rgba joint_name joint_type parent_name child_name joint_xyz joint_rpy"><link name="${wheel_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><cylinder radius="${radius}" length="${length}"/></geometry><material name="${wheel_color}"><color rgba="${rgba}"/></material></visual></link><joint name="${joint_name}" type="${joint_type}"><parent link="${parent_name}"/><child link="${child_name}"/><origin xyz="${joint_xyz}" rpy="${joint_rpy}"/><axis xyz="0 1 0"/></joint></xacro:macro>
</robot>
集中部署到机器人上
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mybot"><!-- ========== Include 部分 ========== --><xacro:include filename="$(find robot_description)/urdf/base.urdf.xacro" /><xacro:include filename="$(find robot_description)/urdf/sensor/camera.urdf.xacro" /><xacro:include filename="$(find robot_description)/urdf/sensor/imu.urdf.xacro" /><xacro:include filename="$(find robot_description)/urdf/sensor/laser.urdf.xacro" /><xacro:include filename="$(find robot_description)/urdf/actuator/wheel.urdf.xacro" /><xacro:include filename="$(find robot_description)/urdf/actuator/caster.urdf.xacro" /><!-- ========== Base ========== --><xacro:base_xacrobase_name="base_link"xyz="0 0 0"rpy="0 0 0"radius="0.1"length="0.12"base_color="white"rgba="1 1 1 0.5" /><!-- ========== IMU ========== --><xacro:imu_xacroimu_name="imu_link"xyz="0 0 0"rpy="0 0 0"size="0.02 0.02 0.02"imu_color="black"rgba="0 0 0 0.5"joint_name="imu_joint"joint_type="fixed"parent_name="base_link"child_name="imu_link"joint_xyz="0 0 0.02"joint_rpy="0 0 0" /><!-- ========== Camera ========== --><xacro:camera_xacrocamera_name="camera_link"xyz="0 0 0"rpy="0 0 0"size="0.02 0.02 0.02"camera_color="black"rgba="0 0 0 0.5"joint_name="camera_joint"joint_type="fixed"parent_name="base_link"child_name="camera_link"joint_xyz="0.1 0 0.075"joint_rpy="0 0 0" /><!-- ========== Laser ========== --><xacro:laser_xacrolaser_name="laser"parent_name="base_link"joint1_name="laser_stand_joint"joint1_type="fixed"joint1_xyz="0 0 0.1"joint1_rpy="0 0 0"joint2_name="laser_mount_joint"joint2_type="fixed"joint2_xyz="0 0 0.05"joint2_rpy="0 0 0"cylinder_xyz="0 0 0"cylinder_rpy="0 0 0"cylinder_radius="0.01"cylinder_length="0.1"cylinder_color="black"cylinder_rgba="0 0 0 1.0"sensor_xyz="0 0 0"sensor_rpy="0 0 0"sensor_radius="0.02"sensor_length="0.02"sensor_color="black"sensor_rgba="0 0 0 1.0" /><!-- ========== Wheel ========== --><xacro:wheel_xacrowheel_name="wheel_left"xyz="0 0 0"rpy="1.57079 0 0"radius="0.032"length="0.04"wheel_color="yellow"rgba="1 1 0 0.8"joint_name="wheel_left_joint"joint_type="continuous"parent_name="base_link"child_name="wheel_left"joint_xyz="0 0.1 -0.06"joint_rpy="0 0 0" /><xacro:wheel_xacrowheel_name="wheel_right"xyz="0 0 0"rpy="1.57079 0 0"radius="0.032"length="0.04"wheel_color="yellow"rgba="1 1 0 0.8"joint_name="wheel_right_joint"joint_type="continuous"parent_name="base_link"child_name="wheel_right"joint_xyz="0 -0.1 -0.06"joint_rpy="0 0 0" /><!-- ========== Caster ========== --><xacro:caster_xacrocaster_name="caster_front"xyz="0 0 0"rpy="0 0 0"radius="0.016"caster_color="yellow"rgba="1 1 0 0.8"joint_name="caster_front_joint"joint_type="fixed"parent_name="base_link"child_name="caster_front"joint_xyz="0.08 0 -0.076"joint_rpy="0 0 0" /><xacro:caster_xacrocaster_name="caster_back"xyz="0 0 0"rpy="0 0 0"radius="0.016"caster_color="yellow"rgba="1 1 0 0.8"joint_name="caster_back_joint"joint_type="fixed"parent_name="base_link"child_name="caster_back"joint_xyz="-0.08 0 -0.076"joint_rpy="0 0 0" /></robot>

简单回顾一下之前的TF,一般由机器人底盘作为整体的父坐标系,而其底盘的原点坐标为下为相对世界坐标系下的坐标,坐标系的关系通过joint进行转换,这样才能将所有不同坐标系下的部件整合到一个大坐标系下统一控制。
| 所在位置 | 含义 | 坐标关系 | 影响对象 |
|---|---|---|---|
link/visual/origin |
模型几何中心(例如立方体或圆柱)在 link 坐标系下的位置与姿态 | 几何体 ← 相对 ← link | 决定 link 的外观模型 |
link/collision/origin |
碰撞体在 link 坐标系下的位置与姿态 | 碰撞体 ← 相对 ← link | 用于仿真碰撞检测 |
joint/origin |
子 link 坐标系在父 link 坐标系下的位置与姿态 | child_link ← 相对 ← parent_link | 决定 link 之间的装配关系 |
刚体
刚体是一种理想化的物理模型,其特征是在任何情况下,物体内部任意两点之间的距离始终保持不变,也就是说,无论受到多大的外力或产生何种运动,刚体都不会发生形变、压缩或拉伸。在机器人仿真过程中,为了简化计算与提高仿真效率,我们通常将各个部件理想化为刚体进行建模和分析。
| 属性 | 说明 |
|---|---|
| name | 刚体的名称(link 名称需唯一) |
| visual | 用于显示的几何外观(仅视觉效果,不参与物理仿真) |
| collision | 用于物理碰撞检测的几何体(通常比 visual 更简单) |
| inertial | 表示刚体的质量和惯性张量(影响物体运动特性) |
碰撞属性
<collision> 元素用于定义刚体在物理仿真中的真实形状,不影响 RViz 可视化,决定“仿真怎么动、怎么撞”和<visual>分工不同
如以下代码所示给部件加入碰撞属性上面为可视化部件,下面为添加碰撞属性,部件位于link坐标系下,其余部件添加碰撞属性也是如此
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:macro name="base_xacro" params="base_name xyz rpy radius length base_color rgba"><link name="${base_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><cylinder radius="${radius}" length="${length}"/></geometry><material name="${base_color}"><color rgba="${rgba}"/></material></visual><collision><origin xyz="${xyz}" rpy="${rpy}"/><geometry><cylinder radius="${radius}" length="${length}"/></geometry><material name="${base_color}"><color rgba="${rgba}"/></material></collision></link><link name="base_footprint"> </link><joint name="joint_name" type="fixed"><parent link="base_footprint"/><child link="${base_name}"/><origin xyz="0.0 0.0 ${length/2.0+0.032-0.01}" rpy="0.0 0.0 0.0"/></joint></xacro:macro>
</robot>
关闭可视化,打开碰撞属性可视化

质量和惯性
真实环境下的机器人的各个部件肯定是有质量和惯性,由于上面我们已经加入的碰撞属性,因此对于碰撞的之后物体会发生哪些变化还需借助质量和关系进行一个判断。
惯性矩阵:描述刚体对不同旋转轴的惯性阻力的一个对称矩阵,它表示物体的质量分布对旋转运动的影响,相当于“质量在旋转意义上的分布。
添加系新的xacro文件储存物体们的惯性矩阵
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><!-- ========== 长方体惯性矩阵 ========== --><!-- 参数: m=质量, w=宽, h=高, d=深 --><xacro:macro name="box_inertia" params="m w h d"><inertial><!-- 惯性中心位姿 --><origin xyz="0 0 0" rpy="0 0 0"/><mass value="${m}"/><inertiaixx="${(m/12.0)*(h*h + d*d)}"ixy="0.0"ixz="0.0"iyy="${(m/12.0)*(w*w + d*d)}"iyz="0.0"izz="${(m/12.0)*(w*w + h*h)}"/></inertial></xacro:macro><!-- ========== 圆柱体惯性矩阵 ========== --><!-- 参数: m=质量, r=半径, h=高度 --><xacro:macro name="cylinder_inertia" params="m r h"><inertial><origin xyz="0 0 0" rpy="0 0 0"/><mass value="${m}"/><inertiaixx="${(m/12.0)*(3*r*r + h*h)}"ixy="0.0"ixz="0.0"iyy="${(m/12.0)*(3*r*r + h*h)}"iyz="0.0"izz="${(m/2.0)*(r*r)}"/></inertial></xacro:macro><!-- ========== 球体惯性矩阵 ========== --><!-- 参数: m=质量, r=半径 --><xacro:macro name="sphere_inertia" params="m r"><inertial><origin xyz="0 0 0" rpy="0 0 0"/><mass value="${m}"/><inertiaixx="${(2.0/5.0)*m*(r*r)}"ixy="0.0"ixz="0.0"iyy="${(2.0/5.0)*m*(r*r)}"iyz="0.0"izz="${(2.0/5.0)*m*(r*r)}"/></inertial></xacro:macro></robot>
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:include filename="$(find robot_description)/urdf/common_inert.urdf.xacro" /><xacro:macro name="caster_xacro" params="caster_name xyz rpy radius caster_color rgba joint_name joint_type parent_name child_name joint_xyz joint_rpy"><link name="${caster_name}"><visual><origin xyz="${xyz}" rpy="${rpy}"/><geometry><sphere radius="${radius}"/></geometry><material name="${caster_color}"><color rgba="${rgba}"/></material></visual><collision><origin xyz="${xyz}" rpy="${rpy}"/><geometry><sphere radius="${radius}"/></geometry><material name="${caster_color}"><color rgba="${rgba}"/></material></collision><!--- 添加对应的惯性矩阵 --><xacro:sphere_inertia m="0.05" r="${radius}"/></link><joint name="${joint_name}" type="${joint_type}"><parent link="${parent_name}"/><child link="${child_name}"/><origin xyz="${joint_xyz}" rpy="${joint_rpy}"/><axis xyz="0 1 0"/></joint></xacro:macro>
</robot>
其余的部件都是通过这种方式进行添加的
















