简介:本资源是一个面向ROS2初学者与机器人仿真开发者的实践型工程包,聚焦多线激光雷达在Gazebo中的建模与仿真应用,解决SLAM、定位与环境感知等任务的前期验证难题。压缩包共30个文件(62KB),涵盖12个xacro宏定义文件(用于模块化构建fishbot机器人URDF模型)、4个Python节点脚本(实现传感器数据发布与基础控制)、2个YAML配置文件(管理参数与插件加载)、1个world场景文件及1个SDF模型文件,并包含launch启动脚本、RVIZ可视化配置、README说明与LICENSE协议等完整工程要素。已有46人学习下载,配套的说明文件.txt与附赠资源.docx详细列出了Ubuntu22.04+ROS2 Humble环境下的编译、启动与调试全流程,特别对xacro到URDF转换逻辑、Gazebo插件绑定机制及多线激光雷达参数映射做了关键注解,显著降低仿真环境搭建门槛。
1. 这不是“跑通一个Demo”,而是一套可复用的激光雷达仿真工程骨架
你搜“ROS2 Humble Gazebo 激光雷达”,刷出来的大多是零散命令、报错截图、半截配置文件——要么卡在gazebo_ros_pkgs编译失败,要么/scan话题永远空,再或者fishbot_description一加载就报<robot> tag not found。我去年带三个实习生做SLAM算法验证时,光是搭出一个能稳定输出16线点云、支持TF树完整、能和Nav2联动的仿真环境,前后踩了27个坑,重装系统4次,最后发现核心问题根本不在代码,而在工程结构设计的底层逻辑缺陷:把URDF、SDF、Gazebo插件、ROS2 Launch、参数文件全揉在一个包里,改一个参数要重启整个仿真,调试效率低得像用算盘跑神经网络。
这个标题里的“Gazebo多线激光雷达仿真示例工程”,表面看是个教学Demo,实际是一套经过生产环境验证的模块化仿真架构。它用fishbot_description作为机器人描述基座,但真正价值在于其分层设计:description包只管几何与物理属性,gazebo包专注传感器仿真与插件集成,launch包解耦启动逻辑,config包集中管理所有可调参数。这种结构让后续接入SLAM、导航、甚至多机协同都变成“替换配置文件+修改Launch参数”的操作,而不是重写整个仿真流程。
关键词里反复出现的ROS2Humble和Ubuntu22_04不是随便写的版本号。Humble是ROS2首个LTS(长期支持)版本,其gazebo_ros_pkgs对Gazebo Classic(11.x)的适配已趋稳定,但和Gazebo Fortress(ROS2 Iron之后默认)存在ABI不兼容;Ubuntu22.04的libignition库版本与Gazebo 11.3.0深度绑定,换到24.04会直接触发ignition-msgs链接错误——这解释了为什么网上那些“Ubuntu24.04 + Gazebo + Nav2”的教程,90%在ros2 launch gazebo_ros gazebo.launch.py这一步就挂掉。而本工程从根目录的CMakeLists.txt到每个Launch文件的find_package()调用,全部锁定ignition-msgs6、ignition-transport8等具体小版本,杜绝了“版本漂移”导致的隐性崩溃。
至于多线激光雷达,标题没写具体型号,但结合fishbot的常见硬件选型和热词中的velodyne16线,实际采用的是gazebo_ros_ray_sensor插件模拟的16线垂直扫描模式。它不像2D单线雷达那样只生成平面点云,而是通过<vertical> <ray>嵌套配置,在Z轴方向生成16个离散扫描层,每层独立控制角度分辨率、最小/最大距离、噪声模型。这种配置直接对应真实Velodyne VLP-16的物理特性,让后续的点云滤波、地面分割、障碍物聚类算法能在仿真中获得接近实车的数据分布特征——这才是“仿真有效”的核心,而不是仅仅让RViz里飘出一堆点。
适合谁参考?如果你正面临这些场景:需要快速验证自研SLAM算法在不同激光雷达配置下的鲁棒性;为新采购的16线雷达做驱动适配前的功能预演;或是给高校课程设计一套可扩展的移动机器人实验平台——那么这个工程不是“抄作业”的模板,而是你构建自己仿真体系的第一块标准砖。它不教你ROS2基础语法,但会告诉你:为什么robot_state_publisher必须用--use-sim-time参数启动,为什么gazebo_ros的spawn_entity.py脚本里-topic参数必须指向/robot_description而非/description,以及当/tf树里突然多出base_link到lidar_link的变换时,该去哪个Xacro文件里检查<origin>偏移量。
2. 工程结构拆解:为什么要把一个机器人拆成5个包?
2.1 核心分层逻辑:从物理世界到ROS2话题的映射链
这个工程最反直觉的设计,是把一个看似简单的“鱼博特+激光雷达”拆成了fishbot_description、fishbot_gazebo、fishbot_bringup、fishbot_control、fishbot_slam五个独立ROS2包。新手常问:“不就一个机器人吗?放一个包里不行?”——行,但代价是每次改激光雷达安装高度,你得同时改URDF、改Gazebo插件配置、改Launch文件里的TF发布参数,最后还要手动重启所有节点。而分层后,修改仅发生在单一包内:
fishbot_description:纯静态描述。只包含urdf/和meshes/目录,定义机器人本体几何、关节、惯性参数,以及lidar_link在base_link坐标系下的固定偏移(<origin xyz="0 0 0.2" rpy="0 0 0"/>)。这里绝不出现任何ROS2相关标签,比如<gazebo>或<ros2_control>,确保描述文件可被MoveIt2、Webots、甚至SolidWorks直接读取。fishbot_gazebo:仿真专属层。包含models/(Gazebo原生SDF模型)、plugins/(自定义传感器插件)、worlds/(仿真场景)。关键在models/fishbot/model.sdf里,通过<include>引用fishbot_description生成的URDF,并注入gazebo_ros_ray_sensor插件。这里定义激光雷达的物理参数:水平视场角180°、垂直视场角30°(16线均匀分布)、角分辨率0.2°、最大测距100m、高斯噪声标准差0.01m——这些数值直接来自VLP-16数据手册,不是随意填写的。fishbot_bringup:启动中枢。launch/目录下有gazebo.launch.py和simulation.launch.py两个主入口。前者只启动Gazebo服务器和spawn_entity,后者则串联robot_state_publisher、joint_state_publisher_gui、gazebo_ros插件节点。这种分离让调试更精准:若Gazebo崩溃,先单独运行gazebo.launch.py确认模型加载无误;若TF树缺失,再检查simulation.launch.py中robot_state_publisher的use_sim_time参数是否设为True。fishbot_control:运动控制层。包含config/下的diff_drive_controller.yaml,定义差速轮PID参数、轮间距、最大线速度。这里有个易忽略的细节:publish_rate: 50.0必须与Gazebo仿真步长<physics type='ode'> <max_step_size>0.001</max_step_size>匹配——0.001秒步长对应1000Hz仿真频率,但控制器只需50Hz发布速度指令,避免CPU过载。若设为100Hz,Gazebo会因频繁状态更新而卡顿。fishbot_slam:算法验证层。提供slam_toolbox的预配置mapper_params_online_sync.yaml,其中map_frame: map、odom_frame: odom、base_frame: base_link三者构成标准TF链。特别注意scan_topic: /scan参数,它强制SLAM节点订阅gazebo_ros_ray_sensor插件发布的原始点云话题,而非经过laser_filters处理后的数据——这是为了验证算法对原始噪声的鲁棒性。
2.2fishbot_description包的URDF精要解析
fishbot_description/urdf/fishbot.urdf.xacro是整个工程的基石。它采用Xacro宏语言,而非纯URDF,原因在于可复用性:<xacro:include filename="$(find-pkg-share fishbot_description)/urdf/common_properties.xacro"/>引入的common_properties.xacro定义了所有轮子、底盘、传感器的通用材质(<material name="Black">)、摩擦系数(<mu1>1.0</mu1>)、阻尼(<damping>0.1</damping>)。当需要更换为四轮麦轮底盘时,只需修改fishbot.urdf.xacro中<xacro:macro name="chassis">部分,无需重写整个URDF。
激光雷达的安装定义在<xacro:macro name="lidar">中:
<link name="lidar_link"> <visual> <geometry> <cylinder radius="0.05" length="0.1"/> </geometry> <material name="Red"/> </visual> <collision> <geometry> <cylinder radius="0.05" length="0.1"/> </geometry> </collision> <inertial> <mass value="0.5"/> <inertia ixx="0.001" iyy="0.001" izz="0.001"/> </inertial> </link> <joint name="lidar_joint" type="fixed"> <parent link="base_link"/> <child link="lidar_link"/> <origin xyz="0 0 0.2" rpy="0 0 0"/> </joint>这里xyz="0 0 0.2"表示激光雷达中心距底盘上表面20cm,符合FishBot实物安装高度。rpy="0 0 0"确保Z轴与机器人前进方向一致,避免点云坐标系旋转导致SLAM建图扭曲。<inertial>块虽小,却影响Gazebo物理仿真精度:若质量设为0,激光雷达在碰撞时会穿透障碍物;若惯性张量过大,机器人急停时雷达会因惯性继续“飞出去”。
fishbot_description还包含meshes/目录,存放STL格式的3D模型。但工程中实际使用的是<geometry><cylinder/></geometry>这类简单几何体——因为Gazebo对复杂STL的碰撞检测计算开销极大,尤其在多机器人仿真时。只有当需要精确模拟传感器外壳遮挡效果时,才启用meshes/lidar.stl并设置<collision><mesh><uri>model://fishbot/meshes/lidar.stl</uri></mesh></collision>。
2.3fishbot_gazebo包的SDF与插件深度配置
fishbot_gazebo/models/fishbot/model.sdf是连接URDF与Gazebo的桥梁。其核心是<include>块:
<include> <uri>model://fishbot_description</uri> <pose>0 0 0 0 0 0</pose> </include>这里model://是Gazebo的资源协议,指向GAZEBO_MODEL_PATH环境变量指定的路径。工程在setup.bash中预置了export GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:/opt/ros/humble/share/gazebo_plugins/models:$COLCON_PREFIX_PATH/share,确保Gazebo能同时找到官方模型库和本工程的fishbot_description。
激光雷达插件配置在<plugin>标签内:
<plugin filename="libgazebo_ros_ray_sensor.so" name="gazebo_ros_lidar"> <robot_namespace>/fishbot</robot_namespace> <frame_name>lidar_link</frame_name> <min_range>0.1</min_range> <max_range>100.0</max_range> <range_noise_mean>0.0</range_noise_mean> <range_noise_stddev>0.01</range_noise_stddev> <horizontal> <samples>900</samples> <resolution>1</resolution> <min_angle>-1.5708</min_angle> <max_angle>1.5708</max_angle> </horizontal> <vertical> <samples>16</samples> <resolution>1</resolution> <min_angle>-0.2618</min_angle> <max_angle>0.2618</max_angle> </vertical> </plugin>关键参数解读:
horizontal/samples=900:水平方向900个采样点,对应0.2°角分辨率(3.1416×2÷900≈0.00698rad≈0.4°),但实际VLP-16为0.2°,故需设为1800。此处设900是为降低CPU负载,教学演示足够。vertical/samples=16:明确声明16线扫描,min_angle到max_angle跨度0.5236rad(30°),每线间隔0.0327rad(1.875°),与VLP-16的30°垂直视场角一致。range_noise_stddev=0.01:距离测量高斯噪声标准差1cm,符合工业级激光雷达规格。若设为0,点云过于“干净”,SLAM算法在实车部署时会因无法适应真实噪声而失效。
插件发布的/scan话题是sensor_msgs/msg/LaserScan类型,但gazebo_ros_ray_sensor实际生成的是sensor_msgs/msg/PointCloud2。工程通过gazebo_ros的convert_scan_to_pointcloud参数自动转换,避免手动编写转换节点。该参数在gazebo.launch.py中通过remappings=[('scan', '/scan')]传递,确保话题名统一。
2.4 Launch文件的参数化设计:如何用一个Launch启动N种场景
fishbot_bringup/launch/gazebo.launch.py采用ROS2标准Launch描述符,但关键在参数注入机制:
def generate_launch_description(): # 从命令行获取参数 use_sim_time = LaunchConfiguration('use_sim_time', default='true') world = LaunchConfiguration('world', default=os.path.join( get_package_share_directory('fishbot_gazebo'), 'worlds', 'empty.world')) return LaunchDescription([ DeclareLaunchArgument( 'use_sim_time', default_value='true', description='Use simulation (Gazebo) clock if true'), DeclareLaunchArgument( 'world', default_value=world, description='Full path to the world model file to load'), # Gazebo服务器节点 IncludeLaunchDescription( PythonLaunchDescriptionSource( os.path.join(get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')), launch_arguments={'world': world}.items(), ), # 实体生成节点 Node( package='gazebo_ros', executable='spawn_entity.py', arguments=[ '-entity', 'fishbot', '-topic', 'robot_description', # 注意:必须是/robot_description,不是/description '-x', '0.0', '-y', '0.0', '-z', '0.0' ], output='screen'), ])-topic 'robot_description'是易错点:很多教程写成-topic /robot_description或-topic description,导致spawn_entity找不到URDF而报错。正确值是robot_description(无斜杠),因为robot_state_publisher发布的/robot_description话题名中的斜杠是ROS2自动添加的命名空间前缀。
fishbot_bringup/launch/simulation.launch.py则实现“一键启动全栈”:
# 启动robot_state_publisher Node( package='robot_state_publisher', executable='robot_state_publisher', name='robot_state_publisher', output='screen', parameters=[{ 'use_sim_time': use_sim_time, 'robot_description': Command(['xacro ', urdf_path]) }], remappings=[('/tf', 'tf'), ('/tf_static', 'tf_static')] ),parameters中'robot_description': Command(['xacro ', urdf_path])动态执行xacro命令生成URDF字符串,避免预编译URDF文件导致的更新延迟。remappings将/tf重映射为tf,是因为robot_state_publisher默认发布/tf,但某些旧版Nav2配置期望tf无前缀——这种兼容性设计让工程能无缝对接不同版本的导航栈。
3. 多线激光雷达仿真实操:从零搭建到点云可视化全流程
3.1 环境准备:Ubuntu22.04 + ROS2 Humble的精准安装
Ubuntu22.04的系统镜像选择至关重要。官方推荐ubuntu-22.04.3-live-server-amd64.iso,而非Desktop版——因为Server版默认禁用GUI,节省Gazebo渲染的GPU资源,且systemd服务管理更稳定。安装时分区建议:/根分区50GB(SSD)、/home分区200GB(HDD)、swap分区8GB(内存<16GB时必需)。
ROS2 Humble安装严格按官网步骤,但有两个隐藏陷阱:
apt源配置:sudo sh -c 'echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" > /etc/apt/sources.list.d/ros2.list'中,$(. /etc/os-release && echo $UBUNTU_CODENAME)必须输出jammy(Ubuntu22.04代号)。若系统语言非英文,$UBUNTU_CODENAME可能为空,需手动替换为jammy。gazebo_ros_pkgs安装:sudo apt install ros-humble-gazebo-ros-pkgs会自动安装gazebo11,但若之前装过Gazebo9或10,残留的libgazebo库会导致冲突。此时需执行sudo apt remove --purge gazebo* libgazebo*彻底清理,再sudo apt autoremove,最后重新安装。
验证环境:
# 检查Gazebo版本 gazebo --version # 应输出 11.3.0 # 检查ROS2接口 ros2 pkg list | grep gazebo # 应含 gazebo_ros, gazebo_msgs # 检查Ignition库 pkg-config --modversion ignition-msgs6 # 应输出 6.11.03.2 工程克隆与编译:解决90%的编译失败问题
工程压缩包Gazeb.zip解压后,目录结构应为:
fishbot_ws/ ├── src/ │ ├── fishbot_description/ │ ├── fishbot_gazebo/ │ ├── fishbot_bringup/ │ └── fishbot_control/ └── build/ # 编译产物目录关键编译命令:
cd fishbot_ws # 初始化colcon环境 source /opt/ros/humble/setup.bash # 安装依赖(自动解析package.xml) rosdep install --from-paths src --ignore-src -r -y # 编译(-j1防止内存溢出) colcon build --packages-select fishbot_description fishbot_gazebo --cmake-args -DCMAKE_BUILD_TYPE=Releaserosdep install是成功率最高的依赖安装方式,它读取每个包的package.xml中的<exec_depend>,自动映射到Ubuntu包名。例如<exec_depend>gazebo_ros</exec_depend>会被解析为ros-humble-gazebo-ros。
若编译报错fatal error: gazebo_ros/utils.hpp: No such file or directory,说明gazebo_ros_pkgs未正确安装。此时不要手动下载头文件,而应执行:
sudo apt update && sudo apt install ros-humble-gazebo-ros-pkgs因为utils.hpp位于/opt/ros/humble/include/gazebo_ros/,由ros-humble-gazebo-ros-pkgs包提供。
编译成功后,source install/setup.bash激活环境。此时运行ros2 pkg list | grep fishbot应列出所有fishbot包。
3.3 启动仿真与点云验证:三步确认激光雷达工作正常
第一步:启动Gazebo空世界
ros2 launch fishbot_bringup gazebo.launch.pyGazebo窗口打开后,左上角菜单栏Insert中应能看到fishbot模型。若无,检查GAZEBO_MODEL_PATH是否包含fishbot_ws/install/fishbot_gazebo/share/fishbot_gazebo/models。
第二步:加载机器人实体在新终端中:
ros2 launch fishbot_bringup simulation.launch.py此时Gazebo中应出现FishBot模型,且RViz2可启动:
ros2 run rviz2 rviz2 -d $(ros2 pkg prefix fishbot_bringup)/share/fishbot_bringup/rviz/fishbot.rvizRViz2配置文件fishbot.rviz已预设RobotModel、TF、LaserScan三个显示项。若LaserScan无点云,检查:
ros2 topic list | grep scan是否有/scan话题ros2 topic echo /scan是否输出header、angle_min等字段ros2 node list中gazebo_ros_lidar节点是否在运行
第三步:点云质量验证运行ros2 topic hz /scan查看发布频率,应为10Hz(Gazebo仿真步长0.001s × 100Hz控制频率 ÷ 10 = 10Hz)。若低于5Hz,检查Gazebo右下角Real Time Factor是否接近1.0;若为0.1,说明CPU过载,需降低horizontal/samples或关闭Gazebo渲染(gzserver替代gazebo)。
点云可视化进阶技巧:在RViz2中LaserScan显示项下,勾选Style: Points,Size (Pixels): 2,Color Transformer: Intensity。此时点云颜色深浅反映回波强度,可直观判断:近处点(强度高)呈白色,远处点(强度衰减)呈灰色,噪声点(随机强度)呈杂色斑点——这正是真实激光雷达的物理特性。
3.4 参数调优实战:让仿真点云逼近真实VLP-16
真实VLP-16的点云密度并非均匀分布。水平方向,中心区域(±30°)点更密,边缘(±90°)点更疏;垂直方向,中间几线(第8-9线)分辨率更高。工程通过<horizontal>和<vertical>的<resolution>参数模拟此特性:
<horizontal> <samples>1800</samples> <resolution>0.5</resolution> <!-- 中心区域采样率翻倍 --> <min_angle>-1.5708</min_angle> <max_angle>1.5708</max_angle> </horizontal> <vertical> <samples>16</samples> <resolution>1.0</resolution> <min_angle>-0.2618</min_angle> <max_angle>0.2618</max_angle> </vertical><resolution>0.5表示在<min_angle>到<max_angle>区间内,实际采样点数为samples × resolution = 1800 × 0.5 = 900,但Gazebo会智能分配:中心区域每0.1°一个点,边缘每0.4°一个点,总点数仍为900。
噪声模型调优更关键。range_noise_stddev设为0.01m时,点云边缘会出现“毛刺”。真实VLP-16的噪声随距离增大而增大,故需启用range_noise_model:
<range_noise_model> <type>gaussian</type> <mean>0.0</mean> <stddev>0.01</stddev> <distance_dependent>true</distance_dependent> <distance_factor>0.0001</distance_factor> </range_noise_model>distance_factor=0.0001表示每米距离增加0.1mm噪声标准差。10m处噪声为0.01 + 10×0.0001 = 0.011m,100m处为0.02m——这与VLP-16实测数据吻合。
提示:修改SDF参数后,必须重新编译
fishbot_gazebo包,因为model.sdf被colcon build复制到install/fishbot_gazebo/share/fishbot_gazebo/models/fishbot/model.sdf。直接编辑src/目录下的文件无效。
4. 常见问题排查:从Gazebo黑屏到点云消失的21个故障点
4.1 Gazebo启动失败:黑屏、闪退、报错汇总
| 故障现象 | 根本原因 | 解决方案 |
|---|---|---|
gzserver: command not found | gazebo_ros_pkgs未安装或PATH未更新 | source /opt/ros/humble/setup.bash后重试;若仍失败,sudo apt install gazebo11 |
Gazebo窗口黑屏,右下角Real Time Factor: 0.0 | GPU驱动未启用或OpenGL版本过低 | Ubuntu22.04安装nvidia-driver-525(NVIDIA)或mesa-utils(Intel/AMD);运行glxinfo | grep "OpenGL version"确认≥3.3 |
Error: Unable to create the rendering window | Wayland会话冲突 | 终端输入export GAZEBO_GUI=0后启动gzserver,或登录时选择Xorg会话 |
Could not find model[fishbot] | GAZEBO_MODEL_PATH未包含工程路径 | 在~/.bashrc中添加export GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:$HOME/fishbot_ws/install/fishbot_gazebo/share/fishbot_gazebo/models |
独家避坑技巧:Gazebo 11.3.0在Ubuntu22.04上偶发Segmentation fault (core dumped),根源是libignition-common的内存释放bug。临时方案:启动前设置export IGNITION_COMMON_DEBUG=0,或升级到ignition-common4(需手动编译)。
4.2 激光雷达无点云:/scan话题消失的根因分析
/scan话题缺失是最常见问题,但原因分三层:
第一层:Gazebo插件未加载
- 检查
model.sdf中<plugin>标签是否拼写错误(如libgazebo_ros_ray_sensor.so误写为libgazebo_ros_laser.so) - 运行
gzserver --verbose启动Gazebo,观察日志中是否有Loaded plugin libgazebo_ros_ray_sensor.so字样
第二层:TF树断裂
- 运行
ros2 run tf2_tools view_frames生成frames.pdf,检查base_link到lidar_link的变换是否存在 - 若缺失,确认
fishbot_description/urdf/fishbot.urdf.xacro中<joint name="lidar_joint">的<parent>和<child>链接名与<link>定义完全一致(大小写敏感!)
第三层:话题重映射错误
ros2 topic list中若出现/fishbot/scan而非/scan,说明robot_namespace参数未生效- 检查
model.sdf中<robot_namespace>/fishbot</robot_namespace>是否被注释,或gazebo.launch.py中IncludeLaunchDescription未传递robot_namespace参数
注意:
gazebo_ros_ray_sensor插件默认发布/scan,但若<robot_namespace>设为/fishbot,则实际话题为/fishbot/scan。此时必须在RViz2中将LaserScan的Topic改为/fishbot/scan,或在Launch文件中添加remappings=[('/scan', '/fishbot/scan')]。
4.3 点云畸变与抖动:物理仿真失真的诊断流程
点云出现“波浪形”畸变或整体抖动,通常源于物理引擎参数不匹配:
检查Gazebo物理引擎设置:
worlds/empty.world中<physics type='ode'>块,<max_step_size>0.001</max_step_size>必须≤<real_time_update_rate>1000.0</real_time_update_rate>的倒数(即0.001s)。若max_step_size设为0.01,仿真会跳步,导致机器人位姿突变。验证机器人惯性参数:运行
ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:="...",观察/tf中base_link的linear.x速度是否突变。若突变,说明URDF中<inertial>的<mass>过小(<0.1kg)或<inertia>过大(>0.01)。激光雷达坐标系校准:点云沿Y轴拉伸,表明
lidar_link的<origin rpy>中rpy值错误。真实VLP-16安装时Z轴向上,故rpy="0 0 0";若误设为rpy="0 1.57 0"(绕Y轴旋转90°),点云将沿X轴展开。
实测心得:我们曾遇到点云在Z轴方向周期性抖动(±2cm),最终定位为<vertical>的<min_angle>和<max_angle>未关于0对称。VLP-16的16线范围是-15°到+15°,若设为-10°到+20°,Gazebo会强制线性插值,导致中间几线密度异常。
4.4 多机仿真冲突:当第二个FishBot加入时的资源抢占
启动第二个机器人时,常出现Failed to spawn entity或/tf树混乱。根源在于:
- 所有机器人共享同一
/robot_description话题,spawn_entity.py无法区分 gazebo_ros_ray_sensor插件默认使用/scan话题名,第二个机器人会覆盖第一个
解决方案:
- 为每个机器人设置独立命名空间:
ros2 launch fishbot_bringup simulation.launch.py \ robot_namespace:=/robot1 \ x:=0.0 y:=0.0 ros2 launch fishbot_bringup simulation.launch.py \ robot_namespace:=/robot2 \ x:=2.0 y:=0.0- 修改
model.sdf中<robot_namespace>为$(arg robot_namespace),并在Launch文件中通过<arg>传递 - 在
gazebo.launch.py中,spawn_entity.py的-topic参数改为$(arg robot_namespace)/robot_description
此时robot1的点云发布到/robot1/scan,robot2发布到/robot2/scan,TF树自动隔离为/robot1/odom和/robot2/odom,彻底解决冲突。
5. 工程扩展指南:从单机仿真到SLAM导航全栈验证
5.1 接入SLAM Toolbox:5分钟完成建图功能
fishbot_slam包已预配置slam_toolbox,但需三步激活:
- 启动SLAM节点:
ros2 launch fishbot_slam online_async_launch.py- 发送初始位姿(否则SLAM认为机器人在(0,0,0),建图偏移):
ros2 topic pub /initialpose geometry_msgs/msg/PoseWithCovarianceStamped "header: stamp: sec: 0 nanosec: 0 frame_id: map pose: pose: position: x: 0.0 y: 0.0 z: 0.0 orientation: x: 0.0 y: 0.0 z: 0.0 w: 1.0 covariance: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]"- 控制机器人移动:
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "linear: x: 0.2 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.5"SLAM建图质量取决于点云密度。若地图边缘模糊,调高model.sdf中<horizontal><samples>至1800,并重启仿真。
5.2 集成Nav2导航栈:让机器人自主到达目标点
Nav2配置在`fish
本文还有配套的精品资源,点击获取