您好,
会员登录 快速注册
退出 ( 条未读消息)
关于本站 意见反馈 首页

公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!
全部文章分类
  • 人工智能 >

  • 编程语言 >

  • WPF系列 >

  • ASP.NET系列 >

  • Linux >

  • 数据库 >

  • 嵌入式 >

  • WEB技术 >

  • PLC系列 >

  • 微服务与框架 >

  • 小宅DIY >

  • 学习资料 >

OpenCv基础 ANN车牌识别 yolov5车牌识别 指针式仪表识别 ROS系列 YOLO Halcon Detectron2 昇腾AI ChatGPT在线体验 英伟达JETSON ChatGLM ChatTTS FunASR 地平线 ByteTrack 魔搭社区 LangChain
C C# C++ Python Java Go
WPF
ASP.NET小功能 GPS定位系统-MVC GPS定位系统-VUE ASP.NET WebRTC
Linux Linux内核 Shell MakeFile
MySql SqlServer Oracle
STM8 STM32 51单片机
VUE入门 HTML JavaScript CSS layui镜像网站 ElementUi中文官网 element-plus 图标
三菱 欧姆龙 西门子 施耐德 松下 台达
IOTSharp IOTGateway ABP FRAMEWORK Docker
亚克力音响 编程仙途:智驭万法
面试题与技巧 Python入门技能树 微软C#教程
首页 编程之美 工具下载 全国就业 流量地图 文心一言
ROS系列
ROS - 介绍 ROS1-常规安装方法 ROS1-Linux下的ROS环境搭建 ROS1-ROS话题:发布者 ROS1-发布者与订阅者通讯 ROS1-服务器与客户端节点通讯 ROS1-动作服务器与客户端通讯 ROS1-发布imu和gps消息 ROS2-新建Ubuntu环境 ROS2-创建一个简单节点 ROS2-Python之消息的发布与订阅 ROS2-C++之消息的发布与订阅 ROS2-调用USB免驱摄像头 ROS2-地瓜机器人笔记 ROS2 控制小车进行矩形运动 ROS2 设置节点开机自启 ROS2 添加自定义msg ROS2 URDF建模 ROS2 Gazebo 仿真环境搭建 ROS2 XACRO建模 ROS2 在Gazebo加载机器人模型 ROS2 Carttographer安装 ROS2 配置cartographer进行建图 ROS2 Nav2导航仿真-新建工程 ROS2 Nav2导航仿真 ROS2 Nav2 API导航
ROS2 添加自定义msg
ROS2 Gazebo 仿真环境搭建
激萌の小宅 小宅博客 ROS系列

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

ROS2 URDF建模

参考博客:https://blog.csdn.net/qq_51482778/article/details/137111113


新建工程drdf

进入src文件中,建立一个新的功能包:robot_car

ros2 pkg create robot_car --build-type ament_python


建立并编写URDF文件

cd robot_car && mkdir urdf
cd urdf

touch fishbot_base.urdf


完成后的robot_car文件结构如下:

robot_car
├── package.xml
├── resource
│   └── robot_car
├── robot_car
│   └── __init__.py
├── setup.cfg
├── setup.py
├── test
│   ├── test_copyright.py
│   ├── test_flake8.py
│   └── test_pep257.py
└── urdf
    └── fishbot_base.urdf


编辑fishbot_base.urdf

添加下面代码

<?xml version="1.0"?>
<robot name="fishbot">
    
  <!-- base link -->
  <link name="base_link">
      <visual>
      <origin xyz="0 0 0.0" rpy="0 0 0"/>
      <geometry>
        <cylinder length="0.12" radius="0.10"/>
      </geometry>
    </visual>
  </link>
    
  <!-- laser link -->
  <link name="laser_link">
      <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder length="0.02" radius="0.02"/>
      </geometry>
      <material name="black">
          <color rgba="0.0 0.0 0.0 0.8" /> 
      </material>
    </visual>
  </link>
    
  <!-- laser joint -->
    <joint name="laser_joint" type="fixed">
        <parent link="base_link" />
        <child link="laser_link" />
        <origin xyz="0 0 0.075" />
    </joint>
</robot>


建立并编写launch文件

在目录src/robot_car下创建launch文件夹并在其下新建display_rviz2.launch.py文件

mkdir launch
touch display_rviz2.launch.py


完成后的robot_car文件结构如下:

robot_car
├── launch
│   └── display_rviz2.launch.py
├── package.xml
├── resource
│   └── robot_car
├── robot_car
│   └── __init__.py
├── setup.cfg
├── setup.py
├── test
│   ├── test_copyright.py
│   ├── test_flake8.py
│   └── test_pep257.py
└── urdf
    └── fishbot_base.urdf


编辑launch文件

import os
from launch import LaunchDescription
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare


def generate_launch_description():
    package_name = 'robot_car'
    urdf_name = "fishbot_base.urdf"

    ld = LaunchDescription()
    pkg_share = FindPackageShare(package=package_name).find(package_name) 
    urdf_model_path = os.path.join(pkg_share, f'urdf/{urdf_name}')

    robot_state_publisher_node = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        arguments=[urdf_model_path]
        )

    joint_state_publisher_node = Node(
        package='joint_state_publisher_gui',
        executable='joint_state_publisher_gui',
        name='joint_state_publisher_gui',
        arguments=[urdf_model_path]
        )

    rviz2_node = Node(
        package='rviz2',
        executable='rviz2',
        name='rviz2',
        output='screen',
        )

    ld.add_action(robot_state_publisher_node)
    ld.add_action(joint_state_publisher_node)
    ld.add_action(rviz2_node)

    return ld


1、generate_launch_description() 函数是入口点,用于生成 LaunchDescription 对象,描述了启动的节点及其参数。

2、FindPackageShare 类用于查找指定包的共享目录,以便获取该包中的资源文件。在这里,它用于获取机器人描述包(fishbot_description)的共享目录路径。

3、LaunchDescription 对象用于存储要启动的节点及其参数。


