260428

嗯...我想了想,其实还是可以引入动态 SLAM 的。

这样的话我们的旗帜变换位置后,小车就可以自行探索封闭空间,然后找到旗帜并停下了,避免将旗帜作为环境之一。

以及,因为 AI 目前来说还是会参与到我部分的代码编写中,但是对于我正在学习的东西的话,我希望还是尽可能我自己来写代码(参考我之前自行实现神经网络和对应的反向传播)。

这也是我正在考虑的一个点——一种更好的引导方式,避免 AI 直接写代码的同时,又可以让我知道怎么去写这个代码来让我自行去实现。

然后我想了想,其实可以为我们的目标写一个大的 roadmap, 在其下写一个 index.md, 其中每个 item 都对应一个目录。

然后在对应的目录下, 我们创建对应的 roadmap, 在对应的 roadmap item 目录中, 编写详细的 roadmap, 验收条件, 文件组织, 文件应有的功能改动等。

具体到让 AI 进行补全,就差不多是下面这样的了:

这个方式很适合你的目标,而且比“直接开写代码”更利于学习和长期迭代。

我建议把它设计成一个 docs/roadmap 风格的学习型工程路线,而不是普通 TODO。核心思想是:

大目标 roadmap
  -> 阶段 index
    -> 子阶段 roadmap
      -> 任务说明
      -> 学习目标
      -> 设计约束
      -> 验收条件
      -> 文件改动计划
      -> 调试方法
      -> 复盘记录

## 推荐目录结构

可以是这样:

docs/
  embodied-ai-roadmap/
    index.md

    00-system-baseline/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    01-slam-localization/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    02-nav2-integration/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    03-frontier-exploration/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    04-vision-flag-detection/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    05-flag-localization/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    06-mission-state-machine/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    07-integrated-demo/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

## index.md 应该承担的职责

index.md 不写太细,主要作为总控视图:

# Embodied AI Roadmap: Autonomous Exploration and Flag Seeking

## Goal

让小车在未知封闭空间中,通过 SLAM、导航、探索和视觉感知,自主探索环境、发现旗帜,并在靠近或发现旗帜后停止。

## Non-goals

- 第一阶段不使用真实机器人。
- 第一阶段不追求复杂语义理解。
- 第一阶段不使用深度学习检测器,除非 HSV / AprilTag / ArUco 无法满足需求。
- 不再直接发布旗帜全局位姿作为任务输入。

## Milestones

| Stage | Name | Purpose | Status |
|---|---|---|---|
| 00 | System Baseline | 梳理当前系统和传感器 | Not Started |
| 01 | SLAM Localization | 建立 map/odom/base_link TF 链路 | Not Started |
| 02 | Nav2 Integration | 支持点到点导航 | Not Started |
| 03 | Frontier Exploration | 自动探索未知区域 | Not Started |
| 04 | Vision Flag Detection | 通过视觉发现旗帜 | Not Started |
| 05 | Flag Localization | 估计旗帜相对或全局位置 | Not Started |
| 06 | Mission State Machine | 探索/追踪/停止状态切换 | Not Started |
| 07 | Integrated Demo | 完整闭环演示 | Not Started |

## 每个子目录建议固定 4 个文件

### 1. roadmap.md

回答“这个阶段要做什么”。

建议格式:

# 04 Vision Flag Detection

## Objective

通过相机图像检测旗帜,并发布结构化检测结果。

## Learning Goals

- 理解 ROS2 图像消息。
- 理解 `cv_bridge`。
- 理解颜色阈值 / 目标检测的基本流程。
- 理解检测结果如何作为任务状态机输入。

## Inputs

- `/camera/image_raw`
- `/camera/camera_info`

## Outputs

- `/flag_detection`

## Proposed Approach

第一版使用 HSV 阈值检测固定颜色旗帜。

## Task Breakdown

- [ ] 确认相机 topic。
- [ ] 定义检测结果消息。
- [ ] 编写检测节点。
- [ ] 在 RViz 或 OpenCV 窗口中验证 bbox。
- [ ] 发布 `/flag_detection`。

