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|[](##)|[](##)|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|[](##)|[](##)|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|[](##)|[](##)|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|[](##)|[](##)|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|[](##)|[](##)|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|[](##)|[](##)|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|[](##)|[](##)|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|[](##)|[](##)|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