Files
StarPilot/openpilot/starpilot/ui/tests/test_lead_bar.py
T
firestar5683 a82935f326 User interfaces and Android Auto
Integrate onroad views, configurable widgets, local settings, steering-profile contracts, Bluetooth and Android Auto with their device and runtime services.

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com>
Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: Shane Smiskol <shane@smiskol.com>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>
Co-authored-by: stef <19478336+stefpi@users.noreply.github.com>
Co-authored-by: whoisdomi <dcantu83@gmail.com>

Co-authored-by: Intelli <contact@intelli.software>
Co-authored-by: pharmacomaniac <blittle65@gmail.com>

Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 20:02:39 -05:00

126 lines
6.3 KiB
Python

"""Lead source, labels, geometry and paint ownership across upstream integration."""
from types import SimpleNamespace as NS
from unittest.mock import Mock, patch
import numpy as np
from openpilot.selfdrive.ui.mici.onroad import model_renderer as native
def fixture():
renderer = native.ModelRenderer.__new__(native.ModelRenderer)
renderer._lead_vehicles = [native.LeadVehicle(), native.LeadVehicle()]
points = np.array([[0., 0., 0.], [20., 0., 0.], [100., 0., 0.]], dtype=np.float32)
renderer._path = native.ModelPoints(raw_points=points)
renderer._lane_lines = [native.ModelPoints(raw_points=points.copy()) for _ in range(4)]
renderer._path_offset_z = 0.
renderer._visual_status = Mock(return_value=native.UIStatus.ENGAGED)
renderer._get_lead_bar = Mock(return_value=np.ones((4, 2), dtype=np.float32))
good = NS(present=True, dRel=20., yRel=.1, vRel=-1., vLead=10.)
values = {'radarState': NS(leadOne=good, leadTwo=NS(present=False)),
'longitudinalPlan': NS(longitudinalPlanSource=native.log.LongitudinalPlan.LongitudinalPlanSource.lead0),
'modelV2': NS(leadsV3=[]), 'selfdriveState': NS(enabled=True, engageable=True),
'carState': NS(brakePressed=False)}
class SubMaster(dict):
valid = {'radarState': True, 'longitudinalPlan': True, 'modelV2': True}
return renderer, SubMaster(values)
def test_radar_offset_labels_and_duplicate_lead_are_consistent():
renderer, sm = fixture()
sm['radarState'].leadTwo = NS(present=True, dRel=21., yRel=.2, vRel=0., vLead=11.)
renderer._update_leads(sm)
assert renderer._get_lead_bar.call_count == 1
assert renderer._get_lead_bar.call_args.args[1:] == (20. + native.RADAR_TO_CAMERA, .1)
assert renderer._format_lead_info(renderer._lead_vehicles[0].info, 1, True) == '20 m'
assert renderer._format_lead_info(renderer._lead_vehicles[0].info, 2, True) == '36 km/h'
assert renderer._lead_vehicles[1].info is None and not renderer._lead_vehicles[1].bar.size
def test_e2e_without_radar_uses_matching_label_and_fails_closed_when_stale():
renderer, sm = fixture()
sm.valid = dict(sm.valid, radarState=False)
sm['longitudinalPlan'].longitudinalPlanSource = native.log.LongitudinalPlan.LongitudinalPlanSource.e2e
sm['modelV2'].leadsV3 = [NS(prob=.9, x=[30.], y=[-.2], v=[12.]), NS(prob=.1, x=[60.], y=[0.], v=[12.])]
renderer._update_leads(sm)
assert renderer._get_lead_bar.call_args.args[1:] == (30., .2)
assert renderer._lead_vehicles[0].info.dRel == 30. - native.RADAR_TO_CAMERA
assert renderer._format_lead_info(renderer._lead_vehicles[0].info, 2, False) == '27 mph'
sm.valid['modelV2'] = False
renderer._update_leads(sm)
assert all(lead.info is None and not lead.bar.size for lead in renderer._lead_vehicles)
def test_invalid_numbers_and_invalid_path_geometry_do_not_project():
for field, value in [('dRel', float('nan')), ('yRel', float('inf')), ('vRel', 'bad'), ('dRel', -1.)]:
renderer, sm = fixture()
setattr(sm['radarState'].leadOne, field, value)
renderer._update_leads(sm)
renderer._get_lead_bar.assert_not_called()
assert renderer._lead_vehicles[0].info is None
for points in (np.empty((0, 3), dtype=np.float32), np.full((3, 3), np.nan, dtype=np.float32)):
renderer, sm = fixture()
renderer._path.raw_points = points
renderer._update_leads(sm)
renderer._get_lead_bar.assert_not_called()
assert all(lead.info is None and not lead.bar.size for lead in renderer._lead_vehicles)
def test_missing_lane_lines_still_project_using_exact_model_path():
renderer, sm = fixture()
renderer._lane_lines[2].raw_points = np.empty((0, 3), dtype=np.float32)
renderer._update_leads(sm)
renderer._get_lead_bar.assert_called_once()
assert renderer._get_lead_bar.call_args.args[0] is renderer._path.raw_points
assert renderer._get_lead_bar.call_args.args[1:] == (20. + native.RADAR_TO_CAMERA, .1)
assert renderer._lead_vehicles[0].info is not None and renderer._lead_vehicles[0].bar.size
def test_brake_and_independent_lateral_availability_retain_snap_and_fade():
renderer, sm = fixture()
sm['selfdriveState'].enabled = sm['selfdriveState'].engageable = False
sm['carState'].brakePressed = True
renderer._update_leads(sm)
assert renderer._lead_vehicles[0].info is not None
sm['carState'].brakePressed = False
renderer._render_lateral_active = True
renderer._update_leads(sm)
assert renderer._lead_vehicles[0].info is not None
sm['radarState'].leadOne.yRel = 8.
renderer._update_leads(sm)
assert renderer._get_lead_bar.call_args.args[2] == 8., 'new lane lead snaps rather than slides'
def test_projection_rejects_zero_depth_degenerate_and_nonfinite_results():
renderer, _ = fixture()
del renderer._get_lead_bar
lane = renderer._lane_lines[1].raw_points
for transform in (np.zeros((3, 3)), np.full((3, 3), float('nan')), np.array([[0., 0., 1.], [0., 0., 1.], [1., 0., 0.]])):
renderer._car_space_transform = transform
assert not renderer._get_lead_bar(lane, 20., 0.).size
def test_render_paint_and_saved_label_context_stay_owned_by_caller():
renderer, sm = fixture()
renderer._lead_indicator_enabled = False
renderer._torque_filter = Mock()
renderer._transform_dirty = False
renderer._update_model = Mock()
renderer._draw_lead_indicator = Mock()
renderer._draw_lead_info = Mock()
renderer._draw_lane_lines = Mock()
renderer._draw_path = Mock()
sm['carOutput'] = NS(actuatorsOutput=NS(torque=0.))
sm['extrinsicsCalibration'] = NS(height=[])
sm['selfdriveState'].experimentalMode = False
sm.recv_frame = {'extrinsicsCalibration': 2, 'modelV2': 2}
sm.updated = {'carParams': False, 'modelV2': False, 'radarState': False}
rect = native.rl.Rectangle(0., 0., 476., 240.)
with patch.object(native, 'ui_state', NS(sm=sm, started_frame=1, status=native.UIStatus.ENGAGED)), \
patch.object(native.ModelRenderer, 'render', autospec=True, side_effect=lambda owner, area: owner._render(area)):
renderer.render_with_lead(rect, True, 1, True, paint=False)
renderer._draw_lead_indicator.assert_not_called()
renderer._draw_lead_info.assert_not_called()
renderer.render_with_lead(rect, True, 2, True)
renderer._draw_lead_indicator.assert_called_once()
renderer._draw_lead_info.assert_called_once_with(rect, '36 km/h')
assert not renderer._lead_indicator_enabled and renderer._lead_info_mode == 0 and renderer._lead_info_metric is None