安装

支持apt 安装

# 安装Cartographer核心包:打开终端,输入以下命令(将${ROS_DISTRO}替换为你使用的ROS发行版名称,例如melodic、noetic等):
sudo apt install ros-${ROS_DISTRO}-cartographer
# 安装Cartographer的ROS接口包:接着安装ROS功能包,以便在ROS中使用Cartographer
sudo apt install ros-${ROS_DISTRO}-cartographer-ros

源码安装步骤

sudo apt-get install -y build-essential protobuf-compiler clang cmake g++ git google-mock libboost-all-dev libcairo2-dev libcurl4-openssl-dev libeigen3-dev libgflags-dev libgoogle-glog-dev liblua5.2-dev libsuitesparse-dev lsb-release ninja-build stow  python3-sphinx libgmock-dev libmetis-dev libceres-dev

# 1. 清理已安装的 Abseil
sudo rm -rf /usr/local/lib/libabsl*
sudo rm -rf /usr/local/include/absl
sudo rm -rf /usr/local/lib/cmake/absl

mkdir -p carto_ws/src
# 2. 下载最新源码
git clone https://github.com/abseil/abseil-cpp.git
cd abseil-cpp
git checkout 20211102.0  # 使用与你的项目兼容的版本

# 3. 创建构建目录并配置(关键步骤:启用-fPIC)
mkdir build && cd build
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
      -DCMAKE_INSTALL_PREFIX=/usr/local \
      -DBUILD_SHARED_LIBS=ON ..  # 也可以构建共享库版本

# 4. 编译和安装
make -j$(nproc)
sudo make install

cd carto_ws/src
git clone https://github.com/cartographer-project/cartographer.git
git clone https://github.com/cartographer-project/cartographer_ros.git


cd carto_ws
# 5. 编译cartographer
catkin_make_isolated --pkg cartographer
catkin_make_isolated --pkg cartographer_ros

相关问题

问题:

CMake Error at /usr/local/lib/cmake/Ceres/CeresConfig.cmake:85 (message):
Failed to find Ceres - Missing requested Ceres components: [SuiteSparse]
(components requested: [SuiteSparse]). Detected Ceres version: 2.0.0
installed in: /usr/local with components: [EigenSparse,
SparseLinearAlgebraLibrary, LAPACK, SchurSpecializations, Multithreading].
Call Stack (most recent call first):
/usr/local/lib/cmake/Ceres/CeresConfig.cmake:313 (ceres_report_not_found)
CMakeLists.txt:39 (find_package)

解决:sudo apt-get install libsuitesparse-dev

问题:

/usr/bin/ld: /usr/local/lib/libabsl_base.a(sysinfo.cc.o): relocation R_X86_64_TPOFF32 against _ZGVZN4absl12lts_2021110213base_internal12GetCachedTIDEvE9thread_id' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/local/lib/libabsl_synchronization.a(mutex.cc.o): relocation R_X86_64_PC32 against symbol ZN4absl12lts_202111029Condition19CallVoidPtrFunctionEPKS1’ can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value

解决:

mkdir build && cd build
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
      -DCMAKE_INSTALL_PREFIX=/usr/local \
      -DBUILD_SHARED_LIBS=ON ..  # 也可以构建共享库版本

# 4. 编译和安装
make -j$(nproc)
sudo make install

问题:

[ERROR] [1758800190.715302590]: PluginlibFactory: The plugin for class ‘Submaps’ failed to load. Error: Failed to load library /home/niebaozhen/workspace/docker_ws/ros1_ws/devel_isolated/cartographer_rviz/lib//libcartographer_rviz.so. Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: Could not load library (Poco exception = libabsl_graphcycles_internal.so.2111.0.0: cannot open shared object file: No such file or directory)

解决:安装步骤,重新执行3、4和5。

问题:

QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to ‘/tmp/runtime-root’
[rospack] Error: package ‘velodyne_description’ not found
[librospack]: error while executing command

解决:cartographer 会自动读取消息类型等,直接订阅velodyne_description 文件。
下载安装

sudo apt-get install ros-<distro>-velodyne-description

因为我是仿真,通过源码下载编译的,所有直接source上velodyne-description对应的空间的setup.sh就可以

问题:The IMU frame must be colocated with the tracking frame.
解决:.lua文件的tracking_frame 必须与/imu topic发布的/frame一致。

Could not compute submap fading: “map” passed to lookupTransform argument target_frame does not exist.
.lua 文件的map_frame=“map” 换成odom


  source devel_isolated/setup.bash #注意:是devel_isolated
  
  rosrun cartographer_ros cartographer_pbstream_map_converter \
    --pbstream_filename=input.pbstream \
    --output_file_prefix=output 

问题:[FATAL] [1760417080.629158361]: F1014 04:44:40.000000 518873 lua_parameter_dictionary.cc:410] Check failed: 1 == reference_counts_.count(key) (1 vs. 0) Key &#x27;use_imu_data&#x27; was used the wrong number of times.
此类问题多为没有对应的参数项,如caartographer 3D 没有use_imu_data的配置项,
解决:通过在carto_ws/devel_isolated/cartographer/share/cartographer/configuration_files下查找对应的lua文件,查看对应的配置项,进行正确配置。

相关链接

添加3D点云支持:
https://zhuanlan.zhihu.com/p/410177996
https://github.com/xiangli0608/cartographer_detailed_comments_ws

官方:
https://google-cartographer.readthedocs.io/en/latest/
https://google-cartographer-ros.readthedocs.io/en/latest/

vlp16 2D支持
https://blog.csdn.net/aidimoli123/article/details/125364445

https://jishuzhan.net/article/1931542166681202689
https://blog.csdn.net/qq_52785580/article/details/127000553


<launch>
  <param name="/use_sim_time" value="true" />

  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename vlp_3d.lua"
      output="screen">
    <!--remap from="scan" to="/scan" /-->
    <remap from="points2" to="/velodyne_points" />
    <remap from="imu" to="/trunk_imu" />
  </node>

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" args="-resolution 0.05" />
  <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/demo_3d.rviz" />

