feat: report EM observation planning cycles

This commit is contained in:
梁薄云
2026-08-05 09:57:38 +08:00
parent 822db6934a
commit 6262a4573a
3 changed files with 31 additions and 10 deletions
@@ -271,6 +271,9 @@ internal static class TrajectoryObservationMovementTestRunner
DateTimeOffset now = state.CapturedAtUtc;
TrajectoryObservationLoopTick tick = observationLoop.Tick(now, state, token);
TrajectoryObservationObservation observation = tick.Observation;
TrajectoryObservationDiagnostic diagnostic = TrajectoryObservationDiagnostics.Create(
tick.LatestCycle, tick.LatestPlanningElapsed, tick.PlanningInFlight,
observation.PublishedTrajectory);
TrajectoryObservationCharts charts = observation.PublishedTrajectory == null
? null
: TrajectoryObservationCharts.Build(observation.PublishedTrajectory, segment,
@@ -284,9 +287,10 @@ internal static class TrajectoryObservationMovementTestRunner
gearSwitchWaitingPrinted = true;
}
if (tick.ShouldLog)
LogIfCurrent(sessionId, CreateTickStatus(sessionId, observation, charts,
tick.LatestCycle, tick.LatestPlanningElapsed, runtimeState.WaitingAtGearSwitch));
if (tick.PlanningStarted)
LogIfCurrent(sessionId, "planning status=pending");
if (tick.PlanningCompleted)
LogIfCurrent(sessionId, diagnostic.Text);
}
}
@@ -383,7 +387,9 @@ internal static class TrajectoryObservationMovementTestRunner
private static void PrintStatus(string message)
{
Hedingben.ToastText(ObserveOnlyNotice + "\n" + message, StatusChannel);
string text = ObserveOnlyNotice + "\n" + message;
Hedingben.ToastText(text, StatusChannel);
Console.WriteLine("[TrajectoryObserver] " + text);
}
private static void Finish(long sessionId, CancellationTokenSource cancellation, Task completed)
@@ -255,12 +255,15 @@ public sealed class TrajectoryObservationController
public sealed class TrajectoryObservationLoopTick
{
internal TrajectoryObservationLoopTick(TrajectoryObservationObservation observation,
PlanningCycleResult latestCycle, TimeSpan latestPlanningElapsed, bool planningInFlight)
PlanningCycleResult latestCycle, TimeSpan latestPlanningElapsed, bool planningInFlight,
bool planningStarted, bool planningCompleted)
{
Observation = observation ?? throw new ArgumentNullException(nameof(observation));
LatestCycle = latestCycle;
LatestPlanningElapsed = latestPlanningElapsed;
PlanningInFlight = planningInFlight;
PlanningStarted = planningStarted;
PlanningCompleted = planningCompleted;
}
public TrajectoryObservationObservation Observation { get; }
@@ -271,6 +274,10 @@ public sealed class TrajectoryObservationLoopTick
public bool PlanningInFlight { get; }
public bool PlanningStarted { get; }
public bool PlanningCompleted { get; }
public bool ShouldLog => true;
}
@@ -293,28 +300,31 @@ public sealed class TrajectoryObservationLoop
if (state == null) throw new ArgumentNullException(nameof(state));
cancellationToken.ThrowIfCancellationRequested();
ConsumeCompletedPlanning(now);
bool planningCompleted = ConsumeCompletedPlanning(now);
bool planningStarted = false;
if (planningTask == null && controller.ShouldStartCycle(now))
{
planningStarted = true;
planningStartedAtUtc = now;
planningTask = controller.StartCycle(now, state, cancellationToken);
ConsumeCompletedPlanning(now);
planningCompleted |= ConsumeCompletedPlanning(now);
}
TrajectoryObservationObservation observation = controller.Observe(now, state);
return new TrajectoryObservationLoopTick(observation, latestCycle, latestPlanningElapsed,
planningTask != null);
planningTask != null, planningStarted, planningCompleted);
}
private void ConsumeCompletedPlanning(DateTimeOffset observedAtUtc)
private bool ConsumeCompletedPlanning(DateTimeOffset observedAtUtc)
{
Task<PlanningCycleResult> completed = planningTask;
if (completed == null || !completed.IsCompleted) return;
if (completed == null || !completed.IsCompleted) return false;
latestCycle = completed.GetAwaiter().GetResult();
TimeSpan elapsed = observedAtUtc - planningStartedAtUtc;
latestPlanningElapsed = elapsed < TimeSpan.Zero ? TimeSpan.Zero : elapsed;
planningTask = null;
return true;
}
}
@@ -72,6 +72,8 @@ internal static class TrajectoryObservationChecks
Verification.Equal("等待真实档位/方向确认;观察模式不会推进下一方向段",
TrajectoryObservationRuntimeState.GearSwitchWaitingNotice,
"observation runtime uses required gear-switch notice");
Verification.True(source.Contains("Console.WriteLine(\"[TrajectoryObserver] \" + text);"),
"observer status is mirrored to the host terminal");
}
private static void VerifiesOperatorDocumentationUsesExactUiEntry()
@@ -238,6 +240,8 @@ internal static class TrajectoryObservationChecks
TrajectoryObservationLoopTick firstTick = loop.Tick(startedAt, firstState, CancellationToken.None);
Verification.True(firstTick.PlanningStarted, "observer first tick reports a planning-cycle start");
Verification.True(!firstTick.PlanningCompleted, "observer first tick has no completed cycle");
Verification.True(firstTick.ShouldLog,
"observer first cadence tick is eligible for session-guarded logging");
Verification.Equal(10L, firstTick.Observation.VehicleState.SequenceId,
@@ -298,6 +302,7 @@ internal static class TrajectoryObservationChecks
Verification.True(completed, "observer delayed planning completes deterministically");
Verification.True(completedTick != null, "observer delayed planning produces a completion tick");
TrajectoryObservationLoopTick finalTick = completedTick!;
Verification.True(finalTick.PlanningCompleted, "observer completion tick reports cycle completion");
Verification.True(finalTick.LatestCycle != null && finalTick.LatestCycle.Published,
"observer delayed planning result is consumed without a continuation");
Verification.Equal(14L, finalTick.Observation.VehicleState.SequenceId,