打造智能机器人感知系统!Isaac Sim激光雷达传感器配置到ROS SLAM建图完全实战指南

845 阅读15分钟

基础:Isaac Sim LiDAR和相机传感器ROS集成教程

1. 教程概述

本教程将指导你在Isaac Sim中设置PhysX LiDAR传感器和相机传感器,并通过ROS1进行数据发布,最终实现SLAM建图功能。适用于扫地机器人等需要环境感知的应用场景。

参考资料

版本说明

重要提醒: 由于Isaac Sim版本更新快,API变化较大,不同版本可能存在不兼容情况。本教程基于Isaac Sim 4.5版本,如遇到节点名称不一致的情况,请参考最新版本文档。

2. 前置准备

2.1 环境要求

  • Isaac Sim 4.5或更高版本
  • ROS Noetic
  • 已安装ROS Bridge扩展

2.2 启用ROS1 Bridge

  1. 打开Isaac Sim
  2. 进入Window > Extensions
  3. 搜索"ROS Bridge"
  4. 启用omni.isaac.ros_bridge扩展

3. 传感器创建与配置

3.1 创建PhysX LiDAR传感器

打开Isaac Sim,进入Window > Script Editor,输入以下代码:

import omni.kit.commands
from pxr import Gf, UsdGeom
from omni.isaac.core.utils.stage import get_current_stage

# 获取当前stage
stage = get_current_stage()

# 创建PhysX LiDAR传感器
omni.kit.commands.execute(
    'CreatePrim',
    prim_path='/World/robot_lidar',
    prim_type='Lidar'
)

# 获取LiDAR prim
lidar_prim = stage.GetPrimAtPath('/World/robot_lidar')

# 设置LiDAR参数
lidar_prim.GetAttribute('horizontalFov').Set(360.0)  # 水平视场角360度
lidar_prim.GetAttribute('horizontalResolution').Set(0.4)  # 水平分辨率0.4度
lidar_prim.GetAttribute('maxRange').Set(100.0)  # 最大量程30米
lidar_prim.GetAttribute('minRange').Set(0.4)  # 最小量程0.4米
lidar_prim.GetAttribute('rotationRate').Set(20.0)  # 旋转速率设为0(一次性获取所有线)
lidar_prim.GetAttribute('verticalFov').Set(0.0)  # 垂直视场角30度
lidar_prim.GetAttribute('verticalResolution').Set(0.0)  # 垂直分辨率1度
lidar_prim.GetAttribute('drawLines').Set(True)  # 显示激光线
lidar_prim.GetAttribute('drawPoints').Set(True)  # 显示激光点

# 设置LiDAR位置
omni.kit.commands.execute(
    'ChangeProperty',
    prop_path='/World/robot_lidar.xformOp:translate',
    value=Gf.Vec3d(0, 0, 0.5),  # x, y, z坐标
    prev=None
)

print("PhysX LiDAR created successfully at /World/robot_lidar")
LiDAR参数说明
  • horizontalFov: 水平视角,默认360度(一周)
  • horizontalResolution: 水平分辨率,度为单位。比如0.4表示水平每0.4度有一个观测线
  • maxRange: LiDAR传感器最远量程,单位米
  • minRange: LiDAR传感器最近量程,单位米
  • rotationRate: 激光线的旋转速率,每秒多少圈。如果为0则表示一次性获得所有激光线
  • verticalFov: 垂直视角,LiDAR传感器在竖直方向上的视角范围,单位度
  • verticalResolution: 竖直分辨率。两条激光线之间的竖直角度,单位度

3.2 创建相机传感器

继续在Script Editor中输入以下代码:

# 创建相机
omni.kit.commands.execute(
    'CreatePrim',
    prim_path='/World/robot_camera',
    prim_type='Camera'
)

# 获取相机prim
camera_prim = stage.GetPrimAtPath('/World/robot_camera')

# 设置相机参数
camera_prim.GetAttribute('focalLength').Set(24.0)  # 焦距
camera_prim.GetAttribute('focusDistance').Set(400.0)  # 对焦距离
camera_prim.GetAttribute('horizontalAperture').Set(20.955)  # 水平光圈
camera_prim.GetAttribute('verticalAperture').Set(15.2908)  # 垂直光圈
camera_prim.GetAttribute('clippingRange').Set(Gf.Vec2f(1.0, 1000000.0))  # 裁剪范围

# 设置相机位置和旋转
omni.kit.commands.execute(
    'ChangeProperty',
    prop_path='/World/robot_camera.xformOp:translate',
    value=Gf.Vec3d(1.0, 0, 1.2),  # x, y, z坐标
    prev=None
)

omni.kit.commands.execute(
    'ChangeProperty',
    prop_path='/World/robot_camera.xformOp:rotateXYZ',
    value=Gf.Vec3d(-15, 0, 0),  # 俯仰角-15度
    prev=None
)

print("Camera created successfully at /World/robot_camera")

4. Action Graph配置

4.1 创建LiDAR数据发布的Action Graph

  1. 打开Window > Visual Scripting > Action Graph
  2. 创建新的Action Graph,命名为"LiDAR_Publisher"
  3. 按以下顺序添加节点并连接:
核心节点列表
  1. On Playbook Tick - 触发节点
  2. Isaac Read Lidar Point Cloud Node - 读取LiDAR点云数据节点
  3. ROS1 Publish Point Cloud - ROS1发布点云数据
  4. Isaac Read Simulation Time - 读取仿真时间
节点配置与连接

节点1:On Playbook Tick

  • 作用:仿真运行时触发整个Graph

节点2:Isaac Read Lidar Point Cloud Node

  • 在Properties面板中设置:

    • inputs:lidarPrim = /World/robot_lidar

节点3:ROS1 Publish Point Cloud

  • 在Properties面板中设置:

    • inputs:topicName = robot_lidar_pointcloud
    • inputs:frameId = robot_lidar_frame

节点4:Isaac Read Simulation Time

  • 提供准确的时间戳
连接方式
On Playback Tick → Isaac Read Lidar Point Cloud Node (execIn)
Isaac Read Lidar Point Cloud Node → ROS1 Publish Point Cloud (execIn)
Isaac Read Lidar Point Cloud Node (pointCloudData) → ROS1 Publish Point Cloud (pointCloudData)
Isaac Read Simulation Time (simulationTime) → ROS1 Publish Point Cloud (timeStamp)

image.png

image.png

4.2 创建相机数据发布的Action Graph

  1. 创建新的Action Graph,命名为"Camera_Publisher"
  2. 按以下顺序添加节点并连接:
核心节点列表
  1. On Playbook Tick - 触发节点
  2. Isaac Create Viewport - 创建视窗
  3. Constant Int - 常量整数节点(设置Viewport ID)
  4. Set Active Camera - 设置活动相机
  5. Get Prim Path - 获取Prim路径
  6. ROS1 Camera Helper - ROS1相机助手
  7. Constant String - 常量字符串节点(设置Topic名称)
节点配置与连接

节点1:On Playbook Tick

  • 作用:仿真运行时触发整个Graph

节点2:Constant Int

  • 在Properties面板中设置:

    • inputs:value = 1 (Viewport ID)

节点3:Isaac Create Viewport

  • 创建新的渲染视窗

节点4:Get Prim Path

  • 在Properties面板中设置:

    • inputs:prim = /World/robot_camera

节点5:Set Active Camera

  • 将相机绑定到Viewport

节点6:Constant String

  • 在Properties面板中设置:

    • inputs:value = robot_camera_image

节点7:ROS1 Camera Helper

  • 在Properties面板中设置:

    • inputs:type = rgb
    • inputs:frameId = robot_camera_frame
连接方式
On Playback Tick → Isaac Create Viewport (execIn)
Constant Int (value) → Isaac Create Viewport (viewportId)
Isaac Create Viewport → Set Active Camera (execIn)
Isaac Create Viewport (viewport) → Set Active Camera (viewport)
Get Prim Path (prim) → Set Active Camera (cameraPrim)
Set Active Camera → ROS1 Camera Helper (execIn)
Isaac Create Viewport (viewport) → ROS1 Camera Helper (viewport)
Constant String (value) → ROS1 Camera Helper (topicName)

image.png

image.png

5. 传感器绑定到机器人

创建传感器后,需要将它们绑定到机器人相应部位:

5.1 绑定LiDAR到底盘

  1. 在Stage面板中,将/World/robot_lidar拖拽到你的机器人底盘节点下
  2. 调整其Transform属性,设置合适的位置

5.2 绑定相机到机械臂

  1. 在Stage面板中,将/World/robot_camera拖拽到你的机械臂末端节点下
  2. 调整其Transform属性,设置合适的位置和角度

6. 运行测试流程

6.1 启动ROS核心(终端1)

# 在第一个终端启动 roscore
roscore

image.png

6.2 启动Isaac Sim(终端2)

在Isaac Sim中点击Play按钮开始仿真。

image.png

6.3 验证ROS话题发布

在新的终端中检查ROS话题:

# 查看所有话题列表
rostopic list

# 检查LiDAR点云话题
rostopic echo /robot_lidar_pointcloud

# 检查相机图像话题
rostopic echo /robot_camera_image

# 查看发布频率
rostopic hz /robot_lidar_pointcloud
rostopic hz /robot_camera_image

# 查看话题信息
rostopic info /robot_lidar_pointcloud
rostopic info /robot_camera_image

6.4 可视化测试(终端3)

# 设置ROS环境
source /opt/ros/noetic/setup.bash

# 启动 rqt_image_view 查看图像话题
rqt_image_view

# 在 rqt_image_view 界面中选择相应的图像话题:
# /robot_camera_image 或类似的话题名称

image.png

6.5 查看节点图(终端4,可选)

# 设置ROS环境
source /opt/ros/noetic/setup.bash

# 启动 rqt_graph 查看节点关系
rqt_graph

image.png

7. RViz可视化LiDAR数据

7.1 启动RViz

在新的终端中运行:

rosrun rviz rviz

7.2 设置固定坐标系

  1. 在RViz左侧面板的Global Options
  2. Fixed Frame设置为:robot_lidar_frame