### 2. acceptance.md

回答“做到什么程度算完成”。

# Acceptance Criteria

## Functional

- 小车前方出现旗帜时,检测节点能发布 `detected=true`。
- 旗帜离开视野后,检测节点能发布 `detected=false`。
- 检测结果包含 bbox 中心点和尺寸。
- 检测频率不低于 5 Hz。

## Integration

- `mission_manager_node` 可以订阅检测结果。
- 不依赖旗帜的仿真全局位姿。
- 不修改 Gazebo 世界中的旗帜发布逻辑作为感知输入。

## Debugging

- 可以通过日志看到检测状态。
- 可以通过 RViz 或 debug image 看到 bbox。

### 3. file-plan.md

回答“预计要动哪些文件”。

# File Plan

## New Files

- `src/kibot_vision/kibot_vision/flag_detector_node.py`
- `src/kibot_interfaces/msg/FlagDetection.msg`
- `src/kibot_vision/launch/flag_detector.launch.py`

## Modified Files

- `src/kibot_interfaces/CMakeLists.txt`
- `src/kibot_interfaces/package.xml`
- `src/kibot_vision/setup.py`

## File Responsibilities

`flag_detector_node.py`

- 订阅图像。
- 转换为 OpenCV 格式。
- 使用 HSV 阈值检测旗帜区域。
- 发布 `FlagDetection`。

`FlagDetection.msg`

- 表达视觉检测结果。
- 不包含任务决策逻辑。

### 4. notes.md

回答“我学到了什么 / 卡在哪里”。

# Notes

## Decisions

- 第一版先使用 HSV,而不是 YOLO。
- 第一版只做 2D bbox,不估计 3D 位姿。

## Problems

- 光照变化可能导致 HSV 阈值不稳定。
- 如果旗帜太小,bbox 抖动明显。

## Review Notes

- 后续可以加入图像形态学处理。
- 后续可以加入 confidence 平滑。

## 我建议补充两个文件

除了每个阶段的 4 个文件,我建议总目录下再加两个全局文件。

### architecture.md

存总体架构,不随着单个任务频繁变化。

Sensor Layer
  RGB Camera
  Lidar
  Odometry

Perception Layer
  Flag Detector
  Optional Flag Localizer

Mapping Layer
  SLAM Toolbox

Navigation Layer
  Nav2

Exploration Layer
  Frontier Explorer

Decision Layer
  Mission Manager

### glossary.md

存概念表。这个对你学习具身智能很有用。

# Glossary

## SLAM

Simultaneous Localization and Mapping,同时定位与建图。

## TF

ROS 中的坐标系变换系统。

## Frontier

已知自由空间和未知空间的边界,常用于自主探索。

## 每个 roadmap item 可以包含“我能引导你的粒度”

我建议每个阶段都写一个 guidance.md,明确我怎么介入:

# Guidance Contract

## You will implement

- Node structure
- Parameters
- Launch files
- Debugging

## Codex will provide

- Architecture review
- Interface design
- Pseudocode
- Code review
- Debugging hints

## Codex will not do unless explicitly asked

- Write full node implementation
- Modify project files directly
- Refactor working code

这个文件很关键,因为它能防止我后面不小心“越界”直接替你实现。

## 更完整的目录结构

我会建议这样:

docs/
  embodied-ai-roadmap/
    index.md
    architecture.md
    glossary.md
    guidance-contract.md

    00-system-baseline/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    01-slam-localization/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    02-nav2-integration/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    03-frontier-exploration/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    04-vision-flag-detection/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

    05-flag-localization/
      roadmap.md
      acceptance.md

    06-mission-state-machine/
      notes.md

    07-integrated-demo/
      roadmap.md
      acceptance.md
      file-plan.md
      notes.md

## 我建议的路线顺序

我不建议直接从视觉开始。更稳的顺序是:

1. 00-system-baseline
   先确认现有机器人、topic、TF、传感器、Gazebo 世界、已有 package。
2. 01-slam-localization
   先让机器人知道自己在哪里。
3. 02-nav2-integration
   先能去指定目标点。
