基础: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
- 打开Isaac Sim
- 进入Window > Extensions
- 搜索"ROS Bridge"
- 启用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
- 打开Window > Visual Scripting > Action Graph
- 创建新的Action Graph,命名为"LiDAR_Publisher"
- 按以下顺序添加节点并连接:
核心节点列表
- On Playbook Tick - 触发节点
- Isaac Read Lidar Point Cloud Node - 读取LiDAR点云数据节点
- ROS1 Publish Point Cloud - ROS1发布点云数据
- 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_pointcloudinputs: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)
4.2 创建相机数据发布的Action Graph
- 创建新的Action Graph,命名为"Camera_Publisher"
- 按以下顺序添加节点并连接:
核心节点列表
- On Playbook Tick - 触发节点
- Isaac Create Viewport - 创建视窗
- Constant Int - 常量整数节点(设置Viewport ID)
- Set Active Camera - 设置活动相机
- Get Prim Path - 获取Prim路径
- ROS1 Camera Helper - ROS1相机助手
- 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=rgbinputs: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)
5. 传感器绑定到机器人
创建传感器后,需要将它们绑定到机器人相应部位:
5.1 绑定LiDAR到底盘
- 在Stage面板中,将
/World/robot_lidar拖拽到你的机器人底盘节点下 - 调整其Transform属性,设置合适的位置
5.2 绑定相机到机械臂
- 在Stage面板中,将
/World/robot_camera拖拽到你的机械臂末端节点下 - 调整其Transform属性,设置合适的位置和角度
6. 运行测试流程
6.1 启动ROS核心(终端1)
# 在第一个终端启动 roscore
roscore
6.2 启动Isaac Sim(终端2)
在Isaac Sim中点击Play按钮开始仿真。
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 或类似的话题名称
6.5 查看节点图(终端4,可选)
# 设置ROS环境
source /opt/ros/noetic/setup.bash
# 启动 rqt_graph 查看节点关系
rqt_graph
7. RViz可视化LiDAR数据
7.1 启动RViz
在新的终端中运行:
rosrun rviz rviz
7.2 设置固定坐标系
- 在RViz左侧面板的Global Options中
- 将Fixed Frame设置为:
robot_lidar_frame
7.3 添加PointCloud2显示插件
- 点击RViz左下角的Add按钮
- 在弹出的窗口中选择PointCloud2
- 点击OK
7.4 配置PointCloud2显示属性
在左侧面板中找到刚添加的PointCloud2,展开其属性:
-
Topic: 设置为
/robot_lidar_pointcloud -
Size (Pixels) : 设置为
3(点的大小) -
Style: 选择
Points(点显示模式) -
Color Transformer: 可以选择:
Intensity- 按强度着色AxisColor- 按轴向着色FlatColor- 单一颜色
-
Decay Time: 设置为
0(不保留历史点云)
7.5 同时可视化相机图像(可选)
如果你也想查看相机图像:
- 再次点击Add按钮
- 选择Image插件
- 设置Image Topic为:
/robot_camera_image
7.6 保存RViz配置
为了方便下次使用,建议保存配置:
- 点击菜单File > Save Config As
- 保存为:
robot_sensors.rviz
8. 效果展示
8.1 运行效果
使用以下命令启动系统:
cd isaacsim
./python.sh /home/lwb/Project/CleanUp_Bench_SVSDF/main_system.py
8.2 激光雷达参数调整效果
通过调整LiDAR参数可以获得不同的扫描效果:
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文档:
为了构建 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米范围,设置为5米
TRAJECTORY_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) -- 保持角度阈值
-- 子图配置 - 关键优化:针对180度450点激光雷达
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
重要:确保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配置步骤:
-
设置Fixed Frame为
map -
添加以下显示项:
- Map (nav_msgs/OccupancyGrid) - Topic:
/map - PointCloud2 (sensor_msgs/PointCloud2) - Topic:
/scan_matched_points2 - TF - 显示坐标系
- Axes - 显示坐标轴
- Map (nav_msgs/OccupancyGrid) - Topic:
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参数详细说明表
PointCloud2 部分
| 参数名称 | 当前值 | 功能说明 |
|---|---|---|
| Topic | /scan_matched_points2 | Cartographer发布的经过扫描匹配处理后的点云数据,用于子图匹配 |
| Status | Ok | 话题连接状态正常 |
| Queue Size | 10 | ROS消息队列大小,控制缓存消息数量 |
| Selectable | ✓ | 允许在RViz中点击选择该显示项 |
| Style | Flat Squares | 点云显示样式,采用平方块渲染 |
| Size (m) | 0.05 | 每个点的显示大小,单位为米 |
| Alpha | 1 | 透明度设置(0-1,1为完全不透明) |
| Decay Time | 0 | 点云衰减时间,0表示永不消失 |
| Position Transformer | XYZ | 位置坐标变换方式,使用标准XYZ坐标 |
| Color Transformer | FlatColor | 颜色变换方式,使用固定颜色 |
| Color | 绿色 (0;255;0) | 点云显示颜色为绿色 |
Trajectories 部分
| 参数名称 | 当前值 | 功能说明 |
|---|---|---|
| Topic | /trajectory_node_list | SLAM轨迹节点列表,显示机器人运动轨迹 |
| Status | Error | 当前连接错误,可能话题未发布或数据格式问题 |
| Marker Topic | /trajectory_node_list | 轨迹可视化标记话题 |
| Queue Size | 100 | 消息队列大小,缓存更多轨迹数据 |
| 相关配置 | trajectory_publish_period_sec | 控制轨迹标记发布频率的参数 |
Landmark Poses 部分
| 参数名称 | 当前值 | 功能说明 |
|---|---|---|
| Topic | /landmark_poses_list | 地标位置列表,用于辅助定位 |
| Status | Ok | 连接状态正常 |
| Marker Topic | /landmark_poses_list | 地标可视化标记话题 |
| Queue Size | 100 | 消息队列大小 |
| 相关配置 | use_landmarks | Lua配置中启用地标功能的开关 |
Constraints 部分(约束可视化)
| 约束类型 | 话题/状态 | 功能说明 |
|---|---|---|
| 主话题 | /constraint_list | 显示所有约束信息的主话题 |
| 整体状态 | Error | 当前显示错误状态 |
| Marker Topic | /constraint_list | 约束可视化标记话题 |
| Queue Size | 100 | 消息队列大小 |
约束子类型详解
| 约束子类型 | 英文名称 | 功能描述 |
|---|---|---|
| 局部约束 | 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话题。