</launch>
include "map_builder.lua"
include "trajectory_builder.lua"

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",
  tracking_frame = "imu_link",
  published_frame = "velodyne",
  odom_frame = "odom",
  provide_odom_frame = true,
  publish_frame_projected_to_2d = false,
  use_pose_extrapolator = true,
  use_odometry = false,
  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,
  lookup_transform_timeout_sec = 0.2,
  submap_publish_period_sec = 0.3,
  pose_publish_period_sec = 5e-3,
  trajectory_publish_period_sec = 30e-3,
  rangefinder_sampling_ratio = 1.,
  odometry_sampling_ratio = 1.,
  fixed_frame_pose_sampling_ratio = 1.,
  imu_sampling_ratio = 1.,
  landmarks_sampling_ratio = 1.,
}

MAP_BUILDER.use_trajectory_builder_3d = true
TRAJECTORY_BUILDER_3D.num_accumulated_range_data = 1
TRAJECTORY_BUILDER_3D.submaps.num_range_data = 160

MAP_BUILDER.num_background_threads = 7
POSE_GRAPH.constraint_builder.sampling_ratio = 0.03
POSE_GRAPH.optimization_problem.ceres_solver_options.max_num_iterations = 10
POSE_GRAPH.constraint_builder.global_localization_min_score = 0.66

POSE_GRAPH.optimization_problem.huber_scale = 1e2
POSE_GRAPH.optimize_every_n_nodes = 35
POSE_GRAPH.constraint_builder.min_score = 0.65
return options         

使用

cartographer_ros

launch参数:

  <node name="cartographer_node" pkg="cartographer_ros" type="cartographer_node" 
    args="-configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename mid360_simple_2d.lua
          -minloglevel 2"
    output="screen">

    <!--remap from="/scan" to="/headLaserScan"/-->
    <!--remap from="points2" to="/livox/lidar"/-->
    <remap from="imu" to="/livox/imu" />
  </node>

-minloglevel 2 :要求输出error及以上级别的log。降低io消耗,从而降低cpu负载
const int GLOG_INFO =0,GLOG_WARNING =1,GLOG_ERROR = 2,GLOG_FATAL = 3, NUM SEVERITIES =4:

carto坐标系

在Cartographer中,地图坐标系(map_frame)z轴与重力对齐。初始时,cartographer提供的odom与map对齐,即同时也与重力对齐。
建筑物通常是与重力(铅垂线)对齐的。

而雷达的本体坐标系通常是完全与机身固连及水平的,由于雷达可能不是按水平安装的,因而其机体坐标系与重力方向是没有对齐的,包括起始阶段

当雷达上下轴(多为z轴)不与重力方向一致放置时,能够看到基于雷达机体坐标系的点云是歪的。rviz显示imu方向时,能够看到其与重力方向一致。

参数配置

Cartographer 的 Lua 配置文件是其高效工作的核心,它决定了传感器数据如何被处理、地图如何构建以及机器人如何定位。

一个典型的Lua配置文件开头会包含以下语句,引入更详细的构建器配置:

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

map_buildertrajectory_builder 字段分别对应这两个引入的配置表。
trajectory_builder.lua又包含trajectory_builder_2d.luatrajectory_builder_3d.lua

在launch时,会在carto_ws/devel_isolated/cartographer/share/cartographer/configuration_files下查找对应的lua文件。该路径下包含的lua文件有:

map_builder.lua map_builder_server.lua pose_graph.lua trajectory_builder.lua trajectory_builder_2d.lua trajectory_builder_3d.lua

参数类别 核心参数示例 简要说明
框架设置 (Frames) map_frame, tracking_frame, published_frame 定义坐标系,是TF树正确构建的基础。
传感器设置 (Sensors) use_odometry, num_laser_scans, num_point_clouds 声明使用哪些传感器以及其数据话题数量。
采样比率 (Sampling Ratios) rangefinder_sampling_ratio, imu_sampling_ratio 控制各类传感器数据的使用频率。
超时与周期 (Timeouts & Periods) lookup_transform_timeout_sec, pose_publish_period_sec 设置TF查找超时和各种信息发布的周期。
地图与轨迹构建器 MAP_BUILDER.use_trajectory_builder_2d/3d 选择2D或3D建图模式,并链接更详细的配置。

- 修改后重新编译:对Lua配置文件进行修改后,需要重新编译Cartographer工作空间才能使更改生效。 测试不需要。

核心参数

这部分参数,直接关系到Cartographer能否正确接收到传感器数据并发布正确的坐标变换。

  • map_frame (字符串,默认"map"): 全局地图的坐标系ID,是所有发布的位姿的父坐标系。
  • tracking_frame (字符串): 关键参数。指定了SLAM算法用于追踪的坐标系。所有传感器数据都需要被转换到这个坐标系下进行计算。如果使用了IMU,通常设置为 "imu_link";如果没有IMU,可以设置为机器人的基坐标系(如 "base_link")。在Gazebo等仿真环境中,有时由于插件问题,可能需要设置为 "base_footprint"
  • published_frame (字符串): 指定Cartographer发布的位姿变换的子坐标系(最底层)。例如,如果系统的里程计坐标系 "odom" 由其他部分提供,这里就设为 "odom";否则,可以设为 "base_link"
  • odom_frame (字符串,默认"odom"): 仅在 provide_odom_frametrue 时使用。它定义了在 published_framemap_frame 之间用于发布局部SLAM结果(非闭环校正)的坐标系。
  • provide_odom_frame (布尔值): 如果启用(设为 true),Cartographer 将提供 map_frameodom_frame 的变换,否则直接提供 map_framepublished_frame 的变换。这决定了TF树的结构是 map -> odom -> base_link 还是 map -> base_link

注意:

  • 坐标系一致性:确保 tracking_frame 等参数设置的坐标系在你的机器人TF树中真实存在,并且所有传感器到该坐标系的变换都已正确发布。这是避免 Could not transformframe does not exist 错误的关键。
  • 参数联动性:例如,published_frameprovide_odom_frame 的设置是联动的,需要根据机器人系统是否有独立的里程计odom来源来共同决定。
