grey panda is unsupported (#2458)

pull/2443/head
Adeeb Shihadeh 5 years ago committed by GitHub
parent 029be49012
commit 47c21f10f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      RELEASES.md
  2. 4
      apk/ai.comma.plus.offroad.apk
  3. 2
      cereal
  4. 1
      common/params_pyx.pyx
  5. 17
      selfdrive/car/car_helpers.py
  6. 11
      selfdrive/car/chrysler/interface.py
  7. 5
      selfdrive/car/chrysler/values.py
  8. 10
      selfdrive/car/ford/interface.py
  9. 4
      selfdrive/car/ford/values.py
  10. 12
      selfdrive/car/gm/interface.py
  11. 4
      selfdrive/car/gm/values.py
  12. 12
      selfdrive/car/honda/carcontroller.py
  13. 5
      selfdrive/car/honda/carstate.py
  14. 41
      selfdrive/car/honda/hondacan.py
  15. 15
      selfdrive/car/honda/interface.py
  16. 6
      selfdrive/car/honda/values.py
  17. 14
      selfdrive/car/hyundai/interface.py
  18. 4
      selfdrive/car/hyundai/values.py
  19. 6
      selfdrive/car/interfaces.py
  20. 10
      selfdrive/car/mazda/interface.py
  21. 4
      selfdrive/car/mazda/values.py
  22. 4
      selfdrive/car/mock/interface.py
  23. 4
      selfdrive/car/nissan/interface.py
  24. 7
      selfdrive/car/subaru/interface.py
  25. 4
      selfdrive/car/subaru/values.py
  26. 51
      selfdrive/car/tests/test_car_interfaces.py
  27. 8
      selfdrive/car/toyota/interface.py
  28. 4
      selfdrive/car/volkswagen/interface.py
  29. 8
      selfdrive/controls/controlsd.py
  30. 4
      selfdrive/controls/lib/alerts_offroad.json
  31. 25
      selfdrive/controls/lib/events.py
  32. 1
      selfdrive/debug/get_fingerprint.py
  33. 1
      selfdrive/test/longitudinal_maneuvers/test_longitudinal.py
  34. 4
      selfdrive/test/process_replay/process_replay.py
  35. 2
      selfdrive/test/process_replay/ref_commit
  36. 44
      selfdrive/test/test_models.py
  37. 11
      selfdrive/thermald/power_monitoring.py
  38. 13
      selfdrive/thermald/tests/test_power_monitoring.py
  39. 11
      selfdrive/thermald/thermald.py
  40. 7
      tools/carcontrols/debug_controls.py
  41. 2
      tools/webcam/README.md

@ -1,5 +1,6 @@
Version 0.7.11 (2020-XX-XX) Version 0.7.11 (2020-XX-XX)
======================== ========================
* Grey panda is no longer supported, upgrade to comma two or black panda
* Lexus NX 2018 support thanks to matt12eagles! * Lexus NX 2018 support thanks to matt12eagles!
* Kia Niro EV 2020 support thanks to nickn17! * Kia Niro EV 2020 support thanks to nickn17!

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b3290c11ee8ededb1dc268aa24000c0831565c64d32ac9ce6521bfef2161b6e6 oid sha256:f9f629c0894ada01bdb7018899cec970ffa058948b25760ca840ebc3f4851767
size 13702753 size 13710345

@ -1 +1 @@
Subproject commit d87b4bbef90404ef4d2629db11499d163d0d15aa Subproject commit eb0ede91af24aba72adcefa545233107e4a970fe

@ -69,6 +69,7 @@ keys = {
b"Offroad_IsTakingSnapshot": [TxType.CLEAR_ON_MANAGER_START], b"Offroad_IsTakingSnapshot": [TxType.CLEAR_ON_MANAGER_START],
b"Offroad_NeosUpdate": [TxType.CLEAR_ON_MANAGER_START], b"Offroad_NeosUpdate": [TxType.CLEAR_ON_MANAGER_START],
b"Offroad_UpdateFailed": [TxType.CLEAR_ON_MANAGER_START], b"Offroad_UpdateFailed": [TxType.CLEAR_ON_MANAGER_START],
b"Offroad_HardwareUnsupported": [TxType.CLEAR_ON_MANAGER_START],
} }
def ensure_bytes(v): def ensure_bytes(v):

@ -9,12 +9,11 @@ from selfdrive.swaglog import cloudlog
import cereal.messaging as messaging import cereal.messaging as messaging
from selfdrive.car import gen_empty_fingerprint from selfdrive.car import gen_empty_fingerprint
from cereal import car, log from cereal import car
EventName = car.CarEvent.EventName EventName = car.CarEvent.EventName
HwType = log.HealthData.HwType
def get_startup_event(car_recognized, controller_available, hw_type): def get_startup_event(car_recognized, controller_available):
if comma_remote and tested_branch: if comma_remote and tested_branch:
event = EventName.startup event = EventName.startup
else: else:
@ -24,8 +23,6 @@ def get_startup_event(car_recognized, controller_available, hw_type):
event = EventName.startupNoCar event = EventName.startupNoCar
elif car_recognized and not controller_available: elif car_recognized and not controller_available:
event = EventName.startupNoControl event = EventName.startupNoControl
elif hw_type == HwType.greyPanda:
event = EventName.startupGreyPanda
return event return event
@ -84,11 +81,11 @@ def only_toyota_left(candidate_cars):
# **** for use live only **** # **** for use live only ****
def fingerprint(logcan, sendcan, has_relay): def fingerprint(logcan, sendcan):
fixed_fingerprint = os.environ.get('FINGERPRINT', "") fixed_fingerprint = os.environ.get('FINGERPRINT', "")
skip_fw_query = os.environ.get('SKIP_FW_QUERY', False) skip_fw_query = os.environ.get('SKIP_FW_QUERY', False)
if has_relay and not fixed_fingerprint and not skip_fw_query: if not fixed_fingerprint and not skip_fw_query:
# Vin query only reliably works thorugh OBDII # Vin query only reliably works thorugh OBDII
bus = 1 bus = 1
@ -171,15 +168,15 @@ def fingerprint(logcan, sendcan, has_relay):
return car_fingerprint, finger, vin, car_fw, source return car_fingerprint, finger, vin, car_fw, source
def get_car(logcan, sendcan, has_relay=False): def get_car(logcan, sendcan):
candidate, fingerprints, vin, car_fw, source = fingerprint(logcan, sendcan, has_relay) candidate, fingerprints, vin, car_fw, source = fingerprint(logcan, sendcan)
if candidate is None: if candidate is None:
cloudlog.warning("car doesn't match any fingerprints: %r", fingerprints) cloudlog.warning("car doesn't match any fingerprints: %r", fingerprints)
candidate = "mock" candidate = "mock"
CarInterface, CarController, CarState = interfaces[candidate] CarInterface, CarController, CarState = interfaces[candidate]
car_params = CarInterface.get_params(candidate, fingerprints, has_relay, car_fw) car_params = CarInterface.get_params(candidate, fingerprints, car_fw)
car_params.carVin = vin car_params.carVin = vin
car_params.carFw = car_fw car_params.carFw = car_fw
car_params.fingerprintSource = source car_params.fingerprintSource = source

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from cereal import car from cereal import car
from selfdrive.car.chrysler.values import Ecu, ECU_FINGERPRINT, CAR, FINGERPRINTS from selfdrive.car.chrysler.values import CAR
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.interfaces import CarInterfaceBase
@ -11,11 +11,11 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0 return float(accel) / 3.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=None, has_relay=False, car_fw=None): def get_params(candidate, fingerprint=None, car_fw=None):
if fingerprint is None: if fingerprint is None:
fingerprint = gen_empty_fingerprint() fingerprint = gen_empty_fingerprint()
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "chrysler" ret.carName = "chrysler"
ret.safetyModel = car.CarParams.SafetyModel.chrysler ret.safetyModel = car.CarParams.SafetyModel.chrysler
@ -52,8 +52,7 @@ class CarInterface(CarInterfaceBase):
# mass and CG position, so all cars will have approximately similar dyn behaviors # mass and CG position, so all cars will have approximately similar dyn behaviors
ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront) ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront)
ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay ret.enableCamera = True
print("ECU Camera Simulated: {0}".format(ret.enableCamera))
return ret return ret