其中涉及三个节点

1、joint_state_publisher_gui 负责发布机器人关节数据信息,通过joint_states话题发布
2、robot_state_publisher_node负责发布机器人模型信息robot_description,并将joint_states数据转换tf信息发布
3、rviz2_node负责显示机器人的信息


attention

这里我们用到了joint_state_publisher_gui和robot_state_publisher两个包,如果你的系统没有安装这两个包,可以手动安装:

sudo apt install ros-$ROS_DISTRO-joint-state-publisher-gui ros-$ROS_DISTRO-robot-state-publisher

或者

apt install ros-humble-joint-state-publisher-gui
apt install ros-humble-robot-state-publisher


joint_state_publisher_gui,还有一个兄弟叫做joint_state_publisher

两者区别在于joint_state_publisher_gui运行起来会跳出一个界面,通过界面可以操作URDF中能动的关节


修改setup.py

导入头文件

from glob import glob
import os


更改data_file列表:
data_files 列表包含了要安装到系统中的其他文件和目录,以及它们的安装路径。在这里需要包含了 resource_index/packages、package.xml、launch 目录下的所有 .launch.py 文件、urdf 目录下的所有文件等。

from setuptools import setup
from glob import glob
import os

package_name = 'robot_car'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
        (os.path.join('share', package_name, 'urdf'), glob('urdf/**')),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='grb',
    maintainer_email='grb@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)


编译测试

回到工作空间,编译

colcon build
或者
colcon build --packages-select robot_car


截图 2025-05-28 11-44-25.jpg


运行测试

source install/setup.bash
ros2 launch robot_car display_rviz2.launch.py


运行起来之后,需要做一些配置

1、设置Global Options -> Fixed Frame -> base_link

2、设置Grid->Reference Frame-> base_link

3、添加RobotModel模块->Description Topic -> /robot_description

4、可以通过添加tf查看link之间的坐标关系

截图 2025-05-28 13-39-01.png


然后放大中间的那一个小红点,可以看到URDF所描述的机器人了

截图 2025-05-28 13-39-39.jpg


博主自己整理的差速轮小车:带两个主动轮、一个万向轮、一个激光雷达、一个IMU,文件名:robot_car.urdf