7.3 添加PointCloud2显示插件

  1. 点击RViz左下角的Add按钮
  2. 在弹出的窗口中选择PointCloud2
  3. 点击OK

7.4 配置PointCloud2显示属性

在左侧面板中找到刚添加的PointCloud2,展开其属性:

  1. Topic: 设置为 /robot_lidar_pointcloud

  2. Size (Pixels) : 设置为 3 (点的大小)

  3. Style: 选择 Points (点显示模式)

  4. Color Transformer: 可以选择:

    • Intensity - 按强度着色
    • AxisColor - 按轴向着色
    • FlatColor - 单一颜色
  5. Decay Time: 设置为 0 (不保留历史点云)

7.5 同时可视化相机图像(可选)

如果你也想查看相机图像:

  1. 再次点击Add按钮
  2. 选择Image插件
  3. 设置Image Topic为:/robot_camera_image

7.6 保存RViz配置

为了方便下次使用,建议保存配置:

  1. 点击菜单File > Save Config As
  2. 保存为:robot_sensors.rviz

8. 效果展示

8.1 运行效果

使用以下命令启动系统:

cd isaacsim
./python.sh /home/lwb/Project/CleanUp_Bench_SVSDF/main_system.py

cbbc168a50edd094d5a1b975b77ccc98.jpg

image.png

8.2 激光雷达参数调整效果

通过调整LiDAR参数可以获得不同的扫描效果:

image.png

image.png

9. SLAM建图

9.1 环境准备

创建指定Python版本的环境:

# 创建指定Python版本的环境(如3.8)
conda create -n myenv_py38 python=3.8

# 激活环境
conda activate myenv_py38

# 验证版本
python --version

9.2 搭建Cartographer进行SLAM

参考Google Cartographer ROS文档:

google-cartographer-ros.readthedocs.io/en/latest/c…

为了构建 Cartographer ROS,我们建议使用 wstool 和 rosdep。为了更快地构建,我们还建议使用 Ninja

在带有 ROS Noetic 的 Ubuntu Focal 上,使用以下命令安装上述工具:

sudo apt-get update
sudo apt-get install -y python3-wstool python3-rosdep ninja-build stow

在较旧的发行版上:

sudo apt-get update
sudo apt-get install -y python-wstool python-rosdep ninja-build stow

安装工具后,在“catkin_ws”中创建一个新的cartographer_ros工作区。

mkdir catkin_ws    #之前就有的话把之前的项目都删掉或者转移,不然会和这个项目冲突
cd catkin_ws
wstool init src
wstool merge -t src https://raw.githubusercontent.com/cartographer-project/cartographer_ros/master/cartographer_ros.rosinstall
wstool update -t src

现在您需要安装cartographer_ros依赖项。 首先,我们用于安装所需的软件包。 如果自安装 ROS 以来已经执行了命令 'sudo rosdep init' 将打印错误。此错误可以忽略。rosdep

sudo rosdep init
rosdep update
rosdep install --from-paths src --ignore-src --rosdistro=${ROS_DISTRO} -y

Cartographer 使用需要使用以下脚本手动安装的 abseil-cpp 库:

src/cartographer/scripts/install_abseil.sh

由于版本冲突,您可能需要使用

sudo apt-get remove ros-${ROS_DISTRO}-abseil-cpp

构建和安装。

catkin_make_isolated --install --use-ninja

这会从 master 分支的最新 HEAD 构建 Cartographer。 如果您想要特定版本,则需要更改 cartographer_ros.rosinstall 中的版本。

现在已经安装了 Cartographer 和 Cartographer 的 ROS 集成 当你想运行cartographer_ros时,你可能需要先运行你的 ROS 环境(如果你的 shell 是 zsh,则用 zsh 替换 bash)source install_isolated/setup.bash

德意志博物馆

下载并启动 2D 背包演示:

wget -P ~/Downloads https://storage.googleapis.com/cartographer-public-data/bags/backpack_2d/cartographer_paper_deutsches_museum.bag
roslaunch cartographer_ros demo_backpack_2d.launch bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag

下载并启动 3D 背包演示:

wget -P ~/Downloads https://storage.googleapis.com/cartographer-public-data/bags/backpack_3d/with_intensities/b3-2016-04-05-14-14-00.bag
roslaunch cartographer_ros demo_backpack_3d.launch bag_filename:=${HOME}/Downloads/b3-2016-04-05-14-14-00.bag
纯本地化

纯本地化使用 2 个不同的袋子。第一个用于生成地图,第二个用于运行纯本地化。

从德意志博物馆下载 2D 包:

wget -P ~/Downloads https://storage.googleapis.com/cartographer-public-data/bags/backpack_2d/b2-2016-04-05-14-44-52.bag
wget -P ~/Downloads https://storage.googleapis.com/cartographer-public-data/bags/backpack_2d/b2-2016-04-27-12-31-41.bag

生成地图(等到cartographer_offline_node完成),然后运行纯本地化:

roslaunch cartographer_ros offline_backpack_2d.launch bag_filenames:=${HOME}/Downloads/b2-2016-04-05-14-44-52.bag
roslaunch cartographer_ros demo_backpack_2d_localization.launch \
   load_state_filename:=${HOME}/Downloads/b2-2016-04-05-14-44-52.bag.pbstream \
   bag_filename:=${HOME}/Downloads/b2-2016-04-27-12-31-41.bag
