文章目录
环境准备
URDF作为ROS中用于描述机器人物理结构的标准格式,本质上是一种标记语言,不支持编程。这意味着URDF代码无法复用,当项目变得复杂之后,就会产生大量冗余,从而难以维护。
Xacro(XML Macros)的出现,就是为了解决URDF的冗余问题。作为URDF的宏语言,Xacro通过通过引入变量、宏和数学计算,大大降低了机器人模型的维护难度,并提高了可读性。
在终端中直接输入xacro,如果没有反应,说明未安装xacro工具,可通过apt安装
bash
sudo apt install ros-lyrical-xacro
下面在URDF初步教程的工作空间中,添加robot.xacro文件。
bash
vim /src/robot_description/urdf/robot.xacro
xacro代码
xacro代码同样采用了xml格式,但和urdf相比,从语法上多了函数计算、代码复用等功能,从功能模块上,多了碰撞、惯性等物理仿真说明。下面在robot.xarco中写入如下代码。
xml
<?xml version="1.0"?>
<!-- 引入 xacro 命名空间 -->
<robot name="simple_robot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- ==================== 1. 定义常量 (Properties) ==================== -->
<xacro:property name="chassis_length" value="0.4"/>
<xacro:property name="chassis_width" value="0.3"/>
<xacro:property name="chassis_height" value="0.1"/>
<xacro:property name="chassis_mass" value="5.0"/> <!-- 质量 5kg -->
<xacro:property name="wheel_radius" value="0.05"/>
<xacro:property name="wheel_thickness" value="0.04"/>
<xacro:property name="wheel_mass" value="0.5"/> <!-- 质量 0.5kg -->
<xacro:property name="wheel_offset_y" value="0.17"/>
<xacro:property name="wheel_offset_z" value="-0.03"/>
<!-- ==================== 2. 定义宏 (Macros) ==================== -->
<!-- 宏:定义标准惯性矩阵 (Gazebo 物理仿真必需) -->
<!-- 这里使用简化的长方体和圆柱体惯性公式 -->
<xacro:macro name="box_inertia" params="m x y z">
<inertial>
<mass value="${m}"/>
<inertia ixx="${m*(y*y+z*z)/12}" ixy="0" ixz="0"
iyy="${m*(x*x+z*z)/12}" iyz="0"
izz="${m*(x*x+y*y)/12}"/>
</inertial>
</xacro:macro>
<xacro:macro name="cylinder_inertia" params="m r h">
<inertial>
<mass value="${m}"/>
<inertia ixx="${m*(3*r*r+h*h)/12}" ixy="0" ixz="0"
iyy="${m*(3*r*r+h*h)/12}" iyz="0"
izz="${m*r*r/2}"/>
</inertial>
</xacro:macro>
<!-- 宏:定义轮子 (包含 visual, collision, inertial) -->
<xacro:macro name="wheel_macro" params="prefix y_offset">
<link name="${prefix}_wheel">
<!-- 外观 -->
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_thickness}"/>
</geometry>
<material name="black">
<color rgba="0.1 0.1 0.1 1.0"/>
</material>
</visual>
<!-- 碰撞 (Gazebo 用于计算物理碰撞) -->
<collision>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_thickness}"/>
</geometry>
</collision>
<!-- 惯性 (Gazebo 用于计算质量和转动惯量) -->
<xacro:cylinder_inertia m="${wheel_mass}" r="${wheel_radius}" h="${wheel_thickness}"/>
</link>
<joint name="${prefix}_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="${prefix}_wheel"/>
<origin xyz="0 ${y_offset} ${wheel_offset_z}" rpy="-1.5708 0 0"/>
<axis xyz="0 0 1"/>
</joint>
</xacro:macro>
<!-- ==================== 3. 实例化机器人 ==================== -->
<!-- 底盘 -->
<link name="base_link">
<visual>
<geometry>
<box size="${chassis_length} ${chassis_width} ${chassis_height}"/>
</geometry>
<material name="blue">
<color rgba="0.2 0.2 0.8 1.0"/>
</material>
</visual>
<collision>
<geometry>
<box size="${chassis_length} ${chassis_width} ${chassis_height}"/>
</geometry>
</collision>
<xacro:box_inertia m="${chassis_mass}" x="${chassis_length}" y="${chassis_width}" z="${chassis_height}"/>
</link>
<!-- 调用宏生成左轮和右轮 -->
<xacro:wheel_macro prefix="left" y_offset="${wheel_offset_y}"/>
<xacro:wheel_macro prefix="right" y_offset="${-wheel_offset_y}"/>
<!-- ==================== 4. 添加激光雷达 (Lidar) ==================== -->
<link name="lidar_link">
<visual>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
<material name="red">
<color rgba="0.8 0.1 0.1 1.0"/>
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
</collision>
<xacro:cylinder_inertia m="0.1" r="0.05" h="0.04"/>
</link>
<joint name="lidar_joint" type="fixed">
<parent link="base_link"/>
<child link="lidar_link"/>
<!-- 安装在底盘顶部中央 -->
<origin xyz="0.1 0 0.07" rpy="0 0 0"/>
</joint>
</robot>
下面逐段拆解上述代码。
其第一部分用于定义常量,具体格式为,用【xacro:property】标签,来对name和value进行变量名和变量值的绑定。
第二部分通过【xacro:macro】标签来定义宏,这实质上是一个写成xml的函数,其中name和params分别是函数名和参数。这部分代码,不仅定义了可供复用的立方体和轮子代码,实现了前面urdf中的功能,同时还添加了碰撞和惯性等物理属性,为后续仿真提供了物理基础。显而易见的是,这部分用更少的代码,实现了比之前URDF更多的功能。
第三部分通过调用上一步创建的宏,完成了机器人的实例化。最后一部分,则为激光雷达留出了安装位置。
修改Launch文件
xacro文件不能直接被robot_state_publisher读取,需要先转换为URDF字符串才能被调用,这一步可在Launch文件中,用xacro命令来实现。
下面修改Launch文件,修改后内容如下
python
import os
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import Command
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
pkg_share = get_package_share_directory('robot_description')
# 指向新的 xacro 文件
xacro_file = os.path.join(pkg_share, 'urdf', 'robot.xacro')
# 【核心】:使用 Command 执行 xacro 命令,将 xacro 转换为 urdf 字符串
robot_desc = Command(['xacro ', xacro_file])
return LaunchDescription([
Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': robot_desc}],
output='screen'
),
Node(
package='joint_state_publisher_gui',
executable='joint_state_publisher_gui',
output='screen'
),
Node(
package='rviz2',
executable='rviz2',
output='screen'
),
])
修改setup.py文件,添加对xacro文件的匹配
python
data_files=[
('share/' + package_name, ['package.xml']),
# 【修改这里】:同时匹配 .urdf 和 .xacro 文件
(os.path.join('share', package_name, 'urdf'),
glob(os.path.join('urdf', '*.urdf')) + glob(os.path.join('urdf', '*.xacro'))),
(os.path.join('share', package_name, 'launch'),
glob(os.path.join('launch', '*launch.[pxy][yma]*'))),
],
编译并运行
python
colcon build
source install/setup.bash
# 启动
ros2 launch robot_description display_robot_launch.py
弹出Rviz2窗口后,将左侧面板Global Options下的Fixed Frame修改为base_link。
然后在点击下方的 Add(添加)按钮,在弹出的窗口中,在By display type选项卡中,选中RobotModel,点击 OK。
此时左侧Displays列表中会多出这个RobotModel,点击展开,确保Visual Enabled选项被勾选,然后将Discription Topic的值设为/robot_description,这时窗口中就会出现我们创建的哪个小车了。
