Skip to content

Commit 08afbd7

Browse files
authored
car: Check params before car state is updated (commaai#364)
* car: Check params before car state is updated * read params in a thread instead * initialize list * Do this instead * type hint * ParamManager * make them internal
1 parent f311c8b commit 08afbd7

File tree

13 files changed

+63
-36
lines changed

13 files changed

+63
-36
lines changed

selfdrive/car/card.py

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/usr/bin/env python3
22
import os
3+
import threading
34
import time
5+
from types import SimpleNamespace
46

57
import cereal.messaging as messaging
68

@@ -14,6 +16,7 @@
1416
from openpilot.selfdrive.pandad import can_list_to_can_capnp
1517
from openpilot.selfdrive.car.car_helpers import get_car, get_one_can
1618
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
19+
from openpilot.selfdrive.car.param_manager import ParamManager
1720
from openpilot.selfdrive.controls.lib.events import Events
1821

1922
REPLAY = "REPLAY" in os.environ
@@ -90,6 +93,10 @@ def __init__(self, CI=None):
9093

9194
self.events = Events()
9295

96+
self.param_manager: ParamManager = ParamManager()
97+
self.param_manager.update(self.params)
98+
self._params_list: SimpleNamespace = self.param_manager.get_params()
99+
93100
# card is driven by can recv, expected at 100Hz
94101
self.rk = Ratekeeper(100, print_delay_threshold=None)
95102

@@ -98,7 +105,7 @@ def state_update(self) -> car.CarState:
98105

99106
# Update carState from CAN
100107
can_strs = messaging.drain_sock_raw(self.can_sock, wait_for_one=True)
101-
CS = self.CI.update(self.CC_prev, can_strs)
108+
CS = self.CI.update(self.CC_prev, can_strs, self._params_list)
102109

103110
self.sm.update(0)
104111

@@ -186,10 +193,23 @@ def step(self):
186193
self.initialized_prev = initialized
187194
self.CS_prev = CS.as_reader()
188195

196+
def sp_params_thread(self, event: threading.Event) -> None:
197+
while not event.is_set():
198+
self.param_manager.update(self.params)
199+
self._params_list = self.param_manager.get_params()
200+
time.sleep(0.1)
201+
189202
def card_thread(self):
190-
while True:
191-
self.step()
192-
self.rk.monitor_time()
203+
event = threading.Event()
204+
thread = threading.Thread(target=self.sp_params_thread, args=(event, ))
205+
try:
206+
thread.start()
207+
while True:
208+
self.step()
209+
self.rk.monitor_time()
210+
finally:
211+
event.set()
212+
thread.join()
193213

194214

195215
def main():

selfdrive/car/chrysler/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
9191

9292
def _update(self, c):
9393
ret = self.CS.update(self.cp, self.cp_cam)
94-
self.sp_update_params()
9594

9695
self.CS.button_events = [
9796
*self.CS.button_events,

selfdrive/car/ford/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
7272

7373
def _update(self, c):
7474
ret = self.CS.update(self.cp, self.cp_cam)
75-
self.sp_update_params()
7675

7776
self.CS.button_events = [
7877
*self.CS.button_events,

selfdrive/car/gm/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
204204
# returns a car.CarState
205205
def _update(self, c):
206206
ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback)
207-
self.sp_update_params()
208207

209208
distance_button = 0
210209

selfdrive/car/honda/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,6 @@ def init(CP, logcan, sendcan):
266266
# returns a car.CarState
267267
def _update(self, c):
268268
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
269-
self.sp_update_params()
270269

271270
self.CS.button_events = [
272271
*create_button_events(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT),

selfdrive/car/hyundai/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,6 @@ def init(CP, logcan, sendcan):
203203

204204
def _update(self, c):
205205
ret = self.CS.update(self.cp, self.cp_cam)
206-
self.sp_update_params()
207206

208207
self.CS.button_events = [
209208
*create_button_events(self.CS.cruise_buttons[-1], self.CS.prev_cruise_buttons, BUTTONS_DICT),

selfdrive/car/interfaces.py

+9-22
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from abc import abstractmethod, ABC
88
from difflib import SequenceMatcher
99
from enum import StrEnum
10+
from types import SimpleNamespace
1011
from typing import Any, NamedTuple
1112
from collections.abc import Callable
1213
from functools import cache
@@ -19,6 +20,7 @@
1920
from openpilot.common.params import Params
2021
from openpilot.common.realtime import DT_CTRL
2122
from openpilot.selfdrive.car import apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, STD_CARGO_KG, ButtonEvents
23+
from openpilot.selfdrive.car.param_manager import ParamManager
2224
from openpilot.selfdrive.car.values import PLATFORMS
2325
from openpilot.selfdrive.controls.lib.desire_helper import get_min_lateral_speed
2426
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET, get_friction
@@ -239,16 +241,10 @@ def __init__(self, CP, CarController, CarState):
239241
self.gear_warning = 0
240242
self.cruise_cancelled_btn = True
241243
self.acc_mads_combo = self.param_s.get_bool("AccMadsCombo")
242-
self.is_metric = self.param_s.get_bool("IsMetric")
243-
self.below_speed_pause = self.param_s.get_bool("BelowSpeedPause")
244-
self.pause_lateral_speed = int(self.param_s.get("PauseLateralSpeed", encoding="utf8"))
245244
self.prev_acc_mads_combo = False
246245
self.mads_event_lock = True
247246
self.gap_button_counter = 0
248247
self.experimental_mode_hold = False
249-
self.experimental_mode = self.param_s.get_bool("ExperimentalMode")
250-
self._frame = 0
251-
self.reverse_dm_cam = self.param_s.get_bool("ReverseDmCam")
252248
self.mads_main_toggle = self.param_s.get_bool("MadsCruiseMain")
253249
self.lkas_toggle = self.param_s.get_bool("LkasToggle")
254250
self.last_mads_init = 0.
@@ -421,13 +417,14 @@ def sp_configure_custom_torque_tune(ret, params):
421417
def _update(self, c: car.CarControl) -> car.CarState:
422418
pass
423419

424-
def update(self, c: car.CarControl, can_strings: list[bytes]) -> car.CarState:
420+
def update(self, c: car.CarControl, can_strings: list[bytes], params_list: SimpleNamespace) -> car.CarState:
425421
# parse can
426422
for cp in self.can_parsers:
427423
if cp is not None:
428424
cp.update_strings(can_strings)
429425

430426
self.CS.button_events = []
427+
self.CS.params_list = params_list
431428

432429
# get CarState
433430
ret = self._update(c)
@@ -472,7 +469,7 @@ def create_common_events(self, cs_out, c, extra_gears=None, pcm_enable=True, all
472469
else:
473470
events.add(EventName.wrongGear)
474471
if cs_out.gearShifter == GearShifter.reverse:
475-
if not self.reverse_dm_cam and cs_out.vEgo < 5:
472+
if not self.CS.params_list.reverse_dm_cam and cs_out.vEgo < 5:
476473
events.add(EventName.spReverseGear)
477474
elif cs_out.vEgo >= 5:
478475
events.add(EventName.reverseGear)
@@ -634,9 +631,9 @@ def get_sp_common_state(self, cs_out, CS, min_enable_speed_pcm=False, gear_allow
634631
if self.CP.openpilotLongitudinalControl:
635632
self.toggle_exp_mode(gap_button)
636633

637-
lane_change_speed_min = get_min_lateral_speed(self.pause_lateral_speed, self.is_metric)
634+
lane_change_speed_min = get_min_lateral_speed(self.CS.params_list.pause_lateral_speed, self.CS.params_list.is_metric)
638635

639-
cs_out.belowLaneChangeSpeed = cs_out.vEgo < lane_change_speed_min and self.below_speed_pause
636+
cs_out.belowLaneChangeSpeed = cs_out.vEgo < lane_change_speed_min and self.CS.params_list.below_speed_pause
640637

641638
if cs_out.gearShifter in [GearShifter.park, GearShifter.reverse] or cs_out.doorOpen or \
642639
(cs_out.seatbeltUnlatched and cs_out.gearShifter != GearShifter.park):
@@ -669,7 +666,7 @@ def toggle_exp_mode(self, gap_pressed):
669666
if self.gap_button_counter > 50:
670667
self.gap_button_counter = 0
671668
self.experimental_mode_hold = True
672-
self.param_s.put_bool_nonblocking("ExperimentalMode", not self.experimental_mode)
669+
self.param_s.put_bool_nonblocking("ExperimentalMode", not self.CS.params_list.experimental_mode)
673670
else:
674671
self.gap_button_counter = 0
675672
self.experimental_mode_hold = False
@@ -735,17 +732,6 @@ def create_sp_events(self, CS, cs_out, events, main_enabled=False, allow_enable=
735732

736733
return events, cs_out
737734

738-
def sp_update_params(self):
739-
self.experimental_mode = self.param_s.get_bool("ExperimentalMode")
740-
self._frame += 1
741-
if self._frame % 100 == 0:
742-
self.is_metric = self.param_s.get_bool("IsMetric")
743-
self.below_speed_pause = self.param_s.get_bool("BelowSpeedPause")
744-
self.pause_lateral_speed = int(self.param_s.get("PauseLateralSpeed", encoding="utf8"))
745-
if self._frame % 300 == 0:
746-
self._frame = 0
747-
self.reverse_dm_cam = self.param_s.get_bool("ReverseDmCam")
748-
749735
class RadarInterfaceBase(ABC):
750736
def __init__(self, CP):
751737
self.rcp = None
@@ -785,6 +771,7 @@ def __init__(self, CP):
785771
self.control_initialized = False
786772

787773
self.button_events: list[capnp.lib.capnp._DynamicStructBuilder] = []
774+
self.params_list: SimpleNamespace = ParamManager().get_params()
788775

789776
Q = [[0.0, 0.0], [0.0, 100.0]]
790777
R = 0.3

selfdrive/car/mazda/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
3737
# returns a car.CarState
3838
def _update(self, c):
3939
ret = self.CS.update(self.cp, self.cp_cam)
40-
self.sp_update_params()
4140

4241
# TODO: add button types for inc and dec
4342
self.CS.button_events = [

selfdrive/car/nissan/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
3232
# returns a car.CarState
3333
def _update(self, c):
3434
ret = self.CS.update(self.cp, self.cp_adas, self.cp_cam)
35-
self.sp_update_params()
3635

3736
self.CS.button_events = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise})
3837

selfdrive/car/param_manager.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from types import SimpleNamespace
2+
3+
from openpilot.common.params import Params
4+
5+
6+
class ParamManager:
7+
def __init__(self):
8+
self._params_list: SimpleNamespace = self._create_namespace({
9+
"below_speed_pause": False,
10+
"experimental_mode": False,
11+
"is_metric": False,
12+
"pause_lateral_speed": 0,
13+
"reverse_dm_cam": False,
14+
})
15+
16+
@staticmethod
17+
def _create_namespace(data: dict) -> SimpleNamespace:
18+
return SimpleNamespace(**data)
19+
20+
def get_params(self) -> SimpleNamespace:
21+
return self._params_list
22+
23+
def update(self, params: Params) -> None:
24+
self._params_list = self._create_namespace({
25+
"below_speed_pause": params.get_bool("BelowSpeedPause"),
26+
"experimental_mode": params.get_bool("ExperimentalMode"),
27+
"is_metric": params.get_bool("IsMetric"),
28+
"pause_lateral_speed": int(params.get("PauseLateralSpeed", encoding="utf8")),
29+
"reverse_dm_cam": params.get_bool("ReverseDmCam"),
30+
})

selfdrive/car/subaru/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ def _get_params(ret, candidate: CAR, fingerprint, car_fw, experimental_long, doc
116116
def _update(self, c):
117117

118118
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
119-
self.sp_update_params()
120119

121120
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
122121

selfdrive/car/toyota/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@ def init(CP, logcan, sendcan):
207207
# returns a car.CarState
208208
def _update(self, c):
209209
ret = self.CS.update(self.cp, self.cp_cam)
210-
self.sp_update_params()
211210

212211
distance_button = 0
213212

selfdrive/car/volkswagen/interface.py

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ def _get_params(ret, candidate: CAR, fingerprint, car_fw, experimental_long, doc
113113
# returns a car.CarState
114114
def _update(self, c):
115115
ret = self.CS.update(self.cp, self.cp_cam, self.cp_ext, self.CP.transmissionType)
116-
self.sp_update_params()
117116

118117
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
119118

0 commit comments

Comments
 (0)