<?xml version="1.0" ?>
<robot name="robot_car">
    <!-- Robot Footprint -->
    <!-- 虚拟根坐标系 base_footprint -->
    <link name="base_footprint"/>  
    <!-- 固定连接 base_joint-->
    <joint name="base_joint" type="fixed">
        <parent link="base_footprint"/>
        <!-- 机器人实际基座 base_link-->
        <child link="base_link"/>
        <origin xyz="0.0 0.0 0.076" rpy="0 0 0"/>
    </joint>

    <!-- 机器人基座(base_link) -->
    <link name="base_link">
        <visual>
            <!-- 原点位于基座坐标系后方 x = -0.18, y = 187 处(xyz参数) -->
            <origin xyz="-0.18 0 0.187" rpy="0 0 0" />
            <geometry>
                <!-- 长方体(长0.565m × 宽0.44m × 高0.222m) -->
                <box size="0.565 0.44 0.222"/>
            </geometry>
            <material name="white">
                <!-- 纯白色(RGBA: 1,1,1,1) -->
                <color rgba="1 1 1 0.8"/>
            </material>
        </visual>
        <!-- 碰撞属性:collision -->
        <collision>
            <!-- origin,表示碰撞体的中心位姿 -->
            <origin xyz="-0.18 0 0.187" rpy="0 0 0"/>
            <!-- geometry,用于表示用于碰撞检测的几何形状 -->
            <geometry>
                <box size="0.565 0.44 0.222"/>
            </geometry>
            <!-- material,可选的,描述碰撞几何体的材料(这个设置可以在gazebo仿真时通过view选项看到碰撞包围体的形状) -->
            <material name="blue">
                <color rgba="1 1 1 0.8" /> 
            </material>
        </collision>
        <!-- 惯性属性:Inertial -->
        <inertial>
            <!-- 质量:22.54千克 -->
            <mass value="22.54"/>
            <!-- 惯性矩阵:ixx = iyy = 0.0122666 kg·m²(绕X/Y轴的转动惯量) -->
            <!-- 惯性矩阵:izz = 0.02 kg·m²(绕Z轴的转动惯量) -->
            <inertia ixx="0.0122666" ixy="0" ixz="0" iyy="0.0122666" iyz="0" izz="0.02"/>
        </inertial>
    </link>   

    <!-- 左轮结构 left_wheel_joint + left_wheel_link -->
    <link name="left_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <!-- 轮子参数:圆柱体(半径0.076m/(152mm/2),厚度0.046m) -->
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <!-- 颜色:纯黑色 -->
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
        <!-- 碰撞属性:collision -->
        <collision>
            <!-- origin,表示碰撞体的中心位姿 -->
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <!-- geometry,用于表示用于碰撞检测的几何形状 -->
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1" /> 
            </material>
        </collision>
        <inertial>
            <!-- 质量:0.2千克 -->
            <mass value="0.2"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <!-- 关节类型:连续旋转关节 continuous -->
    <joint name="left_wheel_joint" type="continuous">
        <parent link="base_link"/>
        <child link="left_wheel_link"/>
        <!-- 安装位置:基座坐标系右侧(Y轴+0.2495m方向) -->
        <origin xyz="0 0.248 0.076" rpy="-1.57 0 0"/>
        <!-- 旋转轴:Y轴(axis xyz="0 1 0") -->
        <axis xyz="0 0 1"/>
    </joint>

    <!-- 右轮结构(right_wheel_joint + right_wheel_link) -->
    <link name="right_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
        <!-- 碰撞属性:collision -->
        <collision>
            <!-- origin,表示碰撞体的中心位姿 -->
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <!-- geometry,用于表示用于碰撞检测的几何形状 -->
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1" /> 
            </material>
        </collision>
        <inertial>
            <!-- 质量:0.2千克 -->
            <mass value="0.2"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <joint name="right_wheel_joint" type="continuous">
        <parent link="base_link"/>
        <child link="right_wheel_link"/>
        <!-- 结构与左轮对称,安装位置在Y轴-0.2495m方向 -->
        <origin xyz="0 -0.248 0.076" rpy="-1.57 0 0"/>
        <axis xyz="0 0 1"/>
    </joint>

    <!-- 前轮结构(front_wheel_joint + front_wheel_link) -->
    <link name="front_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
        <collision>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1"/>
            </material>
        </collision>
        <inertial>
            <mass value="0.02"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <joint name="front_wheel_joint" type="continuous">
        <parent link="base_link"/>
        <child link="front_wheel_link"/>
        <!-- 安装位置:基座坐标系前方(X轴+0.23m方向) -->
        <origin xyz="-0.3 0 0.076" rpy="-1.57 0 0"/>
        <axis xyz="0 0 1"/>
    </joint>

    <!-- 激光雷达传感器(laser_link) -->
    <link name="laser_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <!-- 高度:0.02米(2厘米)半径:0.02米(2厘米) -->
                <cylinder length="0.02" radius="0.02"/>
            </geometry>
            <material name="black">
                <!-- 黑色,透明度:0.5(半透明效果) -->
                <color rgba="0.0 0.0 0.0 0.5" /> 
            </material>
        </visual>
        <collision>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <cylinder length="0.02" radius="0.02"/>
            </geometry>
            <material name="black">
                <color rgba="0.0 0.0 0.0 0.5" /> 
            </material>
        </collision>
        <inertial>
        <mass value="0.1"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <!-- 关节类型:fixed(固定连接) -->
    <joint name="laser_joint" type="fixed">
        <parent link="base_link" />
        <child link="laser_link" />
        <!-- 将激光雷达安装在基座上方*米处 0.308 = 0.222+0.076+0.01 -->
        <origin xyz="0.076 0 0.308" />
    </joint>

    <!-- 惯导 IMU -->
    <link name="imu_link">
        <visual>
            <origin xyz="0 0 0.0" rpy="0 0 0"/>
            <geometry>
                <box size="0.02 0.02 0.02"/>
            </geometry>
        </visual>
        <collision>
            <origin xyz="0 0 0.0" rpy="0 0 0"/>
            <geometry>
                <box size="0.02 0.02 0.02"/>
            </geometry>
        </collision>
        <inertial>
            <mass value="0.1"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <joint name="imu_joint" type="fixed">
        <parent link="base_link" />
        <child link="imu_link" />
        <origin xyz="0 0 0.187" />
    </joint>

    <!-- gazebo 前轮 -->
    <gazebo reference="front_wheel_link">
        <!-- 材质定义 Gazebo/Black:Gazebo内置的预定义材质,使部件在仿真中显示为黑色。 -->
        <material>Gazebo/Black</material>
    </gazebo>
    <!-- 物理属性 -->
    <gazebo reference="front_wheel_link">
        <!--沿接触面法线方向(通常为垂直方向)的摩擦系数 -->
        <mu1 value="0.0"/>
        <!-- 沿接触面切线方向(水平方向)的摩擦系数。 -->
        <mu2 value="0.0"/>
        <!-- 接触刚度(Stiffness),值越大,碰撞时形变越小,物体越“硬” -->
        <kp value="1000000.0" />
        <!-- 阻尼系数(Damping),值越大,碰撞能量耗散越快,模拟“弹性”效果 -->
        <kd value="10.0" />
        <!-- 若取消注释,fdir1会定义摩擦力的主方向(此处为Z轴方向),通常用于各向异性摩擦(如轮胎的纵向/横向摩擦差异) -->
        <!-- <fdir1 value="0 0 1"/> -->
    </gazebo>

    <!-- ROS参数定义 -->
    <gazebo>
        <!-- 差速驱动插件 (diff_drive) -->
        <!-- 实现两轮差速驱动机器人的运动学仿真,将ROS的cmd_vel指令转换为车轮运动,并发布里程计(odometry)数据 -->
        <plugin name='diff_drive' filename='libgazebo_ros_diff_drive.so'>
            <!-- ROS集成 -->
            <ros>
                <!-- ROS命名空间(此处为根命名空间) -->
                <namespace>/</namespace>
                <!-- remapping  将插件的默认话题重映射为ROS标准话题: -->
                <!-- 接收速度指令的话题。 -->
                <remapping>cmd_vel:=cmd_vel</remapping>
                <!-- 发布里程计数据的话题 -->
                <remapping>odom:=odom</remapping>
            </ros>
            <update_rate>30</update_rate>

            <!-- wheels -->
            <!-- <left_joint>left_wheel_joint</left_joint> -->
            <!-- <right_joint>right_wheel_joint</right_joint> -->
            <left_joint>left_wheel_joint</left_joint>
            <right_joint>right_wheel_joint</right_joint>

            <!-- 运动学参数 kinematics -->
            <!-- 两轮间距(单位:米),影响转弯半径计算 -->
            <wheel_separation>0.2</wheel_separation>
            <!-- 车轮直径(单位:米),用于计算线速度。 -->
            <wheel_diameter>0.065</wheel_diameter>

            <!-- 物理限制 limits -->
            <!-- 车轮最大扭矩(N·m),限制电机输出。 -->
            <max_wheel_torque>20</max_wheel_torque>
            <!-- 车轮最大加速度(rad/s²),控制加速平滑性。 -->
            <max_wheel_acceleration>1.0</max_wheel_acceleration>

            <!-- 输出配置 output -->
            <!-- 发布里程计数据(/odom话题) -->
            <publish_odom>true</publish_odom>
            <!-- 发布里程计的TF变换(odom → base_footprint) -->
            <publish_odom_tf>true</publish_odom_tf>
            <!-- 不发布车轮单独的TF -->
            <publish_wheel_tf>false</publish_wheel_tf>
            <!-- 里程计参考坐标系 -->
            <odometry_frame>odom</odometry_frame>
            <!-- 机器人基座坐标系 -->
            <robot_base_frame>base_footprint</robot_base_frame>
        </plugin>

        <!-- 关节状态发布插件 fishbot_joint_state -->
        <plugin name="fishbot_joint_state" filename="libgazebo_ros_joint_state_publisher.so">
            <ros>
                <!-- 将插件默认输出重映射为ROS标准话题/joint_states -->
                <remapping>~/out:=joint_states</remapping>
            </ros>
            <!-- 以30Hz频率发布关节状态 -->
            <update_rate>30</update_rate>
            <!-- 指定需要监控的关节名称(此处为左右车轮关节) -->
            <joint_name>right_wheel_joint</joint_name>
            <joint_name>left_wheel_joint</joint_name>
        </plugin>    
    </gazebo> 

    <!-- IMU 传感器基础配置 -->
    <gazebo reference="imu_link">
        <sensor name="imu_sensor" type="imu">
            <plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
                <ros>
                    <namespace>/</namespace>
                    <!-- 将插件默认输出话题重映射为/imu -->
                    <remapping>~/out:=imu</remapping>
                </ros>
                <!-- 禁用初始方向作为参考,直接输出世界坐标系下的数据。 -->
                <initial_orientation_as_reference>false</initial_orientation_as_reference>
            </plugin>
            <!-- 传感器持续运行,无需外部触发 -->
            <always_on>true</always_on>
            <!-- 以100Hz频率更新数据(高频率适合动态仿真) -->
            <update_rate>100</update_rate>
            <!-- 在Gazebo界面中显示传感器可视化模型(如坐标轴)。 -->
            <visualize>true</visualize>
            <imu>
                <!-- 角速度(陀螺仪)噪声 -->
                <angular_velocity>
                    <x>
                        <noise type="gaussian">
                            <!-- 模拟随机噪声(均值0,标准差2e-4 rad/s) -->
                            <mean>0.0</mean>
                            <stddev>2e-4</stddev>
                            <!-- 模拟传感器零偏(均值7.5e-6 rad/s,标准差8e-7 rad/s),反映真实硬件的长期漂移 -->
                            <bias_mean>0.0000075</bias_mean>
                            <bias_stddev>0.0000008</bias_stddev>
                        </noise>
                    </x>
                    <y>
                        <noise type="gaussian">
                        <mean>0.0</mean>
                        <stddev>2e-4</stddev>
                        <bias_mean>0.0000075</bias_mean>
                        <bias_stddev>0.0000008</bias_stddev>
                        </noise>
                    </y>
                    <z>
                        <noise type="gaussian">
                            <mean>0.0</mean>
                            <stddev>2e-4</stddev>
                            <bias_mean>0.0000075</bias_mean>
                            <bias_stddev>0.0000008</bias_stddev>
                        </noise>
                    </z>
                </angular_velocity>
                <!-- 线加速度(加速度计)噪声 -->
                <linear_acceleration>
                    <x>
                        <noise type="gaussian">
                            <!-- 模拟随机噪声(均值0,标准差1.7e-2 m/s²) -->
                            <mean>0.0</mean>
                            <stddev>1.7e-2</stddev>
                            <!-- 模拟加速度计零偏(均值0.1 m/s²,标准差0.001 m/s²),反映真实硬件的静态误差。 -->
                            <bias_mean>0.1</bias_mean>
                            <bias_stddev>0.001</bias_stddev>
                        </noise>
                    </x>
                    <y>
                        <noise type="gaussian">
                            <mean>0.0</mean>
                            <stddev>1.7e-2</stddev>
                            <bias_mean>0.1</bias_mean>
                            <bias_stddev>0.001</bias_stddev>
                        </noise>
                    </y>
                    <z>
                        <noise type="gaussian">
                            <mean>0.0</mean>
                            <stddev>1.7e-2</stddev>
                            <bias_mean>0.1</bias_mean>
                            <bias_stddev>0.001</bias_stddev>
                        </noise>
                    </z>
                </linear_acceleration>
            </imu>
        </sensor>
    </gazebo>

    <!-- 激光雷达材质(laser_link) -->
    <gazebo reference="laser_link">
        <material>Gazebo/Black</material>
    </gazebo>
    <!-- 激光雷达基础配置 -->
    <gazebo reference="laser_link">
        <sensor name="laser_sensor" type="ray">
            <!-- 传感器持续运行,无需外部触发。 -->
            <always_on>true</always_on>
            <!-- 在Gazebo界面中显示激光束的可视化效果(如扇形扫描区域)。 -->
            <visualize>true</visualize>
            <!-- 以5Hz频率更新数据(适用于低速场景或计算资源受限环境)。 -->
            <update_rate>5</update_rate>
            <!-- 传感器相对于laser_link的位姿(x=0, y=0, z=0.145,无旋转),表示传感器安装在链接上方0.145米处。 -->
            <pose>0 0 0.145 0 0 0</pose>
            <ray>
                <!-- 水平扫描(Horizontal Scan) -->
                <scan>
                    <horizontal>
                        <!-- 单次扫描的射线数量(360条射线)。 -->
                        <samples>360</samples>
                        <!-- 每条射线之间的角度间隔(1度) -->
                        <resolution>1.000000</resolution>
                        <!-- 扫描角度范围(0到6.28弧度,即0°到360°),实现全向扫描。 -->
                        <min_angle>0.000000</min_angle>
                        <max_angle>6.280000</max_angle>
                    </horizontal>
                </scan>
                <range>
                    <!-- 最小测量距离(0.12米),小于此距离的障碍物无法被检测。 -->
                    <min>0.120000</min>
                    <!-- 最大测量距离(3.5米),超出此距离的障碍物无法被检测。 -->
                    <max>3.5</max>
                    <!-- 距离测量精度(0.015米),影响数据离散化程度。 -->
                    <resolution>0.015000</resolution>
                </range>
                <!-- 模拟随机噪声(均值0,标准差0.01米),反映真实激光雷达的测量误差 -->
                <noise>
                    <type>gaussian</type>
                    <mean>0.0</mean>
                    <stddev>0.01</stddev>
                </noise>
            </ray>

            <plugin name="laserscan" filename="libgazebo_ros_ray_sensor.so">
                <ros>
                    <!-- <namespace>/tb3</namespace> -->
                    <!-- 将插件默认输出话题重映射为/scan -->
                    <remapping>~/out:=scan</remapping>
                </ros>
                <!-- 数据格式为sensor_msgs/LaserScan(ROS标准激光雷达消息类型) -->
                <output_type>sensor_msgs/LaserScan</output_type>
                <!-- 数据坐标系为laser_link,确保与TF树一致 -->
                <frame_name>laser_link</frame_name>
            </plugin>
        </sensor>
    </gazebo>

