ROS2 Xacro机器人建模初步教程

文章目录

环境准备

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,这时窗口中就会出现我们创建的哪个小车了。

相关推荐
ms365copilot1 小时前
Excel Copilot分析机器人客户反馈,生成改进方案
机器人·copilot
tianxuanjg3 小时前
工业/协作机器人连接法兰采购指南|高精度安装定位零件怎么选
经验分享·机器人·无人机·制造·材质
QYR-分析5 小时前
机器人扭矩传感器行业深度研究:技术迭代、市场格局与增量前景
机器人
沫儿笙5 小时前
弧机器人混合气节气设备
机器人
YH行业报告分析7 小时前
2026具身智能产业爆发:具身智能训练平台如何破解机器人策略迭代效率痛点?
机器人
天空属于哈夫克37 小时前
企业微信API:企业微信机器人如何开发?
python·机器人·企业微信
微小冷8 小时前
ROS2 URDF机器人建模初步教程
机器人·ros2·urdf·机器人建模
码农5999 小时前
Fast DDS 到底怎么用?一文理清发现、传输与 QoS 配置
机器人
Rocktech_ruixun9 小时前
机器人视觉SLAM对主控硬件有哪些要求?瑞迅科技RK3588/3576/3568分级方案解析
人工智能·嵌入式硬件·机器人