diff --git a/cereal b/cereal index 517fd563..51684706 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 517fd56398c0d3ae4d0a142849b81e2f025d8572 +Subproject commit 5168470661703a64f99bbd9743f2236ebc2c24ab diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc index 900a6222..0ec94c18 100644 --- a/selfdrive/boardd/boardd.cc +++ b/selfdrive/boardd/boardd.cc @@ -92,13 +92,22 @@ bool safety_setter_thread(Panda *panda) { AlignedBuffer aligned_buf; capnp::FlatArrayMessageReader cmsg(aligned_buf.align(params.data(), params.size())); cereal::CarParams::Reader car_params = cmsg.getRoot(); - cereal::CarParams::SafetyModel safety_model = car_params.getSafetyModel(); + cereal::CarParams::SafetyModel safety_model; + int safety_param; + + auto safety_configs = car_params.getSafetyConfigs(); + if (safety_configs.size() > 0) { + safety_model = safety_configs[0].getSafetyModel(); + safety_param = safety_configs[0].getSafetyParam(); + } else { + // If no safety mode is set, default to silent + safety_model = cereal::CarParams::SafetyModel::SILENT; + safety_param = 0; + } panda->set_unsafe_mode(0); // see safety_declarations.h for allowed values - auto safety_param = car_params.getSafetyParam(); LOGW("setting safety model: %d with param %d", (int)safety_model, safety_param); - panda->set_safety_model(safety_model, safety_param); return true; } @@ -242,9 +251,9 @@ void send_empty_peripheral_state(PubMaster *pm) { void send_empty_panda_state(PubMaster *pm) { MessageBuilder msg; - auto pandaState = msg.initEvent().initPandaState(); - pandaState.setPandaType(cereal::PandaState::PandaType::UNKNOWN); - pm->send("pandaState", msg); + auto pandaStates = msg.initEvent().initPandaStates(1); + pandaStates[0].setPandaType(cereal::PandaState::PandaType::UNKNOWN); + pm->send("pandaStates", msg); } bool send_panda_state(PubMaster *pm, Panda *panda, bool spoofing_started) { @@ -278,27 +287,28 @@ bool send_panda_state(PubMaster *pm, Panda *panda, bool spoofing_started) { auto evt = msg.initEvent(); evt.setValid(panda->comms_healthy); - auto ps = evt.initPandaState(); - ps.setUptime(pandaState.uptime); - ps.setIgnitionLine(pandaState.ignition_line); - ps.setIgnitionCan(pandaState.ignition_can); - ps.setControlsAllowed(pandaState.controls_allowed); - ps.setGasInterceptorDetected(pandaState.gas_interceptor_detected); - ps.setCanRxErrs(pandaState.can_rx_errs); - ps.setCanSendErrs(pandaState.can_send_errs); - ps.setCanFwdErrs(pandaState.can_fwd_errs); - ps.setGmlanSendErrs(pandaState.gmlan_send_errs); - ps.setPandaType(panda->hw_type); - ps.setSafetyModel(cereal::CarParams::SafetyModel(pandaState.safety_model)); - ps.setSafetyParam(pandaState.safety_param); - ps.setFaultStatus(cereal::PandaState::FaultStatus(pandaState.fault_status)); - ps.setPowerSaveEnabled((bool)(pandaState.power_save_enabled)); - ps.setHeartbeatLost((bool)(pandaState.heartbeat_lost)); - ps.setHarnessStatus(cereal::PandaState::HarnessStatus(pandaState.car_harness_status)); + // TODO: this has to be adapted to merge in multipanda support + auto ps = evt.initPandaStates(1); + ps[0].setUptime(pandaState.uptime); + ps[0].setIgnitionLine(pandaState.ignition_line); + ps[0].setIgnitionCan(pandaState.ignition_can); + ps[0].setControlsAllowed(pandaState.controls_allowed); + ps[0].setGasInterceptorDetected(pandaState.gas_interceptor_detected); + ps[0].setCanRxErrs(pandaState.can_rx_errs); + ps[0].setCanSendErrs(pandaState.can_send_errs); + ps[0].setCanFwdErrs(pandaState.can_fwd_errs); + ps[0].setGmlanSendErrs(pandaState.gmlan_send_errs); + ps[0].setPandaType(panda->hw_type); + ps[0].setSafetyModel(cereal::CarParams::SafetyModel(pandaState.safety_model)); + ps[0].setSafetyParam(pandaState.safety_param); + ps[0].setFaultStatus(cereal::PandaState::FaultStatus(pandaState.fault_status)); + ps[0].setPowerSaveEnabled((bool)(pandaState.power_save_enabled)); + ps[0].setHeartbeatLost((bool)(pandaState.heartbeat_lost)); + ps[0].setHarnessStatus(cereal::PandaState::HarnessStatus(pandaState.car_harness_status)); // Convert faults bitset to capnp list std::bitset fault_bits(pandaState.faults); - auto faults = ps.initFaults(fault_bits.count()); + auto faults = ps[0].initFaults(fault_bits.count()); size_t i = 0; for (size_t f = size_t(cereal::PandaState::FaultType::RELAY_MALFUNCTION); @@ -308,7 +318,7 @@ bool send_panda_state(PubMaster *pm, Panda *panda, bool spoofing_started) { i++; } } - pm->send("pandaState", msg); + pm->send("pandaStates", msg); return ignition; } @@ -558,7 +568,7 @@ int main() { LOG("set affinity returns %d", err); LOGW("attempting to connect"); - PubMaster pm({"pandaState", "peripheralState"}); + PubMaster pm({"pandaStates", "peripheralState"}); while (!do_exit) { Panda *panda = usb_connect(); diff --git a/selfdrive/boardd/tests/boardd_old.py b/selfdrive/boardd/tests/boardd_old.py index 017fde6d..5e740fbc 100755 --- a/selfdrive/boardd/tests/boardd_old.py +++ b/selfdrive/boardd/tests/boardd_old.py @@ -156,7 +156,7 @@ def boardd_loop(rate=100): # *** publishes can and health logcan = messaging.pub_sock('can') - health_sock = messaging.pub_sock('pandaState') + health_sock = messaging.pub_sock('pandaStates') # *** subscribes to can send sendcan = messaging.sub_sock('sendcan') @@ -168,14 +168,14 @@ def boardd_loop(rate=100): # health packet @ 2hz if (rk.frame % (rate // 2)) == 0: health = can_health() - msg = messaging.new_message('pandaState') + msg = messaging.new_message('pandaStates', 1) # store the health to be logged - msg.pandaState.voltage = health['voltage'] - msg.pandaState.current = health['current'] - msg.pandaState.ignitionLine = health['ignition_line'] - msg.pandaState.ignitionCan = health['ignition_can'] - msg.pandaState.controlsAllowed = True + msg.pandaState[0].voltage = health['voltage'] + msg.pandaState[0].current = health['current'] + msg.pandaState[0].ignitionLine = health['ignition_line'] + msg.pandaState[0].ignitionCan = health['ignition_can'] + msg.pandaState[0].controlsAllowed = True health_sock.send(msg.to_bytes()) diff --git a/selfdrive/boardd/tests/test_boardd_loopback.py b/selfdrive/boardd/tests/test_boardd_loopback.py index 267d396c..21b7a7ce 100755 --- a/selfdrive/boardd/tests/test_boardd_loopback.py +++ b/selfdrive/boardd/tests/test_boardd_loopback.py @@ -40,13 +40,17 @@ def test_boardd_loopback(): time.sleep(2) with Timeout(60, "boardd didn't start"): - sm = messaging.SubMaster(['pandaState']) - while sm.rcv_frame['pandaState'] < 1: + sm = messaging.SubMaster(['pandaStates']) + while sm.rcv_frame['pandaStates'] < 1: sm.update(1000) # boardd blocks on CarVin and CarParams cp = car.CarParams.new_message() - cp.safetyModel = car.CarParams.SafetyModel.allOutput + + safety_config = car.CarParams.SafetyConfig.new_message() + safety_config.safetyModel = car.CarParams.SafetyModel.allOutput + cp.safetyConfigs = [safety_config] + Params().put("CarVin", b"0"*17) Params().put_bool("ControlsReady", True) Params().put("CarParams", cp.to_bytes()) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 9cd13a58..ddb20fe5 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -1,4 +1,5 @@ # functions common among cars +from cereal import car from common.numpy_fast import clip # kg of standard extra cargo to count for drive, gas, etc... @@ -121,3 +122,11 @@ def create_gas_command(packer, gas_amount, idx): def make_can_msg(addr, dat, bus): return [addr, 0, dat, bus] + + +def get_safety_config(safety_model, safety_param = None): + ret = car.CarParams.SafetyConfig.new_message() + ret.safetyModel = safety_model + if safety_param is not None: + ret.safetyParam = safety_param + return ret diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 4d7dab3e..1822d76a 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from cereal import car from selfdrive.car.chrysler.values import CAR -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase @@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "chrysler" - ret.safetyModel = car.CarParams.SafetyModel.chrysler + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.chrysler)] # Speed conversion: 20, 45 mph ret.wheelbase = 3.089 # in meters for Pacifica Hybrid 2017 diff --git a/selfdrive/car/ford/interface.py b/selfdrive/car/ford/interface.py index f62f89f6..8c0b1e1f 100755 --- a/selfdrive/car/ford/interface.py +++ b/selfdrive/car/ford/interface.py @@ -2,7 +2,7 @@ from cereal import car from selfdrive.config import Conversions as CV from selfdrive.car.ford.values import MAX_ANGLE -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase @@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "ford" - ret.safetyModel = car.CarParams.SafetyModel.ford + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.ford)] ret.dashcamOnly = True ret.wheelbase = 2.85 diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 94e95010..a689a782 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -3,7 +3,7 @@ from cereal import car from selfdrive.config import Conversions as CV from selfdrive.car.gm.values import CAR, CruiseButtons, \ AccState, CarControllerParams -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase ButtonType = car.CarState.ButtonEvent.Type @@ -19,7 +19,7 @@ class CarInterface(CarInterfaceBase): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "gm" - ret.safetyModel = car.CarParams.SafetyModel.gm + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.gm)] ret.pcmCruise = False # stock cruise control is kept off # Presence of a camera on the object bus is ok. diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 2a33248c..adeec6bd 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -4,7 +4,7 @@ from panda import Panda from common.numpy_fast import interp from common.params import Params from selfdrive.car.honda.values import CarControllerParams, CruiseButtons, CAR, HONDA_BOSCH, HONDA_BOSCH_ALT_BRAKE_SIGNAL -from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.disable_ecu import disable_ecu from selfdrive.config import Conversions as CV @@ -33,7 +33,7 @@ class CarInterface(CarInterfaceBase): ret.carName = "honda" if candidate in HONDA_BOSCH: - ret.safetyModel = car.CarParams.SafetyModel.hondaBoschHarness + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaBoschHarness)] ret.radarOffCan = True # Disable the radar and let openpilot control longitudinal @@ -42,7 +42,7 @@ class CarInterface(CarInterfaceBase): ret.pcmCruise = not ret.openpilotLongitudinalControl else: - ret.safetyModel = car.CarParams.SafetyModel.hondaNidec + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaNidec)] ret.enableGasInterceptor = 0x201 in fingerprint[0] ret.openpilotLongitudinalControl = True @@ -287,10 +287,10 @@ class CarInterface(CarInterfaceBase): # These cars use alternate user brake msg (0x1BE) if candidate in HONDA_BOSCH_ALT_BRAKE_SIGNAL: - ret.safetyParam |= Panda.FLAG_HONDA_ALT_BRAKE + ret.safetyConfigs[0].safetyParam |= Panda.FLAG_HONDA_ALT_BRAKE if ret.openpilotLongitudinalControl and candidate in HONDA_BOSCH: - ret.safetyParam |= Panda.FLAG_HONDA_BOSCH_LONG + ret.safetyConfigs[0].safetyParam |= Panda.FLAG_HONDA_BOSCH_LONG # min speed to enable ACC. if car can do stop and go, then set enabling speed # to a negative value, so it won't matter. Otherwise, add 0.5 mph margin to not diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index ce25efce..7a012bc5 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -5,7 +5,7 @@ from common.params import Params from selfdrive.config import Conversions as CV from selfdrive.car.hyundai.values import CAR, EV_CAR, HYBRID_CAR, Buttons, CarControllerParams from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.disable_ecu import disable_ecu @@ -22,11 +22,10 @@ class CarInterface(CarInterfaceBase): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "hyundai" - ret.safetyModel = car.CarParams.SafetyModel.hyundai + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hyundai, 0)] ret.radarOffCan = RADAR_START_ADDR not in fingerprint[1] ret.openpilotLongitudinalControl = Params().get_bool("DisableRadar") and candidate in [CAR.SONATA, CAR.SONATA_HYBRID, CAR.PALISADE, CAR.SANTA_FE] - ret.safetyParam = 0 ret.pcmCruise = not ret.openpilotLongitudinalControl @@ -250,13 +249,13 @@ class CarInterface(CarInterfaceBase): if candidate in [CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, CAR.SONATA_LF, CAR.KIA_NIRO_EV, CAR.KIA_OPTIMA, CAR.VELOSTER, CAR.KIA_STINGER, CAR.GENESIS_G70, CAR.GENESIS_G80, CAR.KIA_CEED, CAR.ELANTRA]: - ret.safetyModel = car.CarParams.SafetyModel.hyundaiLegacy + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hyundaiLegacy)] # set appropriate safety param for gas signal if candidate in HYBRID_CAR: - ret.safetyParam = 2 + ret.safetyConfigs[0].safetyParam = 2 elif candidate in EV_CAR: - ret.safetyParam = 1 + ret.safetyConfigs[0].safetyParam = 1 ret.centerToFront = ret.wheelbase * 0.4 @@ -272,7 +271,7 @@ class CarInterface(CarInterfaceBase): ret.enableBsm = 0x58b in fingerprint[0] if ret.openpilotLongitudinalControl: - ret.safetyParam |= Panda.FLAG_HYUNDAI_LONG + ret.safetyConfigs[0].safetyParam |= Panda.FLAG_HYUNDAI_LONG return ret diff --git a/selfdrive/car/mazda/interface.py b/selfdrive/car/mazda/interface.py index bf199a44..5472a029 100755 --- a/selfdrive/car/mazda/interface.py +++ b/selfdrive/car/mazda/interface.py @@ -2,7 +2,7 @@ from cereal import car from selfdrive.config import Conversions as CV from selfdrive.car.mazda.values import CAR, LKAS_LIMITS -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase ButtonType = car.CarState.ButtonEvent.Type @@ -19,7 +19,7 @@ class CarInterface(CarInterfaceBase): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "mazda" - ret.safetyModel = car.CarParams.SafetyModel.mazda + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.mazda)] ret.radarOffCan = True ret.dashcamOnly = True diff --git a/selfdrive/car/mock/interface.py b/selfdrive/car/mock/interface.py index 604851cb..999e735c 100755 --- a/selfdrive/car/mock/interface.py +++ b/selfdrive/car/mock/interface.py @@ -4,7 +4,7 @@ from cereal import car from selfdrive.config import Conversions as CV from selfdrive.swaglog import cloudlog import cereal.messaging as messaging -from selfdrive.car import gen_empty_fingerprint +from selfdrive.car import gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase # mocked car interface to work with chffrplus @@ -37,7 +37,7 @@ class CarInterface(CarInterfaceBase): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "mock" - ret.safetyModel = car.CarParams.SafetyModel.noOutput + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.noOutput)] ret.mass = 1700. ret.rotationalInertia = 2500. ret.wheelbase = 2.70 diff --git a/selfdrive/car/nissan/interface.py b/selfdrive/car/nissan/interface.py index ca97e83c..18ae885f 100644 --- a/selfdrive/car/nissan/interface.py +++ b/selfdrive/car/nissan/interface.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from cereal import car from selfdrive.car.nissan.values import CAR -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase class CarInterface(CarInterfaceBase): @@ -14,7 +14,7 @@ class CarInterface(CarInterfaceBase): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "nissan" - ret.safetyModel = car.CarParams.SafetyModel.nissan + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.nissan)] ret.steerLimitAlert = False ret.steerRateCost = 0.5 @@ -33,7 +33,7 @@ class CarInterface(CarInterfaceBase): ret.steerRatio = 17 elif candidate == CAR.ALTIMA: # Altima has EPS on C-CAN unlike the others that have it on V-CAN - ret.safetyParam = 1 # EPS is on alternate bus + ret.safetyConfigs[0].safetyParam = 1 # EPS is on alternate bus ret.mass = 1492 + STD_CARGO_KG ret.wheelbase = 2.824 ret.centerToFront = ret.wheelbase * 0.44 diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index b907b03e..86bba542 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from cereal import car from selfdrive.car.subaru.values import CAR, PREGLOBAL_CARS -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase class CarInterface(CarInterfaceBase): @@ -14,10 +14,10 @@ class CarInterface(CarInterfaceBase): ret.radarOffCan = True if candidate in PREGLOBAL_CARS: - ret.safetyModel = car.CarParams.SafetyModel.subaruLegacy + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.subaruLegacy)] ret.enableBsm = 0x25c in fingerprint[0] else: - ret.safetyModel = car.CarParams.SafetyModel.subaru + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.subaru)] ret.enableBsm = 0x228 in fingerprint[0] ret.dashcamOnly = candidate in PREGLOBAL_CARS @@ -56,7 +56,7 @@ class CarInterface(CarInterfaceBase): ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01, 0.065, 0.2], [0.001, 0.015, 0.025]] if candidate in [CAR.FORESTER_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018]: - ret.safetyParam = 1 # Outback 2018-2019 and Forester have reversed driver torque signal + ret.safetyConfigs[0].safetyParam = 1 # Outback 2018-2019 and Forester have reversed driver torque signal ret.mass = 1568 + STD_CARGO_KG ret.wheelbase = 2.67 ret.centerToFront = ret.wheelbase * 0.5 diff --git a/selfdrive/car/tesla/interface.py b/selfdrive/car/tesla/interface.py index 72a751ac..e2642154 100755 --- a/selfdrive/car/tesla/interface.py +++ b/selfdrive/car/tesla/interface.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from cereal import car from selfdrive.car.tesla.values import CAR -from selfdrive.car import STD_CARGO_KG, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness +from selfdrive.car import STD_CARGO_KG, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase @@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "tesla" - ret.safetyModel = car.CarParams.SafetyModel.tesla + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.tesla)] # There is no safe way to do steer blending with user torque, # so the steering behaves like autopilot. This is not diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 2c9553b2..7453bda0 100755 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -2,7 +2,7 @@ from cereal import car from selfdrive.config import Conversions as CV from selfdrive.car.toyota.values import Ecu, CAR, TSS2_CAR, NO_DSU_CAR, MIN_ACC_SPEED, PEDAL_HYST_GAP, CarControllerParams -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase EventName = car.CarEvent.EventName @@ -18,7 +18,7 @@ class CarInterface(CarInterfaceBase): ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "toyota" - ret.safetyModel = car.CarParams.SafetyModel.toyota + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.toyota)] ret.steerActuatorDelay = 0.12 # Default delay, Prius has larger delay ret.steerLimitTimer = 0.4 @@ -31,7 +31,7 @@ class CarInterface(CarInterfaceBase): if candidate == CAR.PRIUS: stop_and_go = True - ret.safetyParam = 66 # see conversion factor for STEER_TORQUE_EPS in dbc file + ret.safetyConfigs[0].safetyParam = 66 # see conversion factor for STEER_TORQUE_EPS in dbc file ret.wheelbase = 2.70 ret.steerRatio = 15.74 # unknown end-to-end spec tire_stiffness_factor = 0.6371 # hand-tune @@ -50,7 +50,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.RAV4, CAR.RAV4H]: stop_and_go = True if (candidate in CAR.RAV4H) else False - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.65 ret.steerRatio = 16.88 # 14.5 is spec end-to-end tire_stiffness_factor = 0.5533 @@ -69,7 +69,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.COROLLA: stop_and_go = False - ret.safetyParam = 88 + ret.safetyConfigs[0].safetyParam = 88 ret.wheelbase = 2.70 ret.steerRatio = 18.27 tire_stiffness_factor = 0.444 # not optimized yet @@ -79,7 +79,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.LEXUS_RX: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.79 ret.steerRatio = 14.8 tire_stiffness_factor = 0.5533 @@ -89,7 +89,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.LEXUS_RXH: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.79 ret.steerRatio = 16. # 14.8 is spec end-to-end tire_stiffness_factor = 0.444 # not optimized yet @@ -99,7 +99,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.LEXUS_RX_TSS2: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.79 ret.steerRatio = 14.8 tire_stiffness_factor = 0.5533 # not optimized yet @@ -109,7 +109,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.LEXUS_RXH_TSS2: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.79 ret.steerRatio = 16.0 # 14.8 is spec end-to-end tire_stiffness_factor = 0.444 # not optimized yet @@ -119,7 +119,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.CHR, CAR.CHRH]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.63906 ret.steerRatio = 13.6 tire_stiffness_factor = 0.7933 @@ -129,7 +129,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.CAMRY, CAR.CAMRYH, CAR.CAMRY_TSS2, CAR.CAMRYH_TSS2]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.82448 ret.steerRatio = 13.7 tire_stiffness_factor = 0.7933 @@ -139,7 +139,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.84988 # 112.2 in = 2.84988 m ret.steerRatio = 16.0 tire_stiffness_factor = 0.8 @@ -149,7 +149,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.HIGHLANDER, CAR.HIGHLANDERH]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.78 ret.steerRatio = 16.0 tire_stiffness_factor = 0.8 @@ -159,7 +159,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.AVALON, CAR.AVALON_2019, CAR.AVALONH_2019]: stop_and_go = False - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.82 ret.steerRatio = 14.8 # Found at https://pressroom.toyota.com/releases/2016+avalon+product+specs.download tire_stiffness_factor = 0.7983 @@ -169,7 +169,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.RAV4_TSS2, CAR.RAV4H_TSS2]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.68986 ret.steerRatio = 14.3 tire_stiffness_factor = 0.7933 @@ -187,7 +187,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.67 # Average between 2.70 for sedan and 2.64 for hatchback ret.steerRatio = 13.9 tire_stiffness_factor = 0.444 # not optimized yet @@ -197,7 +197,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.8702 ret.steerRatio = 16.0 # not optimized tire_stiffness_factor = 0.444 # not optimized yet @@ -207,7 +207,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.LEXUS_ESH: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.8190 ret.steerRatio = 16.06 tire_stiffness_factor = 0.444 # not optimized yet @@ -217,7 +217,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.SIENNA: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 3.03 ret.steerRatio = 15.5 tire_stiffness_factor = 0.444 @@ -227,7 +227,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.LEXUS_IS: stop_and_go = False - ret.safetyParam = 77 + ret.safetyConfigs[0].safetyParam = 77 ret.wheelbase = 2.79908 ret.steerRatio = 13.3 tire_stiffness_factor = 0.444 @@ -237,7 +237,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.LEXUS_CTH: stop_and_go = True - ret.safetyParam = 100 + ret.safetyConfigs[0].safetyParam = 100 ret.wheelbase = 2.60 ret.steerRatio = 18.6 tire_stiffness_factor = 0.517 @@ -247,7 +247,7 @@ class CarInterface(CarInterfaceBase): elif candidate in [CAR.LEXUS_NXH, CAR.LEXUS_NX, CAR.LEXUS_NX_TSS2]: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.66 ret.steerRatio = 14.7 tire_stiffness_factor = 0.444 # not optimized yet @@ -257,7 +257,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.PRIUS_TSS2: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.70002 # from toyota online sepc. ret.steerRatio = 13.4 # True steerRation from older prius tire_stiffness_factor = 0.6371 # hand-tune @@ -267,7 +267,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.MIRAI: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 2.91 ret.steerRatio = 14.8 tire_stiffness_factor = 0.8 @@ -277,7 +277,7 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.ALPHARD_TSS2: stop_and_go = True - ret.safetyParam = 73 + ret.safetyConfigs[0].safetyParam = 73 ret.wheelbase = 3.00 ret.steerRatio = 14.2 tire_stiffness_factor = 0.444 diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py index 7375ab1a..f52b8adc 100644 --- a/selfdrive/car/volkswagen/interface.py +++ b/selfdrive/car/volkswagen/interface.py @@ -1,6 +1,6 @@ from cereal import car from selfdrive.car.volkswagen.values import CAR, BUTTON_STATES, CANBUS, NetworkLocation, TransmissionType, GearShifter -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint +from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase EventName = car.CarEvent.EventName @@ -28,7 +28,7 @@ class CarInterface(CarInterfaceBase): if True: # pylint: disable=using-constant-test # Set global MQB parameters - ret.safetyModel = car.CarParams.SafetyModel.volkswagen + ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.volkswagen)] ret.enableBsm = 0x30F in fingerprint[0] # SWA_01 if 0xAD in fingerprint[0]: # Getriebe_11 diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 60a21e33..da2d75ac 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -49,6 +49,7 @@ LaneChangeState = log.LateralPlan.LaneChangeState LaneChangeDirection = log.LateralPlan.LaneChangeDirection EventName = car.CarEvent.EventName ButtonEvent = car.CarState.ButtonEvent +SafetyModel = car.CarParams.SafetyModel class Controls: @@ -72,7 +73,7 @@ class Controls: self.sm = sm if self.sm is None: ignore = ['driverCameraState', 'managerState'] if SIMULATION else None - self.sm = messaging.SubMaster(['deviceState', 'pandaState', 'peripheralState', 'modelV2', 'liveCalibration', + self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration', 'driverMonitoringState', 'longitudinalPlan', 'lateralPlan', 'liveLocationKalman', 'managerState', 'liveParameters', 'radarState'] + self.camera_packets + joystick_packet, ignore_alive=ignore, ignore_avg_freq=['radarState', 'longitudinalPlan']) @@ -110,7 +111,9 @@ class Controls: self.read_only = not car_recognized or not controller_available or \ self.CP.dashcamOnly or community_feature_disallowed if self.read_only: - self.CP.safetyModel = car.CarParams.SafetyModel.noOutput + safety_config = car.CarParams.SafetyConfig.new_message() + safety_config.safetyModel = car.CarParams.SafetyModel.noOutput + self.CP.safetyConfigs = [safety_config] # Write CarParams for radard cp_bytes = self.CP.to_bytes() @@ -240,16 +243,21 @@ class Controls: if self.can_rcv_error or not CS.canValid: self.events.add(EventName.canError) - safety_mismatch = self.sm['pandaState'].safetyModel != self.CP.safetyModel or self.sm['pandaState'].safetyParam != self.CP.safetyParam - if safety_mismatch or self.mismatch_counter >= 200: - self.events.add(EventName.controlsMismatch) + for i, pandaState in enumerate(self.sm['pandaStates']): + # All pandas must match the list of safetyConfigs, and if outside this list, must be silent + if i < len(self.CP.safetyConfigs): + safety_mismatch = pandaState.safetyModel != self.CP.safetyConfigs[i].safetyModel or pandaState.safetyParam != self.CP.safetyConfigs[i].safetyParam + else: + safety_mismatch = pandaState.safetyModel != SafetyModel.silent + if safety_mismatch or self.mismatch_counter >= 200: + self.events.add(EventName.controlsMismatch) if not self.sm['liveParameters'].valid: self.events.add(EventName.vehicleModelInvalid) if len(self.sm['radarState'].radarErrors): self.events.add(EventName.radarFault) - elif not self.sm.valid["pandaState"]: + elif not self.sm.valid["pandaStates"]: self.events.add(EventName.usbError) elif not self.sm.all_alive_and_valid(): self.events.add(EventName.commIssue) @@ -270,8 +278,9 @@ class Controls: self.events.add(EventName.posenetInvalid) if not self.sm['liveLocationKalman'].deviceStable: self.events.add(EventName.deviceFalling) - if log.PandaState.FaultType.relayMalfunction in self.sm['pandaState'].faults: - self.events.add(EventName.relayMalfunction) + for pandaState in self.sm['pandaStates']: + if log.PandaState.FaultType.relayMalfunction in pandaState.faults: + self.events.add(EventName.relayMalfunction) planner_fcw = self.sm['longitudinalPlan'].fcw and self.enabled model_fcw = self.sm['modelV2'].meta.hardBrakePredicted and not CS.brakePressed if planner_fcw or model_fcw: @@ -355,8 +364,10 @@ class Controls: if not self.enabled: self.mismatch_counter = 0 - if not self.sm['pandaState'].controlsAllowed and self.enabled: - self.mismatch_counter += 1 + # All pandas not in silent mode must have controlsAllowed when openpilot is enabled + for pandaState in self.sm['pandaStates']: + if pandaState.safetyModel != SafetyModel.silent and not pandaState.controlsAllowed and self.enabled: + self.mismatch_counter += 1 self.distance_traveled += CS.vEgo * DT_CTRL diff --git a/selfdrive/controls/tests/test_startup.py b/selfdrive/controls/tests/test_startup.py index b53f960d..658adf49 100755 --- a/selfdrive/controls/tests/test_startup.py +++ b/selfdrive/controls/tests/test_startup.py @@ -70,7 +70,7 @@ class TestStartup(unittest.TestCase): # TODO: this should be done without any real sockets controls_sock = messaging.sub_sock("controlsState") - pm = messaging.PubMaster(['can', 'pandaState']) + pm = messaging.PubMaster(['can', 'pandaStates']) params = Params() params.clear_all() @@ -98,9 +98,9 @@ class TestStartup(unittest.TestCase): time.sleep(2) # wait for controlsd to be ready - msg = messaging.new_message('pandaState') - msg.pandaState.pandaType = log.PandaState.PandaType.uno - pm.send('pandaState', msg) + msg = messaging.new_message('pandaStates', 1) + msg.pandaStates[0].pandaType = log.PandaState.PandaType.uno + pm.send('pandaStates', msg) # fingerprint if (car_model is None) or (fw_versions is not None): diff --git a/selfdrive/debug/cycle_alerts.py b/selfdrive/debug/cycle_alerts.py index c3579168..47a37933 100755 --- a/selfdrive/debug/cycle_alerts.py +++ b/selfdrive/debug/cycle_alerts.py @@ -21,10 +21,10 @@ def cycle_alerts(duration=2000, is_metric=False): alerts = [EventName.preLaneChangeLeft, EventName.preLaneChangeRight] CP = CarInterface.get_params("HONDA CIVIC 2016") - sm = messaging.SubMaster(['deviceState', 'pandaState', 'roadCameraState', 'modelV2', 'liveCalibration', + sm = messaging.SubMaster(['deviceState', 'pandaStates', 'roadCameraState', 'modelV2', 'liveCalibration', 'driverMonitoringState', 'longitudinalPlan', 'lateralPlan', 'liveLocationKalman']) - pm = messaging.PubMaster(['controlsState', 'pandaState', 'deviceState']) + pm = messaging.PubMaster(['controlsState', 'pandaStates', 'deviceState']) events = Events() AM = AlertManager() @@ -61,10 +61,9 @@ def cycle_alerts(duration=2000, is_metric=False): dat.deviceState.started = True pm.send('deviceState', dat) - dat = messaging.new_message() - dat.init('pandaState') - dat.pandaState.ignitionLine = True - pm.send('pandaState', dat) + dat = messaging.new_message('pandaStates', 1) + dat.pandaStates[0].ignitionLine = True + pm.send('pandaStates', dat) time.sleep(0.01) diff --git a/selfdrive/debug/internal/check_alive_valid.py b/selfdrive/debug/internal/check_alive_valid.py index 6a64e5d2..da488c21 100755 --- a/selfdrive/debug/internal/check_alive_valid.py +++ b/selfdrive/debug/internal/check_alive_valid.py @@ -4,7 +4,7 @@ import cereal.messaging as messaging if __name__ == "__main__": - sm = messaging.SubMaster(['deviceState', 'pandaState', 'modelV2', 'liveCalibration', 'driverMonitoringState', 'longitudinalPlan', 'lateralPlan']) + sm = messaging.SubMaster(['deviceState', 'pandaStates', 'modelV2', 'liveCalibration', 'driverMonitoringState', 'longitudinalPlan', 'lateralPlan']) i = 0 while True: diff --git a/selfdrive/debug/test_fw_query_on_routes.py b/selfdrive/debug/test_fw_query_on_routes.py index 6a49a84d..44b3ba16 100755 --- a/selfdrive/debug/test_fw_query_on_routes.py +++ b/selfdrive/debug/test_fw_query_on_routes.py @@ -71,8 +71,8 @@ if __name__ == "__main__": dongles.append(dongle_id) for msg in lr: - if msg.which() == "pandaState": - if msg.pandaState.pandaType not in ['uno', 'blackPanda', 'dos']: + if msg.which() == "pandaStates": + if msg.pandaStates[0].pandaType not in ['uno', 'blackPanda', 'dos']: break elif msg.which() == "carParams": diff --git a/selfdrive/debug/uiview.py b/selfdrive/debug/uiview.py index 2df3d2a5..319ead24 100755 --- a/selfdrive/debug/uiview.py +++ b/selfdrive/debug/uiview.py @@ -4,19 +4,20 @@ import cereal.messaging as messaging from selfdrive.manager.process_config import managed_processes if __name__ == "__main__": - services = ['controlsState', 'deviceState', 'pandaState', 'carParams'] procs = ['camerad', 'ui', 'modeld', 'calibrationd'] for p in procs: managed_processes[p].start() - pm = messaging.PubMaster(services) + pm = messaging.PubMaster(['controlsState', 'deviceState', 'pandaStates', 'carParams']) - msgs = {s: messaging.new_message(s) for s in services} + msgs = {s: messaging.new_message(s) for s in ['controlsState', 'deviceState', 'carParams']} msgs['deviceState'].deviceState.started = True - msgs['pandaState'].pandaState.ignitionLine = True msgs['carParams'].carParams.openpilotLongitudinalControl = True + msgs['pandaStates'] = messaging.new_message('pandaStates', 1) + msgs['pandaStates'].pandaStates[0].ignitionLine = True + try: while True: time.sleep(1 / 100) # continually send, rate doesn't matter diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index b90473c1..15ef0d3e 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -240,7 +240,7 @@ CONFIGS = [ proc_name="controlsd", pub_sub={ "can": ["controlsState", "carState", "carControl", "sendcan", "carEvents", "carParams"], - "deviceState": [], "pandaState": [], "peripheralState": [], "liveCalibration": [], "driverMonitoringState": [], "longitudinalPlan": [], "lateralPlan": [], "liveLocationKalman": [], "liveParameters": [], "radarState": [], + "deviceState": [], "pandaStates": [], "peripheralState": [], "liveCalibration": [], "driverMonitoringState": [], "longitudinalPlan": [], "lateralPlan": [], "liveLocationKalman": [], "liveParameters": [], "radarState": [], "modelV2": [], "driverCameraState": [], "roadCameraState": [], "ubloxRaw": [], "managerState": [], }, ignore=["logMonoTime", "valid", "controlsState.startMonoTime", "controlsState.cumLagMs"], diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 941467ae..122ca5f9 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -5ee94677282bcea512e0d929e55e71308f14d530 \ No newline at end of file +22f78d143d7e17e9ac7d0be8e29d5d7b5477ecd3 \ No newline at end of file diff --git a/selfdrive/test/process_replay/regen.py b/selfdrive/test/process_replay/regen.py index 45273a34..0e8a0eaf 100755 --- a/selfdrive/test/process_replay/regen.py +++ b/selfdrive/test/process_replay/regen.py @@ -118,7 +118,7 @@ def regen_segment(lr, frs=None, outdir=FAKEDATA): ], 'pandad': [ multiprocessing.Process(target=replay_service, args=('can', lr)), - multiprocessing.Process(target=replay_service, args=('pandaState', lr)), + multiprocessing.Process(target=replay_service, args=('pandaStates', lr)), ], #'managerState': [ # multiprocessing.Process(target=replay_service, args=('managerState', lr)), diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index bd84d601..3faab970 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -15,6 +15,7 @@ original_segments = [ ("HYUNDAI", "02c45f73a2e5c6e9|2021-01-01--19-08-22--1"), # HYUNDAI.SONATA ("TOYOTA", "0982d79ebb0de295|2021-01-04--17-13-21--13"), # TOYOTA.PRIUS (INDI) ("TOYOTA2", "0982d79ebb0de295|2021-01-03--20-03-36--6"), # TOYOTA.RAV4 (LQR) + ("TOYOTA3", "f7d7e3538cda1a2a|2021-08-16--08-55-34--6"), # TOYOTA.COROLLA_TSS2 ("HONDA", "eb140f119469d9ab|2021-06-12--10-46-24--27"), # HONDA.CIVIC (NIDEC) ("HONDA2", "7d2244f34d1bbcda|2021-06-25--12-25-37--26"), # HONDA.ACCORD (BOSCH) ("CHRYSLER", "4deb27de11bee626|2021-02-20--11-28-55--8"), # CHRYSLER.PACIFICA @@ -29,17 +30,17 @@ original_segments = [ ] segments = [ - ("HYUNDAI", "fakedata|2021-07-09--16-01-34--0"), - ("TOYOTA", "1d6dfff4b6098f01|2021-07-26--07-56-21--2"), - ("TOYOTA2", "fakedata|2021-07-09--16-03-56--0"), - ("TOYOTA3", "f7d7e3538cda1a2a|2021-08-16--08-55-34--6"), # TOYOTA.COROLLA_TSS2 - ("HONDA", "fakedata|2021-07-09--16-05-07--0"), - ("HONDA2", "fakedata|2021-07-09--16-08-28--0"), - ("CHRYSLER", "fakedata|2021-07-09--16-09-39--0"), - ("SUBARU", "fakedata|2021-07-09--16-10-50--0"), - ("GM", "fakedata|2021-07-09--16-13-53--0"), - ("NISSAN", "fakedata|2021-07-09--16-17-35--0"), - ("VOLKSWAGEN", "fakedata|2021-07-09--16-29-13--0"), + ("HYUNDAI", "fakedata|2021-10-07--15-56-26--0"), + ("TOYOTA", "fakedata|2021-10-07--15-57-47--0"), + ("TOYOTA2", "fakedata|2021-10-07--15-59-03--0"), + ("TOYOTA3", "fakedata|2021-10-07--15-53-21--0"), + ("HONDA", "fakedata|2021-10-07--16-00-19--0"), + ("HONDA2", "fakedata|2021-10-07--16-01-35--0"), + ("CHRYSLER", "fakedata|2021-10-07--16-02-52--0"), + ("SUBARU", "fakedata|2021-10-07--16-04-09--0"), + ("GM", "fakedata|2021-10-07--16-05-26--0"), + ("NISSAN", "fakedata|2021-10-07--16-09-53--0"), + ("VOLKSWAGEN", "fakedata|2021-10-07--16-11-11--0"), ] # dashcamOnly makes don't need to be tested until a full port is done diff --git a/selfdrive/test/test_models.py b/selfdrive/test/test_models.py index 34e9e831..e3c8c344 100755 --- a/selfdrive/test/test_models.py +++ b/selfdrive/test/test_models.py @@ -94,8 +94,8 @@ class TestCarModel(unittest.TestCase): # TODO: check safetyModel is in release panda build safety = libpandasafety_py.libpandasafety - set_status = safety.set_safety_hooks(self.CP.safetyModel.raw, self.CP.safetyParam) - self.assertEqual(0, set_status, f"failed to set safetyModel {self.CP.safetyModel}") + set_status = safety.set_safety_hooks(self.CP.safetyConfigs[0].safetyModel.raw, self.CP.safetyConfigs[0].safetyParam) + self.assertEqual(0, set_status, f"failed to set safetyModel {self.CP.safetyConfigs[0].safetyModel}") def test_car_interface(self): # TODO: also check for checkusm and counter violations from can parser @@ -130,7 +130,7 @@ class TestCarModel(unittest.TestCase): self.skipTest("no need to check panda safety for dashcamOnly") safety = libpandasafety_py.libpandasafety - set_status = safety.set_safety_hooks(self.CP.safetyModel.raw, self.CP.safetyParam) + set_status = safety.set_safety_hooks(self.CP.safetyConfigs[0].safetyModel.raw, self.CP.safetyConfigs[0].safetyParam) self.assertEqual(0, set_status) failed_addrs = Counter() @@ -150,7 +150,7 @@ class TestCarModel(unittest.TestCase): self.skipTest("see comments in test_models.py") safety = libpandasafety_py.libpandasafety - set_status = safety.set_safety_hooks(self.CP.safetyModel.raw, self.CP.safetyParam) + set_status = safety.set_safety_hooks(self.CP.safetyConfigs[0].safetyModel.raw, self.CP.safetyConfigs[0].safetyParam) self.assertEqual(0, set_status) checks = defaultdict(lambda: 0) diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 1fc75dd7..1987e21f 100755 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -65,7 +65,7 @@ if TICI: TIMINGS = { # rtols: max/min, rsd "can": [2.5, 0.35], - "pandaState": [2.5, 0.35], + "pandaStates": [2.5, 0.35], "peripheralState": [2.5, 0.35], "sendcan": [2.5, 0.35], "carState": [2.5, 0.35], diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index bddaeba0..43e85149 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -154,7 +154,7 @@ def thermald_thread(): pm = messaging.PubMaster(['deviceState']) pandaState_timeout = int(1000 * 2.5 * DT_TRML) # 2.5x the expected pandaState frequency - pandaState_sock = messaging.sub_sock('pandaState', timeout=pandaState_timeout) + pandaState_sock = messaging.sub_sock('pandaStates', timeout=pandaState_timeout) sm = messaging.SubMaster(["peripheralState", "gpsLocationExternal", "managerState"]) fan_speed = 0 @@ -203,15 +203,15 @@ def thermald_thread(): params.put_bool("BootedOnroad", True) while True: - pandaState = messaging.recv_sock(pandaState_sock, wait=True) + pandaStates = messaging.recv_sock(pandaState_sock, wait=True) sm.update(0) peripheralState = sm['peripheralState'] msg = read_thermal(thermal_config) - if pandaState is not None: - pandaState = pandaState.pandaState + if pandaStates is not None and len(pandaStates.pandaStates) > 0: + pandaState = pandaStates.pandaStates[0] # If we lose connection to the panda, wait 5 seconds before going offroad if pandaState.pandaType == log.PandaState.PandaType.unknown: @@ -446,7 +446,7 @@ def thermald_thread(): cloudlog.event("STATUS_PACKET", count=count, - pandaState=(strip_deprecated_keys(pandaState.to_dict()) if pandaState else None), + pandaStates=(strip_deprecated_keys(pandaStates.to_dict()) if pandaStates else None), peripheralState=strip_deprecated_keys(peripheralState.to_dict()), location=(strip_deprecated_keys(sm["gpsLocationExternal"].to_dict()) if sm.alive["gpsLocationExternal"] else None), deviceState=strip_deprecated_keys(msg.to_dict())) diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 50a104eb..e64606c6 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -134,14 +134,19 @@ static void update_state(UIState *s) { } } } - if (sm.updated("pandaState")) { - auto pandaState = sm["pandaState"].getPandaState(); - scene.pandaType = pandaState.getPandaType(); + if (sm.updated("pandaStates")) { + auto pandaStates = sm["pandaStates"].getPandaStates(); + if (pandaStates.size() > 0) { + scene.pandaType = pandaStates[0].getPandaType(); - if (scene.pandaType != cereal::PandaState::PandaType::UNKNOWN) { - scene.ignition = pandaState.getIgnitionLine() || pandaState.getIgnitionCan(); + if (scene.pandaType != cereal::PandaState::PandaType::UNKNOWN) { + scene.ignition = false; + for (const auto& pandaState : pandaStates) { + scene.ignition |= pandaState.getIgnitionLine() || pandaState.getIgnitionCan(); + } + } } - } else if ((s->sm->frame - s->sm->rcv_frame("pandaState")) > 5*UI_FREQ) { + } else if ((s->sm->frame - s->sm->rcv_frame("pandaStates")) > 5*UI_FREQ) { scene.pandaType = cereal::PandaState::PandaType::UNKNOWN; } if (sm.updated("carParams")) { @@ -220,7 +225,7 @@ static void update_status(UIState *s) { QUIState::QUIState(QObject *parent) : QObject(parent) { ui_state.sm = std::make_unique>({ "modelV2", "controlsState", "liveCalibration", "deviceState", "roadCameraState", - "pandaState", "carParams", "driverMonitoringState", "sensorEvents", "carState", "liveLocationKalman", + "pandaStates", "carParams", "driverMonitoringState", "sensorEvents", "carState", "liveLocationKalman", }); ui_state.wide_camera = Hardware::TICI() ? Params().getBool("EnableWideCamera") : false; diff --git a/tools/sim/bridge.py b/tools/sim/bridge.py index 431cc7d1..52af243c 100755 --- a/tools/sim/bridge.py +++ b/tools/sim/bridge.py @@ -84,17 +84,17 @@ def imu_callback(imu, vehicle_state): pm.send('sensorEvents', dat) def panda_state_function(exit_event: threading.Event): - pm = messaging.PubMaster(['pandaState']) + pm = messaging.PubMaster(['pandaStates']) while not exit_event.is_set(): - dat = messaging.new_message('pandaState') + dat = messaging.new_message('pandaStates', 1) dat.valid = True - dat.pandaState = { + dat.pandaStates[0] = { 'ignitionLine': True, 'pandaType': "blackPanda", 'controlsAllowed': True, 'safetyModel': 'hondaNidec' } - pm.send('pandaState', dat) + pm.send('pandaStates', dat) time.sleep(0.5) def gps_callback(gps, vehicle_state):