mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-23 02:02:08 +08:00
137 lines
3.7 KiB
Python
137 lines
3.7 KiB
Python
from dataclasses import replace
|
|
|
|
import pytest
|
|
|
|
from openpilot.tools.longitudinal.analyze_route_longitudinal import (
|
|
LongitudinalSample,
|
|
analyze_samples,
|
|
anomaly_episode_times,
|
|
parse_settings,
|
|
threshold_sign_changes,
|
|
)
|
|
|
|
|
|
def make_samples(count: int = 20, **overrides) -> list[LongitudinalSample]:
|
|
base = LongitudinalSample(
|
|
segment=4,
|
|
time_s=0.0,
|
|
mono_time=0,
|
|
long_active=True,
|
|
v_ego=20.0,
|
|
a_ego=0.1,
|
|
plan_accel=0.1,
|
|
command_accel=0.1,
|
|
output_accel=0.1,
|
|
source="cruise",
|
|
)
|
|
return [
|
|
replace(base, time_s=index * 0.05, mono_time=index * 50_000_000, **overrides)
|
|
for index in range(count)
|
|
]
|
|
|
|
|
|
def primary_kind(samples: list[LongitudinalSample]) -> str | None:
|
|
report = analyze_samples(samples, "test", samples[-1].time_s)
|
|
return report.findings[0].kind if report.findings else None
|
|
|
|
|
|
def test_threshold_sign_changes_ignores_zero_crossing_noise():
|
|
assert threshold_sign_changes([0.2, 0.03, -0.02, 0.1, -0.2]) == 1
|
|
|
|
|
|
def test_planner_chatter_is_identified_from_repeated_target_reversals():
|
|
samples = make_samples()
|
|
for index, sample in enumerate(samples):
|
|
accel = 0.45 if index % 2 == 0 else -0.45
|
|
samples[index] = replace(sample, plan_accel=accel, command_accel=accel, output_accel=accel, a_ego=accel * 0.8)
|
|
|
|
assert primary_kind(samples) == "planner_chatter"
|
|
|
|
|
|
def test_controller_integrator_is_identified_when_command_opposes_plan():
|
|
samples = make_samples(plan_accel=0.25, command_accel=-0.25, output_accel=-0.25, a_ego=-0.2, i_term=-0.40)
|
|
|
|
assert primary_kind(samples) == "controller_integrator"
|
|
|
|
|
|
def test_lead_instability_is_identified_from_source_and_track_churn():
|
|
samples = make_samples(12, lead_status=True, lead_distance=45.0, lead_velocity=18.0, source="lead0", lead_track_id=10)
|
|
for index, sample in enumerate(samples):
|
|
samples[index] = replace(
|
|
sample,
|
|
source="lead0" if index % 2 == 0 else "lead1",
|
|
lead_track_id=10 if index % 2 == 0 else 11,
|
|
lead_velocity=18.0 if index % 2 == 0 else 20.0,
|
|
)
|
|
|
|
assert primary_kind(samples) == "lead_instability"
|
|
|
|
|
|
def test_unsafe_stop_release_is_critical():
|
|
samples = make_samples(
|
|
6,
|
|
v_ego=2.0,
|
|
plan_accel=0.3,
|
|
command_accel=0.4,
|
|
output_accel=0.4,
|
|
a_ego=0.2,
|
|
should_stop=True,
|
|
lead_status=True,
|
|
lead_distance=7.0,
|
|
lead_velocity=0.0,
|
|
)
|
|
|
|
report = analyze_samples(samples, "test", samples[-1].time_s)
|
|
|
|
assert report.findings[0].kind == "unsafe_stop_release"
|
|
assert report.findings[0].severity == "critical"
|
|
|
|
|
|
def test_late_lead_response_is_identified_from_ttc_and_decel_shortfall():
|
|
samples = make_samples(
|
|
10,
|
|
v_ego=20.0,
|
|
plan_accel=0.0,
|
|
command_accel=0.0,
|
|
output_accel=0.0,
|
|
a_ego=0.0,
|
|
lead_status=True,
|
|
lead_distance=18.0,
|
|
lead_relative_velocity=-8.0,
|
|
lead_velocity=12.0,
|
|
)
|
|
|
|
assert primary_kind(samples) == "late_lead_response"
|
|
|
|
|
|
def test_normal_steady_follow_has_no_deterministic_finding():
|
|
samples = make_samples(
|
|
lead_status=True,
|
|
lead_distance=40.0,
|
|
lead_relative_velocity=0.0,
|
|
lead_velocity=20.0,
|
|
source="lead0",
|
|
)
|
|
|
|
report = analyze_samples(samples, "test", samples[-1].time_s)
|
|
|
|
assert report.findings == []
|
|
|
|
|
|
def test_anomaly_episodes_group_nearby_points():
|
|
samples = make_samples(80)
|
|
samples[10] = replace(samples[10], plan_accel=-0.5)
|
|
samples[11] = replace(samples[11], plan_accel=0.5)
|
|
samples[60] = replace(samples[60], plan_accel=-0.5)
|
|
|
|
episodes = anomaly_episode_times(samples, limit=5)
|
|
|
|
assert len(episodes) == 2
|
|
assert episodes[0] == pytest.approx(0.55)
|
|
|
|
|
|
def test_parse_settings_keeps_only_longitudinal_context():
|
|
settings = parse_settings('{"standard_follow": [1.5, 1.2], "acceleration_profile": "eco", "LaneWidth": 3.5}')
|
|
|
|
assert settings == {"acceleration_profile": "eco", "standard_follow": [1.5, 1.2]}
|