@ -91,8 +91,3 @@ DBC = {
} }
STEER_THRESHOLD = 120 STEER_THRESHOLD = 120
ECU_FINGERPRINT = {
Ecu.fwdCamera: [0x292], # lkas cmd
}

@ -2,8 +2,8 @@
from cereal import car from cereal import car
from selfdrive.swaglog import cloudlog from selfdrive.swaglog import cloudlog
from selfdrive.config import Conversions as CV from selfdrive.config import Conversions as CV
from selfdrive.car.ford.values import MAX_ANGLE, Ecu, ECU_FINGERPRINT, FINGERPRINTS from selfdrive.car.ford.values import MAX_ANGLE
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.interfaces import CarInterfaceBase
@ -14,8 +14,8 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0 return float(accel) / 3.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "ford" ret.carName = "ford"
ret.safetyModel = car.CarParams.SafetyModel.ford ret.safetyModel = car.CarParams.SafetyModel.ford
ret.dashcamOnly = True ret.dashcamOnly = True
@ -43,7 +43,7 @@ class CarInterface(CarInterfaceBase):
ret.steerControlType = car.CarParams.SteerControlType.angle ret.steerControlType = car.CarParams.SteerControlType.angle
ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay ret.enableCamera = True
cloudlog.warning("ECU Camera Simulated: %r", ret.enableCamera) cloudlog.warning("ECU Camera Simulated: %r", ret.enableCamera)
return ret return ret

@ -15,10 +15,6 @@ FINGERPRINTS = {
}], }],
} }
ECU_FINGERPRINT = {
Ecu.fwdCamera: [970, 973, 984]
}
DBC = { DBC = {
CAR.FUSION: dbc_dict('ford_fusion_2018_pt', 'ford_fusion_2018_adas'), CAR.FUSION: dbc_dict('ford_fusion_2018_pt', 'ford_fusion_2018_adas'),
} }

@ -1,9 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from cereal import car from cereal import car
from selfdrive.config import Conversions as CV from selfdrive.config import Conversions as CV
from selfdrive.car.gm.values import CAR, Ecu, ECU_FINGERPRINT, CruiseButtons, \ from selfdrive.car.gm.values import CAR, CruiseButtons, \
AccState, FINGERPRINTS AccState
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.interfaces import CarInterfaceBase
ButtonType = car.CarState.ButtonEvent.Type ButtonType = car.CarState.ButtonEvent.Type
@ -16,8 +16,8 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0 return float(accel) / 4.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "gm" ret.carName = "gm"
ret.safetyModel = car.CarParams.SafetyModel.gm ret.safetyModel = car.CarParams.SafetyModel.gm
ret.enableCruise = False # stock cruise control is kept off ret.enableCruise = False # stock cruise control is kept off
@ -29,7 +29,7 @@ class CarInterface(CarInterfaceBase):
# Presence of a camera on the object bus is ok. # Presence of a camera on the object bus is ok.
# Have to go to read_only if ASCM is online (ACC-enabled cars), # Have to go to read_only if ASCM is online (ACC-enabled cars),
# or camera is on powertrain bus (LKA cars without ACC). # or camera is on powertrain bus (LKA cars without ACC).
ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay ret.enableCamera = True
ret.openpilotLongitudinalControl = ret.enableCamera ret.openpilotLongitudinalControl = ret.enableCamera
tire_stiffness_factor = 0.444 # not optimized yet tire_stiffness_factor = 0.444 # not optimized yet

@ -70,10 +70,6 @@ FINGERPRINTS = {
STEER_THRESHOLD = 1.0 STEER_THRESHOLD = 1.0
ECU_FINGERPRINT = {
Ecu.fwdCamera: [384, 715] # 384 = "ASCMLKASteeringCmd", 715 = "ASCMGasRegenCmd"
}
DBC = { DBC = {
CAR.HOLDEN_ASTRA: dbc_dict('gm_global_a_powertrain', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis'), CAR.HOLDEN_ASTRA: dbc_dict('gm_global_a_powertrain', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis'),
CAR.VOLT: dbc_dict('gm_global_a_powertrain', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis'), CAR.VOLT: dbc_dict('gm_global_a_powertrain', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis'),

@ -145,22 +145,22 @@ class CarController():
# Send steering command. # Send steering command.
idx = frame % 4 idx = frame % 4
can_sends.append(hondacan.create_steering_control(self.packer, apply_steer, can_sends.append(hondacan.create_steering_control(self.packer, apply_steer,
lkas_active, CS.CP.carFingerprint, idx, CS.CP.isPandaBlack, CS.CP.openpilotLongitudinalControl)) lkas_active, CS.CP.carFingerprint, idx, CS.CP.openpilotLongitudinalControl))
# Send dashboard UI commands. # Send dashboard UI commands.
if (frame % 10) == 0: if (frame % 10) == 0:
idx = (frame//10) % 4 idx = (frame//10) % 4
can_sends.extend(hondacan.create_ui_commands(self.packer, pcm_speed, hud, CS.CP.carFingerprint, CS.is_metric, idx, CS.CP.isPandaBlack, CS.CP.openpilotLongitudinalControl, CS.stock_hud)) can_sends.extend(hondacan.create_ui_commands(self.packer, pcm_speed, hud, CS.CP.carFingerprint, CS.is_metric, idx, CS.CP.openpilotLongitudinalControl, CS.stock_hud))
if not CS.CP.openpilotLongitudinalControl: if not CS.CP.openpilotLongitudinalControl:
if (frame % 2) == 0: if (frame % 2) == 0:
idx = frame // 2 idx = frame // 2
can_sends.append(hondacan.create_bosch_supplemental_1(self.packer, CS.CP.carFingerprint, idx, CS.CP.isPandaBlack)) can_sends.append(hondacan.create_bosch_supplemental_1(self.packer, CS.CP.carFingerprint, idx))
# If using stock ACC, spam cancel command to kill gas when OP disengages. # If using stock ACC, spam cancel command to kill gas when OP disengages.
if pcm_cancel_cmd: if pcm_cancel_cmd:
can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.CANCEL, idx, CS.CP.carFingerprint, CS.CP.isPandaBlack)) can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.CANCEL, idx, CS.CP.carFingerprint))
elif CS.out.cruiseState.standstill: elif CS.out.cruiseState.standstill:
can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.RES_ACCEL, idx, CS.CP.carFingerprint, CS.CP.isPandaBlack)) can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.RES_ACCEL, idx, CS.CP.carFingerprint))
else: else:
# Send gas and brake commands. # Send gas and brake commands.
@ -174,7 +174,7 @@ class CarController():
apply_brake = int(clip(self.brake_last * P.BRAKE_MAX, 0, P.BRAKE_MAX - 1)) apply_brake = int(clip(self.brake_last * P.BRAKE_MAX, 0, P.BRAKE_MAX - 1))
pump_on, self.last_pump_ts = brake_pump_hysteresis(apply_brake, self.apply_brake_last, self.last_pump_ts, ts) pump_on, self.last_pump_ts = brake_pump_hysteresis(apply_brake, self.apply_brake_last, self.last_pump_ts, ts)
can_sends.append(hondacan.create_brake_command(self.packer, apply_brake, pump_on, can_sends.append(hondacan.create_brake_command(self.packer, apply_brake, pump_on,
pcm_override, pcm_cancel_cmd, hud.fcw, idx, CS.CP.carFingerprint, CS.CP.isPandaBlack, CS.stock_brake)) pcm_override, pcm_cancel_cmd, hud.fcw, idx, CS.CP.carFingerprint, CS.stock_brake))
self.apply_brake_last = apply_brake self.apply_brake_last = apply_brake
if CS.CP.enableGasInterceptor: if CS.CP.enableGasInterceptor:

