mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-28 00:53:45 +08:00
694b460f80
Provide laptop and device build entry points, cache compatibility checks and developer tooling. Keep distribution assets and model packaging available before runtime consumers. Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
84 lines
4.4 KiB
Python
84 lines
4.4 KiB
Python
import math
|
|
from types import SimpleNamespace as NS
|
|
import unittest
|
|
|
|
from tools.diagnostics.longitudinal import analyze
|
|
|
|
|
|
class Event:
|
|
def __init__(self, service, seconds, **fields):
|
|
self.service = service
|
|
self.logMonoTime = int(seconds * 1e9)
|
|
self.valid = True
|
|
setattr(self, service, NS(**fields))
|
|
|
|
def which(self):
|
|
return self.service
|
|
|
|
|
|
def cluster(t, *, target=1.0, command=0.5, ego=0.2, source="cruise", experimental=False,
|
|
active=True, gas=False, brake=False):
|
|
return [Event("carState", t, aEgo=ego, gasPressed=gas, brakePressed=brake),
|
|
Event("selfdriveState", t, experimentalMode=experimental),
|
|
Event("longitudinalPlan", t, aTarget=target, longitudinalPlanSource=source),
|
|
Event("carControl", t, longActive=active, actuators=NS(accel=command))]
|
|
|
|
|
|
class TestLongitudinalTrace(unittest.TestCase):
|
|
def test_continuous_same_mode_rates_are_signal_derivatives(self):
|
|
messages = cluster(1) + cluster(1.1, target=1.2, command=0.6, ego=0.3) + cluster(1.2, target=1.4, command=0.7, ego=0.4)
|
|
report = analyze(messages)
|
|
command = report["signals"]["commandAccel"]
|
|
self.assertEqual(command["continuousFrameDeltaSeconds"]["sampleCount"], 2)
|
|
self.assertAlmostEqual(command["continuousDeltaRateMps3"]["mean"], 1)
|
|
self.assertEqual(report["pedalContextSamples"]["gas=False,brake=False"], 7)
|
|
|
|
def test_gap_and_mode_transitions_exclude_derivatives(self):
|
|
messages = cluster(1) + cluster(1.1) + cluster(2, active=False, source="lead0", experimental=True, gas=True)
|
|
report = analyze(messages)
|
|
self.assertEqual(report["transitions"]["source"], 1)
|
|
self.assertEqual(report["transitions"]["experimental"], 1)
|
|
self.assertEqual(report["transitions"]["longActive"], 1)
|
|
self.assertEqual(report["signals"]["commandAccel"]["continuousDeltaRateMps3"]["sampleCount"], 1)
|
|
gap = analyze(cluster(1) + cluster(1.1) + cluster(2))
|
|
self.assertGreater(gap["rejectedPairsOrSamples"]["carControl:gap"], 0)
|
|
|
|
def test_nonfinite_missing_and_timestamp_regression_reset_baseline(self):
|
|
messages = cluster(1) + cluster(1.1, command=math.nan) + cluster(1.05) + cluster(1.2)
|
|
report = analyze(messages)
|
|
self.assertEqual(report["signals"]["commandAccel"]["valuesMps2"]["missingCounts"]["missing_or_nonfinite"], 1)
|
|
self.assertGreater(report["rejectedPairsOrSamples"]["carControl:timestamp_regression"], 0)
|
|
self.assertEqual(report["signals"]["commandAccel"]["continuousDeltaRateMps3"]["sampleCount"], 0)
|
|
|
|
def test_stale_context_does_not_create_pair(self):
|
|
messages = cluster(1) + [Event("carControl", 2, longActive=True, actuators=NS(accel=1.0))]
|
|
report = analyze(messages)
|
|
self.assertEqual(report["rejectedPairsOrSamples"]["carControl:missing_or_stale_mode"], 1)
|
|
self.assertEqual(report["signals"]["commandAccel"]["continuousFrameDeltaSeconds"]["sampleCount"], 0)
|
|
|
|
def test_invalid_envelope_is_excluded(self):
|
|
messages = cluster(1) + cluster(1.1)
|
|
messages[-1].valid = False
|
|
messages.append(Event("longitudinalPlan", 1.15, aTarget=1.0, longitudinalPlanSource="cruise"))
|
|
report = analyze(messages)
|
|
self.assertEqual(report["rejectedPairsOrSamples"]["carControl:invalid_envelope"], 1)
|
|
self.assertEqual(report["rejectedPairsOrSamples"]["longitudinalPlan:missing_or_stale_mode"], 2)
|
|
self.assertEqual(report["signals"]["commandAccel"]["valuesMps2"]["sampleCount"], 1)
|
|
|
|
def test_away_and_back_or_invalid_recovery_breaks_other_signal_pair(self):
|
|
baseline = cluster(1) + cluster(1.1)
|
|
toggled = baseline + [Event("selfdriveState", 1.15, experimentalMode=True),
|
|
Event("selfdriveState", 1.16, experimentalMode=False),
|
|
Event("longitudinalPlan", 1.2, aTarget=1.4, longitudinalPlanSource="cruise")]
|
|
report = analyze(toggled)
|
|
self.assertEqual(report["transitions"]["experimental"], 2)
|
|
self.assertEqual(report["signals"]["plannerATarget"]["continuousDeltaRateMps3"]["sampleCount"], 0)
|
|
|
|
invalid = Event("carControl", 1.15, longActive=True, actuators=NS(accel=0.5))
|
|
invalid.valid = None
|
|
recovered = baseline + [invalid, Event("carControl", 1.16, longActive=True, actuators=NS(accel=0.5)),
|
|
Event("longitudinalPlan", 1.2, aTarget=1.4, longitudinalPlanSource="cruise")]
|
|
report = analyze(recovered)
|
|
self.assertEqual(report["rejectedPairsOrSamples"]["carControl:invalid_envelope"], 1)
|
|
self.assertEqual(report["signals"]["plannerATarget"]["continuousDeltaRateMps3"]["sampleCount"], 0)
|