传感器参数

这些参数告诉Cartographer使用哪些传感器。

  • use_odometry (布尔值,默认false): 是否使用里程计数据。如果启用,必须提供 nav_msgs/Odometry 类型的话题(默认话题名为 "odom")。
  • num_laser_scans (整数,默认0): 订阅的单线激光扫描 (sensor_msgs/LaserScan) 话题的数量。如果使用一个普通的单线激光雷达,应设为 1
  • num_multi_echo_laser_scans (整数,默认0): 订阅的多回波激光扫描 (sensor_msgs/MultiEchoLaserScan) 话题的数量。
  • num_point_clouds (整数,默认0): 订阅的点云 (sensor_msgs/PointCloud2) 话题的数量。如果使用VLP-16等3D激光雷达,应设为 1

    重要提示num_laser_scansnum_point_clouds 是互斥的,请根据雷达输出类型正确设置,否则会出现类似 Queue waiting for data 的错误。

  • use_nav_sat (布尔值,默认false): 是否使用GPS数据。
  • use_landmarks (布尔值,默认false): 是否使用路标点。
调优参数
  • 采样比率参数: 例如 odometry_sampling_ratioimu_sampling_ratio。这些参数可以控制传感器数据的使用频率,例如设成0.1即来10帧用1帧。如果某个传感器数据不准,可以降低其采样比率。
  • 超时与周期参数:
    • lookup_transform_timeout_sec (浮点数,默认0.2): 使用tf2查找坐标变换时的超时时间(秒)。
    • submap_publish_period_sec (浮点数,默认0.3): 发布子图的时间间隔。
    • pose_publish_period_sec (浮点数,例如5e-3): 发布位姿的时间间隔,频率为200Hz。
  • POSE_GRAPH.optimization_problem.use_online_imu_extrinsics_in_3d = true :开启imu在线标定,注意这个参数虽然标识了3d,但是是2D和3D lua文件都可以启用的参数。

lua写法

lua文件的配置项有两种写法,点/拓展重新定义
两种写法的作用域和时机不同。

两种写法的本质区别

