mirror of https://github.com/commaai/openpilot.git
GM: enforce steering command message timing (#27250)
* draft
* bump opendbc
* still draft
* that's not right
* superset of the changes, 33hz
* cleanup
* this should work
* remove line
* pass it in again
* actually no need to check updated now
* now_nanos
* consistent name
* fix replay
* one line isn't that bad
switch
switch
* fix CarController tests
* Update ref_commit
old-commit-hash: 8f5057ff2d
This commit is contained in:
parent
2d4faa20be
commit
acc8e38111
|
@ -35,7 +35,7 @@ class CarController:
|
|||
torque -= deadband
|
||||
return torque
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
|
||||
torque_l = 0
|
||||
torque_r = 0
|
||||
|
|
|
@ -43,5 +43,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -19,7 +19,7 @@ class CarController:
|
|||
self.packer = CANPacker(dbc_name)
|
||||
self.params = CarControllerParams(CP)
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
can_sends = []
|
||||
|
||||
lkas_active = CC.latActive and self.lkas_control_bit_prev
|
||||
|
|
|
@ -106,5 +106,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -21,7 +21,7 @@ class CarController:
|
|||
self.lkas_enabled_last = False
|
||||
self.steer_alert_last = False
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
can_sends = []
|
||||
|
||||
actuators = CC.actuators
|
||||
|
|
|
@ -78,5 +78,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -13,6 +13,8 @@ LongCtrlState = car.CarControl.Actuators.LongControlState
|
|||
|
||||
# Camera cancels up to 0.1s after brake is pressed, ECM allows 0.5s
|
||||
CAMERA_CANCEL_DELAY_FRAMES = 10
|
||||
# Enforce a minimum interval between steering messages to avoid a fault
|
||||
MIN_STEER_MSG_INTERVAL_MS = 15
|
||||
|
||||
|
||||
class CarController:
|
||||
|
@ -37,7 +39,7 @@ class CarController:
|
|||
self.packer_obj = CANPacker(DBC[self.CP.carFingerprint]['radar'])
|
||||
self.packer_ch = CANPacker(DBC[self.CP.carFingerprint]['chassis'])
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
hud_alert = hud_control.visualAlert
|
||||
|
@ -64,9 +66,10 @@ class CarController:
|
|||
self.lka_steering_cmd_counter += 1
|
||||
self.sent_lka_steering_cmd = True
|
||||
|
||||
# Avoid GM EPS faults when transmitting messages too close together: skip this transmit if we just
|
||||
# received the ASCMLKASteeringCmd loopback confirmation in the current CS frame
|
||||
if (self.frame - self.last_steer_frame) >= steer_step and not CS.loopback_lka_steering_cmd_updated:
|
||||
# Avoid GM EPS faults when transmitting messages too close together: skip this transmit if we
|
||||
# received the ASCMLKASteeringCmd loopback confirmation too recently
|
||||
last_lka_steer_msg_ms = (now_nanos - CS.loopback_lka_steering_cmd_ts_nanos) * 1e-6
|
||||
if (self.frame - self.last_steer_frame) >= steer_step and last_lka_steer_msg_ms > MIN_STEER_MSG_INTERVAL_MS:
|
||||
# Initialize ASCMLKASteeringCmd counter using the camera until we get a msg on the bus
|
||||
if not self.sent_lka_steering_cmd:
|
||||
self.lka_steering_cmd_counter = CS.pt_lka_steering_cmd_counter + 1
|
||||
|
|
|
@ -18,6 +18,7 @@ class CarState(CarStateBase):
|
|||
can_define = CANDefine(DBC[CP.carFingerprint]["pt"])
|
||||
self.shifter_values = can_define.dv["ECMPRDNL2"]["PRNDL2"]
|
||||
self.loopback_lka_steering_cmd_updated = False
|
||||
self.loopback_lka_steering_cmd_ts_nanos = 0
|
||||
self.pt_lka_steering_cmd_counter = 0
|
||||
self.cam_lka_steering_cmd_counter = 0
|
||||
self.buttons_counter = 0
|
||||
|
@ -33,6 +34,7 @@ class CarState(CarStateBase):
|
|||
|
||||
# Variables used for avoiding LKAS faults
|
||||
self.loopback_lka_steering_cmd_updated = len(loopback_cp.vl_all["ASCMLKASteeringCmd"]["RollingCounter"]) > 0
|
||||
self.loopback_lka_steering_cmd_ts_nanos = loopback_cp.ts_nanos["ASCMLKASteeringCmd"]["RollingCounter"]
|
||||
if self.CP.networkLocation == NetworkLocation.fwdCamera:
|
||||
self.pt_lka_steering_cmd_counter = pt_cp.vl["ASCMLKASteeringCmd"]["RollingCounter"]
|
||||
self.cam_lka_steering_cmd_counter = cam_cp.vl["ASCMLKASteeringCmd"]["RollingCounter"]
|
||||
|
|
|
@ -236,5 +236,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -124,7 +124,7 @@ class CarController:
|
|||
self.brake = 0.0
|
||||
self.last_steer = 0.0
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
hud_v_cruise = hud_control.setSpeed * CV.MS_TO_KPH if hud_control.speedVisible else 255
|
||||
|
|
|
@ -348,5 +348,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
# pass in a car.CarControl
|
||||
# to be called @ 100hz
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -54,7 +54,7 @@ class CarController:
|
|||
self.car_fingerprint = CP.carFingerprint
|
||||
self.last_button_frame = 0
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
|
||||
|
|
|
@ -330,5 +330,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -233,7 +233,7 @@ class CarInterfaceBase(ABC):
|
|||
return reader
|
||||
|
||||
@abstractmethod
|
||||
def apply(self, c: car.CarControl) -> Tuple[car.CarControl.Actuators, List[bytes]]:
|
||||
def apply(self, c: car.CarControl, now_nanos: int) -> Tuple[car.CarControl.Actuators, List[bytes]]:
|
||||
pass
|
||||
|
||||
def create_common_events(self, cs_out, extra_gears=None, pcm_enable=True, allow_enable=True,
|
||||
|
|
|
@ -15,7 +15,7 @@ class CarController:
|
|||
self.brake_counter = 0
|
||||
self.frame = 0
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
can_sends = []
|
||||
|
||||
apply_steer = 0
|
||||
|
|
|
@ -69,5 +69,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -57,7 +57,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
def apply(self, c, now_nanos):
|
||||
# in mock no carcontrols
|
||||
actuators = car.CarControl.Actuators.new_message()
|
||||
return actuators, []
|
||||
|
|
|
@ -18,7 +18,7 @@ class CarController:
|
|||
|
||||
self.packer = CANPacker(dbc_name)
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
|
|
@ -56,5 +56,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -19,7 +19,7 @@ class CarController:
|
|||
self.p = CarControllerParams(CP)
|
||||
self.packer = CANPacker(DBC[CP.carFingerprint]['pt'])
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
|
|
@ -112,5 +112,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -14,7 +14,7 @@ class CarController:
|
|||
self.pt_packer = CANPacker(DBC[CP.carFingerprint]['pt'])
|
||||
self.tesla_can = TeslaCAN(self.packer, self.pt_packer)
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
||||
|
|
|
@ -58,5 +58,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -59,15 +59,15 @@ class TestCarInterfaces(unittest.TestCase):
|
|||
CC = car.CarControl.new_message()
|
||||
for _ in range(10):
|
||||
car_interface.update(CC, [])
|
||||
car_interface.apply(CC)
|
||||
car_interface.apply(CC)
|
||||
car_interface.apply(CC, 0)
|
||||
car_interface.apply(CC, 0)
|
||||
|
||||
CC = car.CarControl.new_message()
|
||||
CC.enabled = True
|
||||
for _ in range(10):
|
||||
car_interface.update(CC, [])
|
||||
car_interface.apply(CC)
|
||||
car_interface.apply(CC)
|
||||
car_interface.apply(CC, 0)
|
||||
car_interface.apply(CC, 0)
|
||||
|
||||
# Test radar interface
|
||||
RadarInterface = importlib.import_module(f'selfdrive.car.{car_params.carName}.radar_interface').RadarInterface
|
||||
|
|
|
@ -149,7 +149,7 @@ class TestCarModelBase(unittest.TestCase):
|
|||
|
||||
for i, msg in enumerate(self.can_msgs):
|
||||
CS = self.CI.update(CC, (msg.as_builder().to_bytes(),))
|
||||
self.CI.apply(CC)
|
||||
self.CI.apply(CC, msg.logMonoTime)
|
||||
|
||||
if CS.canValid:
|
||||
can_valid = True
|
||||
|
|
|
@ -34,7 +34,7 @@ class CarController:
|
|||
self.gas = 0
|
||||
self.accel = 0
|
||||
|
||||
def update(self, CC, CS):
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
|
|
@ -263,5 +263,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
# pass in a car.CarControl
|
||||
# to be called @ 100hz
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, now_nanos)
|
||||
|
|
|
@ -24,7 +24,7 @@ class CarController:
|
|||
self.hcaSameTorqueCount = 0
|
||||
self.hcaEnabledFrameCount = 0
|
||||
|
||||
def update(self, CC, CS, ext_bus):
|
||||
def update(self, CC, CS, ext_bus, now_nanos):
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
can_sends = []
|
||||
|
|
|
@ -244,5 +244,5 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS, self.ext_bus)
|
||||
def apply(self, c, now_nanos):
|
||||
return self.CC.update(c, self.CS, self.ext_bus, now_nanos)
|
||||
|
|
|
@ -187,6 +187,7 @@ class Controls:
|
|||
|
||||
# TODO: no longer necessary, aside from process replay
|
||||
self.sm['liveParameters'].valid = True
|
||||
self.can_log_mono_time = 0
|
||||
|
||||
self.startup_event = get_startup_event(car_recognized, controller_available, len(self.CP.carFw) > 0)
|
||||
|
||||
|
@ -425,6 +426,8 @@ class Controls:
|
|||
# Update carState from CAN
|
||||
can_strs = messaging.drain_sock_raw(self.can_sock, wait_for_one=True)
|
||||
CS = self.CI.update(self.CC, can_strs)
|
||||
if len(can_strs) and REPLAY:
|
||||
self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime
|
||||
|
||||
self.sm.update(0)
|
||||
|
||||
|
@ -731,7 +734,8 @@ class Controls:
|
|||
|
||||
if not self.read_only and self.initialized:
|
||||
# send car controls over can
|
||||
self.last_actuators, can_sends = self.CI.apply(CC)
|
||||
now_nanos = self.can_log_mono_time if REPLAY else int(sec_since_boot() * 1e9)
|
||||
self.last_actuators, can_sends = self.CI.apply(CC, now_nanos)
|
||||
self.pm.send('sendcan', can_list_to_can_capnp(can_sends, msgtype='sendcan', valid=CS.canValid))
|
||||
CC.actuatorsOutput = self.last_actuators
|
||||
if self.CP.steerControlType == car.CarParams.SteerControlType.angle:
|
||||
|
|
|
@ -1 +1 @@
|
|||
35a3dbcbcd8504388ea2a70965be0b4e0869b06a
|
||||
9bfd30202a9e70d9d7459cc02f86c3e55d7c864c
|
||||
|
|
Loading…
Reference in New Issue