4. 03-frontier-exploration
   再能自动探索。
5. 04-vision-flag-detection
   再通过视觉发现旗帜。
6. 05-flag-localization
   再估计旗帜位置。
7. 06-mission-state-machine
   最后把探索、发现、靠近、停止串起来。
8. 07-integrated-demo
   做完整演示和复盘。

原因是:视觉发现旗帜本身不难,难的是发现之后机器人如何在地图、坐标系、导航行为中正确响应。

## 我建议我们的下一步

先不要写代码。下一步可以只创建 roadmap 文档骨架。

但在创建前,我们最好先决定两个点:

1. 文档放在 docs/embodied-ai-roadmap/,还是项目根目录 roadmap/?
2. 这个 roadmap 是中文为主,还是英文为主?

我的建议:

docs/embodied-ai-roadmap/
中文为主,保留 ROS2 / SLAM / Nav2 / TF 等英文术语

这样最适合学习和后续检索。

就这样,我们就创建了 docs/embodied-ai-roadmap/index.md:

# 路线图:自主探索与旗帜寻找

## 目标结果

KiBotTwo 从“读取外部发布的旗帜位姿”演进为“自主探索未知封闭空间、通过视觉发现旗帜、并完成靠近或停止任务”的系统。

最终系统不应把旗帜位姿当作已知环境信息,而应将旗帜作为运行时感知目标。

## 当前路线状态

当前阶段:`00-系统基线`

| 阶段 | 状态 | 依赖 | 阶段产出 |
| --- | --- | --- | --- |
| 00-系统基线 | 已计划 | 无 | 当前系统能力边界和数据流 |
| 01-SLAM-建图与定位 | 受阻 | 00-系统基线 | 可用的 SLAM 建图与定位链路 |
| 02-Nav2-导航接入 | 受阻 | 01-SLAM-建图与定位 | 可执行点到点导航的 Nav2 系统 |
| 03-边界探索 | 受阻 | 02-Nav2-导航接入 | 可自动选择探索目标的探索模块 |
| 04-视觉旗帜检测 | 受阻 | 00-系统基线 | 不依赖旗帜全局位姿的视觉检测模块 |
| 05-旗帜位置估计 | 受阻 | 04-视觉旗帜检测 | 可用于靠近任务的旗帜位置估计 |
| 06-任务状态机 | 受阻 | 03-边界探索、04-视觉旗帜检测 | 探索、发现、靠近、停止的任务状态机 |
| 07-集成演示 | 受阻 | 06-任务状态机 | 端到端演示与复盘 |

## 路线依赖图