运行2D SLAM示例
roslaunch cartographer_ros demo_backpack_2d.launch bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag
运行3D SLAM示例
roslaunch cartographer_ros demo_backpack_3d.launch bag_filename:=${HOME}/Downloads/b3-2016-04-05-14-14-00.bag

进阶:Isaac Sim + Cartographer ROS 2D SLAM 完整配置指南

前置条件检查

  • Isaac Sim 4.5正在运行
  • Ubuntu 20.04 + ROS Noetic
  • Cartographer ROS已安装并可运行演示
  • PhysX LiDAR在Isaac Sim中已配置并发布robot_lidar_pointcloud话题

第一步:文件创建和配置

1.1 创建配置文件

# 进入catkin工作空间
cd ~/catkin_ws

# 确保所有必要目录存在
mkdir -p install_isolated/share/cartographer_ros/configuration_files
mkdir -p install_isolated/share/cartographer_ros/urdf
mkdir -p install_isolated/share/cartographer_ros/launch

1.2 创建文件

创建URDF文件

~/catkin_ws/install_isolated/share/cartographer_ros/urdf/目录下创建isaac_sim_robot.urdf

<!--
  Isaac Sim Robot Description for Cartographer ROS (基于实际激光雷达参数)
  激光雷达配置:180度,450点,0.4-100米,安装高度40cm
-->

<robot name="isaac_sim_robot">
  <material name="blue">
    <color rgba="0.0 0.0 1.0 1.0" />
  </material>
  <material name="red">
    <color rgba="1.0 0.0 0.0 1.0" />
  </material>
  <material name="green">
    <color rgba="0.0 1.0 0.0 1.0" />
  </material>
  <material name="yellow">
    <color rgba="1.0 1.0 0.0 1.0" />
  </material>

  <!-- Base link - 机器人的主体 -->
  <link name="base_link">
    <inertial>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <mass value="10.0"/>
      <inertia ixx="0.1" ixy="0.0" ixz="0.0"
               iyy="0.1" iyz="0.0" izz="0.1"/>
    </inertial>
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <box size="0.5 0.3 0.2"/>
      </geometry>
      <material name="blue"/>
    </visual>
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <box size="0.5 0.3 0.2"/>
      </geometry>
    </collision>
  </link>

  <!-- Base footprint - 用于导航的投影点 -->
  <link name="base_footprint">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <sphere radius="0.01"/>
      </geometry>
      <material name="yellow"/>
    </visual>
  </link>

  <!-- LiDAR link - 匹配Isaac Sim实际位置 -->
  <link name="robot_lidar_frame">
    <inertial>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <mass value="0.5"/>
      <inertia ixx="0.01" ixy="0.0" ixz="0.0"
               iyy="0.01" iyz="0.0" izz="0.01"/>
    </inertial>
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder radius="0.05" length="0.1"/>
      </geometry>
      <material name="red"/>
    </visual>
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder radius="0.05" length="0.1"/>
      </geometry>
    </collision>
  </link>

  <!-- 相机 link -->
  <link name="robot_camera_frame">
    <inertial>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <mass value="0.1"/>
      <inertia ixx="0.001" ixy="0.0" ixz="0.0"
               iyy="0.001" iyz="0.0" izz="0.001"/>
    </inertial>
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.05 0.05"/>
      </geometry>
      <material name="green"/>
    </visual>
  </link>

  <!-- Base footprint joint -->
  <joint name="base_footprint_joint" type="fixed">
    <parent link="base_footprint"/>
    <child link="base_link"/>
    <origin xyz="0.0 0.0 0.1" rpy="0 0 0"/>
  </joint>

  <!-- LiDAR joint - 匹配Isaac Sim实际安装位置和偏移 -->
  <joint name="base_to_lidar" type="fixed">
    <parent link="base_link"/>
    <child link="robot_lidar_frame"/>
    <!-- 匹配Isaac Sim实际位置: X=-0.00036, Y=0.0, Z=0.39336-0.1(base_link高度) -->
    <origin xyz="-0.00036 0.0 0.29336" rpy="0 0 0"/>
  </joint>

  <!-- 相机 joint -->
  <joint name="base_to_camera" type="fixed">
    <parent link="base_link"/>
    <child link="robot_camera_frame"/>
    <origin xyz="0.25 0.0 0.15" rpy="-0.1745 0 0"/>
  </joint>

  <!-- Gazebo传感器属性 - 匹配实际激光雷达参数 -->
  <gazebo reference="robot_lidar_frame">
    <material>Gazebo/Red</material>
    <sensor type="ray" name="lidar_sensor">
      <pose>0 0 0 0 0 0</pose>
      <visualize>true</visualize>
      <update_rate>20</update_rate>  <!-- 匹配rotationRate: 20.0 -->
      <ray>
        <scan>
          <horizontal>
            <samples>450</samples>        <!-- 180度/0.4度 = 450点 -->
            <resolution>1</resolution>
            <min_angle>-1.570796</min_angle>  <!-- -90度 (180度扫描) -->
            <max_angle>1.570796</max_angle>   <!-- +90度 -->
          </horizontal>
        </scan>
        <range>
          <min>0.4</min>               <!-- 匹配minRange -->
          <max>100.0</max>             <!-- 匹配maxRange -->
          <resolution>0.01</resolution>
        </range>
        <noise>
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.02</stddev>        <!-- 对于100米范围,适当增加噪声 -->
        </noise>
      </ray>
    </sensor>
  </gazebo>

  <gazebo reference="robot_camera_frame">
    <material>Gazebo/Green</material>
  </gazebo>

  <gazebo reference="base_link">
    <material>Gazebo/Blue</material>
  </gazebo>

