5. Localization 模块架构设计
本文描述 autonomy/localization 的逻辑架构、Atlas 三线程数据流与核心组件关系。
5.1 设计目标
Localization 模块遵循以下设计原则:
多算法可扩展:Atlas(视觉 SLAM)已实现;AMCL、Cartographer 配置预留,便于插件化接入
经典 SLAM 架构:Tracking / Mapping / Global Optimization 三线程解耦,跟踪低延迟
多传感器支持:单目、双目、RGB-D 统一
system::feed_*接口g2o 统一后端:位姿优化、LBA、GBA、Sim3 均基于 g2o 图优化
地图持久化:msgpack / SQLite3 双格式,支持纯定位模式
5.2 模块总览
<div class="plan-arch-link">
<span class="plan-arch-link-arrow">◄</span>
<span class="plan-arch-link-text">读写<br/>map_db</span>
<span class="plan-arch-link-arrow">►</span>
</div>
<div class="plan-arch-layer plan-arch-map">
<div class="plan-arch-header">
<span class="plan-arch-badge">数据层</span>
<span class="plan-arch-title">data::map_database</span>
</div>
<div class="plan-arch-body">
<div class="nav-body-block">
<div class="nav-body-label">实体</div>
<div class="nav-chip-list">
<span class="nav-chip">keyframe</span>
<span class="nav-chip">landmark</span>
<span class="nav-chip">frame</span>
</div>
</div>
<div class="nav-body-block">
<div class="nav-body-label">图结构</div>
<div class="nav-chip-list">
<span class="nav-chip">共视图</span>
<span class="nav-chip">spanning tree</span>
</div>
</div>
</div>
</div>
<div class="plan-arch-link">
<span class="plan-arch-link-arrow">◄</span>
<span class="plan-arch-link-text">BoW<br/>索引</span>
<span class="plan-arch-link-arrow">►</span>
</div>
<div class="plan-arch-layer plan-arch-post">
<div class="plan-arch-header">
<span class="plan-arch-badge">全局层</span>
<span class="plan-arch-title">global_optimization_module</span>
<span class="plan-arch-sub">独立 global_optimization_thread_</span>
</div>
<div class="plan-arch-body">
<div class="nav-body-block">
<div class="nav-body-label">流程</div>
<div class="nav-chip-list">
<span class="nav-chip">loop_detector</span>
<span class="nav-chip">Sim3 校正</span>
<span class="nav-chip">Loop BA</span>
</div>
</div>
</div>
</div>
5.3 Atlas 三线程架构
5.3.1 线程模型
┌─────────────────────────────────────────────────────────────┐
│ 主线程(调用 feed_*_frame) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ tracking_module::feed_frame │ │
│ │ ORB 提取 → 初始化/跟踪 → PnP → 位姿优化 → 关键帧决策 │ │
│ └─────────────────────────────────────────────────────┘ │
└───────────────────────────┬─────────────────────────────────┘
│ async_add_keyframe
┌─────────────▼─────────────┐
│ mapping_thread_ │
│ mapping_module::run │
│ 三角化 → LBA → 清理 │
└─────────────┬─────────────┘
│ queue_keyframe (BoW)
┌─────────────▼─────────────────────┐
│ global_optimization_thread_ │
│ global_optimization_module │
│ 回环检测 → Sim3 → Loop BA │
└──────────────────────────────────┘
线程 |
同步机制 |
可中断 |
|---|---|---|
Tracking |
同步返回位姿 |
|
Mapping |
|
|
Global Opt |
|
|
5.3.2 生命周期状态机
stateDiagram-v2
[*] --> Constructed: new system(cfg, vocab)
Constructed --> Running: startup()
Running --> Paused: pause_tracker()
Paused --> Running: resume_tracker()
Running --> Stopped: shutdown()
Paused --> Stopped: shutdown()
Stopped --> [*]: 析构
state Running {
[*] --> Initializing
Initializing --> Tracking: 初始化成功
Initializing --> Initializing: 失败重试
Tracking --> Lost: 内点不足
Lost --> Tracking: 重定位成功
Lost --> Lost: 重定位失败
}
5.4 Tracking 模块数据流
flowchart TD
A["feed_frame(新帧)"] --> B{"状态?"}
B -->|Initializing| C["initializer::initialize"]
B -->|Tracking/Lost| D["track()"]
C --> E{"成功?"}
E -->|是| F["Tracking"]
E -->|否| G["返回 nullptr"]
D --> H{"需要重定位?"}
H -->|是| I["relocalizer / relocalize_by_pose"]
H -->|否| J["track_current_frame"]
I --> K{"成功?"}
K -->|否| L["Lost"]
K -->|是| J
J --> M["update_local_map"]
M --> N["optimize_current_frame (PnP+g2o)"]
N --> O{"new_keyframe?"}
O -->|是| P["async_add_keyframe → mapping"]
O -->|否| Q["返回 T_cw"]
P --> Q
5.4.1 子模块职责
子模块 |
文件 |
职责 |
|---|---|---|
|
|
两帧 SfM 初始化 |
|
|
帧间特征匹配 |
|
|
BoW 检索 + PnP 重定位 |
|
|
关键帧插入策略 |
5.5 Mapping 模块数据流
flowchart TD
A["async_add_keyframe"] --> B["keyfrms_queue_"]
B --> C["mapping_with_new_keyframe"]
C --> D["store_new_keyframe"]
D --> E["create_new_landmarks (三角化)"]
E --> F["fuse_landmark_duplication"]
F --> G["local_bundle_adjuster (g2o LBA)"]
G --> H["local_map_cleaner"]
H --> I["queue_keyframe → global_opt"]
队列背压:queue_threshold_ = 2,队列过长时跳过 LBA(is_skipping_localBA)以保证实时性。
5.6 Global Optimization 模块
flowchart TD
A["queue_keyframe + BoW 索引"] --> B["loop_detector::detect"]
B --> C{"候选有效?"}
C -->|否| D["等待下一关键帧"]
C -->|是| E["transform_optimizer (Sim3)"]
E --> F["correct_loop"]
F --> G["correct_covisibility_keyframes/landmarks"]
G --> H["replace_duplicated_landmarks"]
H --> I["loop_bundle_adjuster (异步 GBA)"]
5.7 核心类关系
system
├── config_ # YAML 配置
├── camera_ # camera::base*
├── map_db_ # data::map_database
├── bow_vocab_ / bow_db_ # BoW 词袋与索引
├── tracker_ # tracking_module
├── mapper_ # mapping_module (+ thread)
├── global_optimizer_ # global_optimization_module (+ thread)
├── extractor_left/right/ini # feature::orb_extractor
├── frame_publisher_ # 可视化
├── map_publisher_ # 可视化
└── map_database_io_ # io::map_database_io_*
tracking_module
├── initializer_ # module::initializer
├── frame_tracker_ # module::frame_tracker
├── relocalizer_ # module::relocalizer
├── keyfrm_inserter_ # module::keyframe_inserter
└── pose_optimizer_ # optimize::pose_optimizer (g2o)
mapping_module
├── local_bundle_adjuster_ # optimize::local_bundle_adjuster
└── local_map_cleaner_ # module::local_map_cleaner
global_optimization_module
├── loop_detector_ # module::loop_detector
├── loop_bundle_adjuster_ # module::loop_bundle_adjuster
└── graph_optimizer_ # optimize::graph_optimizer
5.8 求解与优化层
目录 |
算法 |
用途 |
|---|---|---|
|
EPnP + RANSAC |
跟踪 / 重定位位姿 |
|
5pt / 8pt + RANSAC |
初始化 |
|
DLT + RANSAC |
平面初始化 |
|
8pt |
基础矩阵 |
|
g2o SE3 |
单帧位姿优化 |
|
g2o BA |
局部窗口优化 |
|
g2o BA |
全局优化 |
|
g2o Sim3 |
回环 Sim3 估计 |
5.9 匹配策略
匹配器 |
文件 |
场景 |
|---|---|---|
|
投影搜索 |
跟踪局部地图 |
|
立体匹配 |
双目/RGB-D 深度 |
|
BoW 加速 |
重定位 / 回环 |
|
鲁棒匹配 |
重定位请求 |
|
路标融合 |
建图去重 |
|
区域匹配 |
大基线匹配 |
5.10 Cartographer 架构
Cartographer 已集成于 localization 二进制,入口 RunCartographerNode()。
localization_main (--localization_mode=cartographer)
│
▼
CartographerNode (autolink node)
├── MapBuilderBridge ← cartographer::mapping::MapBuilder
│ ├── LocalTrajectoryBuilder2D/3D ← 扫描匹配 + 子图
│ └── PoseGraph2D/3D ← 回环 + 全局优化
├── SensorBridge ← commsgs → Cartographer 传感器
├── TfBridge ← transform::Buffer 查询外参
├── 定时器
│ ├── PublishSubmapList
│ ├── PublishLocalTrajectoryData → tracked_pose + TF
│ ├── PublishOccupancyGrid → /map
│ └── SaveMapImage → data/map.pgm
└── 服务: submap_query / start_trajectory / finish_trajectory / write_state
组件 |
文件 |
职责 |
|---|---|---|
|
|
autolink 订阅/发布/服务 |
|
|
封装 MapBuilder API |
|
|
LaserScan/Imu/Odom 转换 |
|
|
独立栅格发布 |
配置加载:LoadOptions(dir, basename) → Lua 解析 → Protobuf MapBuilderOptions。
静态 TF:自动加载 <basename>_static_transform.yaml(如 backpack_2d_static_transform.yaml)。
5.11 未来扩展:AMCL 接入点
config/localization/localization.lua
│
├── default_algorithm = "amcl" → [待实现] AmclServer
├── localization --localization_mode=cartographer → 已实现
└── localization --localization_mode=atlas → 已实现
建议统一 LocalizationInterface(Start / Stop / GetPose / FeedScan / FeedImage),与 MapInterface 风格对齐。
5.12 线程安全与中断
操作 |
机制 |
|---|---|
地图读写 |
|
暂停 |
各模块 |
重置 |
|
LBA 中断 |
|
Loop BA 中断 |
|
Tracking 暂停时会 pause_other_threads() 同步暂停 Mapping 与 Global Optimization。