@ -336,7 +336,7 @@ class CarState(CarStateBase):
@staticmethod @staticmethod
def get_can_parser(CP): def get_can_parser(CP):
signals, checks = get_can_signals(CP) signals, checks = get_can_signals(CP)
bus_pt = 1 if CP.isPandaBlack and CP.carFingerprint in HONDA_BOSCH else 0 bus_pt = 1 if CP.carFingerprint in HONDA_BOSCH else 0
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, bus_pt) return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, bus_pt)
@staticmethod @staticmethod
@ -361,8 +361,7 @@ class CarState(CarStateBase):
if CP.carFingerprint in [CAR.CRV, CAR.CRV_EU, CAR.ACURA_RDX, CAR.ODYSSEY_CHN]: if CP.carFingerprint in [CAR.CRV, CAR.CRV_EU, CAR.ACURA_RDX, CAR.ODYSSEY_CHN]:
checks = [(0x194, 100)] checks = [(0x194, 100)]
bus_cam = 1 if CP.carFingerprint in HONDA_BOSCH and not CP.isPandaBlack else 2 return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, bus_cam)
@staticmethod @staticmethod
def get_body_can_parser(CP): def get_body_can_parser(CP):

@ -7,24 +7,19 @@ from selfdrive.car.honda.values import HONDA_BOSCH
# 2 = ACC-CAN - camera side # 2 = ACC-CAN - camera side
# 3 = F-CAN A - OBDII port # 3 = F-CAN A - OBDII port
# CAN bus layout with giraffe def get_pt_bus(car_fingerprint):
# 0 = F-CAN B - powertrain return 1 if car_fingerprint in HONDA_BOSCH else 0
# 1 = ACC-CAN - camera side
# 2 = ACC-CAN - radar side
def get_pt_bus(car_fingerprint, has_relay):
return 1 if car_fingerprint in HONDA_BOSCH and has_relay else 0
def get_lkas_cmd_bus(car_fingerprint, radar_disabled=False):
def get_lkas_cmd_bus(car_fingerprint, has_relay, radar_disabled=False):
if radar_disabled: if radar_disabled:
# when radar is disabled, steering commands are sent directly to powertrain bus # when radar is disabled, steering commands are sent directly to powertrain bus
return get_pt_bus(car_fingerprint, has_relay) return get_pt_bus(car_fingerprint)
# normally steering commands are sent to radar, which forwards them to powertrain bus # normally steering commands are sent to radar, which forwards them to powertrain bus
return 2 if car_fingerprint in HONDA_BOSCH and not has_relay else 0 return 0
def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, has_relay, stock_brake): def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, idx, car_fingerprint, stock_brake):
# TODO: do we loose pressure if we keep pump off for long? # TODO: do we loose pressure if we keep pump off for long?
brakelights = apply_brake > 0 brakelights = apply_brake > 0
brake_rq = apply_brake > 0 brake_rq = apply_brake > 0
@ -45,13 +40,13 @@ def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_
"AEB_REQ_2": 0, "AEB_REQ_2": 0,
"AEB_STATUS": 0, "AEB_STATUS": 0,
} }
bus = get_pt_bus(car_fingerprint, has_relay) bus = get_pt_bus(car_fingerprint)
return packer.make_can_msg("BRAKE_COMMAND", bus, values, idx) return packer.make_can_msg("BRAKE_COMMAND", bus, values, idx)
def create_acc_commands(packer, enabled, accel, gas, idx, stopping, starting, car_fingerprint, has_relay): def create_acc_commands(packer, enabled, accel, gas, idx, stopping, starting, car_fingerprint):
commands = [] commands = []
bus = get_pt_bus(car_fingerprint, has_relay) bus = get_pt_bus(car_fingerprint)
control_on = 5 if enabled else 0 control_on = 5 if enabled else 0
# no gas = -30000 # no gas = -30000
@ -84,31 +79,31 @@ def create_acc_commands(packer, enabled, accel, gas, idx, stopping, starting, ca
return commands return commands
def create_steering_control(packer, apply_steer, lkas_active, car_fingerprint, idx, has_relay, radar_disabled): def create_steering_control(packer, apply_steer, lkas_active, car_fingerprint, idx, radar_disabled):
values = { values = {
"STEER_TORQUE": apply_steer if lkas_active else 0, "STEER_TORQUE": apply_steer if lkas_active else 0,
"STEER_TORQUE_REQUEST": lkas_active, "STEER_TORQUE_REQUEST": lkas_active,
} }
bus = get_lkas_cmd_bus(car_fingerprint, has_relay, radar_disabled) bus = get_lkas_cmd_bus(car_fingerprint, radar_disabled)
return packer.make_can_msg("STEERING_CONTROL", bus, values, idx) return packer.make_can_msg("STEERING_CONTROL", bus, values, idx)
def create_bosch_supplemental_1(packer, car_fingerprint, idx, has_relay): def create_bosch_supplemental_1(packer, car_fingerprint, idx):
# non-active params # non-active params
values = { values = {
"SET_ME_X04": 0x04, "SET_ME_X04": 0x04,
"SET_ME_X80": 0x80, "SET_ME_X80": 0x80,
"SET_ME_X10": 0x10, "SET_ME_X10": 0x10,
} }
bus = get_lkas_cmd_bus(car_fingerprint, has_relay) bus = get_lkas_cmd_bus(car_fingerprint)
return packer.make_can_msg("BOSCH_SUPPLEMENTAL_1", bus, values, idx) return packer.make_can_msg("BOSCH_SUPPLEMENTAL_1", bus, values, idx)
def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx, has_relay, openpilot_longitudinal_control, stock_hud): def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx, openpilot_longitudinal_control, stock_hud):
commands = [] commands = []
bus_pt = get_pt_bus(car_fingerprint, has_relay) bus_pt = get_pt_bus(car_fingerprint)
radar_disabled = car_fingerprint in HONDA_BOSCH and openpilot_longitudinal_control radar_disabled = car_fingerprint in HONDA_BOSCH and openpilot_longitudinal_control
bus_lkas = get_lkas_cmd_bus(car_fingerprint, has_relay, radar_disabled) bus_lkas = get_lkas_cmd_bus(car_fingerprint, radar_disabled)
if openpilot_longitudinal_control: if openpilot_longitudinal_control:
if car_fingerprint in HONDA_BOSCH: if car_fingerprint in HONDA_BOSCH:
@ -158,10 +153,10 @@ def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx,
return commands return commands
def spam_buttons_command(packer, button_val, idx, car_fingerprint, has_relay): def spam_buttons_command(packer, button_val, idx, car_fingerprint):
values = { values = {
'CRUISE_BUTTONS': button_val, 'CRUISE_BUTTONS': button_val,
'CRUISE_SETTING': 0, 'CRUISE_SETTING': 0,
} }
bus = get_pt_bus(car_fingerprint, has_relay) bus = get_pt_bus(car_fingerprint)
return packer.make_can_msg("SCM_BUTTONS", bus, values, idx) return packer.make_can_msg("SCM_BUTTONS", bus, values, idx)

