Files
StarPilot/openpilot/starpilot/ui/tests/test_live_developer_sidebar.py
T
2026-10-04 21:28:43 -05:00

115 lines
6.4 KiB
Python

import unittest
from types import SimpleNamespace as NS
from unittest.mock import Mock, patch
import pyray as rl
from openpilot.starpilot.ui.live_developer_sidebar import DeveloperMetrics, render_sidebar
from openpilot.starpilot.ui.layout_preview_sidebar import metric_rects
class TestLiveDeveloperSidebar(unittest.TestCase):
def observe(self, owner, **changes):
values = {'drive': 10, 'car': NS(aEgo=-1.), 'delay': NS(lateralDelay=.15),
'torque': NS(useParams=True, frictionCoefficientFiltered=.12, latAccelFactorFiltered=2.5),
'parameters': NS(steerRatio=16.8, stiffnessFactor=.9), 'metric': True}
return owner.observe(**(values | changes))
def test_original_default_order_real_values_and_drive_reset(self):
owner = DeveloperMetrics()
rows = self.observe(owner)
self.assertEqual([r.label for r in rows], ['ACCEL', 'MAX ACCEL', 'LEARNED DELAY', 'LEARNED FRICTION', 'LEARNED LAT ACCEL', 'STEER RATIO', 'STEER STIFF'])
self.assertEqual(rows[0].value, '-1.00 m/s²')
self.observe(owner, car=NS(aEgo=5., gasPressed=True))
self.assertEqual(self.observe(owner)[1].value, '0.00 m/s²')
self.observe(owner, car=NS(aEgo=2.))
self.assertEqual(self.observe(owner)[1].value, '2.00 m/s²')
self.assertEqual(self.observe(owner, drive=11)[1].value, '0.00 m/s²')
self.assertEqual(self.observe(owner, metric=False)[0].value, '-3.28 ft/s²')
def test_missing_nonfinite_sources_and_explicit_cp_fallback(self):
rows = self.observe(DeveloperMetrics(), car=None, delay=None, torque=None, parameters=None)
self.assertTrue(all(row.value == '—' for row in rows))
rows = self.observe(DeveloperMetrics(), car=NS(aEgo=float('nan')), delay=NS(lateralDelay=float('inf')))
self.assertEqual(rows[0].value, '—')
self.assertEqual(rows[2].value, '—')
cp = NS(steerActuatorDelay=.2, lateralTuning=NS(which=lambda: 'torque', torque=NS(friction=.13, latAccelFactor=2.)))
rows = self.observe(DeveloperMetrics(), delay=None, torque=None, cp=cp)
self.assertEqual(rows[2].label, 'BASE DELAY')
self.assertEqual(rows[2].value, '0.20000')
self.assertEqual(rows[3].value, '0.13000')
def test_live_render_uses_given_metrics_inside_shifted_rail(self):
fonts = Mock()
fonts.measure.return_value = NS(width=100, height=30)
frame = rl.Rectangle(1560, 0, 300, 1080)
rows = self.observe(DeveloperMetrics())
with patch('openpilot.starpilot.ui.live_developer_sidebar.rl.draw_rectangle_rec'), \
patch('openpilot.starpilot.ui.live_developer_sidebar.rl.draw_rectangle_rounded_lines_ex'):
render_sidebar(fonts, frame, rows)
self.assertEqual(fonts.draw.call_count, 14)
self.assertNotIn('SAMPLE DATA', [call.args[0] for call in fonts.draw.call_args_list])
self.assertTrue(all(frame.x <= r.x and r.x + r.width <= frame.x + frame.width for r in metric_rects(frame, 7)))
def test_snapshot_current_stale_and_previous_drive_observations(self):
from openpilot.starpilot.ui.tests.test_runtime_snapshot import NOW, RuntimeSnapshotAdapter, ui_fake
from openpilot.starpilot.ui.shell import ShellMode
ui = ui_fake()
ui.sm['carState'].aEgo = 1.5
ui.sm['carState'].canValid = True
ui.sm['carState'].canTimeout = False
ui.sm.put('lateralDelay', NS(lateralDelay=.12))
ui.sm.put('lateralTorqueParameters', NS(useParams=True, frictionCoefficientFiltered=.15, latAccelFactorFiltered=2.4))
ui.sm.put('vehicleParameters', NS(steerRatio=17., stiffnessFactor=1.1))
adapter = RuntimeSnapshotAdapter(ui)
rows = adapter.build(ShellMode.ONROAD, now_ns=NOW).onroad.developer_metrics
self.assertEqual(rows[0].value, '4.92 ft/s²')
self.assertEqual(rows[3].value, '0.15000')
for service in ('lateralDelay', 'lateralTorqueParameters'):
ui.sm.logMonoTime[service] = NOW - 300_000_000
rows = adapter.build(ShellMode.ONROAD, now_ns=NOW).onroad.developer_metrics
self.assertEqual(rows[2].value, '0.12000')
self.assertEqual(rows[3].value, '0.15000')
for service in ('carState', 'lateralDelay', 'lateralTorqueParameters', 'vehicleParameters'):
ui.sm.logMonoTime[service] = NOW - 600_000_000
rows = adapter.build(ShellMode.ONROAD, now_ns=NOW).onroad.developer_metrics
self.assertTrue(all(row.value == '—' for row in rows))
for service in ('carState', 'lateralDelay', 'lateralTorqueParameters', 'vehicleParameters'):
ui.sm.logMonoTime[service] = NOW
ui.sm.recv_frame[service] = ui.started_frame
rows = adapter.build(ShellMode.ONROAD, now_ns=NOW).onroad.developer_metrics
self.assertTrue(all(row.value == '—' for row in rows))
def test_onroad_view_physical_rail_and_projection_omission(self):
from contextlib import ExitStack
from pathlib import Path
from openpilot.starpilot.ui.onroad import OnroadView
from openpilot.starpilot.ui.onroad_state import OnroadState, SpeedLimitObservation
from openpilot.starpilot.ui.presentation import Profile
fonts = Mock(profile=Profile.LARGE)
fonts.measure.return_value = NS(width=100, height=30)
state = OnroadState(False, False, None, None, SpeedLimitObservation(), viewport_width=1560,
developer_metrics=self.observe(DeveloperMetrics()))
with ExitStack() as stack:
for name in ('draw_rectangle_rec', 'draw_rectangle_gradient_v', 'draw_rectangle_lines_ex',
'draw_rectangle_rounded', 'draw_rectangle_rounded_lines_ex', 'draw_line_ex', 'draw_circle', 'draw_texture_pro',
'rl_push_matrix', 'rl_translatef', 'rl_pop_matrix'):
stack.enter_context(patch('openpilot.starpilot.ui.onroad.rl.' + name))
stack.enter_context(patch('openpilot.starpilot.ui.onroad.clip.begin_scissor_mode'))
stack.enter_context(patch('openpilot.starpilot.ui.onroad.clip.end_scissor_mode'))
stack.enter_context(patch('openpilot.starpilot.ui.onroad.render_corner_hint'))
stack.enter_context(patch('openpilot.starpilot.ui.onroad.gui_app.add_render_prepare'))
rail = stack.enter_context(patch('openpilot.starpilot.ui.onroad.render_live_sidebar'))
view = OnroadView(fonts, Path('/unused'))
view.unified_speed = view.current_speed = view.steering_wheel = Mock()
view.navigation = view.alert = Mock()
view._large(state)
self.assertEqual(rail.call_args.args[1].x, 1560)
self.assertEqual(rail.call_args.args[1].width, 300)
rail.reset_mock()
view.projection_viewport = (1280, 720)
view._large(state)
rail.assert_not_called()