diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 46ecbeb8ce..d7ef691c83 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -80,10 +80,9 @@ repos: rev: '1.6.0' hooks: - id: poetry-check - - id: poetry-lock name: validate poetry lock args: - - --check + - --lock - repo: https://github.com/python-jsonschema/check-jsonschema rev: 0.26.3 hooks: diff --git a/cereal b/cereal index 95485f268c..6bd65e7c7f 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 95485f268cacb16186163744224c9dd8644ecd49 +Subproject commit 6bd65e7c7f2692d15a9b6cc97bad9345f9089c4d diff --git a/docs/CARS.md b/docs/CARS.md index 8bb318c13e..c7a2e849de 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -119,7 +119,7 @@ A supported vehicle is one that just works when you install a comma device. All |Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai G connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|Forte 2023|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai E connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|K5 2021-22|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Kia|K5 Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|K8 Hybrid (with HDA II) 2023[6](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|Niro EV 2019|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai H connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|Niro EV 2020|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai F connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| diff --git a/poetry.lock b/poetry.lock index da870f8cba..ecda132612 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1578,13 +1578,13 @@ files = [ [[package]] name = "hypothesis" -version = "6.46.7" +version = "6.47.5" description = "A library for property-based testing" optional = false python-versions = ">=3.7" files = [ - {file = "hypothesis-6.46.7-py3-none-any.whl", hash = "sha256:2696cdb9005946bf1d2b215cc91d3fc01625e3342eb8743ddd04b667b2f1882b"}, - {file = "hypothesis-6.46.7.tar.gz", hash = "sha256:967009fa561b3a3f8363a73d71923357271c37dc7fa27b30c2d21a1b6092b240"}, + {file = "hypothesis-6.47.5-py3-none-any.whl", hash = "sha256:87049b781ee11ec1c7948565b889ab02e428a1e32d427ab4de8fdb3649242d06"}, + {file = "hypothesis-6.47.5.tar.gz", hash = "sha256:e0c1e253fc97e7ecdb9e2bbff2cf815d8739e0d1d3d093d67c3af5bb6a7211b0"}, ] [package.dependencies] @@ -5106,4 +5106,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "~3.11" -content-hash = "80bd9226bb8fc61c75fe8047c55ba2da3919bc8d9b32a8154ec0a40f9fe2a18e" +content-hash = "f159e93b7b57c4fad45a063d96ef97b01697fc811a51f968c7757b05808cee1c" diff --git a/pyproject.toml b/pyproject.toml index bc28ed1da1..d5302c1184 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -127,7 +127,7 @@ carla = { url = "https://github.com/commaai/carla/releases/download/3.11.4/carla coverage = "*" dictdiffer = "*" ft4222 = "*" -hypothesis = "==6.46.7" +hypothesis = "~6.47" inputs = "*" lru-dict = "*" markdown-it-py = "*" diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py index 899605d989..82c00b3bf2 100755 --- a/selfdrive/athena/athenad.py +++ b/selfdrive/athena/athenad.py @@ -29,7 +29,7 @@ from websocket import (ABNF, WebSocket, WebSocketException, WebSocketTimeoutExce import cereal.messaging as messaging from cereal import log -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.common.api import Api from openpilot.common.basedir import PERSIST from openpilot.common.file_helpers import CallbackReader @@ -309,7 +309,7 @@ def _do_upload(upload_item: UploadItem, callback: Optional[Callable] = None) -> # security: user should be able to request any message from their car @dispatcher.add_method def getMessage(service: str, timeout: int = 1000) -> dict: - if service is None or service not in service_list: + if service is None or service not in SERVICE_LIST: raise Exception("invalid service") socket = messaging.sub_sock(service, timeout=timeout) diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc index b64a81296e..0ec33c1a27 100644 --- a/selfdrive/boardd/boardd.cc +++ b/selfdrive/boardd/boardd.cc @@ -472,12 +472,15 @@ void panda_state_thread(std::vector pandas, bool spoofing_started) { LOGD("start panda state thread"); - // run at 2hz - RateKeeper rk("panda_state_thread", 2); + // run at 10hz + RateKeeper rk("panda_state_thread", 10); while (!do_exit && check_all_connected(pandas)) { - // send out peripheralState - send_peripheral_state(&pm, peripheral_panda); + // send out peripheralState at 2Hz + if (sm.frame % 5 == 0) { + send_peripheral_state(&pm, peripheral_panda); + } + auto ignition_opt = send_panda_states(&pm, pandas, spoofing_started); if (!ignition_opt) { diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 7dec5e3ea3..a4393037b0 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -219,7 +219,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = { HyundaiCarInfo("Kia Forte 2023", car_parts=CarParts.common([CarHarness.hyundai_e])), ], CAR.KIA_K5_2021: HyundaiCarInfo("Kia K5 2021-22", car_parts=CarParts.common([CarHarness.hyundai_a])), - CAR.KIA_K5_HEV_2020: HyundaiCarInfo("Kia K5 Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_a])), + CAR.KIA_K5_HEV_2020: HyundaiCarInfo("Kia K5 Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_a])), CAR.KIA_K8_HEV_1ST_GEN: HyundaiCarInfo("Kia K8 Hybrid (with HDA II) 2023", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])), CAR.KIA_NIRO_EV: [ HyundaiCarInfo("Kia Niro EV 2019", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", car_parts=CarParts.common([CarHarness.hyundai_h])), @@ -1392,15 +1392,18 @@ FW_VERSIONS = { ], (Ecu.eps, 0x7D4, None): [ b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L7000 4DLHC102', + b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L7220 4DLHC102', ], (Ecu.fwdCamera, 0x7C4, None): [ b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.02 99210-L2000 200309', + b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.04 99210-L2000 210527', ], (Ecu.engine, 0x7E0, None): [ b'\xf1\x87391162JLA0', ], (Ecu.transmission, 0x7E1, None): [ b'\xf1\x00PSBG2323 E08\x00\x00\x00\x00\x00\x00\x00TDL2H20KA2\xe3\xc6cz', + b'\xf1\x00PSBG2333 E16\x00\x00\x00\x00\x00\x00\x00TDL2H20KA5T\xf2\xc9\xc2', ], }, CAR.KONA_EV: { diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index 81e55e6bbc..a00b8277de 100755 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -969,7 +969,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { if __name__ == '__main__': # print all alerts by type and priority - from cereal.services import service_list + from cereal.services import SERVICE_LIST from collections import defaultdict, OrderedDict event_names = {v: k for k, v in EventName.schema.enumerants.items()} @@ -977,7 +977,7 @@ if __name__ == '__main__': CP = car.CarParams.new_message() CS = car.CarState.new_message() - sm = messaging.SubMaster(list(service_list.keys())) + sm = messaging.SubMaster(list(SERVICE_LIST.keys())) for i, alerts in EVENTS.items(): for et, alert in alerts.items(): diff --git a/selfdrive/debug/check_lag.py b/selfdrive/debug/check_lag.py index 141156db91..72d11d6eda 100755 --- a/selfdrive/debug/check_lag.py +++ b/selfdrive/debug/check_lag.py @@ -2,7 +2,7 @@ from typing import Dict import cereal.messaging as messaging -from cereal.services import service_list +from cereal.services import SERVICE_LIST TO_CHECK = ['carState'] @@ -20,7 +20,7 @@ if __name__ == "__main__": t = sm.logMonoTime[s] / 1e9 if s in prev_t: - expected = 1.0 / (service_list[s].frequency) + expected = 1.0 / (SERVICE_LIST[s].frequency) dt = t - prev_t[s] if dt > 10 * expected: print(t, s, dt) diff --git a/selfdrive/debug/count_events.py b/selfdrive/debug/count_events.py index a8af5e6fe9..a148996d94 100755 --- a/selfdrive/debug/count_events.py +++ b/selfdrive/debug/count_events.py @@ -7,7 +7,7 @@ from pprint import pprint from tqdm import tqdm from typing import List, Tuple, cast -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.tools.lib.route import Route from openpilot.tools.lib.logreader import LogReader @@ -17,7 +17,7 @@ if __name__ == "__main__": cnt_valid: Counter = Counter() cnt_events: Counter = Counter() - cams = [s for s in service_list if s.endswith('CameraState')] + cams = [s for s in SERVICE_LIST if s.endswith('CameraState')] cnt_cameras = dict.fromkeys(cams, 0) alerts: List[Tuple[float, str]] = [] @@ -62,7 +62,7 @@ if __name__ == "__main__": print("\n") print("Cameras") for k, v in cnt_cameras.items(): - s = service_list[k] + s = SERVICE_LIST[k] expected_frames = int(s.frequency * duration / cast(float, s.decimation)) print(" ", k.ljust(20), f"{v}, {v/expected_frames:.1%} of expected") diff --git a/selfdrive/debug/dump.py b/selfdrive/debug/dump.py index 8436fbd0b0..db18f4c622 100755 --- a/selfdrive/debug/dump.py +++ b/selfdrive/debug/dump.py @@ -8,7 +8,7 @@ import cereal.messaging as messaging from hexdump import hexdump from cereal import log -from cereal.services import service_list +from cereal.services import SERVICE_LIST codecs.register_error("strict", codecs.backslashreplace_errors) @@ -31,7 +31,7 @@ if __name__ == "__main__": poller = messaging.Poller() - for m in args.socket if len(args.socket) > 0 else service_list: + for m in args.socket if len(args.socket) > 0 else SERVICE_LIST: messaging.sub_sock(m, poller, addr=args.addr) values = None diff --git a/selfdrive/debug/internal/qlog_size.py b/selfdrive/debug/internal/qlog_size.py index 9b7f369525..b51cb3af2f 100755 --- a/selfdrive/debug/internal/qlog_size.py +++ b/selfdrive/debug/internal/qlog_size.py @@ -5,7 +5,7 @@ from collections import defaultdict import matplotlib.pyplot as plt -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.route import Route @@ -49,7 +49,7 @@ if __name__ == "__main__": msgs_by_type[m.which()].append(m.as_builder().to_bytes()) qlog_by_type = defaultdict(list) - for name, service in service_list.items(): + for name, service in SERVICE_LIST.items(): if service.decimation is None: continue diff --git a/selfdrive/locationd/test/test_locationd.py b/selfdrive/locationd/test/test_locationd.py index 99047c37f3..707fdd743f 100755 --- a/selfdrive/locationd/test/test_locationd.py +++ b/selfdrive/locationd/test/test_locationd.py @@ -6,7 +6,7 @@ import time import capnp import cereal.messaging as messaging -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.common.params import Params from openpilot.common.transformations.coordinates import ecef2geodetic @@ -74,8 +74,8 @@ class TestLocationdProc(unittest.TestCase): msgs = [] for sec in range(65): for name in self.LLD_MSGS: - for j in range(int(service_list[name].frequency)): - msgs.append(self.get_msg(name, int((sec + j / service_list[name].frequency) * 1e9))) + for j in range(int(SERVICE_LIST[name].frequency)): + msgs.append(self.get_msg(name, int((sec + j / SERVICE_LIST[name].frequency) * 1e9))) for msg in sorted(msgs, key=lambda x: x.logMonoTime): self.pm.send(msg.which(), msg) diff --git a/selfdrive/modeld/models/driving.h b/selfdrive/modeld/models/driving.h index de0250d212..5df172dad6 100644 --- a/selfdrive/modeld/models/driving.h +++ b/selfdrive/modeld/models/driving.h @@ -9,7 +9,7 @@ #include "selfdrive/modeld/models/commonmodel.h" #include "selfdrive/modeld/runners/run.h" -constexpr int FEATURE_LEN = 128; +constexpr int FEATURE_LEN = 512; constexpr int HISTORY_BUFFER_LEN = 99; constexpr int DESIRE_LEN = 8; constexpr int DESIRE_PRED_LEN = 4; diff --git a/selfdrive/modeld/models/supercombo.onnx b/selfdrive/modeld/models/supercombo.onnx index 88f19a7d28..d2bab40150 100644 --- a/selfdrive/modeld/models/supercombo.onnx +++ b/selfdrive/modeld/models/supercombo.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c63ea3eb6c9b5a20c7420c2dc6d6d0f80a6949a39f6d8b74e574f52734154820 -size 47654714 +oid sha256:af5b47a763454cd56a9f16ebe51dbcf54a001898444a9557b39cedb2303d4da3 +size 52272357 diff --git a/selfdrive/test/process_replay/model_replay_ref_commit b/selfdrive/test/process_replay/model_replay_ref_commit index e80315133f..8ae7d62a04 100644 --- a/selfdrive/test/process_replay/model_replay_ref_commit +++ b/selfdrive/test/process_replay/model_replay_ref_commit @@ -1 +1 @@ -4f59f5945633f7a6e54e6f0fcd8ecf0baafa28cd +2af877ca0ce6996a4c1cf54cd11abf5a1f4e0576 diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index eb49d0dedb..753262af12 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -14,7 +14,7 @@ import capnp import cereal.messaging as messaging from cereal import car -from cereal.services import service_list +from cereal.services import SERVICE_LIST from cereal.visionipc import VisionIpcServer, get_endpoint_name as vipc_get_endpoint_name from openpilot.common.params import Params from openpilot.common.prefix import OpenpilotPrefix @@ -364,7 +364,7 @@ def controlsd_rcv_callback(msg, cfg, frame): socks = [ s for s in cfg.subs if - frame % int(service_list[msg.which()].frequency / service_list[s].frequency) == 0 + frame % int(SERVICE_LIST[msg.which()].frequency / SERVICE_LIST[s].frequency) == 0 ] if "sendcan" in socks and (frame - 1) < 2000: socks.remove("sendcan") @@ -428,7 +428,7 @@ class FrequencyBasedRcvCallback: resp_sockets = [ s for s in cfg.subs - if frame % max(1, int(service_list[msg.which()].frequency / service_list[s].frequency)) == 0 + if frame % max(1, int(SERVICE_LIST[msg.which()].frequency / SERVICE_LIST[s].frequency)) == 0 ] return bool(len(resp_sockets)) diff --git a/selfdrive/test/profiling/lib.py b/selfdrive/test/profiling/lib.py index 843bf52211..7f3b0126ff 100644 --- a/selfdrive/test/profiling/lib.py +++ b/selfdrive/test/profiling/lib.py @@ -1,5 +1,5 @@ from collections import defaultdict, deque -from cereal.services import service_list +from cereal.services import SERVICE_LIST import cereal.messaging as messaging import capnp @@ -67,7 +67,7 @@ class SubMaster(messaging.SubMaster): self.msgs = list(reversed(self.msgs)) for s in services: - self.freq[s] = service_list[s].frequency + self.freq[s] = SERVICE_LIST[s].frequency try: data = messaging.new_message(s) except capnp.lib.capnp.KjException: diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 553ef1afa6..894ab15c12 100755 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -13,7 +13,7 @@ from pathlib import Path from cereal import car import cereal.messaging as messaging -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.common.basedir import BASEDIR from openpilot.common.timeout import Timeout from openpilot.common.params import Params @@ -179,7 +179,7 @@ class TestOnroad(unittest.TestCase): continue with self.subTest(service=s): - assert len(msgs) >= math.floor(service_list[s].frequency*55) + assert len(msgs) >= math.floor(SERVICE_LIST[s].frequency*55) def test_cloudlog_size(self): msgs = [m for m in self.lr if m.which() == 'logMessage'] @@ -356,7 +356,7 @@ class TestOnroad(unittest.TestCase): raise Exception(f"missing {s}") ts = np.diff(msgs) / 1e9 - dt = 1 / service_list[s].frequency + dt = 1 / SERVICE_LIST[s].frequency try: np.testing.assert_allclose(np.mean(ts), dt, rtol=0.03, err_msg=f"{s} - failed mean timing check") diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 32cfe11c39..3ccb9349e1 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -13,6 +13,7 @@ import psutil import cereal.messaging as messaging from cereal import log +from cereal.services import SERVICE_LIST from openpilot.common.dict_helpers import strip_deprecated_keys from openpilot.common.time import MIN_DATE from openpilot.common.filter_simple import FirstOrderFilter @@ -33,7 +34,7 @@ NetworkStrength = log.DeviceState.NetworkStrength CURRENT_TAU = 15. # 15s time constant TEMP_TAU = 5. # 5s time constant DISCONNECT_TIMEOUT = 5. # wait 5 seconds before going offroad after disconnect so you get an alert -PANDA_STATES_TIMEOUT = int(1000 * 1.5 * DT_TRML) # 1.5x the expected pandaState frequency +PANDA_STATES_TIMEOUT = round(1000 / SERVICE_LIST['pandaStates'].frequency * 1.5) # 1.5x the expected pandaState frequency ThermalBand = namedtuple("ThermalBand", ['min_temp', 'max_temp']) HardwareState = namedtuple("HardwareState", ['network_type', 'network_info', 'network_strength', 'network_stats', @@ -210,6 +211,10 @@ def thermald_thread(end_event, hw_queue) -> None: while not end_event.is_set(): sm.update(PANDA_STATES_TIMEOUT) + # Run at 2Hz + if sm.frame % round(SERVICE_LIST['pandaStates'].frequency * DT_TRML) != 0: + continue + pandaStates = sm['pandaStates'] peripheralState = sm['peripheralState'] peripheral_panda_present = peripheralState.pandaType != log.PandaState.PandaType.unknown diff --git a/system/camerad/test/test_camerad.py b/system/camerad/test/test_camerad.py index b2aca850d1..b680c1df67 100755 --- a/system/camerad/test/test_camerad.py +++ b/system/camerad/test/test_camerad.py @@ -6,7 +6,7 @@ from collections import defaultdict import cereal.messaging as messaging from cereal import log -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.selfdrive.manager.process_config import managed_processes from openpilot.system.hardware import TICI @@ -43,10 +43,10 @@ class TestCamerad(unittest.TestCase): for cam, msgs in cls.logs.items(): if cls.sensor_type is None: cls.sensor_type = getattr(msgs[0], msgs[0].which()).sensor.raw - expected_frames = service_list[cam].frequency * TEST_TIMESPAN + expected_frames = SERVICE_LIST[cam].frequency * TEST_TIMESPAN assert expected_frames*0.95 < len(msgs) < expected_frames*1.05, f"unexpected frame count {cam}: {expected_frames=}, got {len(msgs)}" - dts = np.abs(np.diff([getattr(m, m.which()).timestampSof/1e6 for m in msgs]) - 1000/service_list[cam].frequency) + dts = np.abs(np.diff([getattr(m, m.which()).timestampSof/1e6 for m in msgs]) - 1000/SERVICE_LIST[cam].frequency) assert (dts < FRAME_DELTA_TOLERANCE[cls.sensor_type]).all(), f"{cam} dts(ms) out of spec: max diff {dts.max()}, 99 percentile {np.percentile(dts, 99)}" for m in msgs: diff --git a/system/hardware/tici/tests/test_power_draw.py b/system/hardware/tici/tests/test_power_draw.py index fbca95f6f6..1409e43cfb 100755 --- a/system/hardware/tici/tests/test_power_draw.py +++ b/system/hardware/tici/tests/test_power_draw.py @@ -8,7 +8,7 @@ from tabulate import tabulate from typing import List import cereal.messaging as messaging -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.system.hardware import HARDWARE, TICI from openpilot.system.hardware.tici.power_monitor import get_power from openpilot.selfdrive.manager.process_config import managed_processes @@ -91,7 +91,7 @@ class TestPowerDraw(unittest.TestCase): cur = used[proc.name] expected = proc.power msgs_received = sum(msg_counts[msg] for msg in proc.msgs) - msgs_expected = int(sum(SAMPLE_TIME * service_list[msg].frequency for msg in proc.msgs)) + msgs_expected = int(sum(SAMPLE_TIME * SERVICE_LIST[msg].frequency for msg in proc.msgs)) tab.append([proc.name, round(expected, 2), round(cur, 2), msgs_expected, msgs_received]) with self.subTest(proc=proc.name): self.assertTrue(math.isclose(cur, expected, rel_tol=proc.rtol, abs_tol=proc.atol)) diff --git a/system/loggerd/tests/test_loggerd.py b/system/loggerd/tests/test_loggerd.py index 3ea29b0d82..9d7d3fa7bd 100755 --- a/system/loggerd/tests/test_loggerd.py +++ b/system/loggerd/tests/test_loggerd.py @@ -12,7 +12,7 @@ from typing import Dict, List import cereal.messaging as messaging from cereal import log -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.common.basedir import BASEDIR from openpilot.common.params import Params from openpilot.common.timeout import Timeout @@ -27,8 +27,8 @@ from openpilot.common.transformations.camera import tici_f_frame_size, tici_d_fr SentinelType = log.Sentinel.SentinelType -CEREAL_SERVICES = [f for f in log.Event.schema.union_fields if f in service_list - and service_list[f].should_log and "encode" not in f.lower()] +CEREAL_SERVICES = [f for f in log.Event.schema.union_fields if f in SERVICE_LIST + and SERVICE_LIST[f].should_log and "encode" not in f.lower()] class TestLoggerd(unittest.TestCase): @@ -219,8 +219,8 @@ class TestLoggerd(unittest.TestCase): self.assertEqual(expected_val, bootlog_val) def test_qlog(self): - qlog_services = [s for s in CEREAL_SERVICES if service_list[s].decimation is not None] - no_qlog_services = [s for s in CEREAL_SERVICES if service_list[s].decimation is None] + qlog_services = [s for s in CEREAL_SERVICES if SERVICE_LIST[s].decimation is not None] + no_qlog_services = [s for s in CEREAL_SERVICES if SERVICE_LIST[s].decimation is None] services = random.sample(qlog_services, random.randint(2, min(10, len(qlog_services)))) + \ random.sample(no_qlog_services, random.randint(2, min(10, len(no_qlog_services)))) @@ -245,7 +245,7 @@ class TestLoggerd(unittest.TestCase): self.assertEqual(recv_cnt, 0, f"got {recv_cnt} {s} msgs in qlog") else: # check logged message count matches decimation - expected_cnt = (len(msgs) - 1) // service_list[s].decimation + 1 + expected_cnt = (len(msgs) - 1) // SERVICE_LIST[s].decimation + 1 self.assertEqual(recv_cnt, expected_cnt, f"expected {expected_cnt} msgs for {s}, got {recv_cnt}") def test_rlog(self): diff --git a/system/proclogd/tests/test_proclog.cc b/system/proclogd/tests/test_proclog.cc index 33fccd4f30..20298cd3d8 100644 --- a/system/proclogd/tests/test_proclog.cc +++ b/system/proclogd/tests/test_proclog.cc @@ -33,15 +33,16 @@ TEST_CASE("Parser::procStat") { SECTION("all processes") { std::vector pids = Parser::pids(); REQUIRE(pids.size() > 1); - int parsed_cnt = 0; for (int pid : pids) { - if (auto stat = Parser::procStat(util::read_file("/proc/" + std::to_string(pid) + "/stat"))) { + std::string stat_path = "/proc/" + std::to_string(pid) + "/stat"; + INFO(stat_path); + if (auto stat = Parser::procStat(util::read_file(stat_path))) { REQUIRE(stat->pid == pid); REQUIRE(allowed_states.find(stat->state) != std::string::npos); - ++parsed_cnt; + } else { + REQUIRE(util::file_exists(stat_path) == false); } } - REQUIRE(parsed_cnt == pids.size()); } } @@ -109,8 +110,6 @@ TEST_CASE("Parser::cmdline") { } TEST_CASE("buildProcLogerMessage") { - std::vector current_pids = Parser::pids(); - MessageBuilder msg; buildProcLogMessage(msg); @@ -131,10 +130,7 @@ TEST_CASE("buildProcLogerMessage") { // test cereal::ProcLog::Process auto procs = log.getProcs(); - REQUIRE(procs.size() == current_pids.size()); - for (auto p : procs) { - REQUIRE_THAT(current_pids, Catch::Matchers::VectorContains(p.getPid())); REQUIRE(allowed_states.find(p.getState()) != std::string::npos); if (p.getPid() == ::getpid()) { REQUIRE(p.getName() == "test_proclog"); @@ -147,8 +143,11 @@ TEST_CASE("buildProcLogerMessage") { std::ifstream stream(cmd_path); auto cmdline = Parser::cmdline(stream); REQUIRE(cmdline.size() == p.getCmdline().size()); - for (int i = 0; i < p.getCmdline().size(); ++i) { - REQUIRE(cmdline[i] == p.getCmdline()[i].cStr()); + // do not check the cmdline of pytest as it will change. + if (cmdline.size() > 0 && cmdline[0].find("[pytest") != 0) { + for (int i = 0; i < p.getCmdline().size(); ++i) { + REQUIRE(cmdline[i] == p.getCmdline()[i].cStr()); + } } } } diff --git a/system/sensord/tests/test_pigeond.py b/system/sensord/tests/test_pigeond.py index 90cbf06340..b23afcb07c 100755 --- a/system/sensord/tests/test_pigeond.py +++ b/system/sensord/tests/test_pigeond.py @@ -3,7 +3,7 @@ import time import unittest import cereal.messaging as messaging -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.common.gpio import gpio_read from openpilot.selfdrive.test.helpers import with_processes from openpilot.selfdrive.manager.process_config import managed_processes @@ -26,10 +26,10 @@ class TestPigeond(unittest.TestCase): sm = messaging.SubMaster(['ubloxRaw']) # setup time - for _ in range(int(5 * service_list['ubloxRaw'].frequency)): + for _ in range(int(5 * SERVICE_LIST['ubloxRaw'].frequency)): sm.update() - for _ in range(int(10 * service_list['ubloxRaw'].frequency)): + for _ in range(int(10 * SERVICE_LIST['ubloxRaw'].frequency)): sm.update() assert sm.all_checks() diff --git a/system/sensord/tests/test_sensord.py b/system/sensord/tests/test_sensord.py index dbe28ab9db..d9743a14ea 100755 --- a/system/sensord/tests/test_sensord.py +++ b/system/sensord/tests/test_sensord.py @@ -7,7 +7,7 @@ from collections import namedtuple, defaultdict import cereal.messaging as messaging from cereal import log -from cereal.services import service_list +from cereal.services import SERVICE_LIST from openpilot.common.gpio import get_irqs_for_action from openpilot.common.timeout import Timeout from openpilot.system.hardware import TICI @@ -172,7 +172,7 @@ class TestSensord(unittest.TestCase): for s, msgs in self.events.items(): with self.subTest(sensor=s): freq = len(msgs) / self.sample_secs - ef = service_list[s].frequency + ef = SERVICE_LIST[s].frequency assert ef*0.85 <= freq <= ef*1.15 def test_logmonottime_timestamp_diff(self): diff --git a/tools/sim/bridge/carla.py b/tools/sim/bridge/carla.py index df25734e19..ffb0d11b44 100644 --- a/tools/sim/bridge/carla.py +++ b/tools/sim/bridge/carla.py @@ -7,20 +7,49 @@ from openpilot.tools.sim.lib.camerad import W, H class CarlaWorld(World): - def __init__(self, world, vehicle, high_quality=False, dual_camera=False): + def __init__(self, client, high_quality, dual_camera, num_selected_spawn_point, town): super().__init__(dual_camera) import carla + + low_quality_layers = carla.MapLayer(carla.MapLayer.Ground | carla.MapLayer.Walls | carla.MapLayer.Decals) + + layers = carla.MapLayer.All if high_quality else low_quality_layers + + world = client.load_world(town, map_layers=layers) + + settings = world.get_settings() + settings.fixed_delta_seconds = 0.01 + world.apply_settings(settings) + + world.set_weather(carla.WeatherParameters.ClearSunset) + self.world = world + world_map = world.get_map() + + blueprint_library = world.get_blueprint_library() + + vehicle_bp = blueprint_library.filter('vehicle.tesla.*')[1] + vehicle_bp.set_attribute('role_name', 'hero') + spawn_points = world_map.get_spawn_points() + assert len(spawn_points) > num_selected_spawn_point, \ + f'''No spawn point {num_selected_spawn_point}, try a value between 0 and {len(spawn_points)} for this town.''' + self.spawn_point = spawn_points[num_selected_spawn_point] + self.vehicle = world.spawn_actor(vehicle_bp, self.spawn_point) + + physics_control = self.vehicle.get_physics_control() + physics_control.mass = 2326 + physics_control.torque_curve = [[20.0, 500.0], [5000.0, 500.0]] + physics_control.gear_switch_time = 0.0 + self.vehicle.apply_physics_control(physics_control) + self.vc: carla.VehicleControl = carla.VehicleControl(throttle=0, steer=0, brake=0, reverse=False) - self.vehicle = vehicle - self.max_steer_angle: float = vehicle.get_physics_control().wheels[0].max_steer_angle + self.max_steer_angle: float = self.vehicle.get_physics_control().wheels[0].max_steer_angle self.params = Params() self.steer_ratio = 15 self.carla_objects = [] - blueprint_library = self.world.get_blueprint_library() transform = carla.Transform(carla.Location(x=0.8, z=1.13)) def create_camera(fov, callback): @@ -31,7 +60,7 @@ class CarlaWorld(World): blueprint.set_attribute('sensor_tick', str(1/20)) if not high_quality: blueprint.set_attribute('enable_postprocess_effects', 'False') - camera = world.spawn_actor(blueprint, transform, attach_to=vehicle) + camera = world.spawn_actor(blueprint, transform, attach_to=self.vehicle) camera.listen(callback) return camera @@ -44,13 +73,13 @@ class CarlaWorld(World): # re-enable IMU imu_bp = blueprint_library.find('sensor.other.imu') imu_bp.set_attribute('sensor_tick', '0.01') - self.imu = world.spawn_actor(imu_bp, transform, attach_to=vehicle) + self.imu = world.spawn_actor(imu_bp, transform, attach_to=self.vehicle) gps_bp = blueprint_library.find('sensor.other.gnss') - self.gps = world.spawn_actor(gps_bp, transform, attach_to=vehicle) + self.gps = world.spawn_actor(gps_bp, transform, attach_to=self.vehicle) self.params.put_bool("UbloxAvailable", True) - self.carla_objects = [self.imu, self.gps, self.road_camera, self.road_wide_camera] + self.carla_objects = [self.imu, self.gps, self.road_camera, self.road_wide_camera, self.vehicle] def close(self): for s in self.carla_objects: @@ -110,6 +139,12 @@ class CarlaWorld(World): def tick(self): self.world.tick() + def reset(self): + import carla + + self.vehicle.set_transform(self.spawn_point) + self.vehicle.set_target_velocity(carla.Vector3D()) + class CarlaBridge(SimulatorBridge): TICKS_PER_FRAME = 5 @@ -126,38 +161,5 @@ class CarlaBridge(SimulatorBridge): client = carla.Client(self.host, self.port) client.set_timeout(5) - world = client.load_world(self.town) - - settings = world.get_settings() - settings.fixed_delta_seconds = 0.01 - world.apply_settings(settings) - - world.set_weather(carla.WeatherParameters.ClearSunset) - - if not self.high_quality: - world.unload_map_layer(carla.MapLayer.Foliage) - world.unload_map_layer(carla.MapLayer.Buildings) - world.unload_map_layer(carla.MapLayer.ParkedVehicles) - world.unload_map_layer(carla.MapLayer.Props) - world.unload_map_layer(carla.MapLayer.StreetLights) - world.unload_map_layer(carla.MapLayer.Particles) - - blueprint_library = world.get_blueprint_library() - - world_map = world.get_map() - - vehicle_bp = blueprint_library.filter('vehicle.tesla.*')[1] - vehicle_bp.set_attribute('role_name', 'hero') - spawn_points = world_map.get_spawn_points() - assert len(spawn_points) > self.num_selected_spawn_point, \ - f'''No spawn point {self.num_selected_spawn_point}, try a value between 0 and {len(spawn_points)} for this town.''' - spawn_point = spawn_points[self.num_selected_spawn_point] - vehicle = world.spawn_actor(vehicle_bp, spawn_point) - - physics_control = vehicle.get_physics_control() - physics_control.mass = 2326 - physics_control.torque_curve = [[20.0, 500.0], [5000.0, 500.0]] - physics_control.gear_switch_time = 0.0 - vehicle.apply_physics_control(physics_control) - - return CarlaWorld(world, vehicle, dual_camera=self.dual_camera) \ No newline at end of file + return CarlaWorld(client, high_quality=self.high_quality, dual_camera=self.dual_camera, + num_selected_spawn_point=self.num_selected_spawn_point, town=self.town) \ No newline at end of file diff --git a/tools/sim/bridge/common.py b/tools/sim/bridge/common.py index 360fdc0e68..4e800226fb 100644 --- a/tools/sim/bridge/common.py +++ b/tools/sim/bridge/common.py @@ -127,6 +127,8 @@ class SimulatorBridge(ABC): self.simulator_state.cruise_button = CruiseButtons.MAIN elif m[0] == "ignition": self.simulator_state.ignition = not self.simulator_state.ignition + elif m[0] == "reset": + self.world.reset() elif m[0] == "quit": break diff --git a/tools/sim/bridge/metadrive.py b/tools/sim/bridge/metadrive.py index f7b937359e..5814364be1 100644 --- a/tools/sim/bridge/metadrive.py +++ b/tools/sim/bridge/metadrive.py @@ -81,8 +81,11 @@ class MetaDriveWorld(World): obs, _, terminated, _, info = self.env.step(self.vc) if terminated: - self.env.reset() - self.reset_time = time.monotonic() + self.reset() + + def reset(self): + self.env.reset() + self.reset_time = time.monotonic() def close(self): pass diff --git a/tools/sim/lib/common.py b/tools/sim/lib/common.py index 3de89f39fc..19012b1c2d 100644 --- a/tools/sim/lib/common.py +++ b/tools/sim/lib/common.py @@ -83,4 +83,8 @@ class World(ABC): @abstractmethod def close(self): + pass + + @abstractmethod + def reset(self): pass \ No newline at end of file diff --git a/tools/sim/lib/keyboard_ctrl.py b/tools/sim/lib/keyboard_ctrl.py index 57d5834026..f8b3517fde 100644 --- a/tools/sim/lib/keyboard_ctrl.py +++ b/tools/sim/lib/keyboard_ctrl.py @@ -55,6 +55,8 @@ def keyboard_poll_thread(q: 'Queue[str]'): q.put("steer_%f" % -0.15) elif c == 'i': q.put("ignition") + elif c == 'r': + q.put("reset") elif c == 'q': q.put("quit") break