历史快照
本专题页写于包拆分与 FAST-LIVO2 / CustomMsg / 图像输入落地之前,反映当时的单包结构与
五前端状态。已知过时点:目录布局(apps/launch 现属 asuka_ros 包)、共享的
config_sensor.json(外参已改为各前端 odometry 配置的 sensor 块)、ROS 层 acc_scale
等描述、前端数量(现六种,新增 fastlivo)、CustomMsg 与图像输入链路。2026-09 下旬以来:lightning / superodom 前端与 optimization_miao 后端已移除
(现五前端:fastlio / batchlio / superlio / fastlivo / srlivo;smallpointlio 已于 2026-10-23 移除,odometry/10-11 为其历史快照);
freedom 扩展已整体迁出 asuka(移入 nagisa 包);KeyFrame::stamp 统一为扫描
起始时刻;执行器新增连续失败熔断与 wait_for() 排空检测、扩展与执行器有
ok() 健康查询。
现行事实以主文档 (index / architecture / parameters / odometry 等)与源码为准。
title: "SuperLIO 辅助设施与预处理" description: >- types/alias/timer 等基础设施(类型别名、计时器)、点云与 IMU 预处理及 create.cpp 插件导出,构成 SuperLIO 子模块的收尾部分。
SuperLIO 辅助设施与预处理
本页收尾 SuperLIO 子模块(src/asuka/include/asuka/odometry/superlio 与对应 src 目录):类型别名、公共状态结构、计时器三个基础设施头,点云与 IMU 预处理,以及 create.cpp 插件导出。它们不承担状态估计本身,但定义了这个实现的数据契约、精度基调与接入主链路的边界。
文件构成与角色
| 文件 | 体量 | 角色 |
|---|---|---|
alias.hpp |
2.2KB | 全子模块共享的标量/向量/矩阵/四元数别名 |
types.hpp |
2.2KB | 状态快照与帧级数据结构(SysState/MeasureGroup 等) |
timer.hpp |
1.6KB | 函数级耗时统计 Timer |
cloud_preprocess.hpp/.cpp |
0.8KB + 2.8KB | 点云预处理,Livox/Robosense 双分支 |
imu_preprocess.hpp/.cpp |
各约 1.2KB | IMU 预处理(本页证据仅含文件清单,未展开内容) |
create.cpp |
183B | extern "C" 插件工厂,dlopen 入口 |
alias.hpp:单精度基调
alias.hpp 只做一件事——为整个 asuka::superlio 命名空间固化数学类型:
Scalar = float:该子模块默认以单精度运算,这与以 double 为主的其它实现形成精度取向差异;V2~V18/VX向量、M1~M18方阵及M3_2/M2_3非方阵,全部基于Scalar;VV3/VV4为带 Eigen 对齐分配器的向量数组;V2d~M18d、Quatd等d后缀的 double 变体,用于与外部接口(如秒级时间戳)交互;- 常量
Eye3/ZeroV3/EyeV3提供零成本默认初值。
其中 15/17/18 维向量与方阵别名正是 LIO 误差状态滤波的典型状态/协差维度,与同目录 eskf.hpp 的状态设计呼应(详见 SuperLIO ESKF 页面)。
types.hpp:状态快照与帧级数据契约
types.hpp 依赖 alias.hpp 与 manifold.hpp(So3/Se3),定义四组载体:
- 滤波状态快照:
SysState(timestamp + rot + p + v + bg + ba,即带零偏的完整 ESKF 状态,可由Se3+速度构造)、NavState(仅 rot/p/v)、PoseT(仅 rot/p)。三者都提供get_se3(),把内部表示统一折叠为流形上的位姿,方便向下游(可视化、扩展模块)输出; - 动态中间量:
DynamicState用裸M3存旋转并附 w/a,偏向数值迭代过程中的瞬时量而非几何对象; - IMU 样本:
ImuSample(secs/acc/gyr),带EIGEN_MAKE_ALIGNED_OPERATOR_NEW保证 16 字节对齐; - 帧级同步组:
LidarData(start_time/end_time +PointCloudT::ConstPtr)与MeasureGroup(LidarData +boost::circular_buffer<ImuSample>)。环形容器意味着 IMU 窗口有界,start_time/end_time的成对出现为去畸变提供点云时间跨度。
timer.hpp:轻量耗时统计
Timer 是一个无锁的 std::map<std::string, TimerRecord>:模板方法 evaluate(func, name) 用 high_resolution_clock 包裹任意可调用对象,按函数名累积毫秒耗时;print_all() 通过 spdlog 输出每个名字的平均耗时与调用次数,clear() 清空。它只适合单线程或阶段性剖析(map 无锁),是主流程做性能归因时的随手工具。
cloud_preprocess:点云预处理
superlio::CloudPreprocess 继承共享抽象基类 asuka::CloudPreprocess,重载 Livox/Robosense 两个 preprocess。ROS 层只持有基类指针,具体过滤策略对上层不可见。
配置期(构造函数):读 config_odometry 的 preprocess 段——min_distance(默认 2.0m)、max_distance(默认 60.0m)、filter_rate(默认 3,std::max(1, ...) 兜底)。前两者在构造时预平方为 min/max_distance_squared(4.0/3600.0),运行期比较免开方;三个参数构造后只读。
运行期(每帧):
- 空(Livox 分支还要求
size >= 2)直接返回空输出; - 取首点
timestamp作时间基准timebase; - 按
filter_rate步进降采样(reserve(raw->size()/filter_rate + 1)预留); - Livox 分支额外做 tag 位段过滤:
(tag & 0x30)既非0x10也非0x00的点剔除,Robosense 分支无此检查; - 距离平方落在
(min, max)之外(<=min或>=max)的点剔除; - 输出
PointT:xyz/intensity 直拷,offset = (timestamp - timebase) / 1e6,即把绝对时间转为相对首点的时间,供下游去畸变使用。
值得注意的细节:函数签名保留了 stamp 参数但两个实现体内均未使用——时间信息完全由点级相对时间承载。
imu_preprocess 与 create.cpp
imu_preprocess.hpp/.cpp 各约 1.2KB,从清单与命名看与 cloud_preprocess 同属“算法私有实现挂接共享基类”的模式;其体量与 FastLIO 版 8.7KB 的 IMU 预处理形成鲜明对比,可推断 SuperLIO 把 IMU 前向传播等重活收进了主流程与 ESKF,预处理层极薄。
create.cpp 全文仅 6 行:extern "C" 导出 create_odometry_estimation(),new 一个无参 superlio::OdometryEstimation 返回裸指针。没有删除器、没有异常处理——生命周期完全交给上层 dlopen 注册表(句柄永不关闭、插件常驻),是五种算法中最小、最标准的插件接入样例。
调用链全景
flowchart TD
subgraph CTOR["装配链(进程启动执行一次)"]
A["AsukaROS 构造"] --> B["load_module(so_name)"]
B --> C["dlopen superlio.so"]
C --> D["create.cpp<br/>create_odometry_estimation()"]
D --> E["new superlio::OdometryEstimation"]
E --> F["CloudPreprocess 构造<br/>读 config_odometry 并平方化门限"]
end
subgraph DATA["数据链(每帧点云)"]
G["AsukaROS::insert_frame"] --> H["共享 cloud_preprocess 基类指针<br/>虚函数分派"]
H --> I["Livox 分支:tag & 0x30 过滤"]
H --> J["Robosense 分支"]
I --> K["距离平方门限 + filter_rate 降采样<br/>offset = 相对首点时间"]
J --> K
K --> L["PointCloudT → 异步队列"]
L --> M["superlio 主流程<br/>MeasureGroup = LidarData + 环形 IMU 缓冲"]
end
F -. "实例被取出为共享指针" .-> H
关键节点:装配链中 create.cpp 是 so 与框架之间唯一命名约定;CloudPreprocess 随主估计器一起构造,参数在此时固化。数据链中 ROS 层通过基类指针回调到本页实现,过滤降采样后的点云携带相对时间进入异步队列,最终在主流程内与 circular_buffer 中的 IMU 样本组装成 MeasureGroup 供 ESKF 消费——本页类型定义正是这条链上各环节的交接口径。
边界条件与扩展点
边界条件:
- 空点云与近空点云(Livox 分支
size < 2)返回空输出而非报错; - 距离门限为闭式剔除(
<=min或>=max),平方比较避免 sqrt;filter_rate被 clamp 到 ≥1,防 步进为 0; - Robosense 分支缺少
size<2检查,但empty已拦截,取points[0]仍安全; Timer的 records 无锁,跨线程共用需外部同步;- 工厂函数无参、无配置注入,配置错误只能靠
param<T>的默认值兜底。
扩展点:
- 接入新雷达类型:基类新增
preprocess重载后在本实现补一个分支(照 Robosense 分支裁剪); - 预处理调参只动
config_odometry的preprocess段,无需改代码; Timer::evaluate可包裹任意 lambda 增加统计点,print_all手动触发汇总;- 若需整体切换精度,改
alias.hpp的Scalar一处即可(需同步评估 ESKF 数值稳定性); types.hpp新增状态结构体并实现get_se3(),即可向可视化/扩展模块暴露新的状态快照。
Sources:
- src/asuka/include/asuka/odometry/superlio/types.hpp#L1-L96
- src/asuka/include/asuka/odometry/superlio/alias.hpp#L1-L73
- src/asuka/include/asuka/odometry/superlio/timer.hpp#L1-L58
- src/asuka/include/asuka/odometry/superlio/cloud_preprocess.hpp#L1-L32
- src/asuka/src/asuka/odometry/superlio/cloud_preprocess.cpp#L1-L82
- src/asuka/src/asuka/odometry/superlio/create.cpp#L1-L6
关联源码
src/asuka/include/asuka/odometry/superlio/types.hppsrc/asuka/include/asuka/odometry/superlio/alias.hppsrc/asuka/include/asuka/odometry/superlio/timer.hppsrc/asuka/src/asuka/odometry/superlio/cloud_preprocess.cppsrc/asuka/src/asuka/odometry/superlio/imu_preprocess.cppsrc/asuka/src/asuka/odometry/superlio/create.cpp