</robot>

创建Lua配置文件

在你的~/catkin_ws/install_isolated/share/cartographer_ros/configuration_files/目录下创建isaac_sim_2d.lua

-- Isaac Sim 2D SLAM Configuration for Cartographer (基于实际激光雷达参数)
-- Copyright 2024 - 优化占用网格更新速度

include "map_builder.lua"
include "trajectory_builder.lua"

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",
  tracking_frame = "robot_lidar_frame",  -- 与Isaac Sim中的LiDAR frame对应
  published_frame = "base_link",
  odom_frame = "odom",
  provide_odom_frame = true,
  publish_frame_projected_to_2d = true,  -- 确保2D投影
  use_pose_extrapolator = true,
  use_odometry = false,  -- Isaac Sim场景通常不需要里程计
  use_nav_sat = false,
  use_landmarks = false,
  num_laser_scans = 0,
  num_multi_echo_laser_scans = 0,
  num_subdivisions_per_laser_scan = 1,
  num_point_clouds = 1,  -- Isaac Sim使用PointCloud2
  lookup_transform_timeout_sec = 0.2,
  submap_publish_period_sec = 0.2,  -- 优化:提高到5Hz
  pose_publish_period_sec = 20e-3,  -- 优化:提高到50Hz  
  trajectory_publish_period_sec = 50e-3,  -- 优化:提高到20Hz
  rangefinder_sampling_ratio = 1.,
  odometry_sampling_ratio = 1.,
  fixed_frame_pose_sampling_ratio = 1.,
  imu_sampling_ratio = 1.,
  landmarks_sampling_ratio = 1.,
}

-- 启用2D轨迹构建器
MAP_BUILDER.use_trajectory_builder_2d = true

-- 2D轨迹构建器配置
TRAJECTORY_BUILDER_2D.num_accumulated_range_data = 1  -- Isaac Sim一次性获取完整扫描

-- 点云处理配置 - 匹配实际激光雷达参数
TRAJECTORY_BUILDER_2D.min_range = 0.4    -- 匹配实际minRange
TRAJECTORY_BUILDER_2D.max_range = 100.0  -- 匹配实际maxRange
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 5.0  -- 对于100米范围,设置为5TRAJECTORY_BUILDER_2D.use_imu_data = false  -- 2D SLAM不强制需要IMU
TRAJECTORY_BUILDER_2D.voxel_filter_size = 0.03  -- 从0.05减少到0.03,提高精度但降低计算量

-- 自适应体素滤波器 - 适配大范围激光雷达
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_length = 1.0  -- 增大以适应100米范围
TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.min_num_points = 200  -- 保持合理的点数

-- 运动滤波器 - 针对大范围环境优化
TRAJECTORY_BUILDER_2D.motion_filter.max_time_seconds = 0.5   -- 从1.0减少到0.5
TRAJECTORY_BUILDER_2D.motion_filter.max_distance_meters = 0.1  -- 从0.2减少到0.1
TRAJECTORY_BUILDER_2D.motion_filter.max_angle_radians = math.rad(1.0)  -- 保持角度阈值

-- 子图配置 - 关键优化:针对180450点激光雷达
TRAJECTORY_BUILDER_2D.submaps.num_range_data = 25  -- 从50减少到25,更快生成子图
TRAJECTORY_BUILDER_2D.submaps.grid_options_2d.grid_type = "PROBABILITY_GRID"
TRAJECTORY_BUILDER_2D.submaps.grid_options_2d.resolution = 0.1  -- 对于100米范围,适当降低分辨率

-- 关键优化:概率网格范围数据插入器参数 - 解决5分钟问题的核心
TRAJECTORY_BUILDER_2D.submaps.range_data_inserter.range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D"
TRAJECTORY_BUILDER_2D.submaps.range_data_inserter.probability_grid_range_data_inserter.insert_free_space = true  -- 确保启用自由空间插入
TRAJECTORY_BUILDER_2D.submaps.range_data_inserter.probability_grid_range_data_inserter.hit_probability = 0.65  -- 提高命中概率
TRAJECTORY_BUILDER_2D.submaps.range_data_inserter.probability_grid_range_data_inserter.miss_probability = 0.35   -- 降低缺失概率

-- 实时相关性扫描匹配器 - 适配180度扫描
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.linear_search_window = 0.15  -- 减小搜索窗口
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.angular_search_window = math.rad(15.0)  -- 减小角度搜索
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.translation_delta_cost_weight = 1e-1
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.rotation_delta_cost_weight = 1e-1