特性 MAP_BUILDER = { use_trajectory_builder_3d = true } MAP_BUILDER.use_trajectory_builder_3d = true
行为 重新定义了整个 MAP_BUILDER 表。 扩展/修改了已存在的 MAP_BUILDER 表。
执行一个赋值操作,创建一个全新的、只包含 use_trajectory_builder_3d 这一个字段的表,并把它赋值给 MAP_BUILDER 变量。这会完全覆盖了之前从 map_builder.lua 加载的、包含所有默认配置的那个表。 执行一个字段赋值操作。它没有创建新表,而是在已存在的 MAP_BUILDER中找到 use_trajectory_builder_3d 这个字段,并将其值修改为 true
结果 重新定义新的MAP_BUILDER,覆盖了之前所有的 MAP_BUILDER 设置。 只修改指定字段,保留其他原有设置
MAP_BUILDER现在只剩下{ use_trajectory_builder_3d = true }。所有其他必要的默认参数(如 num_background_threads` 等)都丢失了。这很可能导致 Cartographer 内部因配置不完整而无法正确初始化,从而使你的设置"无效"。 MAP_BUILDER 表保留了所有从基础文件加载来的默认参数,同时只更新了你关心的这一个参数。这是安全且推荐的做法。

mid360

配置原理

输出与可视化
Cartographer 核心算法库
Cartographer_ros 桥接层
硬件驱动层
/scan
/imu
/odom
转换后的数据
配置参数
TF关系
控制
格式化的数据流
位姿, 子图
/tf, /map, /submap_list
/scan_matched_points
Rviz
可视化
其他ROS节点
SLAM Engine
前端/后端
sensor_bridge
node
ROS管理器
Lua Config Files
轨迹与传感器配置
URDF
坐标系定义
Map Builder Bridge
Lidar
激光雷达
IMU
惯性测量单元
Odometry
里程计
可选
原理模块 对应代码文件 主要配置与优化工作
传感器数据接入与转换 sensor_bridge.cc/h
msg_conversion.cc/h
tf_bridge.cc/h
确保数据格式和坐标系正确:
• 在Lua配置中正确设置 tracking_frame, published_frame, odom_frame
• 确认IMU数据的坐标系和朝向。
• 检查雷达数据的精度和噪声特性。
ROS管理与数据流 node.cc/h
node_main.cc
node_options.cc/h
配置核心参数:
use_odometry: 是否使用里程计。
use_imu_data: 是否使用IMU(2D参数)。
num_laser_scans/num_multi_echo_laser_scans: 雷达类型。
MAP_BUILDER.use_trajectory_builder_2d/3d: 选择2D或3D模式。
算法桥接与配置 map_builder_bridge.cc/h
trajectory_options.cc/h
性能调优(主要修改Lua文件):
前端匹配:调整 TRAJECTORY_BUILDER_xD.ceres_scan_matcherfast_correlative_scan_matcher 参数。
后端优化:调整 POSE_GRAPH.constraint_builder 相关参数(如搜索范围 max_constraint_distance)。
IMU用法:在3D模式下,配置 TRAJECTORY_BUILDER_3D.use_imu_data
地图输出与可视化 occupancy_grid_node_main.cc
submap.cc/h
assets_writer_main.cc
结果处理:
• 调整 occupancy_grid_node_main.cc 发布的地图分辨率。
• 使用 assets_writer_main 导出点云地图用于纯定位。

关键配置文件与参数

  • IMU使用:在3D模式或2D不平坦地面情况下,IMU用于提供重力方向约束和旋转预测。
  • 里程计使用:提供平移运动的先验,减少纯激光匹配的搜索空间。

关键Lua参数:

-- 前端参数
TRAJECTORY_BUILDER_2D = {
  ceres_scan_matcher = {
    occupied_space_weight = 1.0,    -- 占据空间代价权重
    translation_weight = 10.0,      -- 平移变化惩罚
    rotation_weight = 40.0,         -- 旋转变化惩罚
  },
  fast_correlative_scan_matcher = {
    linear_search_window = 7.0,     -- 线性搜索窗口大小
    angular_search_window = math.rad(30.),  -- 角度搜索窗口
  },
  motion_filter = {
    max_time_seconds = 0.5,         -- 最大时间间隔
    max_distance_meters = 0.2,      -- 最大移动距离
    max_angle_radians = math.rad(1.), -- 最大旋转角度
  }
}

-- 后端参数
POSE_GRAPH = {
  constraint_builder = {
    sampling_ratio = 0.3,           -- 子图采样比率
    max_constraint_distance = 15.0, -- 最大约束距离
    min_score = 0.55,               -- 闭环匹配最小分数
  },
  optimize_every_n_nodes = 90,      -- 每N个节点优化一次
}

调试与性能优化要点

  1. 前端问题(定位漂移):

    • 检查 PoseExtrapolator 的预测是否准确
    • 调整扫描匹配的搜索窗口和代价函数权重
  2. 后端问题(闭环不触发):

    • 增加 constraint_builder.max_constraint_distance
    • 降低 constraint_builder.min_score 但要注意误匹配
  3. 性能问题

    • 使用 VoxelFilter 降低点云密度
    • 调整 motion_filter 减少插入的扫描数量

使用LiDAR_IMU_Init标定

  1. 安装依赖库
sudo apt-get install -y liblapack-dev libsuitesparse-dev libcxsparse3 libgflags-dev libgoogle-glog-dev libgtest-dev

下载并编译ceres-1.14.0 (避免版本冲突)

wget http://ceres-solver.org/ceres-solver-1.14.0.tar.gz
tar xvf ceres-solver-1.14.0.tar.gz
mv ceres-solver-1.14.0 ceres-solver && cd ceres-solver
mkdir build && cd build
cmake .. -DBUILD_TESTING=OFF  # 关闭测试加速编译
make -j8
sudo make install

需安装livox_ros_driver2。安装参考:https://blog.csdn.net/weixin_41469272/article/details/151049976

  1. 下载编译Lidar_IMU_Init
cd ~/catkin_ws/src
git clone https://github.com/hku-mars/LiDAR_IMU_Init.git
cd LiDAR_IMU_Init
find . -type f ! -name “*.patch”|xargs sed -i “s/livox_ros_driver/livox_ros_driver2/g”
cd ../.. && catkin_make -j
source devel/setup.bash
  1. Usage
    以mid360为例:
rosrun LiDAR_IMU_Init LiDAR_IMU_Init -r /livox/lidar -i /imu
roslauanch LiDAR_IMU_Init livox_mid360.launch

首先保证雷达最少5秒静止。
然后前后左右上下晃动雷达,对应终端会显示标定进度条。
标定完成后,屏幕会打印标定数据,并保存数据到result/Initialization_result.txt。如下示例:

Initialization result:
Rotation LiDAR to IMU (degree)     = 0.735328 0.424355 0.666829
Translation LiDAR to IMU (meter)   =  0.006028 -0.000659  0.078033
Time Lag IMU to LiDAR (second)     = -0.018201
Bias of Gyroscope  (rad/s)         = -0.032095  0.002117  0.005433
Bias of Accelerometer (meters/s^2) = -0.009808 -0.010242  0.009945
Gravity in World Frame(meters/s^2) =  0.679424 -0.356164 -9.779961

Homogeneous Transformation Matrix from LiDAR to IMU:
 0.999905 -0.011541  0.007554  0.006028
 0.011637  0.999851 -0.012746 -0.000659
-0.007406  0.012832  0.999890  0.078033
 0.000000  0.000000  0.000000  1.000000


Refinement result:
Rotation LiDAR to IMU (degree)     = 0.705306 0.007528 0.690674
Translation LiDAR to IMU (meter)   =  0.012561 -0.006829  0.078586
Time Lag IMU to LiDAR (second)     = -0.018201
Bias of Gyroscope  (rad/s)         = -0.033351  0.008406  0.003908
Bias of Accelerometer (meters/s^2) = -0.014032 -0.007099  0.001429
Gravity in World Frame(meters/s^2) =  0.680758 -0.355685 -9.774088

Homogeneous Transformation Matrix from LiDAR to IMU:
 0.999927 -0.012051  0.000280  0.012561
 0.012053  0.999852 -0.012306 -0.006829
-0.000131  0.012309  0.999924  0.078586
 0.000000  0.000000  0.000000  1.000000
  1. Problems

Lidar_IMU_Init 编译,已经安装了livox_ros_driver,并source livox 的devel setup.sh了,还是报:
– Could not find the required component ‘livox_ros_driver’. The following CMake error indicates that you either need to install the package with the same name or change your environment so that it can be found.
CMake Error at /opt/ros/noetic/share/catkin/cmake/catkinConfig.cmake:83 (find_package):
Could not find a package configuration file provided by “livox_ros_driver”
with any of the following names:
livox_ros_driverConfig.cmake
livox_ros_driver-config.cmake

R:

替换livox_ros_driver驱动:point-lio下提供:
find . -type f ! -name “*.patch”|xargs sed -i “s/livox_ros_driver/livox_ros_driver2/g”


fatal error: numpy/arrayobject.h: No such file or directory
19 | # include <numpy/arrayobject.h>

R:
在CMakelist.txt 对应添加如下内容:

set(Python3_ROOT_DIR "/opt/conda")
find_package(Python3 COMPONENTS Interpreter Development REQUIRED)

execute_process(
    COMMAND ${Python3_EXECUTABLE} -c "import numpy; print(numpy.get_include())"
    OUTPUT_VARIABLE NUMPY_INCLUDE_DIR
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

include_directories( add:
  ${NUMPY_INCLUDE_DIR}

urdf

<robot name="mid360_simple">
  <material name="orange">
    <color rgba="1.0 0.5 0.2 1" />
  </material>
  <material name="gray">
    <color rgba="0.2 0.2 0.2 1" />
  </material>
  <material name="green">
    <color rgba="0.0 1.0 0.0 1" />
  </material>

  <link name="base_link" />

  <link name="livox_frame">
    <visual>
      <origin xyz="0.0 0.0 0.0" />
      <geometry>
        <cylinder length="0.07" radius="0.05" />
      </geometry>
      <material name="gray" />
    </visual>
  </link>

  <link name="imu_link">
    <visual>
      <origin xyz="0.0 0.0 0.0" />
      <geometry>
        <box size="0.06 0.04 0.02" />
      </geometry>
      <material name="orange" />
    </visual>
  </link>

  <!-- imu livox -->
  <joint name="imu_link_joint" type="fixed">
    <parent link="base_link" />
    <child link="imu_link" />
    <origin xyz="0 0 0" rpy="0 0 0" />
  </joint>

  <joint name="livox_frame_joint" type="fixed">
    <parent link="base_link" />
    <child link="livox_frame" />
    <origin xyz="0 0 0" rpy="0 0 0" />
  </joint>
</robot>

2D

关键问题
cartographer的map是对齐重力的,即对齐铅垂线。
将3D雷达通过pointcloud_to_laserscan转为2D scan时,当雷达出现俯仰和滚转时,会使得获得到的scan的横截面发生改变,继而影响scan匹配。
因而使用这种方法时,切记雷达的固连,且尽量不要使机体出现。

更新:

<launch>

  <param name="/use_sim_time" value="false" /> <!-- true: offline (rosbag); false: online -->

  <node pkg="tf2_ros" type="static_transform_publisher" name="lidar2bases" 
    args="0 0 0 0 -0.298 0 livox_frame base_link_alignG" />

  <node pkg="pointcloud_to_laserscan" type="pointcloud_to_laserscan_node" name="pointcloud_to_laserscan"
      respawn="false" output="screen">
      <remap from="cloud_in" to="/livox/lidar"/>
      <!--remap from="cloud_in" to="/rslidar_points"/-->
      <!--remap from="/scan" to="/headLaserScan"/-->
      <rosparam>
          target_frame: base_link_alignG
          transform_tolerance: 0.1
          min_height: 0.1
          max_height: 1.5

          angle_min: -3.14159
          angle_max: 3.14159
          angle_increment: 0.0175
          scan_time: 0.1
          range_min: 0.5
          range_max: 30.0
          use_inf: false

          # Concurrency level, affects number of pointclouds queued for processing and number of threads used
          # 0 : Detect number of cores
          # 1 : Single threaded
          # 2->inf : Parallelism level
          concurrency_level: 1
      </rosparam>
  </node>

  <param name="robot_description" textfile="$(find cartographer_ros)/urdf/mid360_simple.urdf" />


  <node name="joint_state_publisher" pkg="joint_state_publisher"
    type="joint_state_publisher" />
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />

  <node name="cartographer_node" pkg="cartographer_ros" type="cartographer_node" 
    args="-configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename mid360_simple_2d.lua"
    output="screen">

    <!--remap from="/scan" to="/headLaserScan"/-->
    <remap from="imu" to="/livox/imu" />
  </node>

  <!--TODO-->

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
    type="cartographer_occupancy_grid_node" args="-resolution 0.075" />

  <!--node name="rviz" pkg="rviz" type="rviz" required="true" 
    args="-d $(find cartographer_ros)/configuration_files/mid360_2d.rviz" /-->

  <!--node name="playbag" pkg="rosbag" type="play" args="--><!--clock -s 142 $(arg bagfile)" /-->

</launch>
include "map_builder.lua"
include "trajectory_builder.lua"

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",                      
  tracking_frame = "imu_link",            
  published_frame = "base_link",          
  odom_frame = "odom",                    
  provide_odom_frame = true,              
  --provide_tracking_frame_alignG = true,              
                                          
  publish_frame_projected_to_2d = false,  
  use_pose_extrapolator = false,          
  use_odometry = false,
  use_nav_sat = false,
  use_landmarks = false,
  num_laser_scans = 1,                    
  num_multi_echo_laser_scans = 0,         
  num_subdivisions_per_laser_scan = 1,    
  num_point_clouds = 0,                   
  lookup_transform_timeout_sec = 0.2,     
  submap_publish_period_sec = 0.3,        
  pose_publish_period_sec = 5e-3,
  trajectory_publish_period_sec = 30e-3,
  rangefinder_sampling_ratio = 1.,        
  odometry_sampling_ratio = 1.,
  fixed_frame_pose_sampling_ratio = 1.,
  imu_sampling_ratio = 1.,
  landmarks_sampling_ratio = 1.,

  publish_tracked_pose=true,
}


TRAJECTORY_BUILDER_2D.use_imu_data = true
TRAJECTORY_BUILDER_2D.submaps.num_range_data = 50
TRAJECTORY_BUILDER_2D.min_range = 0.3
TRAJECTORY_BUILDER_2D.max_range = 30.
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1.
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.linear_search_window = 0.2
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.angular_search_window = 0.3
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.translation_delta_cost_weight = 20.
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.rotation_delta_cost_weight = 2

TRAJECTORY_BUILDER_2D.ceres_scan_matcher = {
  occupied_space_weight = 2.5e4,
  translation_weight = 3e3,
  rotation_weight = 3e3,
  ceres_solver_options = {
    use_nonmonotonic_steps = false,
    max_num_iterations = 20,
    num_threads = 1,
  },
}

TRAJECTORY_BUILDER_2D.motion_filter = {
  max_time_seconds = 0.2,    -- 最大时间间隔(默认0.5s)
  max_distance_meters = 0.1, -- 最大距离间隔(默认0.4m)
  max_angle_radians = 0.01,  -- 最大角度间隔(默认0.05rad)
}

TRAJECTORY_BUILDER_2D.imu_gravity_time_constant = 3.
TRAJECTORY_BUILDER_2D.pose_extrapolator = {
  use_imu_based = false,  -- 2D true will error
  constant_velocity = {
    imu_gravity_time_constant = 1.,
    pose_queue_duration = 0.001,
  },
  imu_based = {
    pose_queue_duration = 5.,
    gravity_constant = 1,
    pose_translation_weight = 1.,
    pose_rotation_weight = 1.,
    imu_acceleration_weight = 1.,
    imu_rotation_weight = 10.,
    odometry_translation_weight = 1.,
    odometry_rotation_weight = 1.,
    solver_options = {
      use_nonmonotonic_steps = false;
      max_num_iterations = 10;
      num_threads = 1;
    },
  },
}

POSE_GRAPH.optimization_problem.huber_scale = 1e2
POSE_GRAPH.optimize_every_n_nodes = 55
POSE_GRAPH.constraint_builder.min_score = 0.35
POSE_GRAPH.optimization_problem.use_online_imu_extrinsics_in_3d = true

MAP_BUILDER.use_trajectory_builder_2d = true
MAP_BUILDER.num_background_threads = 6
MAP_BUILDER.use_trajectory_builder_2d = true

return options

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

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",
  tracking_frame = "imu_link",
  published_frame = "base_link",
  odom_frame = "odom",
  provide_odom_frame = true,

  publish_frame_projected_to_2d = false,
  use_pose_extrapolator = false,
  use_odometry = false,
  use_nav_sat = false,
  use_landmarks = false,
  num_laser_scans = 1,
  num_multi_echo_laser_scans = 0,
  num_subdivisions_per_laser_scan = 1,
  num_point_clouds = 0,
  lookup_transform_timeout_sec = 0.2,
  submap_publish_period_sec = 0.3,
  pose_publish_period_sec = 5e-3,
  trajectory_publish_period_sec = 30e-3,
  rangefinder_sampling_ratio = 1.,
  odometry_sampling_ratio = 1.,
  fixed_frame_pose_sampling_ratio = 1.,
  imu_sampling_ratio = 1.,
  landmarks_sampling_ratio = 1.,

  publish_tracked_pose=true,
}


TRAJECTORY_BUILDER_2D.use_imu_data = true
TRAJECTORY_BUILDER_2D.submaps.num_range_data = 35
TRAJECTORY_BUILDER_2D.min_range = 0.3
TRAJECTORY_BUILDER_2D.max_range = 30.
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1.
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.linear_search_window = 0.1
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.translation_delta_cost_weight = 10.
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.rotation_delta_cost_weight = 1e-1


--TRAJECTORY_BUILDER_2D = {
--  use_imu_data = true,
--  min_range = 0.01, -- 0.3
--  max_range = 30,
-- 
--  T_lidar_imu = {
--    translation = {0.012561, -0.006829, 0.078586},                
--    rotation = {0.9999, -0.0060, 0.0034, 0.0123},                 
--  },
--  imu_gravity_time_constant = 3.0,                                
--  gravity_constant = 9.80665,                                     
--  gravity_constant = 9.774088,                                    
--  initial_imu_bias = {                                            
--    gyroscope = {-0.033351, 0.008406, 0.003908},                  
--    accelerometer = {-0.014032, -0.007099, 0.001429},             
--  },
--  use_online_time_calibration = true,                             
--  imu_to_lidar_time_offset = -0.018201,                           
--  num_accumulated_range_data = 60,
--  ceres_scan_matcher = {                                          
--    occupied_space_weight = 1., 
--    translation_weight = 1., 
--    rotation_weight = 1., 
--  }
--  --submaps.num_range_data = 80,
--  --submaps.grid_options_2d.resolution = 0.1
--}

--POSE_GRAPH = {
--  optimization_problem = {
--    huber_scale = 5e2,
--    ceres_solver_options = { max_num_iterations = 10 }
--  },
--  optimize_every_n_nodes = 8,
--
--  constraint_builder = {
--    min_score = 0.55,
--    sampling_ratio = 0.03,
--    global_localization_min_score = 0.66,
--  }
--}

TRAJECTORY_BUILDER_2D.imu_gravity_time_constant = 1.
TRAJECTORY_BUILDER_2D.pose_extrapolator = {
  use_imu_based = false,  -- 2D must be false
  constant_velocity = {
    imu_gravity_time_constant = 1.,
    pose_queue_duration = 0.001,
  },
  imu_based = {
    pose_queue_duration = 5.,
    gravity_constant = 1,
    pose_translation_weight = 1.,
    pose_rotation_weight = 1.,
    imu_acceleration_weight = 1.,
    imu_rotation_weight = 10.,
    odometry_translation_weight = 1.,
    odometry_rotation_weight = 1.,
    solver_options = {
      use_nonmonotonic_steps = false;
      max_num_iterations = 10;
      num_threads = 1;
    },
  },
}

POSE_GRAPH.optimization_problem.huber_scale = 1e2
POSE_GRAPH.optimize_every_n_nodes = 35
POSE_GRAPH.constraint_builder.min_score = 0.65

MAP_BUILDER.use_trajectory_builder_2d = true
MAP_BUILDER.num_background_threads = 8
MAP_BUILDER.use_trajectory_builder_2d = true

return options

mid360_simple_2d.lua

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

options = {
  map_builder = MAP_BUILDER,                -- map_builder.lua的配置信息
  trajectory_builder = TRAJECTORY_BUILDER,  -- trajectory_builder.lua的配置信息
  map_frame = "map",                        -- 地图坐标系的名字
  tracking_frame = "imu_link",             -- 将所有传感器数据转换到这个坐标系下 有imu_link就用imu_link
  published_frame = "base_link",            -- tf: map -> footprint
  odom_frame = "odom",                      -- 里程计的坐标系名字
  provide_odom_frame = true,                -- 是否提供odom的tf, 如果为true, 则tf树为map->odom->footprint
                                            -- 如果为false tf树为map->footprint
  publish_frame_projected_to_2d = false,    -- 是否将坐标系投影到平面上
  use_pose_extrapolator = false,            -- 发布tf时是使用pose_extrapolator的位姿还是前端计算出来的位姿
  use_odometry = false,                     -- 是否使用里程计,如果使用要求一定要有odom的tf
  use_nav_sat = false,                      -- 是否使用gps
  use_landmarks = false,                    -- 是否使用landmark
  num_laser_scans = 1,                      -- 是否使用单线激光数据
  num_multi_echo_laser_scans = 0,           -- 是否使用multi_echo_laser_scans数据
  num_subdivisions_per_laser_scan = 1,      -- 1帧数据被分成几次处理,一般为1
  num_point_clouds = 0,                     -- 是否使用点云数据
  lookup_transform_timeout_sec = 0.2,       -- 查找tf时的超时时间
  submap_publish_period_sec = 0.3,          -- 发布数据的时间间隔
  pose_publish_period_sec = 5e-3,
  trajectory_publish_period_sec = 30e-3,
  rangefinder_sampling_ratio = 1.,          -- 传感器数据的采样频率
  odometry_sampling_ratio = 1.,
  fixed_frame_pose_sampling_ratio = 1.,
  imu_sampling_ratio = 1.,
  landmarks_sampling_ratio = 1.,

  publish_tracked_pose=true,

}
MAP_BUILDER.num_background_threads = 8
MAP_BUILDER.use_trajectory_builder_2d = true


TRAJECTORY_BUILDER_2D.use_imu_data = true
TRAJECTORY_BUILDER_2D.min_range = 0.01 -- 0.3
TRAJECTORY_BUILDER_2D.max_range = 30.
TRAJECTORY_BUILDER_2D.min_z = 0.05
TRAJECTORY_BUILDER_2D.max_z = 1.1
--TRAJECTORY_BUILDER_2D.voxel_filter_size = 0.02

--TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_length = 0.5
--TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.min_num_points = 200.
--TRAJECTORY_BUILDER_2D.adaptive_voxel_filter.max_range = 50.

--TRAJECTORY_BUILDER_2D.loop_closure_adaptive_voxel_filter.max_length = 0.9
--TRAJECTORY_BUILDER_2D.loop_closure_adaptive_voxel_filter.min_num_points = 100
--TRAJECTORY_BUILDER_2D.loop_closure_adaptive_voxel_filter.max_range = 50.

TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.occupied_space_weight = 1.
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight = 1.
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.rotation_weight = 1.
--TRAJECTORY_BUILDER_2D.ceres_scan_matcher.ceres_solver_options.max_num_iterations = 12

--TRAJECTORY_BUILDER_2D.motion_filter.max_distance_meters = 0.1
--TRAJECTORY_BUILDER_2D.motion_filter.max_angle_radians = 0.004
--TRAJECTORY_BUILDER_2D.imu_gravity_time_constant = 1.

TRAJECTORY_BUILDER_2D.submaps.num_range_data = 80.
TRAJECTORY_BUILDER_2D.submaps.grid_options_2d.resolution = 0.1

POSE_GRAPH.optimize_every_n_nodes = 160.
POSE_GRAPH.constraint_builder.sampling_ratio = 0.3
POSE_GRAPH.constraint_builder.max_constraint_distance = 15.
POSE_GRAPH.constraint_builder.min_score = 0.48
POSE_GRAPH.constraint_builder.global_localization_min_score = 0.60

return options

mid360_simple_2d.launch

<launch>

  <param name="/use_sim_time" value="false" /> <!-- true: offline (rosbag); false: online --> 

  <node pkg="pointcloud_to_laserscan" type="pointcloud_to_laserscan_node" name="pointcloud_to_laserscan"
      respawn="false" output="screen">
      <remap from="cloud_in" to="/livox/lidar"/>
      <!--remap from="cloud_in" to="/rslidar_points"/-->
      <!--remap from="/scan" to="/headLaserScan"/-->
      <rosparam>
          target_frame: livox_frame
          transform_tolerance: 0.1 
          min_height: 0.0 
          max_height: 1.0 

          angle_min: -3.14159
          angle_max: 3.14159
          angle_increment: 0.0175
          scan_time: 0.1 
          range_min: 0.5 
          range_max: 30.0
          use_inf: false

          # Concurrency level, affects number of pointclouds queued for processing and number of threads used
          # 0 : Detect number of cores
          # 1 : Single threaded
          # 2->inf : Parallelism level
          concurrency_level: 1
      </rosparam>
  </node>

  <param name="robot_description" textfile="$(find cartographer_ros)/urdf/mid360_simple.urdf" />


  <node name="joint_state_publisher" pkg="joint_state_publisher"
    type="joint_state_publisher" />
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />

  <node name="cartographer_node" pkg="cartographer_ros" type="cartographer_node" 
    args="-configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename mid360_simple_2d.lua"
    output="screen">

    <!--remap from="/scan" to="/headLaserScan"/-->
    <remap from="imu" to="/livox/imu" />
  </node>

  <!--TODO-->
  <!--node pkg="tf2_ros" type="static_transform_publisher" name="lidar2bases" 
    args="0 0 0 0 0 0 lidar_link rslidar" /-->
  <!--node pkg="tf2_ros" type="static_transform_publisher" name="lidar2basei" 
    args="0 0 0 0 0 0 imu_link livox_frame" /-->

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
    type="cartographer_occupancy_grid_node" args="-resolution 0.075" />

  <node name="rviz" pkg="rviz" type="rviz" required="true" 
    args="-d $(find cartographer_ros)/configuration_files/demo_2d.rviz" />

  <!--node name="playbag" pkg="rosbag" type="play" args="--><!--clock -s 142 $(arg bagfile)" /-->

</launch>

3D

mid360_simple_3d.lua
新的:

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

options = {                                                         
  map_builder = MAP_BUILDER,                                        
  trajectory_builder = TRAJECTORY_BUILDER,                          
  map_frame = "map", 
  tracking_frame = "livox_frame",                                   
  published_frame = "base_link",                                    
  odom_frame = "odom",
  provide_odom_frame = true,
  use_pose_extrapolator = false, --位姿外推,用加计积分                         
  use_odometry = false,
  use_nav_sat = false,
  use_landmarks = false,
  num_laser_scans = 0,
  num_point_clouds = 1,                                             
  num_multi_echo_laser_scans = 0,                                   
  num_subdivisions_per_laser_scan = 1,                              
  
  publish_frame_projected_to_2d = false,                            
  lookup_transform_timeout_sec = 0.2,                               
  submap_publish_period_sec = 0.3,                                  
  pose_publish_period_sec = 5e-3,
  trajectory_publish_period_sec = 30e-3,                            
  rangefinder_sampling_ratio = 1.,                                  
  odometry_sampling_ratio = 1.,
  fixed_frame_pose_sampling_ratio = 1.,                             
  imu_sampling_ratio = 1.,
  landmarks_sampling_ratio = 1.,                                    
  
  publish_tracked_pose=true,                                        
}                                                                   
  
MAP_BUILDER.use_trajectory_builder_3d = true                        
MAP_BUILDER.num_background_threads = 8                       

TRAJECTORY_BUILDER_3D.min_range = 0.1
TRAJECTORY_BUILDER_3D.max_range = 30.0

TRAJECTORY_BUILDER_3D.imu_gravity_time_constant = 1.
TRAJECTORY_BUILDER_3D.pose_extrapolator.use_imu_based = true
TRAJECTORY_BUILDER_3D.pose_extrapolator.imu_based = {
  pose_queue_duration = 5.,
  gravity_constant = 1, -- livox imu acc norm = 1
  pose_translation_weight = 1.,
  pose_rotation_weight = 10.,
  imu_acceleration_weight = 1.,
  imu_rotation_weight = 10.,
  odometry_translation_weight = 1.,
  odometry_rotation_weight = 1.,
  solver_options = {
    use_nonmonotonic_steps = false;
    max_num_iterations = 10;
    num_threads = 8;
  },
}
    
TRAJECTORY_BUILDER_3D.motion_filter = {                           
    max_time_seconds = 10.0,
    max_distance_meters = 0.1,                                    
    max_angle_radians = math.rad(0.5),                            
}                                                                 


POSE_GRAPH.optimization_problem = {                                 
  huber_scale = 1e1,                                                
  acceleration_weight = 1.1e2,
  huber_scale = 1e1,
  acceleration_weight = 1.1e2,
  rotation_weight = 1.6e4,
  local_slam_pose_translation_weight = 1e5,
  local_slam_pose_rotation_weight = 1e5,
  odometry_translation_weight = 1e5,
  odometry_rotation_weight = 1e5,
  fixed_frame_pose_translation_weight = 1e1,
  fixed_frame_pose_rotation_weight = 1e2,
  fixed_frame_pose_use_tolerant_loss = false,
  fixed_frame_pose_tolerant_loss_param_a = 1,
  fixed_frame_pose_tolerant_loss_param_b = 1,
  log_solver_summary = false,
  use_online_imu_extrinsics_in_3d = true,  --自动标定imu
  fix_z_in_3d = false,
  ceres_solver_options = {
    use_nonmonotonic_steps = false,
    max_num_iterations = 50,
    num_threads = 8,
  },
}

POSE_GRAPH.optimize_every_n_nodes = 100
POSE_GRAPH.constraint_builder.min_score = 0.60
POSE_GRAPH.constraint_builder.sampling_ratio = 0.3
POSE_GRAPH.constraint_builder.global_localization_min_score = 0.66
POSE_GRAPH.constraint_builder.max_constraint_distance = 10.0

return options
include "map_builder.lua"
include "trajectory_builder.lua"

options = {
  map_builder = MAP_BUILDER,
  trajectory_builder = TRAJECTORY_BUILDER,
  map_frame = "map",
  tracking_frame = "imu_link",
  published_frame = "base_link",
  odom_frame = "odom",
  provide_odom_frame = true,
  publish_frame_projected_to_2d = false,
  use_pose_extrapolator = true,
  use_odometry = false,
  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,
  lookup_transform_timeout_sec = 0.2,
  submap_publish_period_sec = 0.3,
  pose_publish_period_sec = 5e-3,
  trajectory_publish_period_sec = 30e-3,
  rangefinder_sampling_ratio = 1.,
  odometry_sampling_ratio = 1.,
  fixed_frame_pose_sampling_ratio = 1.,
  imu_sampling_ratio = 1.,
  landmarks_sampling_ratio = 1.,
}

TRAJECTORY_BUILDER_3D.num_accumulated_range_data = 160

MAP_BUILDER.use_trajectory_builder_3d = true
MAP_BUILDER.num_background_threads = 7
POSE_GRAPH.optimization_problem.huber_scale = 5e2
POSE_GRAPH.optimize_every_n_nodes = 320
POSE_GRAPH.constraint_builder.sampling_ratio = 0.03
POSE_GRAPH.optimization_problem.ceres_solver_options.max_num_iterations = 10
POSE_GRAPH.constraint_builder.min_score = 0.62
POSE_GRAPH.constraint_builder.global_localization_min_score = 0.66

return options
<launch>
  <param name="/use_sim_time" value="false" /> <!-- true: offline (rosbag); false: online --> 
  <param name="robot_description"
    textfile="$(find cartographer_ros)/urdf/mid360_simple.urdf" />

  <node name="joint_state_publisher" pkg="joint_state_publisher"
    type="joint_state_publisher" />
  <node name="robot_state_publisher" pkg="robot_state_publisher"
    type="robot_state_publisher" />

  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename mid360_simple_3d.lua"
      output="screen">

      <remap from="points2" to="/livox/lidar" />
      <remap from="imu" to="/livox/imu" />
  </node>

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" args="-resolution 0.05" />

  <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/demo_3d.rviz" />
  <!--node name="playbag" pkg="rosbag" type="play" args="--><!--clock -s 142 $(arg bagfile)" /-->

</launch>

说明:cartographer 2D和3D的lua对应的配置项不一样。
详细的差别可以通过对比查看trajectory_builder_2d.luatrajectory_builder_3d.lua

Cartographer 的 3D 配置中确实没有 use_imu_datainitial_imu_bias 这两个参数。在 3D 模式下,IMU 数据是必须的,系统会默认使用,因此不需要单独的开关选项。

相关链接

LiDAR_IMU_Init标定: https://blog.csdn.net/qq_46238675/article/details/148529340

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