@ -6,8 +6,8 @@ from common.realtime import DT_CTRL
from selfdrive.swaglog import cloudlog from selfdrive.swaglog import cloudlog
from selfdrive.config import Conversions as CV from selfdrive.config import Conversions as CV
from selfdrive.controls.lib.events import ET from selfdrive.controls.lib.events import ET
from selfdrive.car.honda.values import CruiseButtons, CAR, HONDA_BOSCH, Ecu, ECU_FINGERPRINT, FINGERPRINTS from selfdrive.car.honda.values import CruiseButtons, CAR, HONDA_BOSCH
from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.controls.lib.planner import _A_CRUISE_MAX_V_FOLLOWING from selfdrive.controls.lib.planner import _A_CRUISE_MAX_V_FOLLOWING
from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.interfaces import CarInterfaceBase
@ -119,19 +119,18 @@ class CarInterface(CarInterfaceBase):
return float(max(max_accel, a_target / A_ACC_MAX)) * min(speedLimiter, accelLimiter) return float(max(max_accel, a_target / A_ACC_MAX)) * min(speedLimiter, accelLimiter)
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]): # pylint: disable=dangerous-default-value def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[]): # pylint: disable=dangerous-default-value
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "honda" ret.carName = "honda"
if candidate in HONDA_BOSCH: if candidate in HONDA_BOSCH:
ret.safetyModel = car.CarParams.SafetyModel.hondaBoschHarness if has_relay else car.CarParams.SafetyModel.hondaBoschGiraffe ret.safetyModel = car.CarParams.SafetyModel.hondaBoschHarness
rdr_bus = 0 if has_relay else 2 ret.enableCamera = True
ret.enableCamera = is_ecu_disconnected(fingerprint[rdr_bus], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay
ret.radarOffCan = True ret.radarOffCan = True
ret.openpilotLongitudinalControl = False ret.openpilotLongitudinalControl = False
else: else:
ret.safetyModel = car.CarParams.SafetyModel.hondaNidec ret.safetyModel = car.CarParams.SafetyModel.hondaNidec
ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay ret.enableCamera = True
ret.enableGasInterceptor = 0x201 in fingerprint[0] ret.enableGasInterceptor = 0x201 in fingerprint[0]
ret.openpilotLongitudinalControl = ret.enableCamera ret.openpilotLongitudinalControl = ret.enableCamera

@ -1036,10 +1036,4 @@ SPEED_FACTOR = {
CAR.INSIGHT: 1., CAR.INSIGHT: 1.,
} }
# msgs sent for steering controller by camera module on can 0.
# those messages are mutually exclusive on CRV and non-CRV cars
ECU_FINGERPRINT = {
Ecu.fwdCamera: [0xE4, 0x194], # steer torque cmd
}
HONDA_BOSCH = set([CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G]) HONDA_BOSCH = set([CAR.ACCORD, CAR.ACCORD_15, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G])

@ -1,8 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from cereal import car from cereal import car
from selfdrive.config import Conversions as CV from selfdrive.config import Conversions as CV
from selfdrive.car.hyundai.values import Ecu, ECU_FINGERPRINT, CAR, FINGERPRINTS from selfdrive.car.hyundai.values import CAR
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.interfaces import CarInterfaceBase
class CarInterface(CarInterfaceBase): class CarInterface(CarInterfaceBase):
@ -12,8 +12,8 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0 return float(accel) / 3.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]): # pylint: disable=dangerous-default-value def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[]): # pylint: disable=dangerous-default-value
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "hyundai" ret.carName = "hyundai"
ret.safetyModel = car.CarParams.SafetyModel.hyundai ret.safetyModel = car.CarParams.SafetyModel.hyundai
@ -168,10 +168,10 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 13.75 * 1.15 ret.steerRatio = 13.75 * 1.15
tire_stiffness_factor = 0.5 tire_stiffness_factor = 0.5
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]] ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]] ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
# these cars require a special panda safety mode due to missing counters and checksums in the messages # these cars require a special panda safety mode due to missing counters and checksums in the messages
if candidate in [CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_LTD, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, CAR.SONATA_2019, if candidate in [CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_LTD, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, CAR.SONATA_2019,
CAR.KIA_NIRO_EV, CAR.KIA_OPTIMA, CAR.VELOSTER, CAR.KIA_STINGER, CAR.GENESIS_G70]: CAR.KIA_NIRO_EV, CAR.KIA_OPTIMA, CAR.VELOSTER, CAR.KIA_STINGER, CAR.GENESIS_G70]:
ret.safetyModel = car.CarParams.SafetyModel.hyundaiLegacy ret.safetyModel = car.CarParams.SafetyModel.hyundaiLegacy
@ -186,7 +186,7 @@ class CarInterface(CarInterfaceBase):
ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront, ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront,
tire_stiffness_factor=tire_stiffness_factor) tire_stiffness_factor=tire_stiffness_factor)
ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay ret.enableCamera = True
return ret return ret

@ -150,10 +150,6 @@ FINGERPRINTS = {
}] }]
} }
ECU_FINGERPRINT = {
Ecu.fwdCamera: [832, 1156, 1191, 1342]
}
# Don't use these fingerprints for fingerprinting, they are still used for ECU detection # Don't use these fingerprints for fingerprinting, they are still used for ECU detection
IGNORED_FINGERPRINTS = [CAR.VELOSTER, CAR.GENESIS_G70, CAR.KONA] IGNORED_FINGERPRINTS = [CAR.VELOSTER, CAR.GENESIS_G70, CAR.KONA]

@ -42,15 +42,15 @@ class CarInterfaceBase():
raise NotImplementedError raise NotImplementedError
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
raise NotImplementedError raise NotImplementedError
# returns a set of default params to avoid repetition in car specific params # returns a set of default params to avoid repetition in car specific params
@staticmethod @staticmethod
def get_std_params(candidate, fingerprint, has_relay): def get_std_params(candidate, fingerprint):
ret = car.CarParams.new_message() ret = car.CarParams.new_message()
ret.carFingerprint = candidate ret.carFingerprint = candidate
ret.isPandaBlack = has_relay ret.isPandaBlack = True # TODO: deprecate this field
# standard ALC params # standard ALC params
ret.steerControlType = car.CarParams.SteerControlType.torque ret.steerControlType = car.CarParams.SteerControlType.torque

@ -1,8 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from cereal import car from cereal import car
from selfdrive.config import Conversions as CV from selfdrive.config import Conversions as CV
from selfdrive.car.mazda.values import CAR, LKAS_LIMITS, FINGERPRINTS, ECU_FINGERPRINT, Ecu 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, is_ecu_disconnected from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.interfaces import CarInterfaceBase
ButtonType = car.CarState.ButtonEvent.Type ButtonType = car.CarState.ButtonEvent.Type
@ -15,8 +15,8 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0 return float(accel) / 4.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "mazda" ret.carName = "mazda"
ret.safetyModel = car.CarParams.SafetyModel.mazda ret.safetyModel = car.CarParams.SafetyModel.mazda
@ -67,7 +67,7 @@ class CarInterface(CarInterfaceBase):
ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront, ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront,
tire_stiffness_factor=tire_stiffness_factor) tire_stiffness_factor=tire_stiffness_factor)
ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay ret.enableCamera = True
return ret return ret