-- Ceres扫描匹配器权重
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.occupied_space_weight = 1.0
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight = 10.0
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.rotation_weight = 40.0

-- 全局SLAM配置 - 适配大范围环境
POSE_GRAPH.optimize_every_n_nodes = 30  -- 从50减少到30
POSE_GRAPH.constraint_builder.sampling_ratio = 0.3  -- 对于大范围,适当降低采样比率
POSE_GRAPH.constraint_builder.max_constraint_distance = 20.0  -- 增大约束距离以适应100米范围
POSE_GRAPH.constraint_builder.min_score = 0.5  -- 保持适中的分数阈值

-- 快速相关性扫描匹配器配置 - 适配大范围
POSE_GRAPH.constraint_builder.fast_correlative_scan_matcher.linear_search_window = 10.0  -- 增大线性搜索窗口
POSE_GRAPH.constraint_builder.fast_correlative_scan_matcher.angular_search_window = math.rad(30.0)
POSE_GRAPH.constraint_builder.fast_correlative_scan_matcher.branch_and_bound_depth = 7

-- Ceres扫描匹配器配置
POSE_GRAPH.constraint_builder.ceres_scan_matcher.occupied_space_weight = 20.0
POSE_GRAPH.constraint_builder.ceres_scan_matcher.translation_weight = 10.0
POSE_GRAPH.constraint_builder.ceres_scan_matcher.rotation_weight = 1.0

-- 全局SLAM姿态图优化器
POSE_GRAPH.optimization_problem.huber_scale = 1e1
POSE_GRAPH.optimization_problem.acceleration_weight = 1.1e2
POSE_GRAPH.optimization_problem.rotation_weight = 1.6e4

return options

创建Launch文件

~/catkin_ws/install_isolated/share/cartographer_ros/launch/目录下创建isaac_sim_2d.launch

<!--
  Launch file for Isaac Sim 2D SLAM using Cartographer ROS (基于实际激光雷达参数)
  激光雷达配置:180度,450点,0.4-100米范围
-->

<launch>
  <!-- Robot Description -->
  <param name="robot_description"
    textfile="$(find cartographer_ros)/urdf/isaac_sim_robot.urdf" />

  <!-- Robot State Publisher -->
  <node name="robot_state_publisher" pkg="robot_state_publisher"
    type="robot_state_publisher" />

  <!-- Static Transform Publisher for map->odom if needed -->
  <node pkg="tf2_ros" type="static_transform_publisher" name="map_odom_broadcaster"
    args="0 0 0 0 0 0 map odom" />

  <!-- Cartographer Node -->
  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename isaac_sim_2d.lua"
      output="screen">
    <!-- Topic remapping to match Isaac Sim topics -->
    <remap from="points2" to="robot_lidar_pointcloud" />
    
    <!-- 性能优化参数 -->
    <param name="collect_metrics" value="false"/>
    <param name="use_trajectory_builder_2d" value="true"/>
  </node>

  <!-- Cartographer Occupancy Grid Node - 针对100米范围优化 -->
  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" 
      args="-resolution 0.05 -publish_period_sec 0.5" 
      output="screen">
    
    <!-- 关键参数:占用网格阈值设置 - 提高障碍物识别准确性 -->
    <param name="occupied_thresh" value="0.50"/>     <!-- 降低占用阈值:概率>50%认为是障碍物,更安全 -->
    <param name="free_thresh" value="0.30"/>         <!-- 提高空闲阈值:概率<30%认为是空闲,更保守 -->
    <param name="map_update_rate" value="0.5"/>      <!-- 地图更新频率:0.5Hz (大范围地图) -->

    <!-- 优化参数:保守的障碍物识别策略 -->
    <param name="track_unknown_space" value="true"/> 
    <param name="use_maximum" value="true"/>         <!-- 启用最大值策略,保留障碍物信息 -->
    <param name="lethal_cost_threshold" value="50"/> <!-- 降低致命代价阈值,更早识别障碍物 -->
    <param name="unknown_cost_value" value="-1"/>    
    <param name="trinary_costmap" value="false"/>    <!-- 禁用三元地图,保留更多细节信息 -->     
    
    <!-- 发布设置 -->
    <param name="frame_id" value="map"/>
    <param name="subscribe_to_updates" value="false"/>
  </node>

  <!-- TF2 Buffer Server - 扩大缓冲区以适应大范围环境 -->
  <node pkg="tf2_ros" type="buffer_server" name="tf2_buffer_server">
    <param name="buffer_size" value="300.0"/>  <!-- 增大缓冲区 -->
  </node>

  <!-- RViz Visualization -->
  <node name="rviz" pkg="rviz" type="rviz" 
      args="-d $(find cartographer_ros)/configuration_files/demo_2d.rviz" 
      required="false">
    <param name="frame_timeout" value="30.0"/>  <!-- 增大超时时间 -->
  </node>

  <!-- 诊断工具:监控话题频率和数据质量 -->
  <node pkg="rostopic" type="rostopic" name="lidar_hz_monitor"
      args="hz /robot_lidar_pointcloud -w 10"
      output="log" required="false"/>
      
  <node pkg="rostopic" type="rostopic" name="map_hz_monitor"
      args="hz /map -w 10"
      output="log" required="false"/>

  <!-- 激光雷达数据质量监控 -->
  <node pkg="rostopic" type="rostopic" name="lidar_echo_monitor"
      args="echo /robot_lidar_pointcloud/header -n 5"
      output="log" required="false"/>

