feat: report EM observation planning cycles
This commit is contained in:
+10
-4
@@ -271,6 +271,9 @@ internal static class TrajectoryObservationMovementTestRunner
|
|||||||
DateTimeOffset now = state.CapturedAtUtc;
|
DateTimeOffset now = state.CapturedAtUtc;
|
||||||
TrajectoryObservationLoopTick tick = observationLoop.Tick(now, state, token);
|
TrajectoryObservationLoopTick tick = observationLoop.Tick(now, state, token);
|
||||||
TrajectoryObservationObservation observation = tick.Observation;
|
TrajectoryObservationObservation observation = tick.Observation;
|
||||||
|
TrajectoryObservationDiagnostic diagnostic = TrajectoryObservationDiagnostics.Create(
|
||||||
|
tick.LatestCycle, tick.LatestPlanningElapsed, tick.PlanningInFlight,
|
||||||
|
observation.PublishedTrajectory);
|
||||||
TrajectoryObservationCharts charts = observation.PublishedTrajectory == null
|
TrajectoryObservationCharts charts = observation.PublishedTrajectory == null
|
||||||
? null
|
? null
|
||||||
: TrajectoryObservationCharts.Build(observation.PublishedTrajectory, segment,
|
: TrajectoryObservationCharts.Build(observation.PublishedTrajectory, segment,
|
||||||
@@ -284,9 +287,10 @@ internal static class TrajectoryObservationMovementTestRunner
|
|||||||
gearSwitchWaitingPrinted = true;
|
gearSwitchWaitingPrinted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tick.ShouldLog)
|
if (tick.PlanningStarted)
|
||||||
LogIfCurrent(sessionId, CreateTickStatus(sessionId, observation, charts,
|
LogIfCurrent(sessionId, "planning status=pending");
|
||||||
tick.LatestCycle, tick.LatestPlanningElapsed, runtimeState.WaitingAtGearSwitch));
|
if (tick.PlanningCompleted)
|
||||||
|
LogIfCurrent(sessionId, diagnostic.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +387,9 @@ internal static class TrajectoryObservationMovementTestRunner
|
|||||||
|
|
||||||
private static void PrintStatus(string message)
|
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)
|
private static void Finish(long sessionId, CancellationTokenSource cancellation, Task completed)
|
||||||
|
|||||||
+16
-6
@@ -255,12 +255,15 @@ public sealed class TrajectoryObservationController
|
|||||||
public sealed class TrajectoryObservationLoopTick
|
public sealed class TrajectoryObservationLoopTick
|
||||||
{
|
{
|
||||||
internal TrajectoryObservationLoopTick(TrajectoryObservationObservation observation,
|
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));
|
Observation = observation ?? throw new ArgumentNullException(nameof(observation));
|
||||||
LatestCycle = latestCycle;
|
LatestCycle = latestCycle;
|
||||||
LatestPlanningElapsed = latestPlanningElapsed;
|
LatestPlanningElapsed = latestPlanningElapsed;
|
||||||
PlanningInFlight = planningInFlight;
|
PlanningInFlight = planningInFlight;
|
||||||
|
PlanningStarted = planningStarted;
|
||||||
|
PlanningCompleted = planningCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrajectoryObservationObservation Observation { get; }
|
public TrajectoryObservationObservation Observation { get; }
|
||||||
@@ -271,6 +274,10 @@ public sealed class TrajectoryObservationLoopTick
|
|||||||
|
|
||||||
public bool PlanningInFlight { get; }
|
public bool PlanningInFlight { get; }
|
||||||
|
|
||||||
|
public bool PlanningStarted { get; }
|
||||||
|
|
||||||
|
public bool PlanningCompleted { get; }
|
||||||
|
|
||||||
public bool ShouldLog => true;
|
public bool ShouldLog => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,28 +300,31 @@ public sealed class TrajectoryObservationLoop
|
|||||||
if (state == null) throw new ArgumentNullException(nameof(state));
|
if (state == null) throw new ArgumentNullException(nameof(state));
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
ConsumeCompletedPlanning(now);
|
bool planningCompleted = ConsumeCompletedPlanning(now);
|
||||||
|
bool planningStarted = false;
|
||||||
if (planningTask == null && controller.ShouldStartCycle(now))
|
if (planningTask == null && controller.ShouldStartCycle(now))
|
||||||
{
|
{
|
||||||
|
planningStarted = true;
|
||||||
planningStartedAtUtc = now;
|
planningStartedAtUtc = now;
|
||||||
planningTask = controller.StartCycle(now, state, cancellationToken);
|
planningTask = controller.StartCycle(now, state, cancellationToken);
|
||||||
ConsumeCompletedPlanning(now);
|
planningCompleted |= ConsumeCompletedPlanning(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
TrajectoryObservationObservation observation = controller.Observe(now, state);
|
TrajectoryObservationObservation observation = controller.Observe(now, state);
|
||||||
return new TrajectoryObservationLoopTick(observation, latestCycle, latestPlanningElapsed,
|
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;
|
Task<PlanningCycleResult> completed = planningTask;
|
||||||
if (completed == null || !completed.IsCompleted) return;
|
if (completed == null || !completed.IsCompleted) return false;
|
||||||
|
|
||||||
latestCycle = completed.GetAwaiter().GetResult();
|
latestCycle = completed.GetAwaiter().GetResult();
|
||||||
TimeSpan elapsed = observedAtUtc - planningStartedAtUtc;
|
TimeSpan elapsed = observedAtUtc - planningStartedAtUtc;
|
||||||
latestPlanningElapsed = elapsed < TimeSpan.Zero ? TimeSpan.Zero : elapsed;
|
latestPlanningElapsed = elapsed < TimeSpan.Zero ? TimeSpan.Zero : elapsed;
|
||||||
planningTask = null;
|
planningTask = null;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ internal static class TrajectoryObservationChecks
|
|||||||
Verification.Equal("等待真实档位/方向确认;观察模式不会推进下一方向段",
|
Verification.Equal("等待真实档位/方向确认;观察模式不会推进下一方向段",
|
||||||
TrajectoryObservationRuntimeState.GearSwitchWaitingNotice,
|
TrajectoryObservationRuntimeState.GearSwitchWaitingNotice,
|
||||||
"observation runtime uses required gear-switch notice");
|
"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()
|
private static void VerifiesOperatorDocumentationUsesExactUiEntry()
|
||||||
@@ -238,6 +240,8 @@ internal static class TrajectoryObservationChecks
|
|||||||
|
|
||||||
TrajectoryObservationLoopTick firstTick = loop.Tick(startedAt, firstState, CancellationToken.None);
|
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,
|
Verification.True(firstTick.ShouldLog,
|
||||||
"observer first cadence tick is eligible for session-guarded logging");
|
"observer first cadence tick is eligible for session-guarded logging");
|
||||||
Verification.Equal(10L, firstTick.Observation.VehicleState.SequenceId,
|
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(completed, "observer delayed planning completes deterministically");
|
||||||
Verification.True(completedTick != null, "observer delayed planning produces a completion tick");
|
Verification.True(completedTick != null, "observer delayed planning produces a completion tick");
|
||||||
TrajectoryObservationLoopTick finalTick = completedTick!;
|
TrajectoryObservationLoopTick finalTick = completedTick!;
|
||||||
|
Verification.True(finalTick.PlanningCompleted, "observer completion tick reports cycle completion");
|
||||||
Verification.True(finalTick.LatestCycle != null && finalTick.LatestCycle.Published,
|
Verification.True(finalTick.LatestCycle != null && finalTick.LatestCycle.Published,
|
||||||
"observer delayed planning result is consumed without a continuation");
|
"observer delayed planning result is consumed without a continuation");
|
||||||
Verification.Equal(14L, finalTick.Observation.VehicleState.SequenceId,
|
Verification.Equal(14L, finalTick.Observation.VehicleState.SequenceId,
|
||||||
|
|||||||
Reference in New Issue
Block a user