@ -71,10 +71,6 @@ FINGERPRINTS = {
], ],
} }
ECU_FINGERPRINT = {
Ecu.fwdCamera: [579], # steer torque cmd
}
DBC = { DBC = {
CAR.CX5: dbc_dict('mazda_2017', None), CAR.CX5: dbc_dict('mazda_2017', None),

@ -33,8 +33,8 @@ class CarInterface(CarInterfaceBase):
return accel return accel
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "mock" ret.carName = "mock"
ret.safetyModel = car.CarParams.SafetyModel.noOutput ret.safetyModel = car.CarParams.SafetyModel.noOutput
ret.mass = 1700. ret.mass = 1700.

@ -14,9 +14,9 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0 return float(accel) / 4.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "nissan" ret.carName = "nissan"
ret.safetyModel = car.CarParams.SafetyModel.nissan ret.safetyModel = car.CarParams.SafetyModel.nissan

@ -11,8 +11,8 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0 return float(accel) / 4.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "subaru" ret.carName = "subaru"
ret.radarOffCan = True ret.radarOffCan = True
@ -24,11 +24,8 @@ class CarInterface(CarInterfaceBase):
# Subaru port is a community feature, since we don't own one to test # Subaru port is a community feature, since we don't own one to test
ret.communityFeature = True ret.communityFeature = True
ret.dashcamOnly = candidate in PREGLOBAL_CARS ret.dashcamOnly = candidate in PREGLOBAL_CARS
# force openpilot to fake the stock camera, since car harness is not supported yet and old style giraffe (with switches)
# was never released
ret.enableCamera = True ret.enableCamera = True
ret.steerRateCost = 0.7 ret.steerRateCost = 0.7

@ -78,10 +78,6 @@ STEER_THRESHOLD = {
CAR.OUTBACK_PREGLOBAL_2018: 75, CAR.OUTBACK_PREGLOBAL_2018: 75,
} }
ECU_FINGERPRINT = {
Ecu.fwdCamera: [290, 356], # steer torque cmd
}
DBC = { DBC = {
CAR.ASCENT: dbc_dict('subaru_global_2017_generated', None), CAR.ASCENT: dbc_dict('subaru_global_2017_generated', None),
CAR.IMPREZA: dbc_dict('subaru_global_2017_generated', None), CAR.IMPREZA: dbc_dict('subaru_global_2017_generated', None),

@ -25,36 +25,35 @@ class TestCarInterfaces(unittest.TestCase):
car_fw = [] car_fw = []
for has_relay in [True, False]: car_params = CarInterface.get_params(car_name, fingerprints, car_fw)
car_params = CarInterface.get_params(car_name, fingerprints, has_relay, car_fw) car_interface = CarInterface(car_params, CarController, CarState)
car_interface = CarInterface(car_params, CarController, CarState) assert car_params
assert car_params assert car_interface
assert car_interface
self.assertGreater(car_params.mass, 1) self.assertGreater(car_params.mass, 1)
self.assertGreater(car_params.steerRateCost, 1e-3) self.assertGreater(car_params.steerRateCost, 1e-3)
tuning = car_params.lateralTuning.which() tuning = car_params.lateralTuning.which()
if tuning == 'pid': if tuning == 'pid':
self.assertTrue(len(car_params.lateralTuning.pid.kpV)) self.assertTrue(len(car_params.lateralTuning.pid.kpV))
elif tuning == 'lqr': elif tuning == 'lqr':
self.assertTrue(len(car_params.lateralTuning.lqr.a)) self.assertTrue(len(car_params.lateralTuning.lqr.a))
elif tuning == 'indi': elif tuning == 'indi':
self.assertGreater(car_params.lateralTuning.indi.outerLoopGain, 1e-3) self.assertGreater(car_params.lateralTuning.indi.outerLoopGain, 1e-3)
# Run car interface # Run car interface
CC = car.CarControl.new_message() CC = car.CarControl.new_message()
for _ in range(10): for _ in range(10):
car_interface.update(CC, []) car_interface.update(CC, [])
car_interface.apply(CC) car_interface.apply(CC)
car_interface.apply(CC) car_interface.apply(CC)
CC = car.CarControl.new_message() CC = car.CarControl.new_message()
CC.enabled = True CC.enabled = True
for _ in range(10): for _ in range(10):
car_interface.update(CC, []) car_interface.update(CC, [])
car_interface.apply(CC) car_interface.apply(CC)
car_interface.apply(CC) car_interface.apply(CC)
# Test radar interface # Test radar interface
RadarInterface = importlib.import_module('selfdrive.car.%s.radar_interface' % car_params.carName).RadarInterface RadarInterface = importlib.import_module('selfdrive.car.%s.radar_interface' % car_params.carName).RadarInterface

@ -14,8 +14,8 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 3.0 return float(accel) / 3.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=[]): # pylint: disable=dangerous-default-value def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[]): # pylint: disable=dangerous-default-value
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
ret.carName = "toyota" ret.carName = "toyota"
ret.safetyModel = car.CarParams.SafetyModel.toyota ret.safetyModel = car.CarParams.SafetyModel.toyota
@ -275,7 +275,7 @@ class CarInterface(CarInterfaceBase):
ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront, ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront,
tire_stiffness_factor=tire_stiffness_factor) tire_stiffness_factor=tire_stiffness_factor)
ret.enableCamera = is_ecu_disconnected(fingerprint[0], FINGERPRINTS, ECU_FINGERPRINT, candidate, Ecu.fwdCamera) or has_relay ret.enableCamera = True
# Detect smartDSU, which intercepts ACC_CMD from the DSU allowing openpilot to send it # Detect smartDSU, which intercepts ACC_CMD from the DSU allowing openpilot to send it
smartDsu = 0x2FF in fingerprint[0] smartDsu = 0x2FF in fingerprint[0]
# In TSS2 cars the camera does long control # In TSS2 cars the camera does long control
@ -327,8 +327,6 @@ class CarInterface(CarInterfaceBase):
# events # events
events = self.create_common_events(ret) events = self.create_common_events(ret)
if self.cp_cam.can_invalid_cnt >= 200 and self.CP.enableCamera and not self.CP.isPandaBlack:
events.add(EventName.invalidGiraffeToyota)
if self.CS.low_speed_lockout and self.CP.openpilotLongitudinalControl: if self.CS.low_speed_lockout and self.CP.openpilotLongitudinalControl:
events.add(EventName.lowSpeedLockout) events.add(EventName.lowSpeedLockout)
if ret.vEgo < self.CP.minEnableSpeed and self.CP.openpilotLongitudinalControl: if ret.vEgo < self.CP.minEnableSpeed and self.CP.openpilotLongitudinalControl:

@ -18,8 +18,8 @@ class CarInterface(CarInterfaceBase):
return float(accel) / 4.0 return float(accel) / 4.0
@staticmethod @staticmethod
def get_params(candidate, fingerprint=gen_empty_fingerprint(), has_relay=False, car_fw=None): def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None):
ret = CarInterfaceBase.get_std_params(candidate, fingerprint, has_relay) ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
# VW port is a community feature, since we don't own one to test # VW port is a community feature, since we don't own one to test
ret.communityFeature = True ret.communityFeature = True

