carcontroller.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from openpilot.common.numpy_fast import clip, interp
  2. from opendbc.can.packer import CANPacker
  3. from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fault_avoidance
  4. from openpilot.selfdrive.car.interfaces import CarControllerBase
  5. from openpilot.selfdrive.car.subaru import subarucan
  6. from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_ES_ADDR, CanBus, CarControllerParams, SubaruFlags
  7. # FIXME: These limits aren't exact. The real limit is more than likely over a larger time period and
  8. # involves the total steering angle change rather than rate, but these limits work well for now
  9. MAX_STEER_RATE = 25 # deg/s
  10. MAX_STEER_RATE_FRAMES = 7 # tx control frames needed before torque can be cut
  11. class CarController(CarControllerBase):
  12. def __init__(self, dbc_name, CP, VM):
  13. self.CP = CP
  14. self.apply_steer_last = 0
  15. self.frame = 0
  16. self.cruise_button_prev = 0
  17. self.steer_rate_counter = 0
  18. self.p = CarControllerParams(CP)
  19. self.packer = CANPacker(DBC[CP.carFingerprint]['pt'])
  20. def update(self, CC, CS, now_nanos):
  21. actuators = CC.actuators
  22. hud_control = CC.hudControl
  23. pcm_cancel_cmd = CC.cruiseControl.cancel
  24. can_sends = []
  25. # *** steering ***
  26. if (self.frame % self.p.STEER_STEP) == 0:
  27. apply_steer = int(round(actuators.steer * self.p.STEER_MAX))
  28. # limits due to driver torque
  29. new_steer = int(round(apply_steer))
  30. apply_steer = apply_driver_steer_torque_limits(new_steer, self.apply_steer_last, CS.out.steeringTorque, self.p)
  31. if not CC.latActive:
  32. apply_steer = 0
  33. if self.CP.flags & SubaruFlags.PREGLOBAL:
  34. can_sends.append(subarucan.create_preglobal_steering_control(self.packer, self.frame // self.p.STEER_STEP, apply_steer, CC.latActive))
  35. else:
  36. apply_steer_req = CC.latActive
  37. if self.CP.flags & SubaruFlags.STEER_RATE_LIMITED:
  38. # Steering rate fault prevention
  39. self.steer_rate_counter, apply_steer_req = \
  40. common_fault_avoidance(abs(CS.out.steeringRateDeg) > MAX_STEER_RATE, apply_steer_req,
  41. self.steer_rate_counter, MAX_STEER_RATE_FRAMES)
  42. can_sends.append(subarucan.create_steering_control(self.packer, apply_steer, apply_steer_req))
  43. self.apply_steer_last = apply_steer
  44. # *** longitudinal ***
  45. if CC.longActive:
  46. apply_throttle = int(round(interp(actuators.accel, CarControllerParams.THROTTLE_LOOKUP_BP, CarControllerParams.THROTTLE_LOOKUP_V)))
  47. apply_rpm = int(round(interp(actuators.accel, CarControllerParams.RPM_LOOKUP_BP, CarControllerParams.RPM_LOOKUP_V)))
  48. apply_brake = int(round(interp(actuators.accel, CarControllerParams.BRAKE_LOOKUP_BP, CarControllerParams.BRAKE_LOOKUP_V)))
  49. # limit min and max values
  50. cruise_throttle = clip(apply_throttle, CarControllerParams.THROTTLE_MIN, CarControllerParams.THROTTLE_MAX)
  51. cruise_rpm = clip(apply_rpm, CarControllerParams.RPM_MIN, CarControllerParams.RPM_MAX)
  52. cruise_brake = clip(apply_brake, CarControllerParams.BRAKE_MIN, CarControllerParams.BRAKE_MAX)
  53. else:
  54. cruise_throttle = CarControllerParams.THROTTLE_INACTIVE
  55. cruise_rpm = CarControllerParams.RPM_MIN
  56. cruise_brake = CarControllerParams.BRAKE_MIN
  57. # *** alerts and pcm cancel ***
  58. if self.CP.flags & SubaruFlags.PREGLOBAL:
  59. if self.frame % 5 == 0:
  60. # 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep
  61. # disengage ACC when OP is disengaged
  62. if pcm_cancel_cmd:
  63. cruise_button = 1
  64. # turn main on if off and past start-up state
  65. elif not CS.out.cruiseState.available and CS.ready:
  66. cruise_button = 1
  67. else:
  68. cruise_button = CS.cruise_button
  69. # unstick previous mocked button press
  70. if cruise_button == 1 and self.cruise_button_prev == 1:
  71. cruise_button = 0
  72. self.cruise_button_prev = cruise_button
  73. can_sends.append(subarucan.create_preglobal_es_distance(self.packer, cruise_button, CS.es_distance_msg))
  74. else:
  75. if self.frame % 10 == 0:
  76. can_sends.append(subarucan.create_es_dashstatus(self.packer, self.frame // 10, CS.es_dashstatus_msg, CC.enabled,
  77. self.CP.openpilotLongitudinalControl, CC.longActive, hud_control.leadVisible))
  78. can_sends.append(subarucan.create_es_lkas_state(self.packer, self.frame // 10, CS.es_lkas_state_msg, CC.enabled, hud_control.visualAlert,
  79. hud_control.leftLaneVisible, hud_control.rightLaneVisible,
  80. hud_control.leftLaneDepart, hud_control.rightLaneDepart))
  81. if self.CP.flags & SubaruFlags.SEND_INFOTAINMENT:
  82. can_sends.append(subarucan.create_es_infotainment(self.packer, self.frame // 10, CS.es_infotainment_msg, hud_control.visualAlert))
  83. if self.CP.openpilotLongitudinalControl:
  84. if self.frame % 5 == 0:
  85. can_sends.append(subarucan.create_es_status(self.packer, self.frame // 5, CS.es_status_msg,
  86. self.CP.openpilotLongitudinalControl, CC.longActive, cruise_rpm))
  87. can_sends.append(subarucan.create_es_brake(self.packer, self.frame // 5, CS.es_brake_msg,
  88. self.CP.openpilotLongitudinalControl, CC.longActive, cruise_brake))
  89. can_sends.append(subarucan.create_es_distance(self.packer, self.frame // 5, CS.es_distance_msg, 0, pcm_cancel_cmd,
  90. self.CP.openpilotLongitudinalControl, cruise_brake > 0, cruise_throttle))
  91. else:
  92. if pcm_cancel_cmd:
  93. if not (self.CP.flags & SubaruFlags.HYBRID):
  94. bus = CanBus.alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else CanBus.main
  95. can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg["COUNTER"] + 1, CS.es_distance_msg, bus, pcm_cancel_cmd))
  96. if self.CP.flags & SubaruFlags.DISABLE_EYESIGHT:
  97. # Tester present (keeps eyesight disabled)
  98. if self.frame % 100 == 0:
  99. can_sends.append([GLOBAL_ES_ADDR, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", CanBus.camera])
  100. # Create all of the other eyesight messages to keep the rest of the car happy when eyesight is disabled
  101. if self.frame % 5 == 0:
  102. can_sends.append(subarucan.create_es_highbeamassist(self.packer))
  103. if self.frame % 10 == 0:
  104. can_sends.append(subarucan.create_es_static_1(self.packer))
  105. if self.frame % 2 == 0:
  106. can_sends.append(subarucan.create_es_static_2(self.packer))
  107. new_actuators = actuators.copy()
  108. new_actuators.steer = self.apply_steer_last / self.p.STEER_MAX
  109. new_actuators.steerOutputCan = self.apply_steer_last
  110. self.frame += 1
  111. return new_actuators, can_sends