</launch>

第二步:启动顺序

2.1 终端1:启动ROS核心

# 激活你的conda环境
conda activate myenv_py38

# 设置ROS环境
source /opt/ros/noetic/setup.bash
source ~/catkin_ws/install_isolated/setup.bash

# 启动roscore
roscore

2.2 终端2:启动Isaac Sim

# 启动Isaac Sim(根据你的安装路径调整)
cd ~/isaacsim  # 或者你的Isaac Sim安装路径
./isaac-sim.sh

# 或者如果你有python脚本启动:
./python.sh /path/to/your/isaac_sim_script.py
#笔者自己运行如下
./python.sh /home/lwb/Project/CleanUp_Bench_SVSDF/main_system.py

3d654c97caa3b39a6fa3adb38940bf26.jpg 重要:确保Isaac Sim中的Action Graph正在运行并发布点云数据

2.3 终端3:验证Isaac Sim话题

# 激活环境
conda activate myenv_py38
source /opt/ros/noetic/setup.bash

# 检查话题是否正确发布
rostopic list | grep robot_lidar

# 检查点云数据
rostopic echo /robot_lidar_pointcloud --noarr

# 检查发布频率
rostopic hz /robot_lidar_pointcloud

2.4 终端4:启动Cartographer

# 激活环境
conda activate myenv_py38
source /opt/ros/noetic/setup.bash
source ~/catkin_ws/install_isolated/setup.bash

# 启动Cartographer SLAM
roslaunch cartographer_ros isaac_sim_2d.launch

RViz配置步骤:

  1. 设置Fixed Frame为map

  2. 添加以下显示项:

    • Map (nav_msgs/OccupancyGrid) - Topic: /map
    • PointCloud2 (sensor_msgs/PointCloud2) - Topic: /scan_matched_points2
    • TF - 显示坐标系
    • Axes - 显示坐标轴

4 保存地图

# 保存当前SLAM状态
rosservice call /write_state "{filename: '~/isaac_sim_map.pbstream', include_unfinished_submaps: true}"

# 保存占用栅格地图
rosrun map_server map_saver -f ~/isaac_sim_map map:=/map

Cartographer RViz参数详细说明表

image.png

PointCloud2 部分

参数名称当前值功能说明
Topic/scan_matched_points2Cartographer发布的经过扫描匹配处理后的点云数据,用于子图匹配
StatusOk话题连接状态正常
Queue Size10ROS消息队列大小,控制缓存消息数量
Selectable允许在RViz中点击选择该显示项
StyleFlat Squares点云显示样式,采用平方块渲染
Size (m)0.05每个点的显示大小,单位为米
Alpha1透明度设置(0-1,1为完全不透明)
Decay Time0点云衰减时间,0表示永不消失
Position TransformerXYZ位置坐标变换方式,使用标准XYZ坐标
Color TransformerFlatColor颜色变换方式,使用固定颜色
Color绿色 (0;255;0)点云显示颜色为绿色

Trajectories 部分

参数名称当前值功能说明
Topic/trajectory_node_listSLAM轨迹节点列表,显示机器人运动轨迹
StatusError当前连接错误,可能话题未发布或数据格式问题
Marker Topic/trajectory_node_list轨迹可视化标记话题
Queue Size100消息队列大小,缓存更多轨迹数据
相关配置trajectory_publish_period_sec控制轨迹标记发布频率的参数

Landmark Poses 部分

参数名称当前值功能说明
Topic/landmark_poses_list地标位置列表,用于辅助定位
StatusOk连接状态正常
Marker Topic/landmark_poses_list地标可视化标记话题
Queue Size100消息队列大小
相关配置use_landmarksLua配置中启用地标功能的开关

Constraints 部分(约束可视化)

约束类型话题/状态功能说明
主话题/constraint_list显示所有约束信息的主话题
整体状态Error当前显示错误状态
Marker Topic/constraint_list约束可视化标记话题
Queue Size100消息队列大小

约束子类型详解

约束子类型英文名称功能描述
局部约束Intra constraints轨迹上相邻节点间的自动约束,保持局部结构一致性
局部残差Intra residuals局部约束优化过程中的残差信息
回环约束(同轨迹)Inter constraints, same trajectory同一轨迹内的回环闭合约束,修正累积误差
回环残差(同轨迹)Inter residuals, same trajectory同轨迹回环约束的残差信息
多轨迹约束Inter constraints, different trajectories不同轨迹间的约束(多机器人SLAM场景)

相关配置参数

