mirror of
https://github.com/MoreTore/openpilot.git
synced 2026-09-15 03:54:03 +08:00
f3414250a3
* start at param * start by sending personality * change to personality * POC: button changes personality * what's wrong with this? * fix * not really possible but fuzzy test catches this * there's always a typo * dang, we're dropping messages * clean up * no comment * bump * rename * not all cars yet * works but at what cost * clean up * inside settings * write param so we save the distance button changes * setChecked activates buttonToggled and already writes param! * don't need this, we update from longitudinalPlan on changes * some clean up * more * ui * allow some time for ui to receive and write param * plannerd: only track changes in case no ui * Revert "plannerd: only track changes in case no ui" This reverts commit 2b081aa6ceb92c67a621b74592b2292756d29871. * write in plannerd as well, I assume this is atomic? * don't write when setting checked (only user clicks) * better nane * more * Update selfdrive/controls/lib/longitudinal_planner.py Co-authored-by: Cameron Clough <cameronjclough@gmail.com> * doesn't write param now * ParamWatcher is nice * no debug * Update translations * fix * odd drain sock proc replay behavior * vanish * Revert "odd drain sock proc replay behavior" This reverts commit 29b70b39413e1852bb512155af6b6a94a5bd9454. * add GM * only if OP long * move personality to controlsState, since eventually it won't be exclusive to long planner more bump * diff without translations * fix * put nonblocking * CS should start at up to date personality always (no ui flicker) * update toggle on cereal message change * fix * fix that * ubmp * mypy doesn't know this is an int :( * update translations * fix the tests * revert ui * not here * migrate controlsState * Revert "migrate controlsState" - i see no reason we need to test with any specific personality This reverts commit 6063508f2df1a5623f113cda34dcd59a1f4b2ac9. * Update ref_commit --------- Co-authored-by: Cameron Clough <cameronjclough@gmail.com> old-commit-hash: 29e55f99a54d95215aa79ecf94a22363f82913a6
157 lines
6.0 KiB
Python
Executable File
157 lines
6.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import itertools
|
|
import numpy as np
|
|
import unittest
|
|
|
|
from parameterized import parameterized_class
|
|
from cereal import log
|
|
from openpilot.selfdrive.controls.lib.drive_helpers import VCruiseHelper, V_CRUISE_MIN, V_CRUISE_MAX, V_CRUISE_INITIAL, IMPERIAL_INCREMENT
|
|
from cereal import car
|
|
from openpilot.common.conversions import Conversions as CV
|
|
from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver
|
|
|
|
ButtonEvent = car.CarState.ButtonEvent
|
|
ButtonType = car.CarState.ButtonEvent.Type
|
|
|
|
|
|
def run_cruise_simulation(cruise, e2e, personality, t_end=20.):
|
|
man = Maneuver(
|
|
'',
|
|
duration=t_end,
|
|
initial_speed=max(cruise - 1., 0.0),
|
|
lead_relevancy=True,
|
|
initial_distance_lead=100,
|
|
cruise_values=[cruise],
|
|
prob_lead_values=[0.0],
|
|
breakpoints=[0.],
|
|
e2e=e2e,
|
|
personality=personality,
|
|
)
|
|
valid, output = man.evaluate()
|
|
assert valid
|
|
return output[-1, 3]
|
|
|
|
|
|
@parameterized_class(("e2e", "personality", "speed"), itertools.product(
|
|
[True, False], # e2e
|
|
log.LongitudinalPersonality.schema.enumerants, # personality
|
|
[5,35])) # speed
|
|
class TestCruiseSpeed(unittest.TestCase):
|
|
def test_cruise_speed(self):
|
|
print(f'Testing {self.speed} m/s')
|
|
cruise_speed = float(self.speed)
|
|
|
|
simulation_steady_state = run_cruise_simulation(cruise_speed, self.e2e, self.personality)
|
|
self.assertAlmostEqual(simulation_steady_state, cruise_speed, delta=.01, msg=f'Did not reach {self.speed} m/s')
|
|
|
|
|
|
# TODO: test pcmCruise
|
|
@parameterized_class(('pcm_cruise',), [(False,)])
|
|
class TestVCruiseHelper(unittest.TestCase):
|
|
def setUp(self):
|
|
self.CP = car.CarParams(pcmCruise=self.pcm_cruise)
|
|
self.v_cruise_helper = VCruiseHelper(self.CP)
|
|
self.reset_cruise_speed_state()
|
|
|
|
def reset_cruise_speed_state(self):
|
|
# Two resets previous cruise speed
|
|
for _ in range(2):
|
|
self.v_cruise_helper.update_v_cruise(car.CarState(cruiseState={"available": False}), enabled=False, is_metric=False)
|
|
|
|
def enable(self, v_ego, experimental_mode):
|
|
# Simulates user pressing set with a current speed
|
|
self.v_cruise_helper.initialize_v_cruise(car.CarState(vEgo=v_ego), experimental_mode)
|
|
|
|
def test_adjust_speed(self):
|
|
"""
|
|
Asserts speed changes on falling edges of buttons.
|
|
"""
|
|
|
|
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False)
|
|
|
|
for btn in (ButtonType.accelCruise, ButtonType.decelCruise):
|
|
for pressed in (True, False):
|
|
CS = car.CarState(cruiseState={"available": True})
|
|
CS.buttonEvents = [ButtonEvent(type=btn, pressed=pressed)]
|
|
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=False)
|
|
self.assertEqual(pressed, self.v_cruise_helper.v_cruise_kph == self.v_cruise_helper.v_cruise_kph_last)
|
|
|
|
def test_rising_edge_enable(self):
|
|
"""
|
|
Some car interfaces may enable on rising edge of a button,
|
|
ensure we don't adjust speed if enabled changes mid-press.
|
|
"""
|
|
|
|
# NOTE: enabled is always one frame behind the result from button press in controlsd
|
|
for enabled, pressed in ((False, False),
|
|
(False, True),
|
|
(True, False)):
|
|
CS = car.CarState(cruiseState={"available": True})
|
|
CS.buttonEvents = [ButtonEvent(type=ButtonType.decelCruise, pressed=pressed)]
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=enabled, is_metric=False)
|
|
if pressed:
|
|
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False)
|
|
|
|
# Expected diff on enabling. Speed should not change on falling edge of pressed
|
|
self.assertEqual(not pressed, self.v_cruise_helper.v_cruise_kph == self.v_cruise_helper.v_cruise_kph_last)
|
|
|
|
def test_resume_in_standstill(self):
|
|
"""
|
|
Asserts we don't increment set speed if user presses resume/accel to exit cruise standstill.
|
|
"""
|
|
|
|
self.enable(0, False)
|
|
|
|
for standstill in (True, False):
|
|
for pressed in (True, False):
|
|
CS = car.CarState(cruiseState={"available": True, "standstill": standstill})
|
|
CS.buttonEvents = [ButtonEvent(type=ButtonType.accelCruise, pressed=pressed)]
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=False)
|
|
|
|
# speed should only update if not at standstill and button falling edge
|
|
should_equal = standstill or pressed
|
|
self.assertEqual(should_equal, self.v_cruise_helper.v_cruise_kph == self.v_cruise_helper.v_cruise_kph_last)
|
|
|
|
def test_set_gas_pressed(self):
|
|
"""
|
|
Asserts pressing set while enabled with gas pressed sets
|
|
the speed to the maximum of vEgo and current cruise speed.
|
|
"""
|
|
|
|
for v_ego in np.linspace(0, 100, 101):
|
|
self.reset_cruise_speed_state()
|
|
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False)
|
|
|
|
# first decrement speed, then perform gas pressed logic
|
|
expected_v_cruise_kph = self.v_cruise_helper.v_cruise_kph - IMPERIAL_INCREMENT
|
|
expected_v_cruise_kph = max(expected_v_cruise_kph, v_ego * CV.MS_TO_KPH) # clip to min of vEgo
|
|
expected_v_cruise_kph = float(np.clip(round(expected_v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX))
|
|
|
|
CS = car.CarState(vEgo=float(v_ego), gasPressed=True, cruiseState={"available": True})
|
|
CS.buttonEvents = [ButtonEvent(type=ButtonType.decelCruise, pressed=False)]
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=False)
|
|
|
|
# TODO: fix skipping first run due to enabled on rising edge exception
|
|
if v_ego == 0.0:
|
|
continue
|
|
self.assertEqual(expected_v_cruise_kph, self.v_cruise_helper.v_cruise_kph)
|
|
|
|
def test_initialize_v_cruise(self):
|
|
"""
|
|
Asserts allowed cruise speeds on enabling with SET.
|
|
"""
|
|
|
|
for experimental_mode in (True, False):
|
|
for v_ego in np.linspace(0, 100, 101):
|
|
self.reset_cruise_speed_state()
|
|
self.assertFalse(self.v_cruise_helper.v_cruise_initialized)
|
|
|
|
self.enable(float(v_ego), experimental_mode)
|
|
self.assertTrue(V_CRUISE_INITIAL <= self.v_cruise_helper.v_cruise_kph <= V_CRUISE_MAX)
|
|
self.assertTrue(self.v_cruise_helper.v_cruise_initialized)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|