# Workstation-Bounded Layered Trap Map Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Build a task-level world-coordinate grid bounded by the current vehicle, an adjustable workstation, and independent X/Y margins; tire detection remains an optional layer. **Architecture:** `TrapMapBuilder` validates required inputs, reads the Detour pose, calculates the vehicle/workstation rectangle, creates the base grid, and marks the self layer before attempting tire detection. Tire acquisition records layer health and optionally adds occupancy without controlling map success. `GridMapData` remains the merged output so a future point-cloud layer can rasterize into the same map through a separate step. **Tech Stack:** C# 10, .NET Standard 2.0, ClumsyCore/ClumsyDance, PowerShell reflection/contract tests, `dotnet msbuild`. ## Global Constraints - Do not inspect or modify `TrajPlanner`. - Workstation coordinates use the Detour world frame and millimetres. - Defaults: `WorkstationX=10000f`, `WorkstationY=0f`, `MapMarginX=3000f`, `MapMarginY=3000f`. - `Free` means “not marked by an integrated source,” not sensor-confirmed obstacle-free. - Do not invent a point-cloud API or send chassis commands. - Reject maps above `4_000_000` cells before allocating `byte[,]`. --- ### Task 1: Executable task-bound calculation **Files:** - Modify: `ClumsyPilot/MovementTest.Trapmaptest.cs` - Modify: `ClumsyPilot/tests/verify_trapmap_grid.ps1` **Interfaces:** - Consumes: vehicle/workstation coordinates, X/Y margins, resolution, cell limit. - Produces: `TrapMapBounds.TryCreate(float carX, float carY, float workstationX, float workstationY, float marginX, float marginY, float resolutionMm, int maxCellCount, out TrapMapBounds bounds, out string failureReason)` plus `XMin`, `XMax`, `YMin`, `YMax`, `Rows`, `Cols`, `CellCount`. - [ ] **Step 1: Write failing reflection tests** Append to `verify_trapmap_grid.ps1`: ```powershell $boundsType = $assembly.GetType('MultiWheelC.TrapMapBounds', $true) $tryCreate = $boundsType.GetMethod('TryCreate') function Invoke-Bounds([single]$carX, [single]$carY, [single]$stationX, [single]$stationY, [single]$marginX, [single]$marginY, [single]$resolution, [int]$maxCells) { $args = @($carX, $carY, $stationX, $stationY, $marginX, $marginY, $resolution, $maxCells, $null, $null) $ok = $tryCreate.Invoke($null, $args) [pscustomobject]@{ Ok=$ok; Bounds=$args[8]; Reason=$args[9] } } $result = Invoke-Bounds 2000 -1000 10000 0 3000 4000 50 4000000 Assert-Equal $true $result.Ok 'Valid bounds must succeed.' Assert-Equal ([single]-1000) $result.Bounds.XMin 'Wrong XMin.' Assert-Equal ([single]13000) $result.Bounds.XMax 'Wrong XMax.' Assert-Equal ([single]-5000) $result.Bounds.YMin 'Wrong YMin.' Assert-Equal ([single]4000) $result.Bounds.YMax 'Wrong YMax.' Assert-Equal 280 $result.Bounds.Cols 'Wrong column count.' Assert-Equal 180 $result.Bounds.Rows 'Wrong row count.' Assert-Equal $false (Invoke-Bounds 0 0 100000 100000 0 0 20 4000000).Ok 'Oversized map must fail.' Assert-Equal $false (Invoke-Bounds 0 0 10000 0 -1 3000 50 4000000).Ok 'Negative margin must fail.' ``` - [ ] **Step 2: Prove the new test fails** Run: ```powershell dotnet msbuild ClumsyPilot\ClumsyPilot.csproj /t:Compile /p:RestoreIgnoreFailedSources=true /v:minimal powershell -ExecutionPolicy Bypass -File ClumsyPilot\tests\verify_trapmap_grid.ps1 ``` Expected: compile succeeds; the script fails because `MultiWheelC.TrapMapBounds` is absent. - [ ] **Step 3: Implement the bounds object** Add `TrapMapBounds` beside the input models. `TryCreate` must validate every float with `TrapMapValue.IsFinite`, require margins `>=0`, resolution and limit `>0`, calculate: ```csharp float xMin = Math.Min(carX, workstationX) - marginX; float xMax = Math.Max(carX, workstationX) + marginX; float yMin = Math.Min(carY, workstationY) - marginY; float yMax = Math.Max(carY, workstationY) + marginY; int cols = (int)Math.Ceiling((xMax - xMin) / resolutionMm); int rows = (int)Math.Ceiling((yMax - yMin) / resolutionMm); long cellCount = (long)rows * cols; ``` Reject non-finite/degenerate boundaries and `cellCount > maxCellCount` before returning a populated immutable-result object. Return a concrete Chinese reason for every rejection. - [ ] **Step 4: Recompile and run behavior tests** Run the Step 2 commands. Expected final line: `TrapMap GridMapData behavior checks passed.` - [ ] **Step 5: Commit** ```powershell git add ClumsyPilot/MovementTest.Trapmaptest.cs ClumsyPilot/tests/verify_trapmap_grid.ps1 git commit -m "feat: calculate workstation-bounded trap map" ``` ### Task 2: Base-map-first lifecycle and optional tire layer **Files:** - Modify: `ClumsyPilot/MovementTest.Trapmaptest.cs` - Modify: `ClumsyPilot/tests/verify_trapmap_inputs.ps1` **Interfaces:** - Consumes: Task 1 `TrapMapBounds.TryCreate` with its declared ten parameters, Detour pose, car dimensions, optional `TwoLegDetect` output. - Produces: `WorkstationX`, `WorkstationY`, `MapMarginX`, `MapMarginY`, `WorkstationWorld`, `TrapMapTireLayerStatus TireLayerStatus`, and `string TireLayerMessage`. - [ ] **Step 1: Add failing lifecycle contracts** Add to `verify_trapmap_inputs.ps1`: ```powershell if ($source -match '\bMapHalfSizeMm\b') { $failures.Add('Legacy MapHalfSizeMm remains.') } foreach ($name in 'WorkstationX','WorkstationY','MapMarginX','MapMarginY','TrapMapBounds','TireLayerStatus','TireLayerMessage') { if ($source -notmatch "\b$name\b") { $failures.Add("Missing layered-map member: $name") } } if ($source -notmatch 'WorkstationX\s*=\s*10000f' -or $source -notmatch 'WorkstationY\s*=\s*0f' -or $source -notmatch 'MapMarginX\s*=\s*3000f' -or $source -notmatch 'MapMarginY\s*=\s*3000f') { $failures.Add('Required task-map defaults are missing.') } $createIndex = $source.IndexOf('TryCreateGridMap(') $detectIndex = $source.IndexOf('ReadTireLayer(') if ($createIndex -lt 0 -or $detectIndex -lt 0 -or $createIndex -gt $detectIndex) { $failures.Add('Base map must precede optional tire acquisition.') } if ($source -notmatch 'TRAPMAP_FREE_SEMANTICS') { $failures.Add('Free semantics are undocumented.') } ``` - [ ] **Step 2: Run the contract and confirm failure** Run `powershell -ExecutionPolicy Bypass -File ClumsyPilot\tests\verify_trapmap_inputs.ps1`. Expected: legacy half-size, missing members, and ordering assertions fail. - [ ] **Step 3: Add task-map configuration and status types** Replace `MapHalfSizeMm` with: ```csharp public float WorkstationX { get; set; } = 10000f; public float WorkstationY { get; set; } = 0f; public float MapMarginX { get; set; } = 3000f; public float MapMarginY { get; set; } = 3000f; public const int MaxCellCount = 4_000_000; public Vector2 WorkstationWorld { get; private set; } public TrapMapTireLayerStatus TireLayerStatus { get; private set; } public string TireLayerMessage { get; private set; } ``` Define enum values `NotAttempted`, `Populated`, `NoDetection`, `Unavailable`, `Simulated`. Validate finite workstation coordinates and non-negative finite margins. - [ ] **Step 4: Reorder `Get()` and split population** Implement this required sequence: ```csharp VehiclePose = vehiclePose; WorkstationWorld = new Vector2(WorkstationX, WorkstationY); if (!TryCreateGridMap(out var gridMap, out failureReason) || !TryPopulateSelfLayer(gridMap, out failureReason)) { Fail(failureReason); yield break; } ReadTireLayer(self); TryPopulateTireLayer(gridMap); ``` `TryCreateGridMap` calls Task 1's ten-parameter `TrapMapBounds.TryCreate` and constructs `GridMapData` from the returned limits. The self method marks only the vehicle. Tire population may log a rasterization problem but must not clear or suppress the valid base map. - [ ] **Step 5: Make tire acquisition non-blocking** Rename the required-input method to `ReadTireLayer`. Every exit assigns an empty or populated list plus status/message. Use: ```csharp private void SetEmptyTireLayer(TrapMapTireLayerStatus status, string message) { DetectedObstacles = new List(); TireLayerStatus = status; TireLayerMessage = message; InputSource = "无轮胎障碍输入"; DLog.Log($"轮胎层为空: status={status}, reason={message}", "TrapMapTest"); } ``` Real-mode empty lidar/config errors/exceptions/illegal coordinates become `Unavailable`; `detected == null` becomes `NoDetection`; valid endpoints become `Populated`. Ghost simulation remains `Simulated` and is never a real-mode fallback. Add beside base-map creation: ```csharp // TRAPMAP_FREE_SEMANTICS: 当前 Free 仅表示尚未被已接入层标记, // 不表示传感器确认现实中无障碍。未来实时点云应作为独立障碍层; // 引入 Unknown 后,未观测栅格不应默认允许规划通行。 ``` - [ ] **Step 6: Verify and commit** Run `powershell -ExecutionPolicy Bypass -File ClumsyPilot\tests\verify_trapmap_inputs.ps1`, `dotnet msbuild ClumsyPilot\ClumsyPilot.csproj /t:Compile /p:RestoreIgnoreFailedSources=true /v:minimal`, and `powershell -ExecutionPolicy Bypass -File ClumsyPilot\tests\verify_trapmap_grid.ps1`. Expected: both scripts exit 0 and compile has no TrapMap errors. Then: ```powershell git add ClumsyPilot/MovementTest.Trapmaptest.cs ClumsyPilot/tests/verify_trapmap_inputs.ps1 git commit -m "fix: build trap map before optional tire layer" ``` ### Task 3: Adjustable test entry and workstation visualization **Files:** - Modify: `ClumsyPilot/MovementTest.Trapmaptest.cs` - Modify: `ClumsyPilot/tests/verify_trapmap_inputs.ps1` **Interfaces:** - Consumes: Task 2 builder configuration/status. - Produces: editable test defaults, non-occupying target marker, exact bounds/layer logs. - [ ] **Step 1: Add failing UI/source contracts** ```powershell if ($source -notmatch '_workstationX\s*=\s*10000f' -or $source -notmatch '_workstationY\s*=\s*0f' -or $source -notmatch '_mapMarginX\s*=\s*3000f' -or $source -notmatch '_mapMarginY\s*=\s*3000f') { $failures.Add('MovementTest adjustable defaults are missing.') } if ($source -notmatch 'DrawWorkstationMarker\(') { $failures.Add('Target visualization is missing.') } if ($source -match 'MarkObstacle\(Workstation|MarkOccupied\([^\r\n]*Workstation') { $failures.Add('Workstation must not become occupancy.') } ``` - [ ] **Step 2: Prove the contract fails** Run the input script. Expected: missing test defaults and target visualization are reported. - [ ] **Step 3: Replace manual-edit fields and pass them to builder** ```csharp private const float _gridResolutionMm = 50f; private const float _workstationX = 10000f; private const float _workstationY = 0f; private const float _mapMarginX = 3000f; private const float _mapMarginY = 3000f; private const float _safetyMarginMm = 300f; ``` Pass all values into `TrapMapBuilder`. Log vehicle, workstation, limits, dimensions, cells, `TireLayerStatus`, and `TireLayerMessage`. Remove all half-size/20m-window documentation. - [ ] **Step 4: Draw the workstation without marking occupancy** ```csharp private void DrawWorkstationMarker(Painter painter) { const float radius = 250f; painter.DrawCircle(Color.Lime, WorkstationWorld.X, WorkstationWorld.Y, radius); painter.DrawLine(Color.Lime, WorkstationWorld.X - radius, WorkstationWorld.Y, WorkstationWorld.X + radius, WorkstationWorld.Y, width: 3); painter.DrawLine(Color.Lime, WorkstationWorld.X, WorkstationWorld.Y - radius, WorkstationWorld.X, WorkstationWorld.Y + radius, width: 3); painter.DrawText(Color.Lime, "Workstation", WorkstationWorld.X + radius, WorkstationWorld.Y + radius); } ``` Call it from visualization; never pass `WorkstationWorld` to occupancy methods. - [ ] **Step 5: Update comments and run final verification** Document formulas, defaults, task-level “global” meaning, layer order, optional tire behavior, and future independent point-cloud layer. Run: ```powershell powershell -ExecutionPolicy Bypass -File ClumsyPilot\tests\verify_trapmap_inputs.ps1 dotnet msbuild ClumsyPilot\ClumsyPilot.csproj /t:Compile /p:RestoreIgnoreFailedSources=true /v:minimal powershell -ExecutionPolicy Bypass -File ClumsyPilot\tests\verify_trapmap_grid.ps1 rg -n "MapHalfSizeMm|GetSensor\(|GetPointCloud\(|PredefinedDriveStop\(|SendMotion\(|SendRotateMotion\(" ClumsyPilot\MovementTest.Trapmaptest.cs git diff --check ``` Expected: scripts pass, compile has no TrapMap errors, forbidden search has no matches, and diff check is clean. - [ ] **Step 6: Commit** ```powershell git add ClumsyPilot/MovementTest.Trapmaptest.cs ClumsyPilot/tests/verify_trapmap_inputs.ps1 git commit -m "feat: expose workstation trap map inputs" ```