</robot>


效果如下:

截图 2025-05-30 23-09-22.png


ROS2 添加自定义msg
ROS2 Gazebo 仿真环境搭建

友情链接: CSDN激萌の小宅 95知识库 自考题库 罗分明个人网络博客 精益编程leanboot

小宅博客  www.bilibili996.com All Rights Reserved. 备案号: 闽ICP备2024034575号

网站经营许可证  福建省福州市 Copyright©2021-2025 版权所有

小宅博客
首页 智能家居 地图定位
公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

ROS2 URDF建模

参考博客:https://blog.csdn.net/qq_51482778/article/details/137111113


新建工程drdf

进入src文件中,建立一个新的功能包:robot_car

ros2 pkg create robot_car --build-type ament_python


建立并编写URDF文件

cd robot_car && mkdir urdf
cd urdf

touch fishbot_base.urdf


完成后的robot_car文件结构如下:

robot_car
├── package.xml
├── resource
│   └── robot_car
├── robot_car
│   └── __init__.py
├── setup.cfg
├── setup.py
├── test
│   ├── test_copyright.py
│   ├── test_flake8.py
│   └── test_pep257.py
└── urdf
    └── fishbot_base.urdf


编辑fishbot_base.urdf

添加下面代码

<?xml version="1.0"?>
<robot name="fishbot">
    
  <!-- base link -->
  <link name="base_link">
      <visual>
      <origin xyz="0 0 0.0" rpy="0 0 0"/>
      <geometry>
        <cylinder length="0.12" radius="0.10"/>
      </geometry>
    </visual>
  </link>
    
  <!-- laser link -->
  <link name="laser_link">
      <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder length="0.02" radius="0.02"/>
      </geometry>
      <material name="black">
          <color rgba="0.0 0.0 0.0 0.8" /> 
      </material>
    </visual>
  </link>
    
  <!-- laser joint -->
    <joint name="laser_joint" type="fixed">
        <parent link="base_link" />
        <child link="laser_link" />
        <origin xyz="0 0 0.075" />
    </joint>
