(map-guide)= # 0. Map 地图模块指南 `autonomy/map`:环境地图子系统,对齐 nav2 `nav2_costmap_2d` 与 ETH `grid_map`。输出 `OccupancyGrid`(静态)、`Costmap2D`(规划/避障)、`GridMap`(地形/高程)。 | 本文 §0 | 其他文档 | |---------|----------| | 上手、配置、排错 | [§1 架构](01_architecture.md) · [§2 组件](02_map_components.md) · [§5 综述](05_survey.md) | --- ## 0.1 文档地图 | 角色 | 阅读顺序 | |------|----------| | 新手 | §0.2 → [§1](01_architecture.md) → [§2](02_map_components.md) | | 集成 | §0.2、§0.5、§0.7 → [§3 图层](03_costmap2d.md#39-图层详解) | | 算法 | [§5](05_survey.md) → [§2](02_map_components.md) → [§3–§4](03_costmap2d.md) | | § | 文档 | 内容 | |---|------|------| | 0 | 本指南 | 上手、形式化、配置、排错 | | 1 | [架构](01_architecture.md) | 三条管线、数据流、线程 | | 2 | [组件总览](02_map_components.md) | MapServer / Costmap2D / GridMap 对比 | | 3–4 | Costmap2D · GridMap | 实现专题 | | 5 | [综述](05_survey.md) | 历史、分类、选型 | --- ## 0.2 快速开始 ### Costmap2D(三步) 1. `config/planner/planner.lua` — 配置 `costmap` 块(图层、分辨率、footprint) 2. `config/autonomy.lua` — `planning = AUTONOMY_PLANNER`(`PlannerServer` 自动构造 `Costmap2DWrapper`) 3. 确保 `MapServer` 发布静态地图,或 `static_layer` 订阅 `/map` ```lua -- config/planner/planner.lua costmap = { enabled = true, name = "global_map", frame_id = "map", resolution = 0.05, width = 20.0, height = 20.0, update_frequency = 5.0, robot_radius = 0.22, plugins = {"static_layer", "obstacle_layer", "inflation_layer"}, static_layer = { enabled = true, map_topic = "map" }, obstacle_layer = { enabled = true, sensor_sources = { scan = { topic = "scan", data_type = "LaserScan", marking = true, clearing = true }, }, }, inflation_layer = { enabled = true, inflation_radius = 0.35, cost_scaling_factor = 3.0 }, } ``` ```cpp #include "autonomy/map/costmap_2d/costmap_2d_wrapper.hpp" auto costmap = std::make_shared( autonomy::map::CreateCostmap2DOptions("config"), "global_costmap"); costmap->Start(); costmap->updateRobotPose(x, y, yaw); ``` ### MapServer ```cpp auto server = std::make_shared( autonomy::map::LoadOptions("config").map_server()); server->SetMapPublishCallback([](const auto& grid) { /* → static_layer */ }); server->Start(); ``` ### GridMap ```cpp auto grid = std::make_shared( autonomy::map::CreateGridMapOptions("config")); grid->Start(); // 应用层写入 elevation;查询见 §4 ``` **验证**:`MapServer::HasStaticMap()` · `costmap->isCurrent()` · 自由区 ≈ 0、障碍 ≈ 254。 运行时序见 [§1.3.4](01_architecture.md#134-单次更新数据如何流过各层);组件对比见 [§2](02_map_components.md)。 --- ## 0.3 环境形式化 (map-overview)= 平面环境 $\mathcal{W} \subset \mathbb{R}^2$ 离散为栅格 $\mathcal{M} = \{ c_{ij} \}$,分辨率 $\Delta$ 将 $\mathbf{p}=(x,y)^\top$ 映射到索引 $(m_x, m_y)$。Autonomy 提供两套坐标约定: | 属性 | Costmap2D | GridMap | |------|-----------|---------| | 原点 | 地图**左下角** $(x_0, y_0)$ | 地图**中心** $\mathbf{p}_{\text{map}}$ | | 索引 | $idx = m_y \cdot N_x + m_x$ | Eigen 矩阵 + 循环 buffer | | 数值 | 离散 0–255 | 连续 float,`NaN` 表无效 | 互转须显式处理原点差异;公式见 [§3.5](03_costmap2d.md#35-坐标变换) · [§4.6](04_grid_map.md#46-坐标变换)。 --- ## 0.4 代价值语义 规划读 Costmap2D **快照**;代价值为 Planning / Control 公共输入。 | 值 | 常量 | 含义 | |----|------|------| | 0 | `FREE_SPACE` | 完全自由 | | 1–252 | — | 距障碍越近代价越高 | | 253 | `INSCRIBED_INFLATED_OBSTACLE` | 内切膨胀区 | | 254 | `LETHAL_OBSTACLE` | 致命障碍 | | 255 | `NO_INFORMATION` | 未知 | 膨胀公式与图层见 [§3.6–§3.8](03_costmap2d.md#36-代价值体系);Planning 侧解读见 [Planning §0.4](../08_Planning/00_guide.md#04-代价地图)。 --- ## 0.5 配置与 API (map-usage)= ### Costmap2D | 项 | 值 | |----|-----| | 配置 | `config/planner/planner.lua` → `costmap` | | 加载 | `map::CreateCostmap2DOptions("config")` | | 集成 | `PlannerServer` 自动构造并 `Start()` | **端到端(经 PlannerServer)** ``` MapServer::Start() → PlannerServer 构造 Costmap2DWrapper → static_layer 收地图 → bridge 转发 /scan → TF 就绪 → isReady() ``` | API | 何时 | |-----|------| | `Start()` | 系统启动 | | `applyOccupancyGrid` | 静态地图到达 | | `feedLaserScan` | 每次激光回调 | | `getCostmap()` + lock | 规划前复制快照 | | `isReady()` / `isCurrent()` | 规划前检查 | 图层参数要点见 [§3.9](03_costmap2d.md#39-图层详解);详细 API 见 [§3.3](03_costmap2d.md#33-详细使用指南)。 ### GridMap | 项 | 值 | |----|-----| | Proto | `map_grid_option.proto` | | 封装 | `GridMapWrapper` | | 差异 | 无自动传感器管线;应用层投影点云到 `elevation` | 详见 [§4.3](04_grid_map.md#43-详细使用指南)。 ### MapServer | API | 用途 | |-----|------| | `Start()` | 加载并发布 | | `GetStaticMapShared()` | 获取 `OccupancyGrid` | | `SetMapPublishCallback` | 转发给 `applyOccupancyGrid` | --- ## 0.6 自定义 Costmap 图层 1. 继承 `CostmapLayer` 或 `Layer`,实现 `updateBounds()` / `updateCosts()` 2. 编译为 `.so`,在 `plugins` 列表注册 3. Lua 中添加对应参数块 参考 `autonomy/map/costmap_2d/layers/`;架构见 [§1.12](01_architecture.md#112-扩展自定义图层)。 --- ## 0.7 故障排查 | 现象 | 常见原因 | 处理 | |------|----------|------| | `PlannerTimedOut` | costmap 未更新 | `update_frequency`、`isCurrent()` | | 路径穿墙 | 膨胀不足 | 增大 `inflation_radius` | | 机器人被标为障碍 | footprint 未清除 | `footprint_clearing_enabled=true` | | 全未知 (255) | 静态图未加载 | MapServer、`static_layer.map_topic` | | 坐标偏移 | TF / `frame_id` | 统一 frame 与 TF 树 | | GridMap 查询 NaN | 无数据或越界 | 检查 `move()` 后 buffer | **检查清单**:`HasStaticMap()` · `isCurrent()` · `worldToMap` 边界 · 可视化 costmap 快照。 性能建议:全局图 ≤ 2048² · 更新 5 Hz · 规划时复制 char map 避免长持锁。详见 [§3.3.6](03_costmap2d.md#336-启动检查清单)。