fix: complete EM observation final review

This commit is contained in:
梁薄云
2026-08-04 17:33:14 +08:00
parent d0e673b573
commit bd7170b611
7 changed files with 655 additions and 50 deletions
@@ -252,6 +252,122 @@ public sealed class TrajectoryObservationController
}
}
public sealed class TrajectoryObservationLoopTick
{
internal TrajectoryObservationLoopTick(TrajectoryObservationObservation observation,
PlanningCycleResult latestCycle, TimeSpan latestPlanningElapsed, bool planningInFlight)
{
Observation = observation ?? throw new ArgumentNullException(nameof(observation));
LatestCycle = latestCycle;
LatestPlanningElapsed = latestPlanningElapsed;
PlanningInFlight = planningInFlight;
}
public TrajectoryObservationObservation Observation { get; }
public PlanningCycleResult LatestCycle { get; }
public TimeSpan LatestPlanningElapsed { get; }
public bool PlanningInFlight { get; }
public bool ShouldLog => true;
}
public sealed class TrajectoryObservationLoop
{
private readonly TrajectoryObservationController controller;
private Task<PlanningCycleResult> planningTask;
private DateTimeOffset planningStartedAtUtc;
private PlanningCycleResult latestCycle;
private TimeSpan latestPlanningElapsed;
public TrajectoryObservationLoop(TrajectoryObservationController controller)
{
this.controller = controller ?? throw new ArgumentNullException(nameof(controller));
}
public TrajectoryObservationLoopTick Tick(DateTimeOffset now, VehicleMotionState state,
CancellationToken cancellationToken)
{
if (state == null) throw new ArgumentNullException(nameof(state));
cancellationToken.ThrowIfCancellationRequested();
ConsumeCompletedPlanning(now);
if (planningTask == null && controller.ShouldStartCycle(now))
{
planningStartedAtUtc = now;
planningTask = controller.StartCycle(now, state, cancellationToken);
ConsumeCompletedPlanning(now);
}
TrajectoryObservationObservation observation = controller.Observe(now, state);
return new TrajectoryObservationLoopTick(observation, latestCycle, latestPlanningElapsed,
planningTask != null);
}
private void ConsumeCompletedPlanning(DateTimeOffset observedAtUtc)
{
Task<PlanningCycleResult> completed = planningTask;
if (completed == null || !completed.IsCompleted) return;
latestCycle = completed.GetAwaiter().GetResult();
TimeSpan elapsed = observedAtUtc - planningStartedAtUtc;
latestPlanningElapsed = elapsed < TimeSpan.Zero ? TimeSpan.Zero : elapsed;
planningTask = null;
}
}
public enum TrajectoryObservationSessionEndReason
{
BootstrapFailure,
RuntimeFault,
Cancellation,
}
public static class TrajectoryObservationSessionLifecycle
{
public static bool ShouldClearLayers(TrajectoryObservationSessionEndReason reason)
{
switch (reason)
{
case TrajectoryObservationSessionEndReason.BootstrapFailure:
return false;
case TrajectoryObservationSessionEndReason.RuntimeFault:
case TrajectoryObservationSessionEndReason.Cancellation:
return true;
default:
throw new ArgumentOutOfRangeException(nameof(reason));
}
}
}
public sealed class TrajectoryObservationRuntimeState
{
public const string GearSwitchWaitingNotice =
"等待真实档位/方向确认;观察模式不会推进下一方向段";
private TrajectoryObservationRuntimeState(bool waitingAtGearSwitch)
{
WaitingAtGearSwitch = waitingAtGearSwitch;
WorldNotice = waitingAtGearSwitch ? GearSwitchWaitingNotice : string.Empty;
}
public bool WaitingAtGearSwitch { get; }
public string WorldNotice { get; }
public static TrajectoryObservationRuntimeState Create(DateTimeOffset now, EmTrajectory trajectory)
{
if (trajectory == null || trajectory.Metadata.TerminalType != EmTerminalType.GearSwitch)
return new TrajectoryObservationRuntimeState(false);
EmTrajectoryPoint finalPoint = trajectory.Points[trajectory.Points.Count - 1];
bool waiting = (now - trajectory.Metadata.EffectiveAtUtc).TotalSeconds >= finalPoint.TimeFromStart;
return new TrajectoryObservationRuntimeState(waiting);
}
}
public sealed class TrajectoryObservationLsSample
{
public TrajectoryObservationLsSample(double pathS, double lateralOffset)