# Map 模块文档与注释实施计划

> **For agentic workers:** REQUIRED SUB-SKILL: Use `executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** 为 Map 模块提供根目录结构说明，并为所有公共 API 提供中文、Python docstring 风格的调用说明。

**Architecture:** `Map/README.md` 只说明模块结构、数据流、单位与入口；`.cs` 中的 `/// <summary>` 是参数、返回和约束的唯一 API 文档来源。注释不得改变方法签名、建图算法、缓存键或任何运行时行为。

**Tech Stack:** C# 10、netstandard2.0、PowerShell 验证脚本、Markdown。

## Global Constraints

- 所有新增说明使用中文。
- 公共 API 文档使用可被 C# IDE 识别的 `///`，内容顺序为“功能、参数、返回、注意”。
- 参数说明必须给出单位、坐标系、可空性或输入约束中的适用项。
- 返回说明必须给出结果数据的业务意义；`bool` 说明其 true/false 语义。
- README 不复制逐个属性的完整参数表。
- 不修改运行逻辑，不执行 Git 自检、暂存、提交或重置。

---

### Task 1: 建立 Map README 与文档存在性检查

**Files:**
- Create: `ClumsyPilot/ParkrobTrajplanner/Map/README.md`
- Create: `ClumsyPilot/tests/verify_planning_map_documentation.ps1`

**Interfaces:**
- Consumes: `PlanningMapFactory.Create(PlanningMapRequest request)`、Map 现有目录结构。
- Produces: Map 模块入口说明和可重复运行的文档检查。

- [ ] **Step 1: 写入失败检查**

创建 PowerShell 脚本，读取 `Map/README.md`，断言它不存在时抛出异常；创建后继续断言包含以下固定标题：`# Map 模块说明`、`## 文件结构`、`## 建图数据流`、`## 坐标与单位`、`## 最小调用示例`、`## 缓存与版本`、`## 测试与调试`。

- [ ] **Step 2: 运行检查确认失败**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Expected: 因 `Map/README.md` 不存在而失败。

- [ ] **Step 3: 创建 README**

写入当前 `Core`、`Obstacles`、`Sources`、`Planning`、`Test`、`Test/Visualization` 的目录树；每个 `.cs` 文件后写一句职责。说明数据流为 `PlanningMapRequest → IMapObstacleSource → EnvironmentMapBuilder/MapObstacleRasterizer → EnvironmentGridMap → PlanningMapAdapter/ObstacleDistanceField → PlanningGridMap`。说明环境图使用世界 mm、规划查询使用 m、范围采用左闭右开；示例只经长期持有的 `PlanningMapFactory.Create` 调用；说明 `SourceVersion` 变化与两级缓存的关系；明确 PNG 为可选调试、旧 TrapMap 不属于新运行时入口。

- [ ] **Step 4: 运行检查确认通过**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Expected: `Planning map documentation checks passed.`

### Task 2: 注释公共建图入口与结果契约

**Files:**
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/PlanningMapFactory.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/PlanningMapRequest.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/PlanningMapBuildResult.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Core/MapBuildRequest.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Core/EnvironmentMapBuildResult.cs`

**Interfaces:**
- Consumes: 外部调用者提供的地图范围、分辨率、障碍物来源。
- Produces: 建图请求、构建结果、缓存命中状态的中文 API 契约。

- [ ] **Step 1: 扩展失败检查**

在 `verify_planning_map_documentation.ps1` 中对上述文件断言：`PlanningMapFactory.Create`、`PlanningMapRequest.Bounds`、`PlanningMapBuildResult.Map` 前方紧邻中文 `///` 注释，且包含 `参数：`、`返回：`、`单位：` 或 `注意：` 中适用的说明。

- [ ] **Step 2: 运行检查确认失败**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Expected: 失败并指出缺失的入口契约说明。

- [ ] **Step 3: 添加入口契约注释**

为 `PlanningMapFactory`、构造和 `Create` 写明长期复用要求、请求输入、结果与三种缓存命中语义。为请求与结果的每个公共属性写明单位、可空性和失败/空图语义。为 `PlanningMapCacheHit` 的每个枚举值写明 `None`、`Input`、`Occupancy` 的实际含义。为内部 Map 构建请求和结果的 public 成员补充相同层级说明。

- [ ] **Step 4: 运行入口检查与编译**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Run: `dotnet build .\ClumsyPilot\ClumsyPilot.csproj --no-restore`

Expected: 文档检查通过；编译 0 error。

### Task 3: 注释地图边界、环境栅格与障碍物契约

**Files:**
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Core/MapBoundsMm.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Core/EnvironmentGridMap.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Core/EnvironmentMapBuilder.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Obstacles/IMapObstacle.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Obstacles/CircleObstacle.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Obstacles/AxisAlignedRectangleObstacle.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Obstacles/MapObstacleRasterizer.cs`

**Interfaces:**
- Consumes: 世界坐标毫米几何、有效栅格范围。
- Produces: 环境占据图以及几何到栅格的公开行为说明。

- [ ] **Step 1: 扩展失败检查**

对 `MapBoundsMm` 构造函数、`Contains`、`GetDimensions`，`EnvironmentGridMap` 构造函数和世界/栅格查询方法，以及两种障碍物构造函数与属性，断言有中文 `///`。脚本还断言 `MapObstacleRasterizer.Rasterize` 注释包含其是唯一写栅格入口的约束。

- [ ] **Step 2: 运行检查确认失败**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Expected: 失败并显示尚未文档化的公共几何/栅格 API。

- [ ] **Step 3: 添加边界与几何注释**

