fordcan.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. from cereal import car
  2. from selfdrive.car.ford.values import CANBUS
  3. HUDControl = car.CarControl.HUDControl
  4. def create_lka_command(packer, angle_deg: float, curvature: float):
  5. """
  6. Creates a CAN message for the Ford LKAS Command.
  7. This command can apply "Lane Keeping Aid" manoeuvres, which are subject to the PSCM lockout.
  8. Frequency is 20Hz.
  9. """
  10. values = {
  11. "LkaDrvOvrrd_D_Rq": 0, # driver override level? [0|3]
  12. "LkaActvStats_D2_Req": 0, # action [0|7]
  13. "LaRefAng_No_Req": angle_deg, # angle [-102.4|102.3] degrees
  14. "LaRampType_B_Req": 0, # Ramp speed: 0=Smooth, 1=Quick
  15. "LaCurvature_No_Calc": curvature, # curvature [-0.01024|0.01023] 1/meter
  16. "LdwActvStats_D_Req": 0, # LDW status [0|7]
  17. "LdwActvIntns_D_Req": 0, # LDW intensity [0|3], shake alert strength
  18. }
  19. return packer.make_can_msg("Lane_Assist_Data1", CANBUS.main, values)
  20. def create_tja_command(packer, lca_rq: int, ramp_type: int, precision: int, path_offset: float, path_angle: float, curvature_rate: float, curvature: float):
  21. """
  22. Creates a CAN message for the Ford TJA/LCA Command.
  23. This command can apply "Lane Centering" manoeuvres: continuous lane centering for traffic jam
  24. assist and highway driving. It is not subject to the PSCM lockout.
  25. Ford lane centering command uses a third order polynomial to describe the road centerline. The
  26. polynomial is defined by the following coefficients:
  27. c0: lateral offset between the vehicle and the centerline
  28. c1: heading angle between the vehicle and the centerline
  29. c2: curvature of the centerline
  30. c3: rate of change of curvature of the centerline
  31. As the PSCM combines this information with other sensor data, such as the vehicle's yaw rate and
  32. speed, the steering angle cannot be easily controlled.
  33. The PSCM should be configured to accept TJA/LCA commands before these commands will be processed.
  34. This can be done using tools such as Forscan.
  35. Frequency is 20Hz.
  36. """
  37. values = {
  38. "LatCtlRng_L_Max": 0, # Unknown [0|126] meter
  39. "HandsOffCnfm_B_Rq": 0, # Unknown: 0=Inactive, 1=Active [0|1]
  40. "LatCtl_D_Rq": lca_rq, # Mode: 0=None, 1=ContinuousPathFollowing, 2=InterventionLeft, 3=InterventionRight, 4-7=NotUsed [0|7]
  41. "LatCtlRampType_D_Rq": ramp_type, # Ramp speed: 0=Slow, 1=Medium, 2=Fast, 3=Immediate [0|3]
  42. "LatCtlPrecision_D_Rq": precision, # Precision: 0=Comfortable, 1=Precise, 2/3=NotUsed [0|3]
  43. "LatCtlPathOffst_L_Actl": path_offset, # Path offset [-5.12|5.11] meter
  44. "LatCtlPath_An_Actl": path_angle, # Path angle [-0.5|0.5235] radians
  45. "LatCtlCurv_NoRate_Actl": curvature_rate, # Curvature rate [-0.001024|0.00102375] 1/meter^2
  46. "LatCtlCurv_No_Actl": curvature, # Curvature [-0.02|0.02094] 1/meter
  47. }
  48. return packer.make_can_msg("LateralMotionControl", CANBUS.main, values)
  49. def create_lkas_ui_command(packer, main_on: bool, enabled: bool, steer_alert: bool, hud_control, stock_values: dict):
  50. """
  51. Creates a CAN message for the Ford IPC IPMA/LKAS status.
  52. Show the LKAS status with the "driver assist" lines in the IPC.
  53. Stock functionality is maintained by passing through unmodified signals.
  54. Frequency is 1Hz.
  55. """
  56. # LaActvStats_D_Dsply
  57. # R Intvn Warn Supprs Avail No
  58. # L
  59. # Intvn 24 19 14 9 4
  60. # Warn 23 18 13 8 3
  61. # Supprs 22 17 12 7 2
  62. # Avail 21 16 11 6 1
  63. # No 20 15 10 5 0
  64. #
  65. # TODO: test suppress state
  66. if enabled:
  67. lines = 0 # NoLeft_NoRight
  68. if hud_control.leftLaneDepart:
  69. lines += 4
  70. elif hud_control.leftLaneVisible:
  71. lines += 1
  72. if hud_control.rightLaneDepart:
  73. lines += 20
  74. elif hud_control.rightLaneVisible:
  75. lines += 5
  76. elif main_on:
  77. lines = 0
  78. else:
  79. if hud_control.leftLaneDepart:
  80. lines = 3 # WarnLeft_NoRight
  81. elif hud_control.rightLaneDepart:
  82. lines = 15 # NoLeft_WarnRight
  83. else:
  84. lines = 30 # LA_Off
  85. # TODO: use level 1 for no sound when less severe?
  86. hands_on_wheel_dsply = 2 if steer_alert else 0
  87. values = {
  88. **stock_values,
  89. "LaActvStats_D_Dsply": lines, # LKAS status (lines) [0|31]
  90. "LaHandsOff_D_Dsply": hands_on_wheel_dsply, # 0=HandsOn, 1=Level1 (w/o chime), 2=Level2 (w/ chime), 3=Suppressed
  91. }
  92. return packer.make_can_msg("IPMA_Data", CANBUS.main, values)
  93. def create_acc_ui_command(packer, main_on: bool, enabled: bool, hud_control, stock_values: dict):
  94. """
  95. Creates a CAN message for the Ford IPC adaptive cruise, forward collision warning and traffic jam
  96. assist status.
  97. Stock functionality is maintained by passing through unmodified signals.
  98. Frequency is 20Hz.
  99. """
  100. # Tja_D_Stat
  101. if enabled:
  102. if hud_control.leftLaneDepart:
  103. status = 3 # ActiveInterventionLeft
  104. elif hud_control.rightLaneDepart:
  105. status = 4 # ActiveInterventionRight
  106. else:
  107. status = 2 # Active
  108. elif main_on:
  109. if hud_control.leftLaneDepart:
  110. status = 5 # ActiveWarningLeft
  111. elif hud_control.rightLaneDepart:
  112. status = 6 # ActiveWarningRight
  113. else:
  114. status = 1 # Standby
  115. else:
  116. status = 0 # Off
  117. values = {
  118. **stock_values,
  119. "Tja_D_Stat": status,
  120. }
  121. return packer.make_can_msg("ACCDATA_3", CANBUS.main, values)
  122. def create_button_command(packer, stock_values: dict, cancel = False, resume = False, tja_toggle = False, bus: int = CANBUS.camera):
  123. """
  124. Creates a CAN message for the Ford SCCM buttons/switches.
  125. Includes cruise control buttons, turn lights and more.
  126. """
  127. values = {
  128. **stock_values,
  129. "CcAslButtnCnclPress": 1 if cancel else 0, # CC cancel button
  130. "CcAsllButtnResPress": 1 if resume else 0, # CC resume button
  131. "TjaButtnOnOffPress": 1 if tja_toggle else 0, # TJA toggle button
  132. }
  133. return packer.make_can_msg("Steering_Data_FD1", bus, values)