</robot>


建立并编写launch文件

在目录src/robot_car下创建launch文件夹并在其下新建display_rviz2.launch.py文件

mkdir launch
touch display_rviz2.launch.py


完成后的robot_car文件结构如下:

robot_car
├── launch
│   └── display_rviz2.launch.py
├── package.xml
├── resource
│   └── robot_car
├── robot_car
│   └── __init__.py
├── setup.cfg
├── setup.py
├── test
│   ├── test_copyright.py
│   ├── test_flake8.py
│   └── test_pep257.py
└── urdf
    └── fishbot_base.urdf


编辑launch文件

import os
from launch import LaunchDescription
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare


def generate_launch_description():
    package_name = 'robot_car'
    urdf_name = "fishbot_base.urdf"

    ld = LaunchDescription()
    pkg_share = FindPackageShare(package=package_name).find(package_name) 
    urdf_model_path = os.path.join(pkg_share, f'urdf/{urdf_name}')

    robot_state_publisher_node = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        arguments=[urdf_model_path]
        )

    joint_state_publisher_node = Node(
        package='joint_state_publisher_gui',
        executable='joint_state_publisher_gui',
        name='joint_state_publisher_gui',
        arguments=[urdf_model_path]
        )

    rviz2_node = Node(
        package='rviz2',
        executable='rviz2',
        name='rviz2',
        output='screen',
        )

    ld.add_action(robot_state_publisher_node)
    ld.add_action(joint_state_publisher_node)
    ld.add_action(rviz2_node)

    return ld


1、generate_launch_description() 函数是入口点,用于生成 LaunchDescription 对象,描述了启动的节点及其参数。

2、FindPackageShare 类用于查找指定包的共享目录,以便获取该包中的资源文件。在这里,它用于获取机器人描述包(fishbot_description)的共享目录路径。

3、LaunchDescription 对象用于存储要启动的节点及其参数。


其中涉及三个节点

1、joint_state_publisher_gui 负责发布机器人关节数据信息,通过joint_states话题发布
2、robot_state_publisher_node负责发布机器人模型信息robot_description,并将joint_states数据转换tf信息发布
3、rviz2_node负责显示机器人的信息


attention

这里我们用到了joint_state_publisher_gui和robot_state_publisher两个包,如果你的系统没有安装这两个包,可以手动安装:

sudo apt install ros-$ROS_DISTRO-joint-state-publisher-gui ros-$ROS_DISTRO-robot-state-publisher

或者

apt install ros-humble-joint-state-publisher-gui
apt install ros-humble-robot-state-publisher


joint_state_publisher_gui,还有一个兄弟叫做joint_state_publisher

两者区别在于joint_state_publisher_gui运行起来会跳出一个界面,通过界面可以操作URDF中能动的关节


修改setup.py

导入头文件

from glob import glob
import os


更改data_file列表:
data_files 列表包含了要安装到系统中的其他文件和目录,以及它们的安装路径。在这里需要包含了 resource_index/packages、package.xml、launch 目录下的所有 .launch.py 文件、urdf 目录下的所有文件等。

from setuptools import setup
from glob import glob
import os

