From 965cb04aa811e2a70054dc6977f7674531249f3c Mon Sep 17 00:00:00 2001 From: deanlee Date: Mon, 9 Dec 2024 02:09:36 +0800 Subject: [PATCH 1/7] improve thread-safety with ParameterUpdater class --- selfdrive/car/card.py | 50 ++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 92d9b7eb11ddfd..05ad99460e99b0 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -59,6 +59,35 @@ def can_send(msgs: list[CanData]) -> None: return can_recv, can_send +class ParameterUpdater: + def __init__(self): + self.params = Params() + self.mutex = threading.Lock() + self.is_metric = False + self.experimental_mode = False + + self._update() # Initial update + self.stop_event = threading.Event() + self.update_thread = threading.Thread(target=self._update_periodically) + self.update_thread.start() + + def stop(self): + self.stop_event.set() + self.update_thread.join() + + def _update(self): + is_metric = self.params.get_bool("IsMetric") + experimental_mode = self.params.get_bool("ExperimentalMode") + with self.mutex: + self.is_metric = is_metric + self.experimental_mode = experimental_mode + + def _update_periodically(self): + while not self.stop_event.is_set(): + self._update() + time.sleep(0.1) + + class Car: CI: CarInterfaceBase RI: RadarInterfaceBase @@ -149,8 +178,8 @@ def __init__(self, CI=None, RI=None) -> None: self.mock_carstate = MockCarState() self.v_cruise_helper = VCruiseHelper(self.CP) - self.is_metric = self.params.get_bool("IsMetric") - self.experimental_mode = self.params.get_bool("ExperimentalMode") + self.is_metric = False + self.experimental_mode = False # card is driven by can recv, expected at 100Hz self.rk = Ratekeeper(100, print_delay_threshold=None) @@ -250,23 +279,18 @@ def step(self): self.initialized_prev = initialized - def params_thread(self, evt): - while not evt.is_set(): - self.is_metric = self.params.get_bool("IsMetric") - self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl - time.sleep(0.1) - def card_thread(self): - e = threading.Event() - t = threading.Thread(target=self.params_thread, args=(e, )) + parameter_updater = ParameterUpdater() try: - t.start() while True: + with parameter_updater.mutex: + self.is_metric = parameter_updater.is_metric + self.experimental_mode = parameter_updater.experimental_mode + self.step() self.rk.monitor_time() finally: - e.set() - t.join() + parameter_updater.stop() def main(): From 655966977c0af3aaf605afac0050507b237ca134 Mon Sep 17 00:00:00 2001 From: deanlee Date: Mon, 9 Dec 2024 02:45:35 +0800 Subject: [PATCH 2/7] move to separate file --- selfdrive/car/card.py | 31 +--------------------------- selfdrive/car/parameter_updater.py | 33 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 30 deletions(-) create mode 100644 selfdrive/car/parameter_updater.py diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 05ad99460e99b0..4b2a9b8b58e37c 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import os import time -import threading import cereal.messaging as messaging @@ -21,6 +20,7 @@ from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp from openpilot.selfdrive.car.cruise import VCruiseHelper from openpilot.selfdrive.car.car_specific import MockCarState +from openpilot.selfdrive.car.parameter_updater import ParameterUpdater REPLAY = "REPLAY" in os.environ @@ -59,35 +59,6 @@ def can_send(msgs: list[CanData]) -> None: return can_recv, can_send -class ParameterUpdater: - def __init__(self): - self.params = Params() - self.mutex = threading.Lock() - self.is_metric = False - self.experimental_mode = False - - self._update() # Initial update - self.stop_event = threading.Event() - self.update_thread = threading.Thread(target=self._update_periodically) - self.update_thread.start() - - def stop(self): - self.stop_event.set() - self.update_thread.join() - - def _update(self): - is_metric = self.params.get_bool("IsMetric") - experimental_mode = self.params.get_bool("ExperimentalMode") - with self.mutex: - self.is_metric = is_metric - self.experimental_mode = experimental_mode - - def _update_periodically(self): - while not self.stop_event.is_set(): - self._update() - time.sleep(0.1) - - class Car: CI: CarInterfaceBase RI: RadarInterfaceBase diff --git a/selfdrive/car/parameter_updater.py b/selfdrive/car/parameter_updater.py new file mode 100644 index 00000000000000..7f4df28adec9dd --- /dev/null +++ b/selfdrive/car/parameter_updater.py @@ -0,0 +1,33 @@ +import threading +import time + +from openpilot.common.params import Params + + +class ParameterUpdater: + def __init__(self): + self.params = Params() + self.mutex = threading.Lock() + self.is_metric = False + self.experimental_mode = False + + self._update() # Initial update + self.stop_event = threading.Event() + self.update_thread = threading.Thread(target=self._update_periodically) + self.update_thread.start() + + def stop(self): + self.stop_event.set() + self.update_thread.join() + + def _update(self): + is_metric = self.params.get_bool("IsMetric") + experimental_mode = self.params.get_bool("ExperimentalMode") + with self.mutex: + self.is_metric = is_metric + self.experimental_mode = experimental_mode + + def _update_periodically(self): + while not self.stop_event.is_set(): + self._update() + time.sleep(0.1) From cbe101587040760ba49382568f7399a1a1e08620 Mon Sep 17 00:00:00 2001 From: deanlee Date: Mon, 9 Dec 2024 03:24:12 +0800 Subject: [PATCH 3/7] generic --- common/parameter_updater.py | 53 ++++++++++++++++++++++++++++++ selfdrive/car/card.py | 7 ++-- selfdrive/car/parameter_updater.py | 33 ------------------- 3 files changed, 56 insertions(+), 37 deletions(-) create mode 100644 common/parameter_updater.py delete mode 100644 selfdrive/car/parameter_updater.py diff --git a/common/parameter_updater.py b/common/parameter_updater.py new file mode 100644 index 00000000000000..b38635874d6243 --- /dev/null +++ b/common/parameter_updater.py @@ -0,0 +1,53 @@ +import threading +import time +from typing import Dict, Union +from openpilot.common.params import Params + + +class ParameterUpdater: + def __init__(self, params_to_update: Dict[str, str]): + """ + params_to_update: A dictionary where keys are parameter names, and values are their types ('bool' or 'str'). + Example: {"IsMetric": "bool", "LongitudinalPersonality": "str"} + """ + self.params = Params() + self.params_to_update = params_to_update + self.param_values: Dict[str, Union[bool, str]] = {param: None for param in params_to_update} + + self._update() # Initial update + + self.mutex = threading.Lock() + self.stop_event = threading.Event() + self.update_thread = None + + def start(self) -> None: + if self.update_thread is None or not self.update_thread.is_alive(): + self.update_thread = threading.Thread(target=self._update_periodically, daemon=True) + self.update_thread.start() + + def stop(self) -> None: + if self.update_thread and self.update_thread.is_alive(): + self.stop_event.set() + self.update_thread.join() + + def get_param_value(self, param: str) -> Union[bool, str, None]: + with self.mutex: + return self.param_values.get(param) + + def _update(self) -> None: + new_values: Dict[str, Union[bool, str]] = {} + for param, param_type in self.params_to_update.items(): + if param_type == "bool": + new_values[param] = self.params.get_bool(param) + elif param_type == "str": + new_values[param] = self.params.get(param) + else: + raise ValueError(f"Unsupported type {param_type} for parameter {param}") + + with self.mutex: + self.param_values = new_values + + def _update_periodically(self) -> None: + while not self.stop_event.is_set(): + self._update() + time.sleep(0.1) diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 4b2a9b8b58e37c..030b8650b14875 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -8,6 +8,7 @@ from panda import ALTERNATIVE_EXPERIENCE +from openpilot.common.parameter_updater import ParameterUpdater from openpilot.common.params import Params from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper from openpilot.common.swaglog import cloudlog, ForwardingHandler @@ -20,7 +21,6 @@ from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp from openpilot.selfdrive.car.cruise import VCruiseHelper from openpilot.selfdrive.car.car_specific import MockCarState -from openpilot.selfdrive.car.parameter_updater import ParameterUpdater REPLAY = "REPLAY" in os.environ @@ -254,9 +254,8 @@ def card_thread(self): parameter_updater = ParameterUpdater() try: while True: - with parameter_updater.mutex: - self.is_metric = parameter_updater.is_metric - self.experimental_mode = parameter_updater.experimental_mode + self.is_metric = parameter_updater.get_param_value('is_metric') + self.experimental_mode = parameter_updater.get_param_value('experimental_mode') self.step() self.rk.monitor_time() diff --git a/selfdrive/car/parameter_updater.py b/selfdrive/car/parameter_updater.py deleted file mode 100644 index 7f4df28adec9dd..00000000000000 --- a/selfdrive/car/parameter_updater.py +++ /dev/null @@ -1,33 +0,0 @@ -import threading -import time - -from openpilot.common.params import Params - - -class ParameterUpdater: - def __init__(self): - self.params = Params() - self.mutex = threading.Lock() - self.is_metric = False - self.experimental_mode = False - - self._update() # Initial update - self.stop_event = threading.Event() - self.update_thread = threading.Thread(target=self._update_periodically) - self.update_thread.start() - - def stop(self): - self.stop_event.set() - self.update_thread.join() - - def _update(self): - is_metric = self.params.get_bool("IsMetric") - experimental_mode = self.params.get_bool("ExperimentalMode") - with self.mutex: - self.is_metric = is_metric - self.experimental_mode = experimental_mode - - def _update_periodically(self): - while not self.stop_event.is_set(): - self._update() - time.sleep(0.1) From 23dc77f4e4c5144b6e4bcd68d8965400c43f2c1c Mon Sep 17 00:00:00 2001 From: deanlee Date: Mon, 9 Dec 2024 03:37:53 +0800 Subject: [PATCH 4/7] use ParameterUpdater in selfdrived --- common/parameter_updater.py | 24 +++++++++---------- selfdrive/car/card.py | 16 +++++++++---- selfdrive/selfdrived/selfdrived.py | 37 +++++++++++++++--------------- 3 files changed, 42 insertions(+), 35 deletions(-) diff --git a/common/parameter_updater.py b/common/parameter_updater.py index b38635874d6243..bc9f3f0af47c9d 100644 --- a/common/parameter_updater.py +++ b/common/parameter_updater.py @@ -1,41 +1,41 @@ import threading import time -from typing import Dict, Union + from openpilot.common.params import Params class ParameterUpdater: - def __init__(self, params_to_update: Dict[str, str]): + def __init__(self, params_to_update: dict[str, str]): """ params_to_update: A dictionary where keys are parameter names, and values are their types ('bool' or 'str'). Example: {"IsMetric": "bool", "LongitudinalPersonality": "str"} """ self.params = Params() self.params_to_update = params_to_update - self.param_values: Dict[str, Union[bool, str]] = {param: None for param in params_to_update} + self.param_values = {param: None for param in params_to_update} self._update() # Initial update self.mutex = threading.Lock() self.stop_event = threading.Event() - self.update_thread = None + self.update_thread: threading.Thread | None = None - def start(self) -> None: - if self.update_thread is None or not self.update_thread.is_alive(): + def start(self): + if self.update_thread is None: self.update_thread = threading.Thread(target=self._update_periodically, daemon=True) self.update_thread.start() - def stop(self) -> None: - if self.update_thread and self.update_thread.is_alive(): + def stop(self): + if self.update_thread: self.stop_event.set() self.update_thread.join() - def get_param_value(self, param: str) -> Union[bool, str, None]: + def get_param_value(self, param: str): with self.mutex: return self.param_values.get(param) - def _update(self) -> None: - new_values: Dict[str, Union[bool, str]] = {} + def _update(self): + new_values: dict[str, bool | str | None] = {} for param, param_type in self.params_to_update.items(): if param_type == "bool": new_values[param] = self.params.get_bool(param) @@ -47,7 +47,7 @@ def _update(self) -> None: with self.mutex: self.param_values = new_values - def _update_periodically(self) -> None: + def _update_periodically(self): while not self.stop_event.is_set(): self._update() time.sleep(0.1) diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 030b8650b14875..6d6ea4e878a56f 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -250,13 +250,21 @@ def step(self): self.initialized_prev = initialized + def read_parameters(self, parameter_updater: ParameterUpdater) -> None: + self.is_metric = parameter_updater.get_param_value('is_metric') + self.experimental_mode = parameter_updater.get_param_value('experimental_mode') + def card_thread(self): - parameter_updater = ParameterUpdater() + params_to_update = { + 'IsMetric': 'bool', + 'ExperimentalMode': 'bool', + } + parameter_updater = ParameterUpdater(params_to_update) + parameter_updater.start() + try: while True: - self.is_metric = parameter_updater.get_param_value('is_metric') - self.experimental_mode = parameter_updater.get_param_value('experimental_mode') - + self.read_parameters(parameter_updater) self.step() self.rk.monitor_time() finally: diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index d24939884d5798..633cd53ab73e21 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 import os -import time -import threading import cereal.messaging as messaging @@ -10,6 +8,7 @@ from panda import ALTERNATIVE_EXPERIENCE +from openpilot.common.parameter_updater import ParameterUpdater from openpilot.common.params import Params from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper, DT_CTRL from openpilot.common.swaglog import cloudlog @@ -84,7 +83,7 @@ def __init__(self, CP=None): ignore_valid=ignore, frequency=int(1/DT_CTRL)) # read params - self.is_metric = self.params.get_bool("IsMetric") + self.is_metric = False self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled") car_recognized = self.CP.carName != 'mock' @@ -111,7 +110,7 @@ def __init__(self, CP=None): self.logged_comm_issue = None self.not_running_prev = None self.experimental_mode = False - self.personality = self.read_personality_param() + self.personality = log.LongitudinalPersonality.standard self.recalibrating_seen = False self.state_machine = StateMachine() self.rk = Ratekeeper(100, print_delay_threshold=None) @@ -462,30 +461,30 @@ def step(self): self.CS_prev = CS - def read_personality_param(self): + def read_parameters(self, parameter_updater: ParameterUpdater) -> None: + self.is_metric = parameter_updater.get_param_value("IsMetric") + self.experimental_mode = parameter_updater.get_param_value("ExperimentalMode") and self.CP.openpilotLongitudinalControl try: - return int(self.params.get('LongitudinalPersonality')) + self.personality = int(parameter_updater.get_param_value('LongitudinalPersonality')) except (ValueError, TypeError): - return log.LongitudinalPersonality.standard - - def params_thread(self, evt): - while not evt.is_set(): - self.is_metric = self.params.get_bool("IsMetric") - self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl - self.personality = self.read_personality_param() - time.sleep(0.1) + self.personality = log.LongitudinalPersonality.standard def run(self): - e = threading.Event() - t = threading.Thread(target=self.params_thread, args=(e, )) + params_to_update = { + 'IsMetric': 'bool', + 'ExperimentalMode': 'bool', + 'LongitudinalPersonality': 'str' + } + parameter_updater = ParameterUpdater(params_to_update) + parameter_updater.start() + try: - t.start() while True: + self.read_parameters(parameter_updater) self.step() self.rk.monitor_time() finally: - e.set() - t.join() + parameter_updater.stop() def main(): From c1d46b7d1e9e20d043a581d2022bb293d4d47e8c Mon Sep 17 00:00:00 2001 From: deanlee Date: Mon, 9 Dec 2024 04:25:38 +0800 Subject: [PATCH 5/7] add configurable update interva --- common/parameter_updater.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/parameter_updater.py b/common/parameter_updater.py index bc9f3f0af47c9d..30885b790f6381 100644 --- a/common/parameter_updater.py +++ b/common/parameter_updater.py @@ -5,7 +5,7 @@ class ParameterUpdater: - def __init__(self, params_to_update: dict[str, str]): + def __init__(self, params_to_update: dict[str, str], update_interval: float = 0.1): """ params_to_update: A dictionary where keys are parameter names, and values are their types ('bool' or 'str'). Example: {"IsMetric": "bool", "LongitudinalPersonality": "str"} @@ -13,6 +13,7 @@ def __init__(self, params_to_update: dict[str, str]): self.params = Params() self.params_to_update = params_to_update self.param_values = {param: None for param in params_to_update} + self.update_interval = update_interval self._update() # Initial update @@ -50,4 +51,4 @@ def _update(self): def _update_periodically(self): while not self.stop_event.is_set(): self._update() - time.sleep(0.1) + time.sleep(self.update_interval) From a5216a53b2d31a373d305418a507feb81b47f869 Mon Sep 17 00:00:00 2001 From: deanlee Date: Mon, 9 Dec 2024 11:20:21 +0800 Subject: [PATCH 6/7] simplify --- common/parameter_updater.py | 52 +++++++++++++++--------------- selfdrive/car/card.py | 22 +++---------- selfdrive/selfdrived/selfdrived.py | 29 ++++------------- 3 files changed, 37 insertions(+), 66 deletions(-) diff --git a/common/parameter_updater.py b/common/parameter_updater.py index 30885b790f6381..d3c37d46cdd17b 100644 --- a/common/parameter_updater.py +++ b/common/parameter_updater.py @@ -5,50 +5,50 @@ class ParameterUpdater: - def __init__(self, params_to_update: dict[str, str], update_interval: float = 0.1): - """ - params_to_update: A dictionary where keys are parameter names, and values are their types ('bool' or 'str'). - Example: {"IsMetric": "bool", "LongitudinalPersonality": "str"} - """ + def __init__(self, params_to_update: list[str], update_interval: float = 0.1): self.params = Params() self.params_to_update = params_to_update - self.param_values = {param: None for param in params_to_update} + self.param_values: dict[str, str | None] = {} self.update_interval = update_interval - - self._update() # Initial update - self.mutex = threading.Lock() self.stop_event = threading.Event() self.update_thread: threading.Thread | None = None - def start(self): + # Initial update + self._update() + + def get(self, param: str) -> str | None: + with self.mutex: + return self.param_values[param] + + def get_bool(self, param: str) -> bool: + return self.get(param) == '1' + + def get_int(self, param: str, def_val: int = 0) -> int: + value = self.get(param) + try: + return int(value) if value is not None else def_val + except (ValueError, TypeError): + return def_val + + def start(self) -> None: if self.update_thread is None: + self.stop_event.clear() self.update_thread = threading.Thread(target=self._update_periodically, daemon=True) self.update_thread.start() - def stop(self): + def stop(self) -> None: if self.update_thread: self.stop_event.set() self.update_thread.join() + self.update_thread = None - def get_param_value(self, param: str): - with self.mutex: - return self.param_values.get(param) - - def _update(self): - new_values: dict[str, bool | str | None] = {} - for param, param_type in self.params_to_update.items(): - if param_type == "bool": - new_values[param] = self.params.get_bool(param) - elif param_type == "str": - new_values[param] = self.params.get(param) - else: - raise ValueError(f"Unsupported type {param_type} for parameter {param}") - + def _update(self) -> None: + new_values = {param: self.params.get(param) for param in self.params_to_update} with self.mutex: self.param_values = new_values - def _update_periodically(self): + def _update_periodically(self) -> None: while not self.stop_event.is_set(): self._update() time.sleep(self.update_interval) diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 6d6ea4e878a56f..4819e8a5e93c5e 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -149,8 +149,7 @@ def __init__(self, CI=None, RI=None) -> None: self.mock_carstate = MockCarState() self.v_cruise_helper = VCruiseHelper(self.CP) - self.is_metric = False - self.experimental_mode = False + self.parameter_updater = ParameterUpdater(['IsMetric', 'ExperimentalMode']) # card is driven by can recv, expected at 100Hz self.rk = Ratekeeper(100, print_delay_threshold=None) @@ -181,7 +180,7 @@ def state_update(self) -> tuple[car.CarState, structs.RadarDataT | None]: self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime # TODO: mirror the carState.cruiseState struct? - self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.is_metric) + self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.parameter_updater.get_bool('IsMetric')) CS.vCruise = float(self.v_cruise_helper.v_cruise_kph) CS.vCruiseCluster = float(self.v_cruise_helper.v_cruise_cluster_kph) @@ -239,7 +238,7 @@ def step(self): CS, RD = self.state_update() if self.sm['carControl'].enabled and not self.CC_prev.enabled: - self.v_cruise_helper.initialize_v_cruise(CS, self.experimental_mode) + self.v_cruise_helper.initialize_v_cruise(CS, self.parameter_updater.get_bool('ExperimentalMode')) self.state_publish(CS, RD) @@ -250,25 +249,14 @@ def step(self): self.initialized_prev = initialized - def read_parameters(self, parameter_updater: ParameterUpdater) -> None: - self.is_metric = parameter_updater.get_param_value('is_metric') - self.experimental_mode = parameter_updater.get_param_value('experimental_mode') - def card_thread(self): - params_to_update = { - 'IsMetric': 'bool', - 'ExperimentalMode': 'bool', - } - parameter_updater = ParameterUpdater(params_to_update) - parameter_updater.start() - try: + self.parameter_updater.start() while True: - self.read_parameters(parameter_updater) self.step() self.rk.monitor_time() finally: - parameter_updater.stop() + self.parameter_updater.stop() def main(): diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 633cd53ab73e21..e189df66d5d630 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -82,8 +82,7 @@ def __init__(self, CP=None): ignore_alive=ignore, ignore_avg_freq=ignore+['radarState',], ignore_valid=ignore, frequency=int(1/DT_CTRL)) - # read params - self.is_metric = False + self.parameter_updater = ParameterUpdater(['IsMetric', 'ExperimentalMode', 'LongitudinalPersonality']) self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled") car_recognized = self.CP.carName != 'mock' @@ -109,7 +108,6 @@ def __init__(self, CP=None): self.events_prev = [] self.logged_comm_issue = None self.not_running_prev = None - self.experimental_mode = False self.personality = log.LongitudinalPersonality.standard self.recalibrating_seen = False self.state_machine = StateMachine() @@ -416,7 +414,7 @@ def update_alerts(self, CS): clear_event_types.add(ET.NO_ENTRY) pers = LONGITUDINAL_PERSONALITY_MAP[self.personality] - alerts = self.events.create_alerts(self.state_machine.current_alert_types, [self.CP, CS, self.sm, self.is_metric, + alerts = self.events.create_alerts(self.state_machine.current_alert_types, [self.CP, CS, self.sm, self.parameter_updater.get_bool("IsMetric"), self.state_machine.soft_disable_timer, pers]) self.AM.add_many(self.sm.frame, alerts) self.AM.process_alerts(self.sm.frame, clear_event_types) @@ -430,7 +428,7 @@ def publish_selfdriveState(self, CS): ss.active = self.active ss.state = self.state_machine.state ss.engageable = not self.events.contains(ET.NO_ENTRY) - ss.experimentalMode = self.experimental_mode + ss.experimentalMode = self.parameter_updater.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl ss.personality = self.personality ss.alertText1 = self.AM.current_alert.alert_text_1 @@ -461,30 +459,15 @@ def step(self): self.CS_prev = CS - def read_parameters(self, parameter_updater: ParameterUpdater) -> None: - self.is_metric = parameter_updater.get_param_value("IsMetric") - self.experimental_mode = parameter_updater.get_param_value("ExperimentalMode") and self.CP.openpilotLongitudinalControl - try: - self.personality = int(parameter_updater.get_param_value('LongitudinalPersonality')) - except (ValueError, TypeError): - self.personality = log.LongitudinalPersonality.standard - def run(self): - params_to_update = { - 'IsMetric': 'bool', - 'ExperimentalMode': 'bool', - 'LongitudinalPersonality': 'str' - } - parameter_updater = ParameterUpdater(params_to_update) - parameter_updater.start() - try: + self.parameter_updater.start() while True: - self.read_parameters(parameter_updater) + self.personality = self.parameter_updater.get_int('LongitudinalPersonality', log.LongitudinalPersonality.standard) self.step() self.rk.monitor_time() finally: - parameter_updater.stop() + self.parameter_updater.stop() def main(): From d7400d589f5f7a0871c9f6b4e579382a321da3fd Mon Sep 17 00:00:00 2001 From: deanlee Date: Mon, 9 Dec 2024 12:36:02 +0800 Subject: [PATCH 7/7] add test case --- common/parameter_updater.py | 2 +- common/tests/test_params.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/common/parameter_updater.py b/common/parameter_updater.py index d3c37d46cdd17b..927522ebbc73d5 100644 --- a/common/parameter_updater.py +++ b/common/parameter_updater.py @@ -22,7 +22,7 @@ def get(self, param: str) -> str | None: return self.param_values[param] def get_bool(self, param: str) -> bool: - return self.get(param) == '1' + return self.get(param) == b'1' def get_int(self, param: str, def_val: int = 0) -> int: value = self.get(param) diff --git a/common/tests/test_params.py b/common/tests/test_params.py index 16cbc45295d527..5b5bccfe43c517 100644 --- a/common/tests/test_params.py +++ b/common/tests/test_params.py @@ -5,6 +5,7 @@ import uuid from openpilot.common.params import Params, ParamKeyType, UnknownKeyName +from openpilot.common.parameter_updater import ParameterUpdater class TestParams: def setup_method(self): @@ -100,6 +101,18 @@ def _delayed_writer(): assert q.get("CarParams") is None assert q.get("CarParams", True) == b"1" + def test_parameter_updater(self): + parameter_updater = ParameterUpdater(["DongleId", "CarParams", "IsMetric"]) + parameter_updater.start() + Params().put("DongleId", "cb38263377b873ee") + Params().put("CarParams", "123") + Params().put_bool("IsMetric", True) + time.sleep(0.2) + assert parameter_updater.get("DongleId") == b'cb38263377b873ee' + assert parameter_updater.get_bool("IsMetric") is True + assert parameter_updater.get_int("CarParams") == 123 + parameter_updater.stop() + def test_params_all_keys(self): keys = Params().all_keys()