@ -61,12 +61,10 @@ class Controls:
self.can_sock = messaging.sub_sock('can', timeout=can_timeout) self.can_sock = messaging.sub_sock('can', timeout=can_timeout)
# wait for one health and one CAN packet # wait for one health and one CAN packet
hw_type = messaging.recv_one(self.sm.sock['health']).health.hwType
has_relay = hw_type in [HwType.blackPanda, HwType.uno, HwType.dos]
print("Waiting for CAN messages...") print("Waiting for CAN messages...")
get_one_can(self.can_sock) get_one_can(self.can_sock)
self.CI, self.CP = get_car(self.can_sock, self.pm.sock['sendcan'], has_relay) self.CI, self.CP = get_car(self.can_sock, self.pm.sock['sendcan'])
# read params # read params
params = Params() params = Params()
@ -131,7 +129,7 @@ class Controls:
self.sm['dMonitoringState'].awarenessStatus = 1. self.sm['dMonitoringState'].awarenessStatus = 1.
self.sm['dMonitoringState'].faceDetected = False self.sm['dMonitoringState'].faceDetected = False
self.startup_event = get_startup_event(car_recognized, controller_available, hw_type) self.startup_event = get_startup_event(car_recognized, controller_available)
if not sounds_available: if not sounds_available:
self.events.add(EventName.soundsUnavailable, static=True) self.events.add(EventName.soundsUnavailable, static=True)
@ -141,8 +139,6 @@ class Controls:
self.events.add(EventName.communityFeatureDisallowed, static=True) self.events.add(EventName.communityFeatureDisallowed, static=True)
if not car_recognized: if not car_recognized:
self.events.add(EventName.carUnrecognized, static=True) self.events.add(EventName.carUnrecognized, static=True)
if hw_type == HwType.whitePanda:
self.events.add(EventName.whitePandaUnsupported, static=True)
# controlsd is driven by can recv, expected at 100Hz # controlsd is driven by can recv, expected at 100Hz
self.rk = Ratekeeper(100, print_delay_threshold=None) self.rk = Ratekeeper(100, print_delay_threshold=None)

@ -36,5 +36,9 @@
"Offroad_NeosUpdate": { "Offroad_NeosUpdate": {
"text": "An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install.", "text": "An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install.",
"severity": 0 "severity": 0
},
"Offroad_HardwareUnsupported": {
"text": "White and grey panda are unsupported. Upgrade to comma two or black panda.",
"severity": 0
} }
} }

