* lil more ruff

* no exclusions!

* rm nb exception

* and generated

* not used

* c408

* random

* all

* unittest is fine
This commit is contained in:
Adeeb Shihadeh
2026-07-19 08:51:16 -07:00
committed by GitHub
parent 7d74c3c99b
commit e475d10adc
26 changed files with 136 additions and 116 deletions
+55 -24
View File
@@ -7,12 +7,43 @@ import os
import capnp
import time
from typing import Optional, List, Union, Dict
from typing import Union
from openpilot.cereal import log
from openpilot.cereal.services import SERVICE_LIST
from openpilot.common.utils import MovingAverage
__all__ = (
"NO_TRAVERSAL_LIMIT",
"Context",
"FrequencyTracker",
"IpcError",
"MultiplePublishersError",
"Poller",
"PubMaster",
"PubSocket",
"SocketEventHandle",
"SubMaster",
"SubSocket",
"delete_fake_prefix",
"drain_sock",
"drain_sock_raw",
"fake_event_handle",
"get_fake_prefix",
"log_from_bytes",
"new_message",
"pub_sock",
"recv_one",
"recv_one_or_none",
"recv_one_retry",
"recv_sock",
"reset_context",
"set_fake_prefix",
"sub_sock",
"toggle_fake_events",
"wait_for_one_event",
)
NO_TRAVERSAL_LIMIT = 2**64-1
@@ -22,8 +53,8 @@ def pub_sock(endpoint: str) -> PubSocket:
return msgq.pub_sock(endpoint, segment_size)
def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1",
conflate: bool = False, timeout: Optional[int] = None) -> SubSocket:
def sub_sock(endpoint: str, poller: Poller | None = None, addr: str = "127.0.0.1",
conflate: bool = False, timeout: int | None = None) -> SubSocket:
service = SERVICE_LIST.get(endpoint)
segment_size = service.queue_size if service else 0
return msgq.sub_sock(endpoint, poller=poller, addr=addr, conflate=conflate,
@@ -39,7 +70,7 @@ def log_from_bytes(dat: bytes, struct: capnp.lib.capnp._StructModule = log.Event
return msg
def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
def new_message(service: str | None, size: int | None = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
args = {
'valid': False,
'logMonoTime': int(time.monotonic() * 1e9),
@@ -54,14 +85,14 @@ def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) ->
return dat
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]:
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> list[capnp.lib.capnp._DynamicStructReader]:
"""Receive all message currently available on the queue"""
msgs = drain_sock_raw(sock, wait_for_one=wait_for_one)
return [log_from_bytes(m) for m in msgs]
# TODO: print when we drop packets?
def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._DynamicStructReader]:
def recv_sock(sock: SubSocket, wait: bool = False) -> capnp.lib.capnp._DynamicStructReader | None:
"""Same as drain sock, but only returns latest message. Consider using conflate instead."""
dat = None
@@ -82,14 +113,14 @@ def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._
return dat
def recv_one(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
def recv_one(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader | None:
dat = sock.receive()
if dat is not None:
dat = log_from_bytes(dat)
return dat
def recv_one_or_none(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
def recv_one_or_none(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader | None:
dat = sock.receive(non_blocking=True)
if dat is not None:
dat = log_from_bytes(dat)
@@ -148,27 +179,27 @@ class FrequencyTracker:
class SubMaster:
def __init__(self, services: List[str], poll: Optional[str] = None,
ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None,
ignore_valid: Optional[List[str]] = None, addr: str = "127.0.0.1", frequency: Optional[float] = None):
def __init__(self, services: list[str], poll: str | None = None,
ignore_alive: list[str] | None = None, ignore_avg_freq: list[str] | None = None,
ignore_valid: list[str] | None = None, addr: str = "127.0.0.1", frequency: float | None = None):
self.frame = -1
self.services = services
self.seen = {s: False for s in services}
self.updated = {s: False for s in services}
self.recv_time = {s: 0. for s in services}
self.recv_frame = {s: 0 for s in services}
self.seen = dict.fromkeys(services, False)
self.updated = dict.fromkeys(services, False)
self.recv_time = dict.fromkeys(services, 0.0)
self.recv_frame = dict.fromkeys(services, 0)
self.sock = {}
self.data = {}
self.logMonoTime = {s: 0 for s in services}
self.logMonoTime = dict.fromkeys(services, 0)
# zero-frequency / on-demand services are always alive and presumed valid; all others must pass checks
on_demand = {s: SERVICE_LIST[s].frequency <= 1e-5 for s in services}
self.static_freq_services = set(s for s in services if not on_demand[s])
self.static_freq_services = {s for s in services if not on_demand[s]}
self.alive = {s: on_demand[s] for s in services}
self.freq_ok = {s: on_demand[s] for s in services}
self.valid = {s: on_demand[s] for s in services}
self.freq_tracker: Dict[str, FrequencyTracker] = {}
self.freq_tracker: dict[str, FrequencyTracker] = {}
self.poller = Poller()
polled_services = set([poll, ] if poll is not None else services)
self.non_polled_services = set(services) - polled_services
@@ -211,7 +242,7 @@ class SubMaster:
msgs.append(recv_one_or_none(self.sock[s]))
self.update_msgs(time.monotonic(), msgs)
def update_msgs(self, cur_time: float, msgs: List[capnp.lib.capnp._DynamicStructReader]) -> None:
def update_msgs(self, cur_time: float, msgs: list[capnp.lib.capnp._DynamicStructReader]) -> None:
self.frame += 1
self.updated = dict.fromkeys(self.services, False)
for msg in msgs:
@@ -234,21 +265,21 @@ class SubMaster:
self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency) or (self.seen[s] and self.simulation)
self.freq_ok[s] = self.freq_tracker[s].valid or self.simulation
def all_alive(self, service_list: Optional[List[str]] = None) -> bool:
def all_alive(self, service_list: list[str] | None = None) -> bool:
return all(self.alive[s] for s in (service_list or self.services) if s not in self.ignore_alive)
def all_freq_ok(self, service_list: Optional[List[str]] = None) -> bool:
def all_freq_ok(self, service_list: list[str] | None = None) -> bool:
return all(self.freq_ok[s] for s in (service_list or self.services) if self._check_avg_freq(s))
def all_valid(self, service_list: Optional[List[str]] = None) -> bool:
def all_valid(self, service_list: list[str] | None = None) -> bool:
return all(self.valid[s] for s in (service_list or self.services) if s not in self.ignore_valid)
def all_checks(self, service_list: Optional[List[str]] = None) -> bool:
def all_checks(self, service_list: list[str] | None = None) -> bool:
return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list)
class PubMaster:
def __init__(self, services: List[str]):
def __init__(self, services: list[str]):
self.sock = {}
for s in services:
self.sock[s] = pub_sock(s)
@@ -1,6 +1,7 @@
import random
import time
from typing import Sized, cast
from typing import cast
from collections.abc import Sized
import openpilot.cereal.messaging as messaging
from openpilot.cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
+2 -4
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
from enum import IntEnum
from typing import Optional
# TODO: this should be automatically determined using the capnp schema
@@ -11,7 +10,7 @@ class QueueSize(IntEnum):
class Service:
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None,
def __init__(self, should_log: bool, frequency: float, decimation: int | None = None,
queue_size: QueueSize = QueueSize.SMALL):
self.should_log = should_log
self.frequency = frequency
@@ -112,8 +111,7 @@ def build_header():
for k, v in SERVICE_LIST.items():
should_log = "true" if v.should_log else "false"
decimation = -1 if v.decimation is None else v.decimation
h += ' { "%s", {"%s", %s, %f, %d, %d}},\n' % \
(k, k, should_log, v.frequency, decimation, v.queue_size)
h += f' {{ "{k}", {{"{k}", {should_log}, {v.frequency:f}, {decimation:d}, {v.queue_size:d}}}}},\n'
h += "};\n"
h += "#endif\n"
+1 -1
View File
@@ -39,7 +39,7 @@ class SwaglogRotatingFileHandler(BaseRotatingHandler):
return stream
def get_existing_logfiles(self):
log_files = list()
log_files = []
base_dir = os.path.dirname(self.base_filename)
for fn in os.listdir(base_dir):
fp = os.path.join(base_dir, fn)
+1 -1
View File
@@ -2,7 +2,7 @@ import time
import os
import pytest
import random
import unittest # noqa: TID251
import unittest
from collections import defaultdict, Counter
import hypothesis.strategies as st
from hypothesis import Phase, given, settings
@@ -7,8 +7,6 @@ from opendbc.car.lateral import get_friction, FRICTION_THRESHOLD
from openpilot.common.realtime import DT_MDL
from openpilot.selfdrive.locationd.torqued import TorqueEstimator, MIN_BUCKET_POINTS, POINTS_PER_BUCKET, STEER_BUCKET_BOUNDS
np.random.seed(0)
LA_ERR_STD = 1.0
INPUT_NOISE_STD = 0.08
V_EGO = 30.0
+2 -1
View File
@@ -69,6 +69,7 @@ class NPQueue:
class PointBuckets:
def __init__(self, x_bounds: list[tuple[float, float]], min_points: list[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None:
self._rng = np.random.default_rng()
self.x_bounds = x_bounds
self.buckets = {bounds: NPQueue(maxlen=points_per_bucket, rowsize=rowsize) for bounds in x_bounds}
self.buckets_min_points = dict(zip(x_bounds, min_points, strict=True))
@@ -98,7 +99,7 @@ class PointBuckets:
points = np.vstack([x.arr for x in self.buckets.values()])
if num_points is None:
return points
return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)]
return points[self._rng.choice(np.arange(len(points)), min(len(points), num_points), replace=False)]
def load_points(self, points: list[list[float]]) -> None:
for point in points:
@@ -81,6 +81,7 @@ class TestLagd:
assert retrieve_initial_lag(params, CP) is None
def test_ncc(self):
rng = np.random.default_rng()
lag_frames = random.randint(1, 19)
desired_sig = np.sin(np.arange(0.0, 10.0, 0.1))
@@ -91,15 +92,15 @@ class TestLagd:
assert np.argmax(corr) == lag_frames
# add some noise
desired_sig += np.random.normal(0, 0.05, len(desired_sig))
actual_sig += np.random.normal(0, 0.05, len(actual_sig))
desired_sig += rng.normal(0, 0.05, len(desired_sig))
actual_sig += rng.normal(0, 0.05, len(actual_sig))
corr = masked_normalized_cross_correlation(desired_sig, actual_sig, mask, 200)[len(desired_sig) - 1:len(desired_sig) + 20]
assert np.argmax(corr) in range(lag_frames - MAX_ERR_FRAMES, lag_frames + MAX_ERR_FRAMES + 1)
# mask out 40% of the values, and make them noise
mask = np.random.choice([True, False], size=len(desired_sig), p=[0.6, 0.4])
desired_sig[~mask] = np.random.normal(0, 1, size=np.sum(~mask))
actual_sig[~mask] = np.random.normal(0, 1, size=np.sum(~mask))
mask = rng.choice([True, False], size=len(desired_sig), p=[0.6, 0.4])
desired_sig[~mask] = rng.normal(0, 1, size=np.sum(~mask))
actual_sig[~mask] = rng.normal(0, 1, size=np.sum(~mask))
corr = masked_normalized_cross_correlation(desired_sig, actual_sig, mask, 200)[len(desired_sig) - 1:len(desired_sig) + 20]
assert np.argmax(corr) in range(lag_frames - MAX_ERR_FRAMES, lag_frames + MAX_ERR_FRAMES + 1)
+2 -2
View File
@@ -242,7 +242,7 @@ def compile_jit(jit, make_random_inputs, input_keys, make_queues):
SEED = 42
def random_inputs_run(fn, seed, test_val=None, test_buffers=None, expect_match=True):
input_queues, npy = make_queues(Device.DEFAULT)
np.random.seed(seed)
rng = np.random.default_rng(seed)
Tensor.manual_seed(seed)
testing = test_val is not None or test_buffers is not None
@@ -250,7 +250,7 @@ def compile_jit(jit, make_random_inputs, input_keys, make_queues):
for i in range(n_runs):
for v in npy.values():
v[:] = np.random.randn(*v.shape).astype(v.dtype)
v[:] = rng.standard_normal(v.shape).astype(v.dtype)
Device.default.synchronize()
random_inputs = make_random_inputs()
st = time.perf_counter()
@@ -38,10 +38,10 @@ class TestBoarddSpi:
total_recv_count = 0
total_sent_count = 0
sent_msgs = {bus: list() for bus in range(3)}
sent_msgs = {bus: [] for bus in range(3)}
st = time.monotonic()
ts = {s: list() for s in socks.keys()}
ts = {s: [] for s in socks.keys()}
for _ in range(int(os.getenv("TEST_TIME", "20"))):
# send some CAN messages
if not JUNGLE_SPAM:
+1 -1
View File
@@ -7,7 +7,7 @@ from openpilot.common.utils import tabulate
DEMO_ROUTE = "5beb9b58bd12b691/0000010a--a51155e496"
MB = 1024 * 1024
TABULATE_OPTS = dict(tablefmt="simple_grid", stralign="center", numalign="center")
TABULATE_OPTS = {"tablefmt": "simple_grid", "stralign": "center", "numalign": "center"}
def _get_procs():
@@ -1,5 +1,5 @@
import pyray as rl
from dataclasses import dataclass
from dataclasses import dataclass, field
from enum import IntEnum
from collections.abc import Callable
from openpilot.selfdrive.ui.layouts.settings.developer import DeveloperLayout
@@ -43,7 +43,7 @@ class PanelType(IntEnum):
class PanelInfo:
name: str
instance: Widget
button_rect: rl.Rectangle = rl.Rectangle(0, 0, 0, 0)
button_rect: rl.Rectangle = field(default_factory=lambda: rl.Rectangle(0, 0, 0, 0))
class SettingsLayout(Widget):
@@ -92,7 +92,7 @@ if __name__ == "__main__":
vipc.create_buffers(VisionStreamType.VISION_STREAM_ROAD, 5, W, H)
vipc.start_listener()
yuv_buffer_size = W * H + (W // 2) * (H // 2) * 2
yuv_data = np.random.randint(0, 256, yuv_buffer_size, dtype=np.uint8).tobytes()
yuv_data = np.random.default_rng().integers(0, 256, yuv_buffer_size, dtype=np.uint8).tobytes()
with cProfile.Profile() as pr:
for _ in gui_app.render():
if ui_state.sm.frame >= len(message_chunks):
@@ -437,7 +437,7 @@ class TestAthenadMethods:
thread.join()
def test_get_logs_to_send_sorted(self):
fl = list()
fl = []
for i in range(10):
file = f'swaglog.{i:010}'
self._create_file(file, Paths.swaglog_root())
@@ -18,8 +18,8 @@ class FakeLogHandler(logging.Handler):
self.reset()
def reset(self):
self.upload_order = list()
self.upload_ignored = list()
self.upload_order = []
self.upload_ignored = []
def emit(self, record):
try:
+2 -2
View File
@@ -152,7 +152,7 @@ class ShaderState:
self.initialized = False
def _configure_shader_color(state: ShaderState, color: Optional[rl.Color],
def _configure_shader_color(state: ShaderState, color: Optional[rl.Color], # noqa: UP045 # rl.Color is a function, so `rl.Color | None` fails
gradient: Gradient | None, origin_rect: rl.Rectangle):
assert (color is not None) != (gradient is not None), "Either color or gradient must be provided"
@@ -204,7 +204,7 @@ def triangulate(pts: np.ndarray) -> list[tuple[float, float]]:
def draw_polygon(origin_rect: rl.Rectangle, points: np.ndarray,
color: Optional[rl.Color] = None, gradient: Gradient | None = None):
color: Optional[rl.Color] = None, gradient: Gradient | None = None): # noqa: UP045 # rl.Color is a function, so `rl.Color | None` fails
"""
Draw a ribbon polygon (two chains) with a triangle strip and gradient.
+3 -2
View File
@@ -566,13 +566,14 @@ def webrtcd_thread(host: str, port: int, debug: bool):
http_thread.start()
shutting_down = False
shutdown_task = None
def request_shutdown() -> None:
nonlocal shutting_down
nonlocal shutting_down, shutdown_task
if shutting_down:
return
shutting_down = True
loop.create_task(_shutdown(server, state, loop))
shutdown_task = loop.create_task(_shutdown(server, state, loop))
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, request_shutdown)
+1 -1
View File
@@ -21,7 +21,7 @@ logging.getLogger("urllib3").setLevel(logging.WARNING)
def hash_url(link: str) -> str:
return md5((link.split("?")[0]).encode('utf-8')).hexdigest()
return md5(link.split("?", maxsplit=1)[0].encode('utf-8')).hexdigest()
def prune_cache(new_entry: str | None = None) -> None:
+1 -1
View File
@@ -269,7 +269,7 @@ def hevc_index(hevc_file_name: str, allow_corrupt: bool=False) -> tuple[list, in
raise VideoFileInvalid("first byte must be 0x00")
prefix_dat = b""
frame_types = list()
frame_types = []
i = 1 # skip past first byte 0x00
try:
+2 -2
View File
@@ -122,8 +122,8 @@ def init_plots(arr, name_to_arr_idx, plot_xlims, plot_ylims, plot_names, plot_co
title_texts = []
for j2, (nm, cl) in enumerate(zip(pl_list, plot_colors[i], strict=False)):
if j2 > 0:
title_texts.append(TextArea(", ", textprops=dict(color="white", fontsize=10)))
title_texts.append(TextArea(nm, textprops=dict(color=label_palette[cl], fontsize=10)))
title_texts.append(TextArea(", ", textprops={"color": "white", "fontsize": 10}))
title_texts.append(TextArea(nm, textprops={"color": label_palette[cl], "fontsize": 10}))
packed = HPacker(children=title_texts, pad=0, sep=0)
ab = AnchoredOffsetbox(loc='lower center', child=packed, bbox_to_anchor=(0.5, 1.0),
bbox_transform=axs[i].transAxes, frameon=False, pad=0)
@@ -29,11 +29,11 @@ def curve_block(length, angle=45, direction=0):
def create_map(track_size=60):
curve_len = track_size * 2
return dict(
type=MapGenerateMethod.PG_MAP_FILE,
lane_num=2,
lane_width=4.5,
config=[
return {
"type": MapGenerateMethod.PG_MAP_FILE,
"lane_num": 2,
"lane_width": 4.5,
"config": [
None,
straight_block(track_size),
curve_block(curve_len, 90),
@@ -44,7 +44,7 @@ def create_map(track_size=60):
straight_block(track_size),
curve_block(curve_len, 90),
]
)
}
class MetaDriveBridge(SimulatorBridge):
@@ -65,29 +65,29 @@ class MetaDriveBridge(SimulatorBridge):
if self.dual_camera:
sensors["rgb_wide"] = (RGBCameraWide, W, H)
config = dict(
use_render=self.should_render,
vehicle_config=dict(
enable_reverse=False,
render_vehicle=False,
image_source="rgb_road",
),
sensors=sensors,
image_on_cuda=_cuda_enable,
image_observation=True,
interface_panel=[],
out_of_route_done=False,
on_continuous_line_done=False,
crash_vehicle_done=False,
crash_object_done=False,
arrive_dest_done=False,
traffic_density=0.0, # traffic is incredibly expensive
map_config=create_map(),
decision_repeat=1,
physics_world_step_size=self.TICKS_PER_FRAME/100,
preload_models=False,
show_logo=False,
anisotropic_filtering=False
)
config = {
"use_render": self.should_render,
"vehicle_config": {
"enable_reverse": False,
"render_vehicle": False,
"image_source": "rgb_road",
},
"sensors": sensors,
"image_on_cuda": _cuda_enable,
"image_observation": True,
"interface_panel": [],
"out_of_route_done": False,
"on_continuous_line_done": False,
"crash_vehicle_done": False,
"crash_object_done": False,
"arrive_dest_done": False,
"traffic_density": 0.0, # traffic is incredibly expensive
"map_config": create_map(),
"decision_repeat": 1,
"physics_world_step_size": self.TICKS_PER_FRAME/100,
"preload_models": False,
"show_logo": False,
"anisotropic_filtering": False
}
return MetaDriveWorld(queue, config, self.test_duration, self.test_run, self.dual_camera)
+6 -13
View File
@@ -152,33 +152,26 @@ lint.select = [
"E", "F", "W", "PIE", "C4", "ISC", "A", "B",
"NPY", # numpy
"UP", # pyupgrade
"ASYNC",
"B904", "B905",
"PLC0207",
"TRY203", "TRY400", "TRY401", # try/excepts
"RUF008", "RUF100",
"RUF006", "RUF008", "RUF009", "RUF061", "RUF064", "RUF100", "RUF102", "RUF103", "RUF104",
"TID251",
"PLE", "PLR1704",
]
lint.ignore = [
"E741",
"E402",
"C408",
"ISC003",
"B027",
"B024",
"NPY002", # new numpy random syntax is worse
"UP045", "UP007", # these don't play nice with raylib atm
"UP007", # this doesn't play nice with raylib atm
]
line-length = 160
exclude = [
"openpilot/cereal",
"*.ipynb",
"generated",
]
lint.flake8-implicit-str-concat.allow-multiline = false
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
"unittest".msg = "Use pytest"
"time.time".msg = "Use time.monotonic"
"time.time".msg = "Use time.monotonic" # time.time can skip due to its reference clock, you probably want a monotonic clock
# raylib banned APIs
"pyray.measure_text_ex".msg = "Use openpilot.system.ui.lib.text_measure"
@@ -9,7 +9,6 @@
"source": [
"# Import all cars from opendbc\n",
"\n",
"from opendbc.car import structs\n",
"from opendbc.car.values import PLATFORMS as TEST_PLATFORMS\n",
"\n",
"# Example: add additional platforms/segments to test outside of commaCarSegments\n",
@@ -147,8 +146,8 @@
}
],
"source": [
"from openpilot.tools.lib.logreader import LogReader, comma_car_segments_source\n",
"from tqdm.notebook import tqdm, tnrange\n",
"from openpilot.tools.lib.logreader import comma_car_segments_source\n",
"from tqdm.notebook import tnrange\n",
"\n",
"# Example search for CAN ignition messages\n",
"# Be careful when filtering by bus, account for odd harness arrangements on Honda/HKG\n",
@@ -53,12 +53,12 @@
" if vin.startswith('1FT'):\n",
" if vin_positions_567 in F150_CODES:\n",
" if vin[7] in LIGHTNING_CODES:\n",
" return f\"FORD F-150 LIGHTNING 1ST GEN\"\n",
" return \"FORD F-150 LIGHTNING 1ST GEN\"\n",
" else:\n",
" return f\"FORD F-150 14TH GEN\"\n",
" return \"FORD F-150 14TH GEN\"\n",
" elif vin.startswith('3FM'):\n",
" if vin_positions_567 in MACHE_CODES:\n",
" return f\"FORD MUSTANG MACH-E 1ST GEN\"\n",
" return \"FORD MUSTANG MACH-E 1ST GEN\"\n",
" elif vin.startswith('5LM'):\n",
" pass\n",
"\n",
@@ -147,7 +147,8 @@
"source": [
"for vin, real_fingerprint in VINS_TO_CHECK:\n",
" determined_fingerprint = ford_vin_fingerprint(vin)\n",
" print(f\"vin: {vin} real platform: {real_fingerprint: <30} determined platform: {determined_fingerprint: <30} correct: {real_fingerprint == determined_fingerprint}\")"
" print(f\"vin: {vin} real platform: {real_fingerprint: <30} \" +\n",
" f\"determined platform: {determined_fingerprint: <30} correct: {real_fingerprint == determined_fingerprint}\")"
]
}
],
@@ -21,9 +21,7 @@
}
],
"source": [
"from opendbc.car import structs\n",
"from opendbc.car.hyundai.values import CAR, HyundaiFlags\n",
"from opendbc.car.hyundai.fingerprints import FW_VERSIONS\n",
"\n",
"TEST_PLATFORMS = set(CAR.with_flags(HyundaiFlags.CANFD)) & set(CAR.with_flags(HyundaiFlags.EV)) # CAN-FD electric vehicles only\n",
"#TEST_PLATFORMS = set(CAR.with_flags(HyundaiFlags.CANFD)) - set(CAR.with_flags(HyundaiFlags.EV)) # CAN-FD hybrid and ICE vehicles only\n",
@@ -190,15 +188,13 @@
],
"source": [
"import copy\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"from opendbc.can.parser import CANParser\n",
"from opendbc.car.hyundai.values import DBC\n",
"from opendbc.car.hyundai.hyundaicanfd import CanBus\n",
"\n",
"from openpilot.selfdrive.pandad import can_capnp_to_list\n",
"from openpilot.tools.lib.logreader import LogReader, comma_car_segments_source\n",
"from openpilot.tools.lib.logreader import comma_car_segments_source\n",
"\n",
"message_names = [\"GEAR_SHIFTER\", \"ACCELERATOR\", \"GEAR\", \"GEAR_ALT\", \"GEAR_ALT_2\"]\n",
"\n",
@@ -229,11 +225,11 @@
" for i, parsed_messages in enumerate(parsed_message_history):\n",
" gear = parsed_messages[name][\"GEAR\"]\n",
" if gear != gear_prev:\n",
" print(f\" *** Signal transition found! ***\")\n",
" print(\" *** Signal transition found! ***\")\n",
" examples.append(i)\n",
" gear_prev = gear\n",
"\n",
"print(f\"Analysis finished\")\n"
"print(\"Analysis finished\")\n"
]
},
{
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import argparse
import sys
import unittest # noqa: TID251
import unittest
from opendbc.car.tests.routes import CarTestRoute
from openpilot.selfdrive.car.tests.test_models import TestCarModel
from openpilot.tools.lib.route import SegmentRange