Point_LIO(激光与IMU融合里程计,建图与定位算法)
Point_LIO(激光与IMU融合里程计,建图与定位算法)
| YAML 层级 | 主要内容 |
|---|---|
直接放在 ros__parameters 下的参数 | 估计模型、传播方式、饱和检查、地图初始化、降采样及日志开关 |
common | 输入话题、合帧、拆帧和时间差 |
prior_pcd | 先验地图及初始位置 |
preprocess | 雷达格式、线数、逐点时间单位和近距离过滤 |
mapping | IMU、重力、外参、噪声及匹配参数 |
odometry | 里程计发布方式 |
publish | 轨迹、点云和 TF 发布开关 |
pcd_save | 点云保存开关与保存间隔 |
参数
ros__parameters(ROS节点参数)
参数表
point_lio:
ros__parameters:
use_imu_as_input: False # Change to True to use IMU as input of Point-LIO
prop_at_freq_of_imu: True
check_satu: True
init_map_size: 10
point_filter_num: 8 # Options: 4, 3
space_down_sample: True
filter_size_surf: 0.2 # Options: 0.5, 0.3, 0.2, 0.15, 0.1
filter_size_map: 0.2 # Options: 0.5, 0.3, 0.15, 0.1
ivox_nearby_type: 18 # Options: 0, 6, 18, 26
runtime_pos_log_enable: False # Option: True
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
use_imu_as_input | False | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 选择 IMU 输入模型或观测模型 | 不适用 | 不适用 | False:IMU 作为观测纠正滤波状态;True:IMU 作为运动预测输入。False 仍使用 IMU |
prop_at_freq_of_imu | True | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 选择协方差预测的时序 | 不适用 | 不适用 | True:主要在 IMU 时刻预测协方差;False:还在激光逐点时刻预测。不会设置硬件采样频率 |
check_satu | True | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 检查 IMU 各轴是否接近饱和,并排除饱和轴的观测更新 | 不适用 | 不适用 | 当前 use_imu_as_input=False 分支使用;阈值来自 mapping.satu_acc/satu_gyro |
init_map_size | 10 | 点,计数 | 通常保持当前值,不作为优先调试项 | 初始化地图累计点数的最低门槛 | 累计更多初始点;超过单帧点数时可能延后开始匹配 | 更早满足门槛,但初始地图可能更少 | 不是帧数,也不是 IMU 初始化次数;初始点云来自预处理结果 |
point_filter_num | 8 | 无量纲,取点间隔 | 实物运行时重点观察,有问题再针对性调整 | Livox 点通过 line/tag 初筛后,每 N 个选一个 | 保留点更少,通常计算量下降,可能丢失有效结构 | 保留点更多,通常计算量增加,结构更丰富 | 当前 Livox 分支实际使用;应为正整数;注释中的“4、3”不是完整允许范围 |
space_down_sample | True | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 是否对当前扫描做空间体素降采样 | 不适用 | 不适用 | True 使用 filter_size_surf;False 跳过该阶段,但前面的间隔取点仍执行 |
filter_size_surf | 0.2 | m,体素边长 | 实物运行时重点观察,有问题再针对性调整 | 压缩当前扫描中空间上重复的点 | 通常扫描点更少、计算更快,小结构保留更少 | 通常扫描点更多、细节更多,计算量增加 | space_down_sample=True 时使用;0.2 m 不是定位精度 |
filter_size_map | 0.2 | m,地图筛选尺度 | 实物运行时重点观察,有问题再针对性调整 | 地图更新时,抑制向已有点的体素重复插入新点 | 通常地图更稀疏、增长更慢,细节减少 | 通常地图更密、增长更快,内存和搜索负担增加 | 在地图插入阶段使用,独立于扫描降采样开关 |
ivox_nearby_type | 18 | 不适用,枚举 | 通常保持当前值,不作为优先调试项 | 选择地图最近邻搜索涉及的邻接网格 | 不适用 | 不适用 | 支持 0/6/18/26;邻域越多,候选范围越广,通常搜索成本越高 |
runtime_pos_log_enable | False | 不适用,布尔 | 根据实际功能需求开启或设置 | 启用详细状态记录和耗时统计 | 不适用 | 不适用 | True 增加状态写盘和终端输出;False 时源码仍会打开部分日志文件 |
参数详解
use_imu_as_input(IMU参与运动估计的方式)
use_imu_as_input 决定 IMU 怎样参与滤波。
当前 False 的处理方式是:滤波器内部估计角速度、加速度等状态,收到 IMU 后用测量纠正这些状态,再进行运动预测和激光匹配。
设为 True 后,加速度与角速度作为预测输入,经过单位缩放、偏置处理后推动运动状态。切换模型还会改变所使用的噪声参数,所以首轮保持当前 False。
关闭 IMU 对应的是另一个参数 mapping.imu_en。
prop_at_freq_of_imu(按IMU时刻更新估计不确定性)
prop_at_freq_of_imu 主要影响协方差传播。
协方差可以理解为滤波器对当前估计的不确定程度。当前 True 时,代码在处理 IMU 时刻传播它;状态仍会推进到激光点的采样时刻。
改成 False 后,代码还会在激光逐点时刻增加协方差预测,通常计算量更大。它不是“把 Point-LIO 输出频率设成 IMU 频率”的开关,也不能保证切换后精度更高。
check_satu(IMU读数量程保护)
check_satu 是逐轴处理。
当前代码分别比较三个加速度轴和三个角速度轴:abs(原始轴值) ≥ 0.99 × 对应饱和阈值
被标记的轴停止参与这次 IMU 观测更新,其他轴继续使用。因此,它需要配合正确单位和量程的 satu_acc/satu_gyro。这项检查在当前 output 模型中生效。
init_map_size(初始化地图的最少点数)
init_map_size=10 只是一道点数门槛。
代码判断的是:init_feats_world->size() >= init_map_size
如果一帧预处理后已有几千个点,设置 10 或 100 都可能在同一帧满足条件。因此,增大它不一定增加初始化时间,也不能替代静止 IMU 初始化。
初始化地图使用的是预处理后的点云,并没有直接使用经过 filter_size_surf 体素降采样的那份点云。
三个点数控制参数作用于不同阶段。
初始化完成后的常规处理,大致是:
原始点云
→ line/tag 初筛
→ point_filter_num:按间隔取点
→ 距离等过滤
→ filter_size_surf:扫描空间降采样
→ 逐点匹配
→ filter_size_map:地图插入筛选
例如,有约 10,000 个点通过 line/tag 初筛:
- point_filter_num=8:先选择约 1,250 个,后续过滤可能继续减少。
- 改为 4:先选择约 2,500 个。
- 随后扫描体素降采样,还会进一步压缩空间上密集的点。
因此,间隔取点更多,不一定等比例增加最终匹配点数,还要看扫描体素、遮挡和匹配条件。
ivox_nearby_type(地图邻格搜索范围)
ivox_nearby_type=18 表示邻接网格类型。
本地实现实际搜索的网格数包含中心网格:
| 配置值 | 搜索范围 | 总网格数 |
|---|---|---|
0 | 仅中心网格 | 1 |
6 | 中心+面相邻网格 | 7 |
18 | 再加入棱相邻网格 | 19 |
26 | 再加入角相邻网格 | 27 |
它不表示“找 18 个点”或“搜索 18 米”。
实际空间尺度还取决于 mapping.ivox_grid_resolution,当前为 0.5 m;匹配过程中另有最近邻和残差条件。
以后调这组参数时,主要比较输出延迟、有效环境结构、点云重影和轨迹连续性。先使用当前值建立基准,再针对具体表现改变一个参数,才能判断改善来自哪里。
common(输入话题与点云时间处理)
参数表
common:
lid_topic: "livox/lidar"
imu_topic: "livox/imu"
con_frame: False # True: if you need to combine several LiDAR frames into one
con_frame_num: 1 # the number of frames combined
cut_frame: False # True: if you need to cut one LiDAR frame into several subframes
cut_frame_time_interval: 0.05 # should be integral fraction of 1 / LiDAR frequency
time_diff_lidar_to_imu: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme)
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
common.lid_topic | "livox/lidar" | 不适用,话题名 | 上实物前必须核对并正确配置 | 指定点云订阅话题 | 不适用 | 不适用 | 当前 lidar_type=1,要求该话题发布 Livox CustomMsg;还需匹配命名空间 |
common.imu_topic | "livox/imu" | 不适用,话题名 | 上实物前必须核对并正确配置 | 指定 IMU 订阅话题 | 不适用 | 不适用 | 当前连接 MID360 内部 IMU;读取加速度、角速度和时间戳 |
common.con_frame | False | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 是否先合并多帧点云,再送入后续处理 | 不适用 | 不适用 | True 会进入合帧分支,但数量写死为10;当前实现还有下一帧未加入的问题 |
common.con_frame_num | 1 | 帧,计数 | 当前运行不使用这个参数,暂不调整 | 注释意图:指定合并帧数 | 当前实现无变化 | 当前实现无变化 | 参数已读取,但合帧代码使用固定数字10,没有使用它 |
common.cut_frame | False | 不适用,布尔 | 当前运行不使用这个参数,暂不调整 | 注释意图:启用点云拆帧 | 不适用 | 不适用 | 实际分支检查的是另一个变量 cut_frame_init;没有看到二者连接 |
common.cut_frame_time_interval | 0.05 | s | 当前运行不使用这个参数,暂不调整 | 注释意图:指定拆分后的时间间隔 | 当前实现无变化 | 当前实现无变化 | 参数已读取,未发现参与拆帧计算 |
common.time_diff_lidar_to_imu | 0.0 | s,时间偏移量 | 当前运行不使用这个参数,暂不调整 | 注释意图:补偿雷达与 IMU 的时间差 | 当前实现无变化 | 当前实现无变化 | 参数已读取,但 IMU 时间戳修正没有使用它 |
参数详解
lid_topic 与 imu_topic(雷达与IMU输入话题)
两个话题参数:名称、消息类型和命名空间必须同时对应。
当前实车驱动设置 xfer_format=4、multi_topic=0,源码发布:
livox/lidar → Livox CustomMsg
livox/lidar/pointcloud → PointCloud2
livox/imu → sensor_msgs/Imu
Point-LIO 当前 lidar_type=1,订阅的是 CustomMsg,因此配置中的 livox/lidar 与驱动匹配。
这两个配置都是相对话题名:
| 节点命名空间 | livox/lidar 实际解析为 |
|---|---|
| 空命名空间 | /livox/lidar |
/red_standard_robot1 | /red_standard_robot1/livox/lidar |
驱动和 Point-LIO 的命名空间或话题重映射要一致。话题名负责选择输入源,消息中的 frame_id 表示坐标名称;选择话题不会自动进行坐标变换。
con_frame 与 con_frame_num(多帧点云合并)
con_frame 的实际行为与注释不完全一致。
当前 Livox 合帧分支执行的是:
- 收到前10帧,累计它们的点。
- 把每帧逐点时间调整到第一帧的起始时间。
- 第11次回调时,把累计点云放入处理队列。
- 这次回调收到的第11帧没有加入累计点云,然后计数清零。
所以即使设置:
con_frame: True
con_frame_num: 1
也不会按“合并1帧”执行。代码仍累计10帧,再由下一次回调触发输出。
假设驱动稳定20 Hz,这段逻辑理论上约每11个回调输出一个合并包,即约 1.82 Hz,累计点云覆盖约 0.5秒。这会增加等待时间和单次处理点数,因此首轮保持 False。
cut_frame 与 cut_frame_time_interval(点云拆帧设置)
拆帧函数存在,但 YAML 开关没有连接到它。
实际代码检查:
if (cut_frame_init)
{
process_cut_frame_livox(..., cut_frame_num, ...);
}
其中 cut_frame_init 默认 False。当前没有发现把 common.cut_frame 赋给它,也没有发现使用 cut_frame_time_interval。 此外,这个内部函数按点数分段,使用 cut_frame_num,并不是直接按照 YAML 中的0.05秒切分。 因此,单独修改这两个 YAML 参数不会实现注释描述的拆帧行为。
time_diff_lidar_to_imu(雷达与IMU时间偏移)
时间差参数没有接入,不代表系统不需要同步。
IMU 回调实际修正时间戳的表达式是:
修正后时间 = 原始时间
− timediff_imu_wrt_lidar
− time_lag_IMU_wtr_lidar
它使用的是另外两个变量,目前初始化为零;没有使用 common.time_diff_lidar_to_imu。
Point-LIO 仍然会根据时间戳等待 IMU 覆盖点云扫描末尾。但这只是按时间戳组织数据,不能证明两种传感器的物理采样时间已经对齐。
以后实车需要测量实际同步状态;如果发现偏移,必须先确认校正方式及其符号,再处理对应代码或驱动配置。当前把 time_diff_lidar_to_imu 填成非零值,不会完成校正。
prior_pcd(先验点云地图)
参数表
prior_pcd:
enable: False
# NOTE: `prior_pcd_map_path` will be provided in the launch file
# prior_pcd_map_path: ""
init_pose: [ 0.0, 0.0, 0.0 ]
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
prior_pcd.enable | False | 不适用,布尔 | 根据实际功能需求开启或设置 | 选择初始地图来源:当前扫描或已有 PCD | 不适用 | 不适用 | False:从当前扫描建立初始地图;True:加载先验 PCD;集成建图的 slam_launch.py 强制为 False,切换工作方式后按用途配置 |
prior_pcd.prior_pcd_map_path | YAML 未设置;程序默认 "" | 不适用,文件路径 | 根据实际功能需求开启或设置 | 指定先验 PCD 文件 | 不适用 | 不适用 | 当前未启用先验,无需填写;仅启用先验时读取;定位 launch 会传入路径,直接运行节点不会自动获得该路径 |
prior_pcd.init_pose | [0.0,0.0,0.0] | m,分别为 x/y/z | 当前运行不使用这个参数,暂不调整 | 给内部 IMU 的位置状态赋初始位置 | 某分量增大,位置沿对应坐标轴正方向偏移 | 某分量减小,位置沿对应坐标轴负方向偏移 | 仅 enable=True 且 use_imu_as_input=False 时使用;实际赋值位于首次输出位姿阶段 |
参数详解
enable(先验地图加载开关)
enable 改变的是初始匹配地图的来源。
当前 False 的流程是:
IMU 初始化
→ 累计当前扫描点
→ 达到 init_map_size 门槛
→ 用这些点建立地图
→ 后续匹配并更新地图
开启后,达到同样的初始化门槛时,代码改为读取 PCD,并把其中的点加入地图搜索结构。
加载先验地图不会自动完成全局重定位,也不会自动确定机器人在整张地图中的位置。初始位置、姿态和地图坐标必须足够一致,后续局部匹配才有基础。
另外,开启先验后,代码会延后新点插入;相关有效处理计数超过200后,仍会继续更新地图。因此这个开关也不意味着地图永久冻结。
先验 PCD 加载时没有自动做坐标旋转或单位缩放,地图还必须与当前 Point-LIO 参考系一致。源码对 PCD 读取失败返回的空指针也没有在调用处检查,所以启用前需要确认文件有效。
prior_pcd_map_path(先验点云地图路径)
路径注释只对相应启动链成立。
localization_launch.py 会将启动参数 prior_pcd_file 传给:prior_pcd.prior_pcd_map_path
但它没有因此自动把 prior_pcd.enable 改成 True。当前配置即使获得路径,Point-LIO 仍不加载它。
而 slam_launch.py 会明确覆盖:prior_pcd.enable: False
这与从当前扫描建图的用途一致。
同一定位启动链中的 small_gicp 也会接收先验文件,但它是另一个节点。Point-LIO 关闭先验,不代表 small_gicp 没有使用地图。
init_pose(内部IMU的初始位置)
init_pose 有三个容易误解的地方:
- 它是 x,y,z,三个数都是米。 第三个数不是 yaw,也不包含 roll/pitch/yaw。
- 它对应内部 IMU 原点在 camera_init 中的位置。 不是直接设置 base_footprint 的导航位置。
- 本地代码的赋值时机比较特殊。 它在首次输出位姿时直接修改 kf_output.x_.pos,并非在加载先验、开始匹配之前统一完成初始化。
尤其在你当前“高频里程计开启、path 关闭”的设置下,这次赋值发生在首次成功匹配后的里程计输出中。因此,未来启用先验时,不能只填一个位置就认为首轮匹配已经从该位置开始;这段初始化顺序需要另行审查。
preprocess(雷达格式与点云预处理)
参数表
preprocess:
lidar_type: 1 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR
scan_line: 4
timestamp_unit: 3 # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond.
blind: 0.5
当前 lidar_type=1、scan_line=4 与本地 MID360 驱动实现一致;blind=0.5 可以先作为基准。 timestamp_unit=3 在当前 Livox CustomMsg 分支中没有参与换算,但逐点时间仍被正确地按 ns 处理。
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
preprocess.lidar_type | 1 | 不适用,枚举 | 按设备型号和驱动核对,通常保持当前值 | 选择点云消息类型及字段解析方式 | 不适用 | 不适用 | 当前走 Livox CustomMsg 分支;必须与输入消息格式匹配 |
preprocess.scan_line | 4 | 条,计数 | 按设备型号和驱动核对,通常保持当前值 | 指定接受的扫描线编号范围 | 提高允许编号上限;输入仍只有0~3时不会增加点数 | 丢弃超过编号上限的点,减少有效数据 | 本地驱动为 MID360 设置4个 line 编号;Point-LIO 判断 line < scan_line |
preprocess.timestamp_unit | 3 | 不适用,单位选择枚举 | 当前运行不使用这个参数,暂不调整 | 指定 PointCloud2 逐点时间字段的单位 | 不适用 | 不适用 | 当前 CustomMsg 直接将 offset_time 从 ns 换成 ms,不通过此开关 |
preprocess.blind | 0.5 | m,距离 | 实物运行时重点观察,有问题再针对性调整 | 排除距离点云坐标原点过近的点 | 排除范围扩大,近处干扰减少,同时丢失更多有效结构 | 保留更多近处结构,也可能保留更多车体或近距离干扰点 | 在当前 Livox 预处理中实际使用;按三维距离过滤 |
参数详解
lidar_type(雷达类型与输入格式)
lidar_type:选择消息格式和解析分支。 本地支持的值是:
| 值 | 处理方式 |
|---|---|
1 | Livox CustomMsg;内部名称为 AVIA,当前 MID360 也走此路径 |
2 | Velodyne 样式 PointCloud2,包含 time、ring 等字段 |
3 | Ouster 样式 PointCloud2,包含 t、ring 等字段 |
4 | Hesai XT32 样式 PointCloud2;原 YAML 注释没有列出这一项 |
它不仅决定字段怎样解析,还决定订阅 CustomMsg 还是 PointCloud2。当前实车驱动在 livox/lidar 发布 CustomMsg,所以设置为 1。
仿真使用 2,是因为转换器生成了 Velodyne 样式字段,并不代表仿真中换了一台 Velodyne 雷达。
scan_line(有效扫描线数量)
scan_line:限制接受的 line 编号。 当前判断条件是:msg->points[i].line < N_SCANS
N_SCANS 来自 scan_line,所以设置4时允许:line = 0、1、2、3
本地驱动对 MID360 定义 kLineNumberMid360=4,并按:point.line = i % pkt.line_num;生成 line 字段。因此,当前4这个值有驱动代码依据。
例如:
- 改成2:只接受 line 0、1,丢弃 line 2、3。
- 改成8:如果输入仍只有0~3,就不会多出新的点。 它主要是输入格式匹配参数。调节点数密度应首先看前面讲过的 point_filter_num 和体素尺寸。
timestamp_unit(点内时间单位)
timestamp_unit:解释逐点时间字段的单位。 本地枚举及转换关系为:
| 值 | 输入字段单位 | 换算成内部 ms 的倍率 |
|---|---|---|
0 | 秒,s | ×1000 |
1 | 毫秒,ms | ×1 |
2 | 微秒,μs | ×0.001 |
3 | 纳秒,ns | ×0.000001 |
这个选择在普通 PointCloud2 分支中使用。例如 Velodyne 的 time、Ouster 的 t 会经过相应换算。
但你当前的 Livox CustomMsg 路径直接执行:curvature = offset_time / 1000000.0;也就是固定从 ns 转成 ms。因此,当前修改 timestamp_unit 不会改变这条输入路径的时间解释。
举个纯数值例子:
offset_time = 25,000,000 ns
= 25 ms
= 0.025 s
该点的处理时刻就是:
点云 header.stamp + 0.025 s
逐点时间参与运动预测与点云匹配,不能在输入转换中随意丢弃;时间单位换算也不会完成雷达与 IMU 的时差校准。
blind(近距离盲区过滤)
blind:近距离排除半径。 当前代码计算:
[ r^2=x^2+y^2+z^2 ]
当:
[ r^2<\texttt{blind}^2 ]
就丢弃该点。因此 blind=0.5 表示排除距离雷达点云坐标原点不足0.5 m的点,范围是一个球形区域。
例如:
- 距离0.3 m的点:被这项过滤排除。
- 距离0.6 m的点:通过距离下限检查,之后仍可能被其他条件排除。
这里的距离是三维距离,与点的高度、机器人中心距离不同。这个过滤同时作用于机器人点和环境点,所以增大它时,也会丢失近处墙面、地面和障碍物的有效点。
实车到位后,先观察0.5 m过滤后是否仍有明显车体干扰、近处有效结构是否不足,再决定是否调整。当前没有这些实测证据,先保持0.5。
mapping(运动状态估计与点云匹配)
实车上先看哪些问题
这块先负责让 Point-LIO 把位置、运动和地图估计对;坡道能不能通行,随后才由地形分析和代价地图判断。实车遇到问题时,先按下面的现象找参数,不必先读噪声公式。
| 实车上看到什么 | 先看哪些参数/关系 | 具体要核对什么 |
|---|---|---|
| 车没动,估计位置却明显变化 | acc_norm、gravity,再检查数据时间和安装关系 | 加速度单位是否正确、系统的上下方向是否与导航参考系相符;不能仅凭漂移就认定某个噪声值错误 |
| 平地被显示成斜面,坡道的高低方向不对 | gravity 和整条坐标转换关系 | 静止 IMU 读数、雷达安装方向、Point-LIO 参考系到 odom 的关系要对得上;不是直接套一个“向下”的数组 |
| MID360 整体倾斜安装,或随云台 yaw 转动 | extrinsic_T/R 与机器人安装 TF | 内部雷达/IMU 关系和整台传感器装在车上的关系要分开;整机转动不改变内部两者的位置 |
| 过接缝、颠簸时定位突跳 | satu_acc、imu_meas_acc_cov、acc_cov_output | 先看支架是否牢固、加速度单位与峰值、时间接口;确认后再判断算法应怎样看待振动和真实运动 |
| 快速转底盘或云台时墙面重影、方向跳变 | satu_gyro、imu_meas_omg_cov、gyr_cov_output,以及点时间接口 | 看角速度是否接近量程边缘、数据是否及时;这些现象不能只靠改噪声解决 |
| 墙角、地面或斜坡上可用匹配点很少 | plane_thr、match_s、ivox_grid_resolution | 是否有足够、可靠的地图邻点;斜坡也可以是平整的面,这三项没有规定“最大爬坡角度” |
当前使用的是 MID360 内部 IMU,保持 imu_en=True、use_imu_as_input=False。MCU 世界姿态不能代替机械关节角;实际 yaw 在 gimbal_yaw_joint,实际 pitch 在 gimbal_pitch_joint,两个 odom 关节固定,MID360 随 yaw、不随独立 pitch 转动。
下面的噪声参数主要决定“系统更信测量,还是更相信原来的运动趋势”。先确认单位、时间与安装关系,再讨论噪声;它们不会让松动支架变稳,也不是车辆速度或坡度限制。本轮没有实物,不据这些现象指定新的调参值。
参数表
当前采用 use_imu_as_input=False 的 output 模型,以下按这个运行分支解释;“当前值”来自实物配置,不是本轮读取的运行节点值。表中的 g₀ 是上方 YAML 中的重力向量,当前模长约9.81 m/s²。
噪声参数的单位按本地运动方程及协方差公式推导;它们不都等同于传感器手册中的噪声密度。
mapping:
imu_en: True
extrinsic_est_en: False # for aggressive motion, set this variable False
imu_time_inte: 0.005 # = 1 / frequency of IMU
lidar_time_inte: 0.1
satu_acc: 4.0 # the saturation value of IMU's acceleration. not related to the units
satu_gyro: 35.0 # the saturation value of IMU's angular velocity. not related to the units
acc_norm: 1.0 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU's acceleration
lidar_meas_cov: 0.01 # 0.001
acc_cov_output: 500.0
gyr_cov_output: 1000.0
b_acc_cov: 0.0001
b_gyr_cov: 0.0001
imu_meas_acc_cov: 0.1
imu_meas_omg_cov: 0.1
gyr_cov_input: 0.1 # for IMU as input model
acc_cov_input: 0.1 # for IMU as input model
plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane
match_s: 81.0
ivox_grid_resolution: 0.5
# 测量平均值是[0.00423894,0.71588876,0.69592434]经过公式计算得出[-0.04166067, -7.03407005, -6.83785222]
gravity: [-0.04166067, -7.03407005, -6.83785222] # gravity to be aligned # rpy = [0, pi/6, 0]
gravity_init: [-0.04166067, -7.03407005, -6.83785222] # preknown gravity in the first IMU body frame, use when imu_en is False or start from a non-stationary state
extrinsic_T: [ -0.011, -0.02329, 0.04412 ]
extrinsic_R: [ 1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 ]
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
mapping.imu_en | True | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 让算法使用 MID360 内部 IMU,帮助判断转动和加速度 | 不适用 | 不适用 | 当前保持 True;关闭后不再使用这路惯性信息,不是减少振动的普通调参方法 |
mapping.extrinsic_est_en | False | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 是否让算法边运行边修正内部雷达/IMU的位置和朝向关系 | 不适用 | 不适用 | 当前 False 使用固定外参;整台 MID360 倾斜或云台 yaw 转动不要求因此开启 |
mapping.imu_time_inte | 0.005 | s | 当前运行不使用这个参数,暂不调整 | 记录标称 IMU 时间间隔,当前未接入计算 | 当前实现无变化 | 当前实现无变化 | 0.005秒对应200 Hz的标称周期;实际时间来自消息时间戳,改它不能改变硬件频率 |
mapping.lidar_time_inte | 0.1 | s | 通常保持当前值,不作为优先调试项 | 异常点云分支使用的回退时间窗口 | 回退窗口更长 | 回退窗口更短 | 正常扫描按逐点时间计算末尾;不是设置雷达频率的参数 |
mapping.satu_acc | 4.0 | g,当前原始输入单位 | 按设备型号和驱动核对,通常保持当前值 | 发现某轴加速度接近量程边缘时,暂时不用该轴更新 | 更少数据被屏蔽,也可能接受已经限幅的数据 | 更多数据被屏蔽,也可能误排除正常颠簸 | 当前实际门槛3.96 g;应对照输入单位、设备量程和实际峰值核对,不是车辆允许加速度 |
mapping.satu_gyro | 35.0 | rad/s | 按设备型号和驱动核对,通常保持当前值 | 发现某轴转速接近量程边缘时,暂时不用该轴更新 | 更少数据被屏蔽 | 更多数据被屏蔽 | 当前实际门槛34.65 rad/s,约1985°/s;不是车辆或云台的速度上限 |
mapping.acc_norm | 1.0 | g,当前原始输入单位 | 上实物前必须核对并正确配置 | 把 IMU 的原始加速度换成算法使用的米制单位 | 换算后的加速度变小 | 换算后的加速度变大 | 当前原始输入以 g 表达,所以用1.0;静止三轴合起来约1 g,不要求某一轴必须为1 |
mapping.lidar_meas_cov | 0.01 | 按意图为 m²;实现存在冲突 | 通常保持当前值,不作为优先调试项 | 控制激光匹配对位姿的影响程度,但本地代码用法不一致 | 不同求解分支的影响方向相反 | 不同求解分支的影响方向相反 | 先保留0.01;源码不一致需单独核实,不能当作统一的激光信任度旋钮 |
mapping.acc_cov_output | 500.0 | m²/s⁶,按本地公式推导 | 实物运行时重点观察,有问题再针对性调整 | 允许估计中的加速度多快改变 | 更容易跟随观测改变,也可能跟随抖动 | 更倾向维持原来的趋势,急加减速时可能跟得慢 | 当前 output 模型使用;与加速度测量噪声一起理解 |
mapping.gyr_cov_output | 1000.0 | rad²/s⁴,按本地公式推导 | 实物运行时重点观察,有问题再针对性调整 | 允许估计中的转速多快改变 | 更容易跟随观测改变,也可能跟随抖动 | 更倾向维持原来的趋势,突然转动时可能跟得慢 | 当前 output 模型使用;不是转速或陀螺实际噪声的数值 |
mapping.b_acc_cov | 0.0001 | m²/s⁶,按本地公式推导 | 通常保持当前值,不作为优先调试项 | 允许算法估计的加速度零偏多快变化 | 零偏更容易改变,过大可能把真实运动当成偏差 | 零偏更稳定,适应缓慢漂移也可能更慢 | 两种模型均使用;先保持当前值,不能用于掩盖单位或方向错误 |
mapping.b_gyr_cov | 0.0001 | rad²/s⁴,按本地公式推导 | 通常保持当前值,不作为优先调试项 | 允许算法估计的陀螺零偏多快变化 | 零偏更容易改变 | 零偏更稳定,适应漂移也可能更慢 | 两种模型均使用;静止转速偏离零应先检查实际数据与偏差来源 |
mapping.imu_meas_acc_cov | 0.1 | m²/s⁴ | 实物运行时重点观察,有问题再针对性调整 | 决定算法有多相信这次加速度读数 | 更不相信加速度测量,减少其影响 | 更相信加速度测量,也更容易跟随噪声 | 当前 output 模型使用;作用在换算后的加速度,不是原始 g 数值的方差 |
mapping.imu_meas_omg_cov | 0.1 | rad²/s² | 实物运行时重点观察,有问题再针对性调整 | 决定算法有多相信这次角速度读数 | 更不相信角速度测量 | 更相信角速度测量,也更容易跟随噪声 | 当前 output 模型使用;振动和急转时要与转速变化参数一起看 |
mapping.gyr_cov_input | 0.1 | rad²/s² | 当前运行不使用这个参数,暂不调整 | 另一种估计模型使用的角速度输入噪声 | 当前无影响;换到 input 模型后预测不确定程度增大 | 当前无影响;换到 input 模型后预测不确定程度减小 | 当前 use_imu_as_input=False,不参与本轮预测 |
mapping.acc_cov_input | 0.1 | m²/s⁴ | 当前运行不使用这个参数,暂不调整 | 另一种估计模型使用的加速度输入噪声 | 当前无影响;换到 input 模型后预测不确定程度增大 | 当前无影响;换到 input 模型后预测不确定程度减小 | 当前 use_imu_as_input=False,不参与本轮预测 |
mapping.plane_thr | 0.1 | m | 实物运行时重点观察,有问题再针对性调整 | 判断一小片地图点是否足够平整,可以拿来匹配 | 接受更不平整的点群,也可能混入边缘和曲面 | 要求更平整,可用匹配可能减少 | 检查5个地图邻点到拟合面的偏离;面可以倾斜,不是坡度或通行高度门槛 |
mapping.match_s | 81.0 | 隐含 m⁻¹,经验系数 | 实物运行时重点观察,有问题再针对性调整 | 判断当前雷达点是否与找到的地图面足够接近 | 更严格,接受的匹配更少 | 更宽松,接受更多匹配,也可能混入错误匹配 | 检查当前点与地图面的距离误差;不是地图精度或车辆允许离障碍的距离 |
mapping.ivox_grid_resolution | 0.5 | m,网格边长 | 实物运行时重点观察,有问题再针对性调整 | 把地图分块,以便寻找附近可匹配的点 | 固定邻格能覆盖更大范围,查找可能更费时 | 覆盖范围更小,可能找不到足够邻点 | 不直接删减地图点;不是只检测多大障碍的参数 |
mapping.gravity | g₀ | m/s² | 上实物前必须核对并正确配置 | 确定 Point-LIO 参考系中的重力方向和换算大小 | 同方向增大长度:重力和加速度换算一起增大 | 同方向减小长度:两者一起减小 | 大小已约9.81,不重复修改;初始 IMU 自身重力与目标参考系重力要区分,方向仍待核对 |
mapping.gravity_init | g₀ | m/s² | 当前运行不使用这个参数,暂不调整 | 没有启用 IMU 时使用的初始重力预设 | 当前无影响 | 当前无影响 | 当前 imu_en=True,初始化使用 IMU 平均加速度,改这项不能调整当前的上下方向 |
mapping.extrinsic_T | [-0.011,-0.02329,0.04412] | m,三维平移 | 按设备型号和驱动核对,通常保持当前值 | 说明雷达原点相对内部 IMU 在哪里 | 相应坐标轴方向的换算偏移增加 | 相应坐标轴方向的换算偏移减小 | 单位米;换算成毫米为-11,-23.29,+44.12;不是雷达相对底盘或云台的安装位置 |
mapping.extrinsic_R | 3×3单位矩阵 | 无量纲,旋转矩阵 | 按设备型号和驱动核对,通常保持当前值 | 说明雷达与内部 IMU 的坐标轴怎样对应 | 不适用,不能逐元素随意增大 | 不适用,不能逐元素随意减小 | 单位矩阵表示输入两系轴向一致;整台 MID360 的安装倾斜属于机器人 TF,还需核对驱动是否额外旋转数据 |
参数详解
imu_en(启用雷达内部IMU)
当前 True 表示使用 MID360 内部 IMU。雷达连续扫描时,IMU 帮助算法判断传感器正在怎样转动、加减速,也参与初始方向判断。
它与 use_imu_as_input=False 不冲突:IMU仍在使用,只是算法使用它的方式不同。实车有振动时,先检查安装和数据,不应把“关闭 IMU”作为普通的抗振办法。
extrinsic_est_en(在线估计雷达与IMU外参)
这项决定“雷达和内部 IMU 之间的位置、朝向关系,是固定使用,还是让算法边运行边估计”。当前 False使用配置中的 extrinsic_T/R。
MID360 的雷达与内部 IMU 装在同一台设备里,整机倾斜安装、底盘转动和云台 yaw 转动都不会改变两者之间的固定关系。整台雷达在车上如何安装、随哪个关节转动,由机器人 TF描述,不能靠开启这项替代。
imu_time_inte(IMU标称时间间隔)
0.005秒对应200 Hz的标称周期,但当前源码只读入这个值,没有用它计算。改成更小的数不会让实物 IMU输出得更快;实际数据间隔要看消息时间戳。当前暂不调整。
lidar_time_inte(异常点云的回退时间窗口)
它主要给失去点云、没有有效点等回退分支提供时间窗口。正常扫描的结束时间由每个点的时间计算,不是由这个0.1秒强制规定。
因此不能只看到驱动发布20 Hz,就按1/20把它改成0.05。真实频率、逐点时间和回退窗口是不同事项,当前先保留。
satu_acc(加速度读数饱和门槛)
可以把它理解为“加速度读数快到量程边缘时,算法先别完全相信这一轴”。当前代码逐轴比较原始读数,达到 0.99×4.0=3.96 g 就屏蔽该轴的这次 IMU更新。
上实物时,它与颠簸、急加减速和振动有关,但4.0不代表已经确认硬件量程就是4 g,更不是车辆允许的最大加速度。要先核对型号/实际量程设置、输入单位和正常运动峰值。阈值太低可能把正常颠簸数据屏蔽,太高可能继续接受已限幅的读数。
原注释“与单位无关”不成立。当前输入是 g;如果换成 m/s²仍照用4.0,正常静止时某轴读数就可能超过门槛。单位改变时必须一起复核这项。
satu_gyro(角速度读数饱和门槛)
这是角速度的同类保护,当前实际门槛为 0.99×35.0=34.65 rad/s,约1985°/s、5.51圈/秒。比较的是各轴 IMU读数,不是下发给底盘的自旋速度。
快速转底盘或云台时,应看真实峰值是否接近设备量程、是否出现限幅;当前 check_satu=True 才执行这项保护。调大它不会使车辆允许转得更快,也不能直接解决航向漂移。
acc_norm(加速度单位换算基准)
这项最重要的作用是单位换算。当前本地驱动把 MID360 的加速度以 g发布,Point-LIO内部按 m/s²计算,所以 acc_norm=1.0 把原始1 g换成约9.81 m/s²。Livox 驱动的数据单位定义
实物静止时,三个轴合起来的大小应接近1 g。雷达倾斜安装后,重力会分到多个轴上,不要求某一个轴必须等于1,也不要求另外两个轴都为0。这里的 acc_norm 与 gravity 长度约9.81并不冲突:一个对应原始读数单位,一个对应内部米制计算。
若仍是 g输入却把它改成9.81,原始1 g会被换成约1 m/s²,比例就错了近10倍。当前保持1.0;这项不能用来“压住漂移”或消除振动。换驱动、做了单位转换或换传感器后,才按实际输入重新确认。
lidar_meas_cov(激光匹配对位姿的影响)
这项影响“激光匹配结果对位姿有多大作用”。但本地代码的两个求解分支方向不一致,不能简单记成“调大就少信雷达”。
当前一次更新有效匹配少于30个点时,调大通常降低激光影响;达到30个点时,另一条公式的影响方向相反。这里统计的是一次逐点/时间组更新,不是整帧点数。源码不一致已确认,实际触发和影响尚未测试,当前保留0.01。
下面的 IMU噪声可以先用两句话理解:测量噪声管“有多相信这次读数”;运动状态的过程噪声管“允许原来的运动估计多快改变”。它们作用不同,不应因为名字都有 cov 就一起加大。表中单位按本地公式推导,也不能直接与厂家噪声密度或原始 g读数比较。
acc_cov_output(加速度估计的变化不确定性)
它管“估计中的加速度是否容易改变”。车急加速、刹车或颠簸时,调大通常允许测量更快修正原来的估计,调小更倾向维持原来的趋势;如果读数主要是振动,允许变化过快也可能让估计跟着抖。
当前500是程序内部的不确定程度系数,不是给车添加500的加速度,也不是已测得的传感器噪声。应与 imu_meas_acc_cov 一起理解,先排除单位、时间和安装错误。
gyr_cov_output(转速估计的变化不确定性)
它与上一项类似,管“估计中的转速是否容易改变”。突然转底盘或云台时,调大通常允许更快跟随观测,调小则更相信原有转动趋势。
当前1000不是车辆转速上限,也不是陀螺实际噪声的测量结果。需要与 imu_meas_omg_cov、角速度峰值和时间接口一起检查,不能仅凭转动时重影就认定该项要增大。
b_acc_cov(加速度零偏变化的噪声)
“零偏”就是传感器读数中持续存在的一点偏差。它允许算法估计的加速度零偏多快变化:调大变化更容易,调小更稳定但适应漂移较慢。过大时可能把真实运动解释成偏差,当前先保持0.0001。
b_gyr_cov(陀螺零偏变化的噪声)
它管陀螺零偏估计的变化速度。实物静止时角速度若持续偏离零,需要先核对真实数据和偏差来源;这项不保证调大就能消除航向漂移。当前先保持0.0001。
imu_meas_acc_cov(加速度读数可信度)
它管“有多相信这次加速度读数”。调大表示更不相信读数,减少其修正作用;调小更相信读数,也更容易受振动影响。
当前0.1是算法采用的噪声假设,不是已经量出的传感器精度;它作用于换算后的 m/s²数据。与 acc_cov_output 配合时,要分清“读数可信不可信”和“估计能不能跟上真实变化”这两件事。
imu_meas_omg_cov(转速读数可信度)
它管“有多相信这次转速读数”。调大减少角速度测量的影响,调小更相信它。实物转动或振动时,应同时观察读数是否干净、运动估计是否跟得上,再结合 gyr_cov_output 判断。当前0.1也不是厂家的精度承诺。
gyr_cov_input(IMU预测模型的转速噪声)
当前 use_imu_as_input=False,这项不参与当前模型的预测。改它不能改善本轮转动表现,暂不调整。换到另一种模型后才重新解释和核对。
acc_cov_input(IMU预测模型的加速度噪声)
同样属于另一种模型,当前不参与预测。不要因为加速度有抖动就先改这项;当前应检查实际生效的加速度噪声项、单位和安装。
plane_thr(地图邻点的平整度门槛)
它判断“附近这5个地图点,能不能算作一张比较平整的面”。当前0.1 m表示每个邻点偏离拟合面不应超过10 cm。
斜坡也可以是一张平整的斜面。 源码没有用这项限制面的倾斜角,所以它不是最大坡度,也不是“高出地面10 cm就禁止通行”的障碍门槛;后者属于地形与代价地图的判断。
实车墙角、曲面、杂乱点或稀疏点附近匹配不足时可检查它。调大接受更不平整的点群,也可能接受错误的面;调小更严格,可用匹配可能减少。
match_s(新点与地图平面的匹配门槛)
在地图邻点已经组成一个面后,它再判断“当前雷达点离这个面是不是太远”。地图墙面重影、错误匹配或有效匹配很少时,才结合这项分析。
当前81越大,条件越严格。代码允许的距离误差还随点到雷达的距离变化,例如1 m处约11.1 cm、4 m处约22.2 cm;这些是匹配门槛,不是定位精度或车必须离墙多远。
plane_thr 检查地图邻点自己是否平整;match_s 检查新点能否对上这个面。两项不能只因为地图不好看就一起放宽,时间和外参错误也会造成类似现象。
ivox_grid_resolution(地图搜索网格大小)
它把地图分块,方便查找附近的匹配点。当前网格边长0.5 m,与邻格搜索方式一起决定每次查找的覆盖范围。
调大能覆盖更大范围,但可能查找更多点;调小范围变小,可能找不到足够的邻点。它不会直接把小于0.5 m的障碍删掉,也不是当前扫描的降采样尺寸,先结合匹配点数量与计算负担观察。
gravity与gravity_init(目标参考系重力与初始化重力)
gravity 最重要的实物含义是:Point-LIO建立自己的参考系时,应该把哪边理解为“向下”,以及重力的大小按多少计算。 它会影响初始姿态和加速度换算;方向弄错时,地面、高低和后续坡道识别都可能受到影响,不能先靠放宽地形高度范围掩盖。
当前向量长度已经约9.81 m/s²,不需要再改大小。雷达整体倾斜时,IMU自己的几个轴上会同时看到重力分量;车上坡后各轴分量也会改变。这不意味着要让配置中的 gravity 每次跟着读数改,它描述的是所选目标参考系的关系。
需要分清两个东西:
- 初始 IMU自己看到的重力方向: 当前
imu_en=True,代码从一段初始加速度读数的平均值归一化、取反,并按9.81换算得到。它仍是 IMU自身坐标中的方向。 - Point-LIO参考系中希望采用的重力方向: 由
mapping.gravity给出。代码会计算两者之间的初始转动关系,后续接口还要把结果正确接到导航使用的odom。
所以,静止读数取反能告诉我们“重力在初始IMU系中指向哪里”,不能未经坐标核对就直接等同于 mapping.gravity。同样,也不能看到导航通常让 z朝上,就擅自改成0,0,-9.81;还需核对 Point-LIO参考系、整机安装和后续接口怎样连接。本轮保留方向与数值,待核实。
gravity_init 则是在不使用 IMU时提供的初始重力预设。当前参数虽然被读入,但初始化采用真实 IMU平均加速度,gravity_init 不参与这条分支;改它不能修正当前系统的上下方向。
下面保留原日志的安装理论和测量记录作为线索。本轮没有执行其中的命令,也没有新增实物测量;这些记录所用的设备、安装方向和驱动配置仍需核对。
当前模型把整台 MID360的安装 roll设为-π/4,即-45°;模型设置是否与旧实物记录的实际轴向一致,还需要核对。
方法一:在坐标轴约定一致、初始车体水平、只存在上述 roll时的理论计算
机器人静止时,IMU 的 linear_acceleration 本质上测的是与重力反向的“比力”。如果只绕 X 轴 roll 一个角度 r,那么静止时大致有:
ax = 0
ay = g·sin(r)
az = g·cos(r)
g = 9.81 m/s²
r = -45°
ax = 0
ay = 9.81 × sin(-45°)
≈ -6.9367
az = 9.81 × cos(-45°)
≈ +6.9367
仿真
方法二:测量法
仿真环境下imu测量:
ros2 topic echo /red_standard_robot1/livox/imu --once
linear_acceleration:
x: 1.877548187489191e-05
y: -6.929646440459081
z: 6.929646470797371
这组旧仿真记录的 Y负、Z正,与上述理论条件下的计算一致;它没有验证实物安装,也不能单独证明导航参考系的上下方向正确。
然后取反得到初始 IMU自身坐标中的重力。下面旧代码片段的 gravity标签应按这个含义理解,不是要求直接填到 mapping.gravity:
gravity
≈ [0, +6.93, -6.93]
静止测量有助于核对 IMU实际轴向,但测得的初始 IMU方向仍要与目标参考系区别开;不能只用测量结果代替整条坐标关系检查。
旧实物记录(安装与数据来源待核对)
方法二:测量法
source install/setup.bash
ros2 launch livox_ros_driver2 msg_MID360_launch.py
ros2 topic echo /livox/imu --once
平均 linear_acceleration ≈
x = 0.00424
y = 0.71589
z = 0.69592
这组旧记录的 Y为正,而上面-45°理论和仿真记录的 Y为负。atan2(0.716, 0.696) ≈ 45.8° 不能只解释为0.8°的小加工误差:还存在方向符号差异。应先核对当时实物安装、坐标轴、启动配置和驱动有无额外旋转,再判断记录是否能直接比较;本轮没有实物证据解释其来源。
下面是Point-LIO代码:
tmp_gravity =
-mean_acc / mean_acc.norm() * G_m_s2;
就是三步:先求平均加速度 → 求这个向量的模 → 归一化后取反。
先求平均加速度mean_acc = 0.00423894,0.71588876,0.69592434 再求这个mean_acc的模,mean_acc.norm() =sqrt(0.00423894²+ 0.71588876²+ 0.69592434²) ≈ 0.99841142 ≈ 1.0 原始三轴合起来约1 g;代码内部使用 G_m_s2≈9.81 m/s²进行换算。这里的1与9.81对应不同单位。 所以代入公式得0.04166067, 7.03407005, 6.83785222,公式里有个负号,取反后得出-0.04166067, -7.03407005, -6.83785222
这得到的是旧记录对应的初始 IMU自身重力向量。当前 YAML确实采用了同一组数,但是否符合选定的 Point-LIO/导航参考系仍待核实;长度约9.81正确,不意味着方向关系也已经通过验证。本轮不改方向。
源码补充:初始两重力方向恰好完全反向时,Set_init 的一个分支返回 -Eye3d,该矩阵不是有效的三维旋转矩阵。这个极端分支需单独核实;本轮没有证明现有配置触发它,也没有修改源码。
extrinsic_T(雷达与内部IMU的位置关系)
它描述雷达原点相对 MID360 内部 IMU原点的位置,当前按代码使用 p_I=R_IL·p_L+t_IL。[-0.011,-0.02329,+0.04412] m 换成毫米就是-11,-23.29,+44.12 mm。
这组内部关系与雷达装在底盘/云台上的位置是两回事。换支架、把整机倾斜或转动云台,不会让内部两个原点之间的距离变化;整机安装位置应在机器人 TF中描述。值或方向弄错,转动时可能出现位置偏差和重影,但同样现象也可能来自时间或后续接口。
实物需要核对设备型号、点云与IMU原点的定义,以及数据进入 Point-LIO前有没有额外变换;不能把云台到雷达的安装距离填到这里。现有数值保留,不作为本轮新标定结论。
extrinsic_R(雷达与内部IMU的轴向关系)
它描述雷达坐标轴与内部 IMU坐标轴怎样对应。当前单位矩阵表示两路输入按轴向一致使用。整台 MID360斜装时,雷达与内部IMU一起倾斜,不能因此再把整机的-45°安装角填进这项。
还要核对驱动是否已经旋转了数据:本地驱动有对IMU进行旋转的代码,当前所读 MID360配置的旋转三项均为0。后续换配置时,要检查点云和IMU是否仍按预期对应,不能只看它们的消息名称。
整机安装角属于机器人 TF,内部轴向对应属于 extrinsic_R。旋转矩阵要由明确的坐标关系给出,不能逐个数字随意调大或调小。
vel_cov(速度估计的变化不确定性)
这项在当前 YAML中没写,源码默认20,当前 output模型使用它描述速度状态的不确定程度。它不是车辆最高速度:调大允许估计速度更容易被观测改变,调小更倾向维持原来的估计。先保持默认值;加减速反应异常也应先排除单位、时间和位姿转换问题。
本块实物核对与验证范围
实物到位、另行获准检查后,这块优先核对:静止三轴加速度合起来是否约1 g、转速读数是否接近零且单位正确;点云和IMU是否按预期轴向发布;整机安装与内部外参有没有混填;车体/云台转动或颠簸时,读数是否出现限幅、位姿和墙面是否跟得上。
当前不能把“地面斜了、墙面重影、静止漂移”等任何单一现象直接当成某个参数必须修改的证据。原始单位、时间、安装和后续 IMU/雷达位姿接口都会影响表现,其中源码缺口需要单独处理,不能通过盲调噪声保证解决。
- 源码能确认: 当前 IMU输入单位、加速度换算、饱和门槛、各参数的生效分支、内部外参用途和已记录的求解/初始化疑点。容器中只核对了安装包与当前实物 YAML的来源,没有读取运行节点参数。
- 仿真已观察: 2026-10-08 的静止和约20 cm往返有 Point-LIO位姿与配准点云输出;未验证坡道、长距离、快速转动、独立云台 yaw或实际振动。本块旧命令与读数作为历史记录保留,不扩大本轮验证范围。
- 必须实物核实: 真实安装、轴向与原点定义、量程设置、静止读数和运动峰值。重力大小已约9.81,方向与目标参考系尚待核对;没有新增测量,也没有改动源码、配置或参数值。
odometry(里程计发布设置)
参数表
odometry:
publish_odometry_without_downsample: True
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
publish_odometry_without_downsample | True | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 选择逐点更新后或每帧处理结束后发布里程计 | 不适用 | 不适用 | True:成功匹配更新后发布;False:每帧发布一次;点云降采样仍执行 |
参数详解
publish_odometry_without_downsample(里程计发布节拍)
这个开关控制里程计输出的节拍:
- True:每次成功的逐点/时间组匹配后发布,时间戳为当前采样时刻,输出更密集,实际频率取决于成功更新次数。
- False:每帧处理结束后发布一次,时间戳为扫描末尾;输入20 Hz且每帧正常处理时,通常约20 Hz输出。
当前先保持 True。后续若输出和接收负载过高,再考虑 False;改变的是输出节拍,逐点估计与点云降采样仍然执行。
publish(轨迹、点云与TF输出开关)
参数表
publish:
path_en: False # False: close the path output
scan_publish_en: True # False: close all the point cloud output
scan_bodyframe_pub_en: False # True: output the point cloud scans in IMU-body-frame
tf_send_en: False # True: send transform from 'camera_init' to 'aft_mapped'
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
path_en | False | 不适用,布尔 | 根据实际功能需求开启或设置 | 是否发布累计运行轨迹 | 不适用 | 不适用 | True 发布 path,坐标系为 camera_init;轨迹持续累计 |
scan_publish_en | True | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 是否发布参考系中的配准扫描点云 | 不适用 | 不适用 | 发布 cloud_registered,坐标系为 camera_init;本地 PCD 点云累计也依赖此开关 |
scan_bodyframe_pub_en | False | 不适用,布尔 | 根据实际功能需求开启或设置 | 是否额外发布内部 IMU 坐标系中的点云 | 不适用 | 不适用 | 需 scan_publish_en 同时为 True;话题为 cloud_registered_body,坐标系为 body |
tf_send_en | False | 不适用,布尔 | 通常保持当前值,不作为优先调试项 | 是否由 Point-LIO 发布自身位姿 TF | 不适用 | 不适用 | 当前集成链保持 False;True 发布 camera_init → aft_mapped,数值对应内部 IMU 位姿;独立调试开启时需核对 TF 组织,不是底盘位姿 TF |
参数详解
path_en(里程计轨迹发布)
True 时发布 path 累计轨迹,方便在 RViz 中观察机器人传感器的运动路线;False 时关闭该轨迹输出,里程计仍照常发布。
观察 SLAM 轨迹时可以按需开启。轨迹没有固定长度上限,长时间累计会增加内存和显示负担。
scan_publish_en(参考系中的配准点云发布)
当前保持 True,发布 cloud_registered 配准扫描,供 RViz 和后续接口使用。
False 时关闭当前配准扫描及依赖它的 body 点云输出,内部估计和建图仍继续。原注释“关闭全部点云输出”不完全准确:初始化的 Laser_map 仍可发布。另外,本地 PCD 保存所需的点云累计也放在这个分支内,后续启用保存时应保持 True。
scan_bodyframe_pub_en(内部IMU自身系点云发布)
True 时额外发布 cloud_registered_body,将预处理点云通过内部外参转换到 IMU 坐标系,主要用于辅助检查点云和外参;需要 scan_publish_en 同时为 True。
这里的 body 指 MID360 内部 IMU 坐标系。当前没有这项调试需求,先保持 False。
tf_send_en(Point-LIO位姿TF发布)
True 时随里程计发布 camera_init → aft_mapped 的 TF;False 时关闭这条 TF,里程计和配准扫描仍可继续输出。
当前集成链先保持 False,底盘 TF 由其他接口节点发布。单独调试需要显示 Point-LIO 自身位姿 TF 时,再考虑开启;这条 TF 表达内部 IMU 位姿,不是 odom → base_footprint。
pcd_save(点云地图保存)
参数表
pcd_save:
pcd_save_en: False
interval: -1 # how many LiDAR frames saved in each pcd file;
# -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames.
| 参数名 | 当前值 | 单位 | 实车处理建议 | 作用 | 调大效果 | 调小效果 | 生效条件/备注 |
|---|---|---|---|---|---|---|---|
pcd_save_en | False | 不适用,布尔 | 根据实际功能需求开启或设置 | 是否累计并保存配准扫描为 PCD 文件 | 不适用 | 不适用 | 本地累计点云需 scan_publish_en=True;集成 SLAM launch 会覆盖为 True |
interval | -1 | 次,扫描处理计数;-1为特殊值 | 根据实际功能需求开启或设置 | 控制每累计多少次扫描处理后保存一份文件 | 正数范围内:保存间隔更长,单文件通常更大、缓存更多 | 正数范围内:保存更频繁,单文件通常更小、写盘次数更多 | -1:累计到正常退出再保存;大于0:分批保存并清空累计缓存;不是秒;仅实际保存开启时生效,集成 SLAM launch 会开启保存 |
参数详解
pcd_save_en(点云地图保存开关)
False 时关闭 PCD 保存,估计和建图仍继续;True 时累计 camera_init 坐标系中的配准扫描,保存为二进制 PCD。
当前先保持 False,需要存档时再开启,并保持 publish.scan_publish_en=True。注意:slam_launch.py 会把该参数覆盖为 True,所以是否保存还要看实际启动方式。
interval(点云保存的帧数间隔)
- -1:持续累计点云,正常退出时保存到 scans.pcd。长时间运行会增加内存占用,需要正常结束程序才能执行退出保存。
- 大于0:每累计指定次数的扫描处理就保存为 scans_1.pcd、scans_2.pcd 等,并清空累计缓存;正常退出时,剩余点仍保存到 scans.pcd。
这个计数按进入保存分支的扫描处理次数增加。例如稳定20 Hz且每帧正常处理时,100次约为5秒,但 interval 本身不是时间参数。本地仅在 interval>0 时分批保存,0及其他负值也不会触发周期保存,使用默认特殊值 -1 更清楚。
保存目录由编译时ROOT_DIR确定:CMake使用当时的Point-LIO源码目录,保存代码再拼接PCD/。当前安装程序的输出目录为:
/src/pb2025_sentry_nav/point_lio/PCD/
这不是相对于运行目录的路径;在其他目录重新编译后需重新核对安装产物。
保存内容是多帧配准扫描的累计点云;文件不会自动放到导航先验地图目录。输出文件名固定,需保留不同轮次结果时,应先归档已有文件。