@ -252,31 +252,6 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.),
}, },
EventName.startupGreyPanda: {
ET.PERMANENT: Alert(
"WARNING: Grey panda is deprecated",
"Upgrade to comma two or black panda",
AlertStatus.userPrompt, AlertSize.mid,
Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.),
},
EventName.invalidGiraffeToyota: {
ET.PERMANENT: Alert(
"Unsupported Giraffe Configuration",
"Visit comma.ai/tg",
AlertStatus.normal, AlertSize.mid,
Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
},
EventName.whitePandaUnsupported: {
ET.PERMANENT: Alert(
"White Panda No Longer Supported",
"Upgrade to comma two or black panda",
AlertStatus.normal, AlertSize.mid,
Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
ET.NO_ENTRY: NoEntryAlert("Unsupported Hardware"),
},
EventName.invalidLkasSetting: { EventName.invalidLkasSetting: {
ET.PERMANENT: Alert( ET.PERMANENT: Alert(
"Stock LKAS is turned on", "Stock LKAS is turned on",

@ -6,7 +6,6 @@
# - connect to a Panda # - connect to a Panda
# - run selfdrive/boardd/boardd # - run selfdrive/boardd/boardd
# - launching this script # - launching this script
# - turn on the car in STOCK MODE (set giraffe switches properly).
# Note: it's very important that the car is in stock mode, in order to collect a complete fingerprint # Note: it's very important that the car is in stock mode, in order to collect a complete fingerprint
# - since some messages are published at low frequency, keep this script running for at least 30s, # - since some messages are published at low frequency, keep this script running for at least 30s,
# until all messages are received at least once # until all messages are received at least once

@ -325,6 +325,7 @@ def setup_output():
class LongitudinalControl(unittest.TestCase): class LongitudinalControl(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
os.environ['SKIP_FW_QUERY'] = "1"
os.environ['NO_CAN_TIMEOUT'] = "1" os.environ['NO_CAN_TIMEOUT'] = "1"
setup_output() setup_output()

@ -75,10 +75,6 @@ class DumbSocket:
# lists # lists
dat = messaging.new_message(s, 0) dat = messaging.new_message(s, 0)
# TODO: remove this after deprecated all hw without a relay
if s == "health":
dat.health.hwType = log.HealthData.HwType.uno
self.data = dat.to_bytes() self.data = dat.to_bytes()
def receive(self, non_blocking=False): def receive(self, non_blocking=False):

@ -1 +1 @@
f863303a303348b27d624a1e301857ec0b432e17 f863303a303348b27d624a1e301857ec0b432e17

@ -30,6 +30,12 @@ ignore_can_valid = [
"TOYOTA AVALON 2016", "TOYOTA AVALON 2016",
"HONDA PILOT 2019 ELITE", "HONDA PILOT 2019 ELITE",
"HYUNDAI SANTA FE LIMITED 2019", "HYUNDAI SANTA FE LIMITED 2019",
# TODO: get new routes for these cars, current routes are from giraffe with different buses
"HONDA CR-V 2019 HYBRID",
"HONDA ACCORD 2018 SPORT 2T",
"HONDA INSIGHT 2019 TOURING",
"HONDA ACCORD 2018 HYBRID TOURING",
] ]
@parameterized_class(('car_model'), [(car,) for car in all_known_cars()]) @parameterized_class(('car_model'), [(car,) for car in all_known_cars()])
@ -53,7 +59,6 @@ class TestCarModel(unittest.TestCase):
if seg == 0: if seg == 0:
raise raise
has_relay = False
can_msgs = [] can_msgs = []
fingerprint = {i: dict() for i in range(3)} fingerprint = {i: dict() for i in range(3)}
for msg in lr: for msg in lr:
@ -62,41 +67,38 @@ class TestCarModel(unittest.TestCase):
if m.src < 128: if m.src < 128:
fingerprint[m.src][m.address] = len(m.dat) fingerprint[m.src][m.address] = len(m.dat)
can_msgs.append(msg) can_msgs.append(msg)
elif msg.which() == "health":
has_relay = msg.health.hwType in [HwType.blackPanda, HwType.uno, HwType.dos]
cls.can_msgs = sorted(can_msgs, key=lambda msg: msg.logMonoTime) cls.can_msgs = sorted(can_msgs, key=lambda msg: msg.logMonoTime)
CarInterface, CarController, CarState = interfaces[cls.car_model] CarInterface, CarController, CarState = interfaces[cls.car_model]
# TODO: test with relay and without cls.CP = CarInterface.get_params(cls.car_model, fingerprint, [])
cls.car_params = CarInterface.get_params(cls.car_model, fingerprint, has_relay, []) assert cls.CP
assert cls.car_params
cls.CI = CarInterface(cls.car_params, CarController, CarState) cls.CI = CarInterface(cls.CP, CarController, CarState)
assert cls.CI assert cls.CI
def test_car_params(self): def test_car_params(self):
if self.car_params.dashcamOnly: if self.CP.dashcamOnly:
self.skipTest("no need to check carParams for dashcamOnly") self.skipTest("no need to check carParams for dashcamOnly")
# make sure car params are within a valid range # make sure car params are within a valid range
self.assertGreater(self.car_params.mass, 1) self.assertGreater(self.CP.mass, 1)
self.assertGreater(self.car_params.steerRateCost, 1e-3) self.assertGreater(self.CP.steerRateCost, 1e-3)
tuning = self.car_params.lateralTuning.which() tuning = self.CP.lateralTuning.which()
if tuning == 'pid': if tuning == 'pid':
self.assertTrue(len(self.car_params.lateralTuning.pid.kpV)) self.assertTrue(len(self.CP.lateralTuning.pid.kpV))
elif tuning == 'lqr': elif tuning == 'lqr':
self.assertTrue(len(self.car_params.lateralTuning.lqr.a)) self.assertTrue(len(self.CP.lateralTuning.lqr.a))
elif tuning == 'indi': elif tuning == 'indi':
self.assertGreater(self.car_params.lateralTuning.indi.outerLoopGain, 1e-3) self.assertGreater(self.CP.lateralTuning.indi.outerLoopGain, 1e-3)
self.assertTrue(self.car_params.enableCamera) self.assertTrue(self.CP.enableCamera)
# TODO: check safetyModel is in release panda build # TODO: check safetyModel is in release panda build
safety = libpandasafety_py.libpandasafety safety = libpandasafety_py.libpandasafety
set_status = safety.set_safety_hooks(self.car_params.safetyModel.raw, self.car_params.safetyParam) set_status = safety.set_safety_hooks(self.CP.safetyModel.raw, self.CP.safetyParam)
self.assertEqual(0, set_status, f"failed to set safetyModel {self.car_params.safetyModel}") self.assertEqual(0, set_status, f"failed to set safetyModel {self.CP.safetyModel}")
def test_car_interface(self): def test_car_interface(self):
# TODO: also check for checkusm and counter violations from can parser # TODO: also check for checkusm and counter violations from can parser
@ -115,8 +117,8 @@ class TestCarModel(unittest.TestCase):
def test_radar_interface(self): def test_radar_interface(self):
os.environ['NO_RADAR_SLEEP'] = "1" os.environ['NO_RADAR_SLEEP'] = "1"
RadarInterface = importlib.import_module('selfdrive.car.%s.radar_interface' % self.car_params.carName).RadarInterface RadarInterface = importlib.import_module('selfdrive.car.%s.radar_interface' % self.CP.carName).RadarInterface
RI = RadarInterface(self.car_params) RI = RadarInterface(self.CP)
assert RI assert RI
error_cnt = 0 error_cnt = 0
@ -127,11 +129,11 @@ class TestCarModel(unittest.TestCase):
self.assertLess(error_cnt, 20) self.assertLess(error_cnt, 20)
def test_panda_safety_rx(self): def test_panda_safety_rx(self):
if self.car_params.dashcamOnly: if self.CP.dashcamOnly:
self.skipTest("no need to check panda safety for dashcamOnly") self.skipTest("no need to check panda safety for dashcamOnly")
safety = libpandasafety_py.libpandasafety safety = libpandasafety_py.libpandasafety
set_status = safety.set_safety_hooks(self.car_params.safetyModel.raw, self.car_params.safetyParam) set_status = safety.set_safety_hooks(self.CP.safetyModel.raw, self.CP.safetyParam)
self.assertEqual(0, set_status) self.assertEqual(0, set_status)
failed_addrs = Counter() failed_addrs = Counter()

@ -9,7 +9,6 @@ from common.params import Params, put_nonblocking
from common.hardware import TICI from common.hardware import TICI
from selfdrive.swaglog import cloudlog from selfdrive.swaglog import cloudlog
PANDA_OUTPUT_VOLTAGE = 5.28
CAR_VOLTAGE_LOW_PASS_K = 0.091 # LPF gain for 5s tau (dt/tau / (dt/tau + 1)) CAR_VOLTAGE_LOW_PASS_K = 0.091 # LPF gain for 5s tau (dt/tau / (dt/tau + 1))
# A C2 uses about 1W while idling, and 30h seens like a good shutoff for most cars # A C2 uses about 1W while idling, and 30h seens like a good shutoff for most cars
@ -62,11 +61,6 @@ def _read_param(path, parser, default=0):
return default return default
def panda_current_to_actual_current(panda_current):
# From white/grey panda schematic
return (3.3 - (panda_current * 3.3 / 4096)) / 8.25
class PowerMonitoring: class PowerMonitoring:
def __init__(self): def __init__(self):
self.params = Params() self.params = Params()
@ -135,11 +129,6 @@ class PowerMonitoring:
# If the battery is discharging, we can use this measurement # If the battery is discharging, we can use this measurement
# On C2: this is low by about 10-15%, probably mostly due to UNO draw not being factored in # On C2: this is low by about 10-15%, probably mostly due to UNO draw not being factored in
current_power = ((get_battery_voltage() / 1000000) * (get_battery_current() / 1000000)) current_power = ((get_battery_voltage() / 1000000) * (get_battery_current() / 1000000))
elif (health.health.hwType in [log.HealthData.HwType.whitePanda, log.HealthData.HwType.greyPanda]) and (health.health.current > 1):
# If white/grey panda, use the integrated current measurements if the measurement is not 0
# If the measurement is 0, the current is 400mA or greater, and out of the measurement range of the panda
# This seems to be accurate to about 5%
current_power = (PANDA_OUTPUT_VOLTAGE * panda_current_to_actual_current(health.health.current))
elif (self.next_pulsed_measurement_time is not None) and (self.next_pulsed_measurement_time <= now): elif (self.next_pulsed_measurement_time is not None) and (self.next_pulsed_measurement_time <= now):
# TODO: Figure out why this is off by a factor of 3/4??? # TODO: Figure out why this is off by a factor of 3/4???
FUDGE_FACTOR = 1.33 FUDGE_FACTOR = 1.33

@ -18,8 +18,7 @@ def mock_sec_since_boot():
with patch("common.realtime.sec_since_boot", new=mock_sec_since_boot): with patch("common.realtime.sec_since_boot", new=mock_sec_since_boot):
with patch("common.params.put_nonblocking", new=params.put): with patch("common.params.put_nonblocking", new=params.put):
from selfdrive.thermald.power_monitoring import PowerMonitoring, CAR_BATTERY_CAPACITY_uWh, \ from selfdrive.thermald.power_monitoring import PowerMonitoring, CAR_BATTERY_CAPACITY_uWh, \
PANDA_OUTPUT_VOLTAGE, CAR_CHARGING_RATE_W, \ CAR_CHARGING_RATE_W, VBATT_PAUSE_CHARGING
VBATT_PAUSE_CHARGING
def actual_current_to_panda_current(actual_current): def actual_current_to_panda_current(actual_current):
return max(int(((3.3 - (actual_current * 8.25)) * 4096) / 3.3), 0) return max(int(((3.3 - (actual_current * 8.25)) * 4096) / 3.3), 0)
@ -66,16 +65,6 @@ class TestPowerMonitoring(unittest.TestCase):
pm.calculate(self.mock_health(True, hw_type)) pm.calculate(self.mock_health(True, hw_type))
self.assertEqual(pm.get_power_used(), 0) self.assertEqual(pm.get_power_used(), 0)
# Test to see that it integrates with white/grey panda while charging
@parameterized.expand([(log.HealthData.HwType.whitePanda,), (log.HealthData.HwType.greyPanda,)])
def test_offroad_integration_white(self, hw_type):
with pm_patch("get_battery_voltage", 4e6), pm_patch("get_battery_current", 1e5), pm_patch("get_battery_status", "Charging"):
pm = PowerMonitoring()
for _ in range(TEST_DURATION_S + 1):
pm.calculate(self.mock_health(False, hw_type, current=0.1))
expected_power_usage = ((TEST_DURATION_S/3600) * (0.1 * PANDA_OUTPUT_VOLTAGE) * 1e6)
self.assertLess(abs(pm.get_power_used() - expected_power_usage), 10)
# Test to see that it integrates with discharging battery # Test to see that it integrates with discharging battery
@parameterized.expand(ALL_PANDA_TYPES) @parameterized.expand(ALL_PANDA_TYPES)
def test_offroad_integration_discharging(self, hw_type): def test_offroad_integration_discharging(self, hw_type):

@ -198,7 +198,6 @@ def thermald_thread():
should_start_prev = False should_start_prev = False
handle_fan = None handle_fan = None
is_uno = False is_uno = False
has_relay = False
params = Params() params = Params()
pm = PowerMonitoring() pm = PowerMonitoring()
@ -229,7 +228,6 @@ def thermald_thread():
# Setup fan handler on first connect to panda # Setup fan handler on first connect to panda
if handle_fan is None and health.health.hwType != log.HealthData.HwType.unknown: if handle_fan is None and health.health.hwType != log.HealthData.HwType.unknown:
is_uno = health.health.hwType == log.HealthData.HwType.uno is_uno = health.health.hwType == log.HealthData.HwType.uno
has_relay = health.health.hwType in [log.HealthData.HwType.blackPanda, log.HealthData.HwType.uno, log.HealthData.HwType.dos]
if (not EON) or is_uno: if (not EON) or is_uno:
cloudlog.info("Setting up UNO fan handler") cloudlog.info("Setting up UNO fan handler")
@ -286,7 +284,7 @@ def thermald_thread():
# since going onroad increases load and can make temps go over 107 # since going onroad increases load and can make temps go over 107
# We only do this if there is a relay that prevents the car from faulting # We only do this if there is a relay that prevents the car from faulting
is_offroad_for_5_min = (started_ts is None) and ((not started_seen) or (off_ts is None) or (sec_since_boot() - off_ts > 60 * 5)) is_offroad_for_5_min = (started_ts is None) and ((not started_seen) or (off_ts is None) or (sec_since_boot() - off_ts > 60 * 5))
if max_cpu_temp > 107. or bat_temp >= 63. or (has_relay and is_offroad_for_5_min and max_cpu_temp > 70.0): if max_cpu_temp > 107. or bat_temp >= 63. or (is_offroad_for_5_min and max_cpu_temp > 70.0):
# onroad not allowed # onroad not allowed
thermal_status = ThermalStatus.danger thermal_status = ThermalStatus.danger
elif max_comp_temp > 96.0 or bat_temp > 60.: elif max_comp_temp > 96.0 or bat_temp > 60.:
@ -350,7 +348,6 @@ def thermald_thread():
startup_conditions["not_uninstalling"] = not params.get("DoUninstall") == b"1" startup_conditions["not_uninstalling"] = not params.get("DoUninstall") == b"1"
startup_conditions["accepted_terms"] = params.get("HasAcceptedTerms") == terms_version startup_conditions["accepted_terms"] = params.get("HasAcceptedTerms") == terms_version
completed_training = params.get("CompletedTrainingVersion") == training_version
panda_signature = params.get("PandaFirmware") panda_signature = params.get("PandaFirmware")
startup_conditions["fw_version_match"] = (panda_signature is None) or (panda_signature == FW_SIGNATURE) # don't show alert is no panda is connected (None) startup_conditions["fw_version_match"] = (panda_signature is None) or (panda_signature == FW_SIGNATURE) # don't show alert is no panda is connected (None)
@ -358,7 +355,8 @@ def thermald_thread():
# with 2% left, we killall, otherwise the phone will take a long time to boot # with 2% left, we killall, otherwise the phone will take a long time to boot
startup_conditions["free_space"] = msg.thermal.freeSpace > 0.02 startup_conditions["free_space"] = msg.thermal.freeSpace > 0.02
startup_conditions["completed_training"] = completed_training or (current_branch in ['dashcam', 'dashcam-staging']) startup_conditions["completed_training"] = params.get("CompletedTrainingVersion") == training_version or \
(current_branch in ['dashcam', 'dashcam-staging'])
startup_conditions["not_driver_view"] = not params.get("IsDriverViewEnabled") == b"1" startup_conditions["not_driver_view"] = not params.get("IsDriverViewEnabled") == b"1"
startup_conditions["not_taking_snapshot"] = not params.get("IsTakingSnapshot") == b"1" startup_conditions["not_taking_snapshot"] = not params.get("IsTakingSnapshot") == b"1"
# if any CPU gets above 107 or the battery gets above 63, kill all processes # if any CPU gets above 107 or the battery gets above 63, kill all processes
@ -367,6 +365,9 @@ def thermald_thread():
set_offroad_alert_if_changed("Offroad_TemperatureTooHigh", (not startup_conditions["device_temp_good"])) set_offroad_alert_if_changed("Offroad_TemperatureTooHigh", (not startup_conditions["device_temp_good"]))
should_start = all(startup_conditions.values()) should_start = all(startup_conditions.values())
startup_conditions["hardware_supported"] = health is not None and health.health.hwType not in [log.HealthData.HwType.whitePanda, log.HealthData.HwType.greyPanda]
set_offroad_alert_if_changed("Offroad_HardwareUnsupported", not startup_conditions["hardware_supported"])
if should_start: if should_start:
if not should_start_prev: if not should_start_prev:
params.delete("IsOffroad") params.delete("IsOffroad")

@ -14,7 +14,6 @@ def steer_thread():
poller = messaging.Poller() poller = messaging.Poller()
logcan = messaging.sub_sock('can') logcan = messaging.sub_sock('can')
health = messaging.sub_sock('health')
joystick_sock = messaging.sub_sock('testJoystick', conflate=True, poller=poller) joystick_sock = messaging.sub_sock('testJoystick', conflate=True, poller=poller)
carstate = messaging.pub_sock('carState') carstate = messaging.pub_sock('carState')
@ -24,13 +23,11 @@ def steer_thread():
button_1_last = 0 button_1_last = 0
enabled = False enabled = False
# wait for health and CAN packets # wait for CAN packets
hw_type = messaging.recv_one(health).health.hwType
has_relay = hw_type in [HwType.blackPanda, HwType.uno, HwType.dos]
print("Waiting for CAN messages...") print("Waiting for CAN messages...")
get_one_can(logcan) get_one_can(logcan)
CI, CP = get_car(logcan, sendcan, has_relay) CI, CP = get_car(logcan, sendcan)
Params().put("CarParams", CP.to_bytes()) Params().put("CarParams", CP.to_bytes())
CC = car.CarControl.new_message() CC = car.CarControl.new_message()

@ -5,7 +5,7 @@ What's needed:
- Python 3.8.2 - Python 3.8.2
- GPU (recommended) - GPU (recommended)
- Two USB webcams, at least 720p and 78 degrees FOV (e.g. Logitech C920/C615) - Two USB webcams, at least 720p and 78 degrees FOV (e.g. Logitech C920/C615)
- [Car harness](https://comma.ai/shop/products/comma-car-harness) with black panda (or the outdated grey panda/giraffe combo) to connect to your car - [Car harness](https://comma.ai/shop/products/comma-car-harness) with black panda to connect to your car
- [Panda paw](https://comma.ai/shop/products/panda-paw) (or USB-A to USB-A cable) to connect panda to your computer - [Panda paw](https://comma.ai/shop/products/panda-paw) (or USB-A to USB-A cable) to connect panda to your computer
- Tape, Charger, ... - Tape, Charger, ...
That's it! That's it!

Loading…
Cancel
Save