```text
00-系统基线
  -> 01-SLAM-建图与定位
    -> 02-Nav2-导航接入
      -> 03-边界探索
        -> 06-任务状态机
          -> 07-集成演示

00-系统基线
  -> 04-视觉旗帜检测
    -> 05-旗帜位置估计
      -> 06-任务状态机

阶段 00:系统基线

状态:已计划

阶段目的:

  • 明确当前项目已经具备什么能力。
  • 找出当前“直接发布旗帜位姿”的数据路径。
  • 确认后续 SLAM、Nav2、视觉模块接入的真实工程入口。

进入条件:

  • 项目可以正常构建,或至少可以启动当前仿真。
  • 能访问当前 package、launch、URDF/Xacro、world、节点代码和接口定义。

阶段产出:

  • 当前 ROS2 graph 的概要记录。
  • 当前 TF tree 的概要记录。
  • 当前传感器列表。
  • 当前旗帜位姿发布和消费链路。
  • 后续阶段的实现风险清单。

完成条件:

  • 能说明当前小车如何移动。
  • 能说明当前旗帜信息如何进入任务逻辑。
  • 能说明当前是否已有 lidar、camera、odom、imu、TF。
  • 能决定 01-SLAM-建图与定位04-视觉旗帜检测 的最小切入点。

后续阶段:

  • 01-SLAM-建图与定位
  • 04-视觉旗帜检测

阶段 01:SLAM 建图与定位

状态:受阻

依赖阶段:

  • 00-系统基线

阶段目的:

  • 引入或整理 SLAM 链路。
  • 建立 map -> odom -> base_link 的定位基础。
  • 让小车在未知环境中生成可用于导航的地图。

阶段产出:

  • SLAM launch / config 方案。
  • 可在 RViz 中观察的 map。
  • 稳定的 TF 链路。
  • 对 lidar / odom 数据质量的判断。

完成条件:

  • 小车移动时地图可以持续更新。
  • mapodombase_link 的 TF 关系清晰且无冲突。
  • 生成的地图足够支持 Nav2 costmap。

后续阶段:

  • 02-Nav2-导航接入

阶段 02:Nav2 导航接入

状态:受阻

依赖阶段:

  • 01-SLAM-建图与定位

阶段目的:

  • 引入 Nav2 点到点导航能力。
  • 让小车能够在地图和 costmap 基础上执行目标点导航。

阶段产出:

  • Nav2 bringup 方案。
  • planner / controller / costmap 的最小配置。
  • 可通过 RViz 或 action client 发送目标点。

完成条件:

  • 小车能接收 NavigateToPose 目标。
  • 小车能规划路径并尝试到达目标点。
  • 障碍物和未知区域在 costmap 中表现合理。

后续阶段:

  • 03-边界探索

阶段 03:边界探索

状态:受阻

依赖阶段:

  • 02-Nav2-导航接入

阶段目的:

  • 让小车从“被动接收目标点”升级为“主动选择探索目标”。
  • 使用 frontier 或等价策略驱动未知空间探索。

阶段产出:

  • frontier 提取策略。
  • frontier 评分和过滤策略。
  • 向 Nav2 发送探索目标的模块设计。
  • 探索失败和目标不可达处理策略。

完成条件:

  • 小车能在没有人工目标点的情况下探索未知空间。
  • 探索目标不会明显重复或频繁震荡。
  • 遇到不可达目标时能切换到其他目标。

后续阶段:

  • 06-任务状态机

阶段 04:视觉旗帜检测

状态:受阻

依赖阶段:

  • 00-系统基线

阶段目的:

  • 通过相机图像发现旗帜。
  • 移除任务逻辑对旗帜全局位姿输入的依赖。

阶段产出:

  • 旗帜视觉检测方案。
  • 检测结果 topic / message 设计。
  • 第一版检测节点的输入输出契约。

完成条件:

  • 旗帜进入视野时能发布检测结果。
  • 旗帜离开视野时能恢复未检测状态。
  • 检测结果与任务决策解耦。

后续阶段:

  • 05-旗帜位置估计
  • 06-任务状态机

阶段 05:旗帜位置估计

状态:受阻

依赖阶段:

  • 04-视觉旗帜检测

阶段目的:

  • 将图像中的旗帜检测转化为机器人可用的空间位置估计。
  • 判断第一版任务应采用“发现即停止”还是“发现后靠近”。

阶段产出:

  • 旗帜位置估计策略。
  • 坐标系转换链路。
  • 检测抖动和丢失目标处理策略。

完成条件:

  • 能给出旗帜相对 base_linkcamera_link 的估计。
  • 如需要全局导航,能转换到 map 坐标系。
  • 能明确估计误差对靠近任务的影响。

后续阶段:

  • 06-任务状态机

阶段 06:任务状态机

状态:受阻

依赖阶段:

  • 03-边界探索
  • 04-视觉旗帜检测

可选依赖:

  • 05-旗帜位置估计

阶段目的:

  • 将探索、视觉发现、靠近旗帜和停止行为组织成明确状态机。
  • 避免探索逻辑、视觉逻辑和导航逻辑互相耦合。

阶段产出:

  • 任务状态定义。
  • 状态切换条件。
  • Nav2 goal 发送、取消和切换策略。
  • 误检、目标丢失、导航失败、超时的处理规则。

完成条件:

  • 小车可从 EXPLORING 切换到旗帜相关状态。
  • 检测到旗帜后不会继续盲目探索。
  • 停止条件明确且可复现。

后续阶段:

  • 07-集成演示

阶段 07:集成演示

状态:受阻

依赖阶段:

  • 06-任务状态机

阶段目的:

  • 完成从启动仿真到任务结束的端到端闭环。
  • 记录系统能力边界、失败模式和下一轮优化方向。

阶段产出:

  • 一套可复现的 demo 流程。
  • RViz 可视化配置。
  • 运行指令。
  • 已知问题列表。
  • 下一版路线图候选项。

完成条件:

  • 在未知封闭空间中,小车能开始探索。
  • 旗帜位置变化后,小车仍能通过视觉发现旗帜。
  • 小车能按当前策略靠近或停下。
  • 不依赖直接发布的旗帜全局位姿完成任务。

路线图更新规则

  • 只有当前阶段可以进入 进行中
  • 阶段完成后,再创建或补全下一阶段的详细 roadmap。
  • 如果某阶段发现前置假设错误,应回到依赖阶段更新结论。
  • 每个阶段结束时,必须记录新的风险、取舍和下一步入口。

阶段状态说明

已计划    尚未开始,但已进入近期计划
进行中    当前正在推进
受阻      等待依赖阶段完成
已完成    已达到完成条件
暂缓      暂时不做,但不阻塞主线
返工      已完成过,但需要重新调整

在这个的基础上,我们在对应的阶段创建实际的 Roadmap 的详细 item 就可以了。

我们先实现阶段 0 的 item,写入docs/embodied-ai-roadmap/00-系统基线/roadmap.md​:

```markdown
# 阶段 00:系统基线调查报告