package_name = 'robot_car'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
        (os.path.join('share', package_name, 'urdf'), glob('urdf/**')),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='grb',
    maintainer_email='grb@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)


编译测试

回到工作空间,编译

colcon build
或者
colcon build --packages-select robot_car


截图 2025-05-28 11-44-25.jpg


运行测试

source install/setup.bash
ros2 launch robot_car display_rviz2.launch.py


运行起来之后,需要做一些配置

1、设置Global Options -> Fixed Frame -> base_link

2、设置Grid->Reference Frame-> base_link

3、添加RobotModel模块->Description Topic -> /robot_description

4、可以通过添加tf查看link之间的坐标关系

截图 2025-05-28 13-39-01.png


然后放大中间的那一个小红点,可以看到URDF所描述的机器人了

截图 2025-05-28 13-39-39.jpg


博主自己整理的差速轮小车:带两个主动轮、一个万向轮、一个激光雷达、一个IMU,文件名:robot_car.urdf

<?xml version="1.0" ?>
<robot name="robot_car">
    <!-- Robot Footprint -->
    <!-- 虚拟根坐标系 base_footprint -->
    <link name="base_footprint"/>  
    <!-- 固定连接 base_joint-->
    <joint name="base_joint" type="fixed">
        <parent link="base_footprint"/>
        <!-- 机器人实际基座 base_link-->
        <child link="base_link"/>
        <origin xyz="0.0 0.0 0.076" rpy="0 0 0"/>
    </joint>

    <!-- 机器人基座(base_link) -->
    <link name="base_link">
        <visual>
            <!-- 原点位于基座坐标系后方 x = -0.18, y = 187 处(xyz参数) -->
            <origin xyz="-0.18 0 0.187" rpy="0 0 0" />
            <geometry>
                <!-- 长方体(长0.565m × 宽0.44m × 高0.222m) -->
                <box size="0.565 0.44 0.222"/>
            </geometry>
            <material name="white">
                <!-- 纯白色(RGBA: 1,1,1,1) -->
                <color rgba="1 1 1 0.8"/>
            </material>
        </visual>
        <!-- 碰撞属性:collision -->
        <collision>
            <!-- origin,表示碰撞体的中心位姿 -->
            <origin xyz="-0.18 0 0.187" rpy="0 0 0"/>
            <!-- geometry,用于表示用于碰撞检测的几何形状 -->
            <geometry>
                <box size="0.565 0.44 0.222"/>
            </geometry>
            <!-- material,可选的,描述碰撞几何体的材料(这个设置可以在gazebo仿真时通过view选项看到碰撞包围体的形状) -->
            <material name="blue">
                <color rgba="1 1 1 0.8" /> 
            </material>
        </collision>
        <!-- 惯性属性:Inertial -->
        <inertial>
            <!-- 质量:22.54千克 -->
            <mass value="22.54"/>
            <!-- 惯性矩阵:ixx = iyy = 0.0122666 kg·m²(绕X/Y轴的转动惯量) -->
            <!-- 惯性矩阵:izz = 0.02 kg·m²(绕Z轴的转动惯量) -->
            <inertia ixx="0.0122666" ixy="0" ixz="0" iyy="0.0122666" iyz="0" izz="0.02"/>
        </inertial>
    </link>   

    <!-- 左轮结构 left_wheel_joint + left_wheel_link -->
    <link name="left_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <!-- 轮子参数:圆柱体(半径0.076m/(152mm/2),厚度0.046m) -->
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <!-- 颜色:纯黑色 -->
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
        <!-- 碰撞属性:collision -->
        <collision>
            <!-- origin,表示碰撞体的中心位姿 -->
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <!-- geometry,用于表示用于碰撞检测的几何形状 -->
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1" /> 
            </material>
        </collision>
        <inertial>
            <!-- 质量:0.2千克 -->
            <mass value="0.2"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <!-- 关节类型:连续旋转关节 continuous -->
    <joint name="left_wheel_joint" type="continuous">
        <parent link="base_link"/>
        <child link="left_wheel_link"/>
        <!-- 安装位置:基座坐标系右侧(Y轴+0.2495m方向) -->
        <origin xyz="0 0.248 0.076" rpy="-1.57 0 0"/>
        <!-- 旋转轴:Y轴(axis xyz="0 1 0") -->
        <axis xyz="0 0 1"/>
    </joint>

    <!-- 右轮结构(right_wheel_joint + right_wheel_link) -->
    <link name="right_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
        <!-- 碰撞属性:collision -->
        <collision>
            <!-- origin,表示碰撞体的中心位姿 -->
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <!-- geometry,用于表示用于碰撞检测的几何形状 -->
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1" /> 
            </material>
        </collision>
        <inertial>
            <!-- 质量:0.2千克 -->
            <mass value="0.2"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <joint name="right_wheel_joint" type="continuous">
        <parent link="base_link"/>
        <child link="right_wheel_link"/>
        <!-- 结构与左轮对称,安装位置在Y轴-0.2495m方向 -->
        <origin xyz="0 -0.248 0.076" rpy="-1.57 0 0"/>
        <axis xyz="0 0 1"/>
    </joint>

    <!-- 前轮结构(front_wheel_joint + front_wheel_link) -->
    <link name="front_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
        <collision>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <cylinder radius="0.076" length = "0.046"/>
            </geometry>
            <material name="black">
                <color rgba="0 0 0 1"/>
            </material>
        </collision>
        <inertial>
            <mass value="0.02"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <joint name="front_wheel_joint" type="continuous">
        <parent link="base_link"/>
        <child link="front_wheel_link"/>
        <!-- 安装位置:基座坐标系前方(X轴+0.23m方向) -->
        <origin xyz="-0.3 0 0.076" rpy="-1.57 0 0"/>
        <axis xyz="0 0 1"/>
    </joint>

    <!-- 激光雷达传感器(laser_link) -->
    <link name="laser_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <!-- 高度:0.02米(2厘米)半径:0.02米(2厘米) -->
                <cylinder length="0.02" radius="0.02"/>
            </geometry>
            <material name="black">
                <!-- 黑色,透明度:0.5(半透明效果) -->
                <color rgba="0.0 0.0 0.0 0.5" /> 
            </material>
        </visual>
        <collision>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <geometry>
                <cylinder length="0.02" radius="0.02"/>
            </geometry>
            <material name="black">
                <color rgba="0.0 0.0 0.0 0.5" /> 
            </material>
        </collision>
        <inertial>
        <mass value="0.1"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <!-- 关节类型:fixed(固定连接) -->
    <joint name="laser_joint" type="fixed">
        <parent link="base_link" />
        <child link="laser_link" />
        <!-- 将激光雷达安装在基座上方*米处 0.308 = 0.222+0.076+0.01 -->
        <origin xyz="0.076 0 0.308" />
    </joint>

    <!-- 惯导 IMU -->
    <link name="imu_link">
        <visual>
            <origin xyz="0 0 0.0" rpy="0 0 0"/>
            <geometry>
                <box size="0.02 0.02 0.02"/>
            </geometry>
        </visual>
        <collision>
            <origin xyz="0 0 0.0" rpy="0 0 0"/>
            <geometry>
                <box size="0.02 0.02 0.02"/>
            </geometry>
        </collision>
        <inertial>
            <mass value="0.1"/>
            <inertia ixx="0.000190416666667" ixy="0" ixz="0" iyy="0.0001904" iyz="0" izz="0.00036"/>
        </inertial>
    </link>
    <joint name="imu_joint" type="fixed">
        <parent link="base_link" />
        <child link="imu_link" />
        <origin xyz="0 0 0.187" />
    </joint>

    <!-- gazebo 前轮 -->
    <gazebo reference="front_wheel_link">
        <!-- 材质定义 Gazebo/Black:Gazebo内置的预定义材质,使部件在仿真中显示为黑色。 -->
        <material>Gazebo/Black</material>
    </gazebo>
    <!-- 物理属性 -->
    <gazebo reference="front_wheel_link">
        <!--沿接触面法线方向(通常为垂直方向)的摩擦系数 -->
        <mu1 value="0.0"/>
        <!-- 沿接触面切线方向(水平方向)的摩擦系数。 -->
        <mu2 value="0.0"/>
        <!-- 接触刚度(Stiffness),值越大,碰撞时形变越小,物体越“硬” -->
        <kp value="1000000.0" />
        <!-- 阻尼系数(Damping),值越大,碰撞能量耗散越快,模拟“弹性”效果 -->
        <kd value="10.0" />
        <!-- 若取消注释,fdir1会定义摩擦力的主方向(此处为Z轴方向),通常用于各向异性摩擦(如轮胎的纵向/横向摩擦差异) -->
        <!-- <fdir1 value="0 0 1"/> -->
    </gazebo>

    <!-- ROS参数定义 -->
    <gazebo>
        <!-- 差速驱动插件 (diff_drive) -->
        <!-- 实现两轮差速驱动机器人的运动学仿真,将ROS的cmd_vel指令转换为车轮运动,并发布里程计(odometry)数据 -->
        <plugin name='diff_drive' filename='libgazebo_ros_diff_drive.so'>
            <!-- ROS集成 -->
            <ros>
                <!-- ROS命名空间(此处为根命名空间) -->
                <namespace>/</namespace>
                <!-- remapping  将插件的默认话题重映射为ROS标准话题: -->
                <!-- 接收速度指令的话题。 -->
                <remapping>cmd_vel:=cmd_vel</remapping>
                <!-- 发布里程计数据的话题 -->
                <remapping>odom:=odom</remapping>
            </ros>
            <update_rate>30</update_rate>

            <!-- wheels -->
            <!-- <left_joint>left_wheel_joint</left_joint> -->
            <!-- <right_joint>right_wheel_joint</right_joint> -->
            <left_joint>left_wheel_joint</left_joint>
            <right_joint>right_wheel_joint</right_joint>

            <!-- 运动学参数 kinematics -->
            <!-- 两轮间距(单位:米),影响转弯半径计算 -->
            <wheel_separation>0.2</wheel_separation>
            <!-- 车轮直径(单位:米),用于计算线速度。 -->
            <wheel_diameter>0.065</wheel_diameter>

            <!-- 物理限制 limits -->
            <!-- 车轮最大扭矩(N·m),限制电机输出。 -->
            <max_wheel_torque>20</max_wheel_torque>
            <!-- 车轮最大加速度(rad/s²),控制加速平滑性。 -->
            <max_wheel_acceleration>1.0</max_wheel_acceleration>

            <!-- 输出配置 output -->
            <!-- 发布里程计数据(/odom话题) -->
            <publish_odom>true</publish_odom>
            <!-- 发布里程计的TF变换(odom → base_footprint) -->
            <publish_odom_tf>true</publish_odom_tf>
            <!-- 不发布车轮单独的TF -->
            <publish_wheel_tf>false</publish_wheel_tf>
            <!-- 里程计参考坐标系 -->
            <odometry_frame>odom</odometry_frame>
            <!-- 机器人基座坐标系 -->
            <robot_base_frame>base_footprint</robot_base_frame>
        </plugin>

        <!-- 关节状态发布插件 fishbot_joint_state -->
        <plugin name="fishbot_joint_state" filename="libgazebo_ros_joint_state_publisher.so">
            <ros>
                <!-- 将插件默认输出重映射为ROS标准话题/joint_states -->
                <remapping>~/out:=joint_states</remapping>
            </ros>
            <!-- 以30Hz频率发布关节状态 -->
            <update_rate>30</update_rate>
            <!-- 指定需要监控的关节名称(此处为左右车轮关节) -->
            <joint_name>right_wheel_joint</joint_name>
            <joint_name>left_wheel_joint</joint_name>
        </plugin>    
    </gazebo> 

    <!-- IMU 传感器基础配置 -->
    <gazebo reference="imu_link">
        <sensor name="imu_sensor" type="imu">
            <plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
                <ros>
                    <namespace>/</namespace>
                    <!-- 将插件默认输出话题重映射为/imu -->
                    <remapping>~/out:=imu</remapping>
                </ros>
                <!-- 禁用初始方向作为参考,直接输出世界坐标系下的数据。 -->
                <initial_orientation_as_reference>false</initial_orientation_as_reference>
            </plugin>
            <!-- 传感器持续运行,无需外部触发 -->
            <always_on>true</always_on>
            <!-- 以100Hz频率更新数据(高频率适合动态仿真) -->
            <update_rate>100</update_rate>
            <!-- 在Gazebo界面中显示传感器可视化模型(如坐标轴)。 -->
            <visualize>true</visualize>
            <imu>
                <!-- 角速度(陀螺仪)噪声 -->
                <angular_velocity>
                    <x>
                        <noise type="gaussian">
                            <!-- 模拟随机噪声(均值0,标准差2e-4 rad/s) -->
                            <mean>0.0</mean>
                            <stddev>2e-4</stddev>
                            <!-- 模拟传感器零偏(均值7.5e-6 rad/s,标准差8e-7 rad/s),反映真实硬件的长期漂移 -->
                            <bias_mean>0.0000075</bias_mean>
                            <bias_stddev>0.0000008</bias_stddev>
                        </noise>
                    </x>
                    <y>
                        <noise type="gaussian">
                        <mean>0.0</mean>
                        <stddev>2e-4</stddev>
                        <bias_mean>0.0000075</bias_mean>
                        <bias_stddev>0.0000008</bias_stddev>
                        </noise>
                    </y>
                    <z>
                        <noise type="gaussian">
                            <mean>0.0</mean>
                            <stddev>2e-4</stddev>
                            <bias_mean>0.0000075</bias_mean>
                            <bias_stddev>0.0000008</bias_stddev>
                        </noise>
                    </z>
                </angular_velocity>
                <!-- 线加速度(加速度计)噪声 -->
                <linear_acceleration>
                    <x>
                        <noise type="gaussian">
                            <!-- 模拟随机噪声(均值0,标准差1.7e-2 m/s²) -->
                            <mean>0.0</mean>
                            <stddev>1.7e-2</stddev>
                            <!-- 模拟加速度计零偏(均值0.1 m/s²,标准差0.001 m/s²),反映真实硬件的静态误差。 -->
                            <bias_mean>0.1</bias_mean>
                            <bias_stddev>0.001</bias_stddev>
                        </noise>
                    </x>
                    <y>
                        <noise type="gaussian">
                            <mean>0.0</mean>
                            <stddev>1.7e-2</stddev>
                            <bias_mean>0.1</bias_mean>
                            <bias_stddev>0.001</bias_stddev>
                        </noise>
                    </y>
                    <z>
                        <noise type="gaussian">
                            <mean>0.0</mean>
                            <stddev>1.7e-2</stddev>
                            <bias_mean>0.1</bias_mean>
                            <bias_stddev>0.001</bias_stddev>
                        </noise>
                    </z>
                </linear_acceleration>
            </imu>
        </sensor>
    </gazebo>

    <!-- 激光雷达材质(laser_link) -->
    <gazebo reference="laser_link">
        <material>Gazebo/Black</material>
    </gazebo>
    <!-- 激光雷达基础配置 -->
    <gazebo reference="laser_link">
        <sensor name="laser_sensor" type="ray">
            <!-- 传感器持续运行,无需外部触发。 -->
            <always_on>true</always_on>
            <!-- 在Gazebo界面中显示激光束的可视化效果(如扇形扫描区域)。 -->
            <visualize>true</visualize>
            <!-- 以5Hz频率更新数据(适用于低速场景或计算资源受限环境)。 -->
            <update_rate>5</update_rate>
            <!-- 传感器相对于laser_link的位姿(x=0, y=0, z=0.145,无旋转),表示传感器安装在链接上方0.145米处。 -->
            <pose>0 0 0.145 0 0 0</pose>
            <ray>
                <!-- 水平扫描(Horizontal Scan) -->
                <scan>
                    <horizontal>
                        <!-- 单次扫描的射线数量(360条射线)。 -->
                        <samples>360</samples>
                        <!-- 每条射线之间的角度间隔(1度) -->
                        <resolution>1.000000</resolution>
                        <!-- 扫描角度范围(0到6.28弧度,即0°到360°),实现全向扫描。 -->
                        <min_angle>0.000000</min_angle>
                        <max_angle>6.280000</max_angle>
                    </horizontal>
                </scan>
                <range>
                    <!-- 最小测量距离(0.12米),小于此距离的障碍物无法被检测。 -->
                    <min>0.120000</min>
                    <!-- 最大测量距离(3.5米),超出此距离的障碍物无法被检测。 -->
                    <max>3.5</max>
                    <!-- 距离测量精度(0.015米),影响数据离散化程度。 -->
                    <resolution>0.015000</resolution>
                </range>
                <!-- 模拟随机噪声(均值0,标准差0.01米),反映真实激光雷达的测量误差 -->
                <noise>
                    <type>gaussian</type>
                    <mean>0.0</mean>
                    <stddev>0.01</stddev>
                </noise>
            </ray>

            <plugin name="laserscan" filename="libgazebo_ros_ray_sensor.so">
                <ros>
                    <!-- <namespace>/tb3</namespace> -->
                    <!-- 将插件默认输出话题重映射为/scan -->
                    <remapping>~/out:=scan</remapping>
                </ros>
                <!-- 数据格式为sensor_msgs/LaserScan(ROS标准激光雷达消息类型) -->
                <output_type>sensor_msgs/LaserScan</output_type>
                <!-- 数据坐标系为laser_link,确保与TF树一致 -->
                <frame_name>laser_link</frame_name>
            </plugin>
        </sensor>
    </gazebo>

</robot>


效果如下:

截图 2025-05-30 23-09-22.png