test: verify EM observation movement test

This commit is contained in:
梁薄云
2026-08-04 16:57:16 +08:00
parent ea043ea0a6
commit 417f8ca9ea
2 changed files with 54 additions and 0 deletions
@@ -48,3 +48,26 @@ rejected before EM planning.
`EmTrajectoryPoint.VelocityX` and `VelocityY` are world-frame components. They are not chassis-frame velocity commands `EmTrajectoryPoint.VelocityX` and `VelocityY` are world-frame components. They are not chassis-frame velocity commands
and must never be forwarded directly to a vehicle motion interface. This MovementTest performs no coordinate conversion and must never be forwarded directly to a vehicle motion interface. This MovementTest performs no coordinate conversion
for driving and has no driving capability; any future execution mode requires a separate safety-reviewed design. for driving and has no driving capability; any future execution mode requires a separate safety-reviewed design.
## Operator launch and stop checklist
The vehicle UI entry is `EM杞ㄨ抗瑙勫垝瑙傚療闂幆娴嬭瘯`. It is an observation session only; it has no chassis,
motor, steering, brake, or gear output.
Before starting:
1. Ensure the vehicle is in a safe, supervised state; this test reads live localization and signed chassis speed but
never controls the vehicle.
2. Confirm localization and the chassis read interface are available. The session reports a startup failure if either
cannot be read.
3. Set a finite goal X/Y/yaw (or be ready to enter them when prompted), then enter zero to twenty manual obstacles.
Each obstacle must remain inside the configured start/goal rectangle plus map padding.
To start, select the entry in the vehicle UI and start the MovementTest. Confirm the status begins with
`OBSERVE_ONLY: no chassis command is sent.`, then review the bootstrap status and the
`TrajectoryObserver.World`, `TrajectoryObserver.LS`, and `TrajectoryObserver.ST` layers. A logged trajectory control
command is diagnostic information only and must not be copied into a vehicle-control interface.
To stop, use the vehicle UI's normal MovementTest stop action. Confirm the status says
`Observation stop requested; all observer layers were cleared.` The cancellation request stops observer work and clears
all three layers. Stopping, running, or starting this test must not issue chassis, motor, steering, brake, or gear output.
@@ -25,6 +25,7 @@ internal static class TrajectoryObservationChecks
VerifiesLsPresentationUsesPathSOnHorizontalAxis(); VerifiesLsPresentationUsesPathSOnHorizontalAxis();
VerifiesRollingRequestUsesOnePublishedTrajectorySnapshot(); VerifiesRollingRequestUsesOnePublishedTrajectorySnapshot();
FreezesBootstrapVehicleForRollingRequests(); FreezesBootstrapVehicleForRollingRequests();
VerifiesEmptyMapBootstrapProducesPublishableReference();
} }
private static void VerifiesObservationSourceHasNoActuatorCalls() private static void VerifiesObservationSourceHasNoActuatorCalls()
@@ -259,6 +260,36 @@ internal static class TrajectoryObservationChecks
expectedMaximumCurvature, expectedMinimumRadius, "replaced bootstrap job vehicle"); expectedMaximumCurvature, expectedMinimumRadius, "replaced bootstrap job vehicle");
} }
private static void VerifiesEmptyMapBootstrapProducesPublishableReference()
{
var settings = new TrajectoryObservationSettings();
CoarsePathPlanningJob job = TrajectoryObservationSetupFactory.CreateBootstrapJob(
new Pose2D(0.5d, 0.5d, 0d), new Pose2D(3.5d, 0.5d, 0d), settings,
Array.Empty<TrajectoryObservationObstacle>(), 0L);
TrajectoryObservationBootstrapResult bootstrap = new TrajectoryObservationBootstrapper()
.Bootstrap(job, CancellationToken.None);
Verification.True(bootstrap.Succeeded, "observer empty-map bootstrap succeeds");
Verification.True(bootstrap.CoarseResult.MapResult.Succeeded,
"observer empty-map bootstrap builds a successful map");
Verification.True(bootstrap.Map != null, "observer empty-map bootstrap returns a map");
Verification.Equal(PlanningStatus.Success, bootstrap.CoarseResult.PlanningResult.Status,
"observer empty-map coarse planning succeeds");
Verification.True(bootstrap.SmoothedPath != null && IsPublishableSmoothingStatus(bootstrap.SmoothedPath.Status),
"observer empty-map bootstrap returns a publishable smoothing result");
Verification.True(bootstrap.Segments.Count > 0,
"observer empty-map bootstrap returns at least one direction segment");
}
private static bool IsPublishableSmoothingStatus(PathSmoothingStatus status)
{
return status == PathSmoothingStatus.Complete ||
status == PathSmoothingStatus.PartialImprovement ||
status == PathSmoothingStatus.NotNeeded ||
status == PathSmoothingStatus.Unchanged;
}
private static void AssertVehicleSnapshot(VehicleParameters actual, double expectedLength, double expectedWidth, private static void AssertVehicleSnapshot(VehicleParameters actual, double expectedLength, double expectedWidth,
double expectedMargin, double? expectedMaximumCurvature, double? expectedMinimumRadius, string name) double expectedMargin, double? expectedMaximumCurvature, double? expectedMinimumRadius, string name)
{ {