Skip to content

Commit

Permalink
move car.capnp to opendbc (#33722)
Browse files Browse the repository at this point in the history
* move car.capnp to opendbc

* bump

* do card

* fix some more tests

* rm helpers

* format fp

* more

* whoops

* bump

* bump to master
  • Loading branch information
sshane authored Oct 3, 2024
1 parent af774d8 commit 8149f7c
Show file tree
Hide file tree
Showing 14 changed files with 41 additions and 845 deletions.
722 changes: 0 additions & 722 deletions cereal/car.capnp

This file was deleted.

1 change: 1 addition & 0 deletions cereal/car.capnp
24 changes: 10 additions & 14 deletions selfdrive/car/card.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,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.helpers import convert_carControl, convert_to_capnp

REPLAY = "REPLAY" in os.environ

Expand Down Expand Up @@ -63,8 +62,7 @@ def can_send(msgs: list[CanData]) -> None:
class Car:
CI: CarInterfaceBase
RI: RadarInterfaceBase
CP: structs.CarParams
CP_capnp: car.CarParams
CP: car.CarParams

def __init__(self, CI=None, RI=None) -> None:
self.can_sock = messaging.sub_sock('can', timeout=20)
Expand Down Expand Up @@ -144,9 +142,7 @@ def __init__(self, CI=None, RI=None) -> None:
self.params.put("CarParamsPrevRoute", prev_cp)

# Write CarParams for controls and radard
# convert to pycapnp representation for caching and logging
self.CP_capnp = convert_to_capnp(self.CP)
cp_bytes = self.CP_capnp.to_bytes()
cp_bytes = self.CP.to_bytes()
self.params.put("CarParams", cp_bytes)
self.params.put_nonblocking("CarParamsCache", cp_bytes)
self.params.put_nonblocking("CarParamsPersistent", cp_bytes)
Expand All @@ -160,19 +156,19 @@ def __init__(self, CI=None, RI=None) -> None:
# card is driven by can recv, expected at 100Hz
self.rk = Ratekeeper(100, print_delay_threshold=None)

def state_update(self) -> tuple[car.CarState, structs.RadarData | None]:
def state_update(self) -> tuple[car.CarState, structs.RadarDataT | None]:
"""carState update loop, driven by can"""

can_strs = messaging.drain_sock_raw(self.can_sock, wait_for_one=True)
can_list = can_capnp_to_list(can_strs)

# Update carState from CAN
CS = convert_to_capnp(self.CI.update(can_list))
CS = self.CI.update(can_list)
if self.CP.carName == 'mock':
CS = self.mock_carstate.update(CS)

# Update radar tracks from CAN
RD: structs.RadarData | None = self.RI.update(can_list)
RD: structs.RadarDataT | None = self.RI.update(can_list)

self.sm.update(0)

Expand All @@ -192,20 +188,20 @@ def state_update(self) -> tuple[car.CarState, structs.RadarData | None]:

return CS, RD

def state_publish(self, CS: car.CarState, RD: structs.RadarData | None):
def state_publish(self, CS: car.CarState, RD: structs.RadarDataT | None):
"""carState and carParams publish loop"""

# carParams - logged every 50 seconds (> 1 per segment)
if self.sm.frame % int(50. / DT_CTRL) == 0:
cp_send = messaging.new_message('carParams')
cp_send.valid = True
cp_send.carParams = self.CP_capnp
cp_send.carParams = self.CP
self.pm.send('carParams', cp_send)

# publish new carOutput
co_send = messaging.new_message('carOutput')
co_send.valid = self.sm.all_checks(['carControl'])
co_send.carOutput.actuatorsOutput = convert_to_capnp(self.last_actuators_output)
co_send.carOutput.actuatorsOutput = self.last_actuators_output
self.pm.send('carOutput', co_send)

# kick off controlsd step while we actuate the latest carControl packet
Expand All @@ -219,7 +215,7 @@ def state_publish(self, CS: car.CarState, RD: structs.RadarData | None):
if RD is not None:
tracks_msg = messaging.new_message('liveTracks')
tracks_msg.valid = len(RD.errors) == 0
tracks_msg.liveTracks = convert_to_capnp(RD)
tracks_msg.liveTracks = RD
self.pm.send('liveTracks', tracks_msg)

def controls_update(self, CS: car.CarState, CC: car.CarControl):
Expand All @@ -235,7 +231,7 @@ def controls_update(self, CS: car.CarState, CC: car.CarControl):
if self.sm.all_alive(['carControl']):
# send car controls over can
now_nanos = self.can_log_mono_time if REPLAY else int(time.monotonic() * 1e9)
self.last_actuators_output, can_sends = self.CI.apply(convert_carControl(CC), now_nanos)
self.last_actuators_output, can_sends = self.CI.apply(CC, now_nanos)
self.pm.send('sendcan', can_list_to_can_capnp(can_sends, msgtype='sendcan', valid=CS.canValid))

self.CC_prev = CC
Expand Down
74 changes: 0 additions & 74 deletions selfdrive/car/helpers.py

This file was deleted.

15 changes: 7 additions & 8 deletions selfdrive/car/tests/test_car_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from opendbc.car.fingerprints import all_known_cars
from opendbc.car.fw_versions import FW_VERSIONS, FW_QUERY_CONFIGS
from opendbc.car.mock.values import CAR as MOCK
from openpilot.selfdrive.car.card import convert_carControl, convert_to_capnp
from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle
from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID
from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque
Expand Down Expand Up @@ -41,6 +40,7 @@ def test_car_interfaces(self, car_name, data):

car_params = CarInterface.get_params(car_name, args['fingerprints'], args['car_fw'],
experimental_long=args['experimental_long'], docs=False)
car_params = car_params.as_reader()
car_interface = CarInterface(car_params, CarController, CarState)
assert car_params
assert car_interface
Expand Down Expand Up @@ -72,15 +72,15 @@ def test_car_interfaces(self, car_name, data):
# Run car interface
now_nanos = 0
CC = car.CarControl.new_message(**cc_msg)
CC = convert_carControl(CC.as_reader())
CC = CC.as_reader()
for _ in range(10):
car_interface.update([])
car_interface.apply(CC, now_nanos)
now_nanos += DT_CTRL * 1e9 # 10 ms

CC = car.CarControl.new_message(**cc_msg)
CC.enabled = True
CC = convert_carControl(CC.as_reader())
CC = CC.as_reader()
for _ in range(10):
car_interface.update([])
car_interface.apply(CC, now_nanos)
Expand All @@ -89,11 +89,10 @@ def test_car_interfaces(self, car_name, data):
# Test controller initialization
# TODO: wait until card refactor is merged to run controller a few times,
# hypothesis also slows down significantly with just one more message draw
car_params_capnp = convert_to_capnp(car_params).as_reader()
LongControl(car_params_capnp)
LongControl(car_params)
if car_params.steerControlType == CarParams.SteerControlType.angle:
LatControlAngle(car_params_capnp, car_interface)
LatControlAngle(car_params, car_interface)
elif car_params.lateralTuning.which() == 'pid':
LatControlPID(car_params_capnp, car_interface)
LatControlPID(car_params, car_interface)
elif car_params.lateralTuning.which() == 'torque':
LatControlTorque(car_params_capnp, car_interface)
LatControlTorque(car_params, car_interface)
17 changes: 7 additions & 10 deletions selfdrive/car/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import capnp
import copy
import dataclasses
import os
import pytest
import random
Expand All @@ -20,7 +18,6 @@
from opendbc.car.honda.values import CAR as HONDA, HondaFlags
from opendbc.car.values import Platform
from opendbc.car.tests.routes import non_tested_cars, routes, CarTestRoute
from openpilot.selfdrive.car.card import convert_to_capnp
from openpilot.selfdrive.selfdrived.events import ET
from openpilot.selfdrive.selfdrived.selfdrived import SelfdriveD
from openpilot.selfdrive.pandad import can_capnp_to_list
Expand Down Expand Up @@ -187,15 +184,15 @@ def tearDownClass(cls):
del cls.can_msgs

def setUp(self):
self.CI = self.CarInterface(copy.deepcopy(self.CP), self.CarController, self.CarState)
self.CI = self.CarInterface(self.CP.copy(), self.CarController, self.CarState)
assert self.CI

Params().put_bool("OpenpilotEnabledToggle", self.openpilot_enabled)

# TODO: check safetyModel is in release panda build
self.safety = libpanda_py.libpanda

cfg = car.CarParams.SafetyConfig(**dataclasses.asdict(self.CP.safetyConfigs[-1]))
cfg = self.CP.safetyConfigs[-1]
set_status = self.safety.set_safety_hooks(cfg.safetyModel.raw, cfg.safetyParam)
self.assertEqual(0, set_status, f"failed to set safetyModel {cfg}")
self.safety.init_tests()
Expand All @@ -220,7 +217,7 @@ def test_car_interface(self):
# TODO: also check for checksum violations from can parser
can_invalid_cnt = 0
can_valid = False
CC = structs.CarControl()
CC = structs.CarControl().as_reader()

for i, msg in enumerate(self.can_msgs):
CS = self.CI.update(can_capnp_to_list((msg.as_builder().to_bytes(),)))
Expand Down Expand Up @@ -312,17 +309,17 @@ def test_car_controller(car_control):

# Make sure we can send all messages while inactive
CC = structs.CarControl()
test_car_controller(CC)
test_car_controller(CC.as_reader())

# Test cancel + general messages (controls_allowed=False & cruise_engaged=True)
self.safety.set_cruise_engaged_prev(True)
CC = structs.CarControl(cruiseControl=structs.CarControl.CruiseControl(cancel=True))
test_car_controller(CC)
test_car_controller(CC.as_reader())

# Test resume + general messages (controls_allowed=True & cruise_engaged=True)
self.safety.set_controls_allowed(True)
CC = structs.CarControl(cruiseControl=structs.CarControl.CruiseControl(resume=True))
test_car_controller(CC)
test_car_controller(CC.as_reader())

# Skip stdout/stderr capture with pytest, causes elevated memory usage
@pytest.mark.nocapture
Expand Down Expand Up @@ -409,7 +406,7 @@ def test_panda_safety_carstate(self):
selfdrived = SelfdriveD(CP=self.CP)
selfdrived.initialized = True
for idx, can in enumerate(self.can_msgs):
CS = convert_to_capnp(self.CI.update(can_capnp_to_list((can.as_builder().to_bytes(), ))))
CS = self.CI.update(can_capnp_to_list((can.as_builder().to_bytes(), ))).as_reader()
for msg in filter(lambda m: m.src in range(64), can.can):
to_send = libpanda_py.make_CANPacket(msg.address, msg.src % 4, msg.dat)
ret = self.safety.safety_rx_hook(to_send)
Expand Down
2 changes: 0 additions & 2 deletions selfdrive/controls/lib/tests/test_latcontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from opendbc.car.honda.values import CAR as HONDA
from opendbc.car.toyota.values import CAR as TOYOTA
from opendbc.car.nissan.values import CAR as NISSAN
from openpilot.selfdrive.car.card import convert_to_capnp
from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID
from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque
from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle
Expand All @@ -21,7 +20,6 @@ def test_saturation(self, car_name, controller):
CarInterface, CarController, CarState, RadarInterface = interfaces[car_name]
CP = CarInterface.get_non_essential_params(car_name)
CI = CarInterface(CP, CarController, CarState)
CP = convert_to_capnp(CP)
VM = VehicleModel(CP)

controller = controller(CP.as_reader(), CI)
Expand Down
3 changes: 1 addition & 2 deletions selfdrive/controls/lib/tests/test_vehicle_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@

from opendbc.car.honda.interface import CarInterface
from opendbc.car.honda.values import CAR
from openpilot.selfdrive.car.card import convert_to_capnp
from openpilot.selfdrive.controls.lib.vehicle_model import VehicleModel, dyn_ss_sol, create_dyn_state_matrices


class TestVehicleModel:
def setup_method(self):
CP = CarInterface.get_non_essential_params(CAR.HONDA_CIVIC)
self.VM = VehicleModel(convert_to_capnp(CP))
self.VM = VehicleModel(CP)

def test_round_trip_yaw_rate(self):
# TODO: fix VM to work at zero speed
Expand Down
11 changes: 8 additions & 3 deletions selfdrive/debug/format_fingerprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
import jinja2
import os

from cereal import car
from openpilot.common.basedir import BASEDIR
from opendbc.car.interfaces import get_interface_attr

Ecu = car.CarParams.Ecu

CARS = get_interface_attr('CAR')
FW_VERSIONS = get_interface_attr('FW_VERSIONS')
FINGERPRINTS = get_interface_attr('FINGERPRINTS')
ECU_NAME = {v: k for k, v in Ecu.schema.enumerants.items()}

FINGERPRINTS_PY_TEMPLATE = jinja2.Template("""
{%- if FINGERPRINTS[brand] %}
Expand Down Expand Up @@ -45,7 +49,7 @@
{% for car, _ in FW_VERSIONS[brand].items() %}
CAR.{{car.name}}: {
{% for key, fw_versions in FW_VERSIONS[brand][car].items() %}
(Ecu.{{key[0]}}, 0x{{"%0x" | format(key[1] | int)}}, \
(Ecu.{{ECU_NAME[key[0]]}}, 0x{{"%0x" | format(key[1] | int)}}, \
{% if key[2] %}0x{{"%0x" | format(key[2] | int)}}{% else %}{{key[2]}}{% endif %}): [
{% for fw_version in (fw_versions + extra_fw_versions.get(car, {}).get(key, [])) | unique | sort %}
{{fw_version}},
Expand All @@ -67,8 +71,9 @@ def format_brand_fw_versions(brand, extra_fw_versions: None | dict[str, dict[tup
comments = [line for line in f.readlines() if line.startswith("#") and "noqa" not in line]

with open(fingerprints_file, "w") as f:
f.write(FINGERPRINTS_PY_TEMPLATE.render(brand=brand, comments=comments, FINGERPRINTS=FINGERPRINTS,
FW_VERSIONS=FW_VERSIONS, extra_fw_versions=extra_fw_versions))
f.write(FINGERPRINTS_PY_TEMPLATE.render(brand=brand, comments=comments, ECU_NAME=ECU_NAME,
FINGERPRINTS=FINGERPRINTS, FW_VERSIONS=FW_VERSIONS,
extra_fw_versions=extra_fw_versions))


if __name__ == "__main__":
Expand Down
3 changes: 1 addition & 2 deletions selfdrive/modeld/modeld.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from openpilot.common.transformations.camera import DEVICE_CAMERAS
from openpilot.common.transformations.model import get_warp_matrix
from openpilot.system import sentry
from openpilot.selfdrive.car.card import convert_to_capnp
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
from openpilot.selfdrive.modeld.runners import ModelRunner, Runtime
from openpilot.selfdrive.modeld.parse_model_outputs import Parser
Expand Down Expand Up @@ -184,7 +183,7 @@ def main(demo=False):


if demo:
CP = convert_to_capnp(get_demo_car_params())
CP = get_demo_car_params()
else:
CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams)
cloudlog.info("modeld got CarParams: %s", CP.carName)
Expand Down
Loading

0 comments on commit 8149f7c

Please sign in to comment.