为范围、行列、世界 mm 坐标、左闭右开边界、越界 `false`/占据行为、`out row/col` 的失败值写明说明。为圆和矩形的坐标、半径与 `IsValid` 写明单位和 true/false 条件。为环境构建器 `Build` 写明必需来源失败会整体失败、可选来源只记录状态的规则。

- [ ] **Step 4: 运行检查与 Map 适配器脚本**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_adapter.ps1`

Expected: 两个脚本通过。

### Task 4: 注释障碍物来源与 TwoLeg 投影契约

**Files:**
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Sources/IMapObstacleSource.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Sources/ManualObstacleSource.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Sources/TwoLegProjectionInput.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Sources/TwoLegObstacleSource.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Sources/TwoLegObstacleProjector.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Sources/ObstacleProjectionResult.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Sources/ObstacleSourceStatus.cs`

**Interfaces:**
- Consumes: 纯检测快照和外部障碍物几何。
- Produces: 世界 mm 几何、来源状态和诊断信息。

- [ ] **Step 1: 扩展失败检查**

对来源接口的 ID、版本、必需性和 `ProjectToWorld`，TwoLeg 输入构造函数/属性，以及投影结果工厂方法和状态枚举值断言中文 API 说明。

- [ ] **Step 2: 运行检查确认失败**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Expected: 失败并指出缺失的来源或 TwoLeg 契约说明。

- [ ] **Step 3: 添加来源注释**

明确 `ProjectToWorld` 不得读传感器、定位、UI、时钟；`SourceVersion` 必须在快照内容变化时递增；`IsRequired` 的失败语义；TwoLeg 检测时世界位姿和两腿局部 mm 坐标、航向弧度、半径单位；`Applied/Empty/Unavailable/Invalid` 的规划含义。

- [ ] **Step 4: 运行来源工厂验证**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_factory.ps1`

Expected: `Planning map factory checks passed.`

### Task 5: 注释规划快照、距离场与缓存契约

**Files:**
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Planning/PlanningGridMap.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Planning/PlanningMapAdapter.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Planning/ObstacleDistanceField.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Planning/EuclideanDistanceTransform.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Planning/PlanningMapCache.cs`

**Interfaces:**
- Consumes: 环境占据栅格和建图输入/占据哈希。
- Produces: 不可变规划快照、保守距离和缓存复用行为说明。

- [ ] **Step 1: 扩展失败检查**

断言 `PlanningGridMap` 的公共属性与查询方法、适配器/距离场/EDT 的公共静态方法、缓存公共方法均有中文 `///`；检查 `PlanningGridMap` 注释含 m 与 mm 的单位区分。

- [ ] **Step 2: 运行检查确认失败**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Expected: 失败并报告缺失的规划或缓存说明。

- [ ] **Step 3: 添加规划与缓存注释**

说明 `PlanningGridMap` 不可变、规划世界查询使用 m、越界视为占据/零净距、距离是保守下界；说明适配器从 mm 环境图转为 m 规划图；说明 EDT 输出平方距离；说明缓存容量为四、输入命中返回同一快照、占据命中共享数组但颁发新快照元数据。

- [ ] **Step 4: 运行适配器和工厂验证**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_adapter.ps1`

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_factory.ps1`

Expected: 两个脚本通过。

### Task 6: 注释测试、PNG 调试公共 API并完成总验证

**Files:**
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Test/MovementTest.MapTest.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Test/Visualization/PlanningMapImageExportRequest.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Test/Visualization/PlanningMapImageExportResult.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Test/Visualization/PlanningMapImageExporter.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Test/Visualization/PlanningMapImageRenderer.cs`
- Modify: `ClumsyPilot/ParkrobTrajplanner/Map/Test/Visualization/ValidatedPngWriter.cs`

**Interfaces:**
- Consumes: 只读 `PlanningGridMap` 和可选 PNG 输出目录。
- Produces: 清晰的 MapTest 配置/日志语义和 PNG 导出结果说明。

- [ ] **Step 1: 扩展失败检查**

对 `PlanningMapTest.Test/TestStop`、PNG 请求/结果的每个属性、导出器常量与 `ExportIfEnabled`、渲染器和 PNG 写入器公共方法断言中文 `///`。

- [ ] **Step 2: 运行检查确认失败**

Run: `powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1`

Expected: 失败并列出测试或可视化公共成员。

- [ ] **Step 3: 添加测试与 PNG 注释**

说明 MapTest 是手工 Clumsy 入口，日志/PNG 开关仅影响调试；说明 PNG 不参与建图和缓存；说明输出目录、像素尺寸、字节大小、Saved/Skipped 的语义；说明 `ValidatedPngWriter.Write` 输入是 RGBA 行主序字节及其宽高。

- [ ] **Step 4: 完整验证**

Run:

```powershell
dotnet build .\ClumsyPilot\ClumsyPilot.csproj --no-restore
powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_documentation.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_utils.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_factory.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_adapter.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_image.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\ClumsyPilot\tests\verify_planning_map_test_config.ps1
```

Expected: 所有脚本通过；编译 0 error。现有过时 API 警告若仍来自 `MovementTests.TireFollowing.cs` 或 `TireFollowing.cs`，记录为非本任务引入。

## Plan Self-Review

- Spec coverage: Task 1 覆盖 README 和目录结构；Task 2 至 Task 6 覆盖全部 public API 分层；Task 6 覆盖完整验证。
- Placeholder scan: 本计划没有 TODO、TBD 或未指定的验证命令。
- Type consistency: 文中使用的类型和方法名均来自当前 Map 源码；不引入新运行时接口。
