test: verify rolling EM execution
This commit is contained in:
@@ -343,3 +343,105 @@ PASS longitudinal-integration
|
||||
PASS trajectory
|
||||
PASS em-planning-service
|
||||
```
|
||||
|
||||
## Rolling execution ownership and deployment
|
||||
|
||||
The first-version boundary has three independently testable layers:
|
||||
|
||||
```text
|
||||
caller snapshots -> EmPlanningCoordinator -> immutable published EmTrajectory
|
||||
-> TrajectoryExecutor -> TrajectoryControlCommand
|
||||
```
|
||||
|
||||
- `EmPlanningService` remains a pure, synchronous, one-shot planner. It consumes only the request snapshot and never
|
||||
reads a clock, current directory, UI, localization, wheel speed, or hardware object.
|
||||
- The caller owns state capture, map/reference-path version selection, the replan clock, and any hardware-specific
|
||||
action after it receives a generic command. `IVehicleStateProvider.Capture()` belongs to this execution boundary and
|
||||
returns a `VehicleMotionState` snapshot; it is not a planner dependency.
|
||||
- `EmPlanningCoordinator` owns latest-wins cycle cancellation and atomic publication. A cycle binds
|
||||
`MapSnapshotId`, `ReferencePathId`, vehicle-state `SequenceId`, `PreviousTrajectoryId`, and `SegmentIndex`; a
|
||||
result publishes only when that complete identity and its version are still current. The default update cadence is
|
||||
`0.20 s` (with the configured `6.0 s` / `5.0 m` planning horizons).
|
||||
- `TrajectoryExecutor` only samples the immutable published trajectory with caller-provided time and measured state.
|
||||
It never extrapolates beyond the final point. A failed replan leaves the last complete published trajectory in
|
||||
service through its exact zero-speed safety tail.
|
||||
|
||||
### Handoff and gear changes
|
||||
|
||||
A normal replan may use a future sample from the prior trajectory only when it is within the configured age and
|
||||
position/yaw/speed tracking tolerances, remains in the same segment and direction, and does not cross a gear boundary.
|
||||
Unsafe tracking, stale data, a terminal boundary, or any segment/direction mismatch causes a deterministic reset to
|
||||
the caller-supplied measured state with no trajectory seed.
|
||||
|
||||
At an exact `GearSwitchApproach` boundary the executor follows this sequence:
|
||||
|
||||
```text
|
||||
Following -> ApproachingGearSwitch -> HoldingZero
|
||||
-> RequestingDirectionChange (one request) -> AwaitingDirectionConfirmation -> Following
|
||||
```
|
||||
|
||||
Measured absolute speed must remain below `0.01 m/s` continuously for `0.20 s` before the single direction-change
|
||||
request. Every holding, direction-confirmation, rolling-stop, and goal-completion command is zero speed and zero yaw
|
||||
rate. `Goal` and `RollingSafetyStop` leave the executor completed while braking is held.
|
||||
|
||||
### Trajectory telemetry and generic command
|
||||
|
||||
Every `EmTrajectoryPoint` retains these fields for execution telemetry and independent validation:
|
||||
|
||||
```text
|
||||
X, Y, Yaw,
|
||||
SignedLongitudinalVelocity, Speed, VelocityX, VelocityY, YawRate, VehicleCurvature,
|
||||
TimeFromStart,
|
||||
SegmentIndex, SegmentLocalS, PathS, Direction, BoundaryType,
|
||||
LongitudinalAcceleration, LongitudinalJerk
|
||||
```
|
||||
|
||||
`SignedLongitudinalVelocity` is authoritative: `Speed = abs(signedV)`, world `VelocityX/Y` are derived from vehicle
|
||||
yaw, and `YawRate = signedV * VehicleCurvature`. Pose, world velocity, speed, and curvature stay available in
|
||||
`TrajectoryExecutionState.SelectedPoint`; they are monitoring telemetry, not controller inputs.
|
||||
|
||||
`TrajectoryControlAdapter` produces only the controller-neutral immutable command below:
|
||||
|
||||
```text
|
||||
SignedLongitudinalVelocity
|
||||
YawRate
|
||||
Direction
|
||||
RequestDirectionChange
|
||||
HoldBrake
|
||||
IsTrajectoryComplete
|
||||
```
|
||||
|
||||
There is intentionally no body-lateral-velocity, crab-motion, in-place-rotation, UI, or hardware field. A later
|
||||
hardware adapter may map this command only after that controller's field semantics are independently confirmed.
|
||||
|
||||
### Windows x64 plugin package
|
||||
|
||||
The build output carries the pinned OSQP runtime and notices. Create the deployable plugin tree from a built managed
|
||||
assembly with an explicit destination that is neither a drive root nor the repository root:
|
||||
|
||||
```powershell
|
||||
& .\ClumsyPilot\scripts\Publish-ClumsyPilotPlugin.ps1 `
|
||||
-ManagedDll .\ClumsyPilot\bin\Debug\netstandard2.0\ClumsyPilot.dll `
|
||||
-OutputDirectory C:\deploy\ParkingRobot
|
||||
```
|
||||
|
||||
The transactional publisher verifies a 64-bit PowerShell host, the OSQP PE machine type, and the pinned
|
||||
`ThirdParty/OSQP/SHA256SUMS` hash before staging and renaming exactly:
|
||||
|
||||
```text
|
||||
plugins/ClumsyPilot.dll
|
||||
plugins/osqp.dll
|
||||
plugins/licenses/OSQP-LICENSE.txt
|
||||
plugins/licenses/OSQP-NOTICE.txt
|
||||
plugins/licenses/OSQP-VERSION.txt
|
||||
```
|
||||
|
||||
Run the complete first-version gate from the repository root:
|
||||
|
||||
```powershell
|
||||
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-all
|
||||
```
|
||||
|
||||
Dynamic-obstacle prediction, time-space occupancy, following/yielding/overtaking behavior, dynamic rerouting,
|
||||
body-lateral motion, in-place rotation, UI integration, and hardware integration are explicitly deferred and are not
|
||||
implemented by this first version.
|
||||
|
||||
Reference in New Issue
Block a user