## 本阶段定位

本阶段由 Codex 负责完成项目梳理,用于承接当前系统,并为后续 SLAM、Nav2、自主探索和视觉旗帜检测提供工程入口。

本阶段不是学习任务清单,也不是功能实现阶段。它的产物应该回答:

```text
当前系统是什么样?
当前能力边界在哪里?
后续阶段应该从哪里接入?
哪些现有逻辑需要保留、替换或隔离?

调查方式

本次基线基于源码静态分析完成,未启动 Gazebo 或 ROS2 graph 做运行时采样。

已阅读范围:

  • README.md
  • src/kibot_one_control 的 package、launch 和 Python 节点
  • src/kibot_one_interface 的 msg / srv 接口
  • src/kibot_one_sim 的 launch、bridge 配置、world 和 SDF 模型

核心结论

当前系统是一个基于 Gazebo Sim 的移动机器人仿真项目,主要能力是:

  • 启动 Gazebo 世界。
  • 通过 ros_gz_bridge 桥接 Gazebo 和 ROS2。
  • 使用 /cmd_vel 控制 Gazebo 中的差速机器人模型。
  • 使用 /odom/robot_pose/flag_pose/scan 做目标跟随。
  • 通过模式系统在 STOP、CRUISE、MANUAL、FOLLOW 之间切换。
  • FOLLOW 模式下,follow_controller 直接读取机器人全局位姿和旗帜全局位姿,结合激光雷达做局部避障跟随。

当前系统还不具备:

  • 相机传感器。
  • 深度相机。
  • IMU。
  • SLAM。
  • Nav2。
  • map frame。
  • 标准 base_link frame。
  • 基于视觉的旗帜检测。
  • 自主探索。

当前主线数据流

Gazebo world
  -> kibot_one_base model
  -> DiffDrive plugin
  -> /model/kibot_one_base/odometry
  -> ros_gz_bridge
  -> /odom

Gazebo world
  -> follow_flag model
  -> PosePublisher plugin
  -> /model/follow_flag/pose
  -> ros_gz_bridge
  -> /flag_pose

Gazebo lidar
  -> /scan
  -> ros_gz_bridge
  -> /scan

/mode
/odom or /robot_pose
/flag_pose
/scan
  -> follow_controller
  -> /cmd_vel_raw
  -> cmd_vel_watchdog
  -> /cmd_vel
  -> ros_gz_bridge
  -> /model/kibot_one_base/cmd_vel
  -> Gazebo DiffDrive

当前任务逻辑判断

当前“找旗帜”的任务并不是感知任务,而是位姿跟随任务。

follow_controller 直接订阅 /flag_pose,从消息中读取 x/y 作为目标点;同时订阅 /robot_pose/odom 获取机器人自身位置,再计算到旗帜的方向和距离。当距离小于 stop_distance 时发布零速度停止。

这条链路绕过了:

  • 视觉发现。
  • 目标识别。
  • 从图像估计目标位置。
  • 地图构建。
  • 全局路径规划。

因此后续目标不是简单替换某个参数,而是要逐步把“已知旗帜位姿输入”改造成“运行时视觉感知输入”。

对后续阶段的直接影响

对阶段 01:SLAM 建图与定位

当前已有 /scan/odom,这是接入 2D SLAM 的基础。

但存在关键风险:

  • 当前机器人坐标 frame 是 chassis,不是 Nav2 / SLAM 常见的 base_link
  • 激光 frame 是 lidar_link,但 ROS 侧是否存在 chassis -> lidar_link 的 TF 需要运行时确认。
  • 当前没有 map frame。
  • 当前没有 robot_state_publisher,模型是 Gazebo SDF,不是 URDF / Xacro。

阶段 01 的首要任务应该不是直接调 slam_toolbox 参数,而是先补齐或确认 TF 结构。

对阶段 02:Nav2 导航接入

当前控制入口是 /cmd_vel,理论上 Nav2 controller 可以输出到 /cmd_vel

但当前已有 cmd_vel_watchdog 和多个控制节点会通过 /cmd_vel_raw -> /cmd_vel 链路控制机器人。后续接入 Nav2 时必须避免多个控制源同时发布速度。

阶段 02 需要明确:

  • Nav2 是否直接发布 /cmd_vel
  • 是否保留 cmd_vel_watchdog
  • FOLLOW / MANUAL / CRUISE 模式与 Nav2 控制权如何互斥。

对阶段 03:边界探索

当前没有地图,也没有 Nav2,因此不能直接做 frontier exploration。

边界探索必须依赖:

  • map
  • 机器人在 map 中的定位。
  • 可用的 Nav2 goal 接口。

对阶段 04:视觉旗帜检测

当前没有相机,因此视觉检测阶段必须先给机器人模型增加 RGB camera,并通过 bridge 暴露 ROS2 图像 topic。

当前旗帜模型具备红色旗面,尺寸约为 0.30 x 0.02 x 0.20,适合第一版用颜色阈值做检测。

对阶段 05:旗帜位置估计

当前没有深度相机。若只增加 RGB camera,第一版可以先做“发现即停止”;若要“发现后靠近”,需要至少满足一个条件:

  • 增加 depth camera。
  • 利用已知旗帜尺寸做单目测距。
  • 结合机器人运动和多帧观测做估计。

对阶段 06:任务状态机

当前模式系统已经有 STOP、CRUISE、MANUAL、FOLLOW,但 FOLLOW 逻辑是“直接跟随旗帜位姿”。

后续可以复用模式管理思想,但不建议继续把探索、视觉、导航和停止逻辑塞进现有 follow_controller

更合理的方向是新增 mission manager,让它管理:

探索中
  -> 发现旗帜
  -> 取消探索目标
  -> 靠近或停止
  -> 任务结束

本阶段结论

阶段 00 已经足够解锁两个并行方向:

  • 01-SLAM-建图与定位:基于 /scan/odom,先解决 TF 命名和激光 frame 问题。
  • 04-视觉旗帜检测:先给 SDF 机器人模型增加 RGB camera,再桥接图像 topic,最后检测红色旗面。

推荐先推进 01-SLAM-建图与定位,因为自主探索和后续靠近旗帜都依赖地图、定位和导航能力。


目前就是对我们系统的调查情况了,在此基础上我们可以继续后续的 roadmap:01-SLAM-建图与定位。

我觉得这个东西有必要打包为 skill。

最后写了个第一版放到了我的 Skill 仓库里,就叫 guided-engineering-roadmap​吧。

对应的仓库地址:https://github.com/JeseKi/jese\_skills/blob/main/guided-engineering-roadmap/SKILL.md​