配置参数作用说明
POSE_GRAPH.optimize_every_n_nodes控制全局优化频率,设为0可禁用全局SLAM
POSE_GRAPH.constraint_builder.log_matches启用约束匹配日志记录
POSE_GRAPH.log_residual_histograms启用残差直方图日志
TRAJECTORY_BUILDER_nD.voxel_filter_size影响点云密度和显示效果

终极:对未知地图的探索

完整的MapEx环境设置教程

1. 确保MapEx仓库已克隆

# 如果还没有克隆仓库,先执行:
cd ~
git clone --recurse-submodules https://github.com/castacks/MapEx.git
cd MapEx
git checkout main
git submodule update --init --recursive

2. 进入lama子模块目录并创建conda环境

# 从你当前的位置进入MapEx/lama目录
cd ~/MapEx/lama

# 使用conda创建环境(替代原文档中的mamba命令)
conda env create -f conda_env.yml

# 激活lama环境
conda activate lama

4. 下载预训练模型

您可以从此链接下载预训练模型。将 zip 文件放在Downloads文件夹目录下并解压缩文件。

# 创建预训练模型目录(如果不存在)
mkdir -p ~/MapEx/pretrained_models
# 下载并解压预训练模型(需要先下载weights.zip文件)
# 假设你已经下载了weights.zip到Downloads文件夹
mv ~/Downloads/weights.zip ~/MapEx/pretrained_models/
cd ~/MapEx/pretrained_models/
unzip weights.zip

5. 安装range_libc

# 确保lama环境已激活
conda activate lama

# 进入range_libc目录并安装
cd ~/MapEx/range_libc/pywrapper
python3 setup.py install 
pip3 install Cython

6. 安装KTH工具箱依赖项

# 安装Python依赖
python3 -m pip install pyastar2d

# 使用conda安装numba
conda install numba --yes

7. 验证安装

# 测试运行MapEx
cd ~/MapEx/scripts/
python3 explore.py

8.更新文件

/home/lwb/MapEx/configs/base.yaml
/home/lwb/MapEx/scripts/explore.py

环境路径说明

  • 你的miniconda3安装在:/home/lwb/miniconda3
  • lama环境将创建在:/home/lwb/miniconda3/envs/lama
  • MapEx项目目录:~/MapEx(即/home/lwb/MapEx

常用命令

# 激活lama环境
conda activate lama

# 退出环境
conda deactivate

# 查看已安装的包
conda list

# 删除环境(如果需要重新安装)
conda env remove -n lama

详细运行步骤(6个终端)

终端1: 启动ROS核心

# 激活Cartographer环境
conda activate myenv_py38
source /opt/ros/noetic/setup.bash
source ~/catkin_ws/install_isolated/setup.bash

# 启动roscore
roscore

终端2: 启动ROS桥接节点

# 激活Cartographer环境(与ROS同环境)
conda activate myenv_py38
source /opt/ros/noetic/setup.bash
source ~/catkin_ws/install_isolated/setup.bash

# 启动独立ROS桥接节点
cd /home/lwb/Project/CleanUp_Bench_SVSDF/
python3 ros_bridge_node.py

重要: 这个节点负责Isaac Sim与ROS系统的通信,必须在Isaac Sim启动前运行。

终端3: 启动Isaac Sim主系统

# 进入Isaac Sim目录
cd ~/isaacsim

# 启动主系统(使用Isaac Sim的Python 3.10环境)
./python.sh /home/lwb/Project/CleanUp_Bench_SVSDF/main_system.py

等待: 确保看到"ROS桥接连接成功!"消息后再继续下一步。

终端4: 启动Cartographer SLAM

# 激活Cartographer环境
conda activate myenv_py38
source ~/catkin_ws/install_isolated/setup.bash && roslaunch cartographer_ros isaac_sim_2d.launch

等待: 确保Isaac Sim已开始发布/robot_lidar_pointcloud话题。

终端5: 启动ROS桥接节点

# 激活Cartographer环境(与ROS同环境)
conda activate myenv_py38
source /opt/ros/noetic/setup.bash
source ~/catkin_ws/install_isolated/setup.bash

# 启动独立ROS桥接节点
cd /home/lwb/Project/CleanUp_Bench_SVSDF/
python3 MapEx_Bridge_Node.py

终端6: 启动MapEx探索

# 激活MapEx环境
conda activate lama
cd ~/MapEx/scripts/

# 等待Cartographer开始建图后运行
python3 explore.py

终端7: 验证连接

conda activate myenv\_py38
source /opt/ros/noetic/setup.bash

echo "=== 系统连接验证 ==="

echo "1. 检查Isaac Sim激光雷达数据:"
timeout 5s rostopic echo /robot\_lidar\_pointcloud --noarr | head -3

echo "2. 检查Cartographer地图:"
timeout 5s rostopic echo /map --noarr | head -3

echo "3. 检查速度指令:"
timeout 5s rostopic echo /cmd\_vel --noarr | head -3

echo "4. 节点连接图:"
rosnode list | grep -E "(bridge|cartographer|isaac)"

echo "5. 话题频率:"
echo "激光雷达频率:"
timeout 10s rostopic hz /robot\_lidar\_pointcloud

echo "地图更新频率:"
timeout 10s rostopic hz /map

等待: 确保Cartographer已开始发布/map话题。