from cereal import car from selfdrive.car.ford.values import CANBUS HUDControl = car.CarControl.HUDControl def create_lka_command(packer, angle_deg: float, curvature: float): """ Creates a CAN message for the Ford LKAS Command. This command can apply "Lane Keeping Aid" manoeuvres, which are subject to the PSCM lockout. Frequency is 20Hz. """ values = { "LkaDrvOvrrd_D_Rq": 0, # driver override level? [0|3] "LkaActvStats_D2_Req": 0, # action [0|7] "LaRefAng_No_Req": angle_deg, # angle [-102.4|102.3] degrees "LaRampType_B_Req": 0, # Ramp speed: 0=Smooth, 1=Quick "LaCurvature_No_Calc": curvature, # curvature [-0.01024|0.01023] 1/meter "LdwActvStats_D_Req": 0, # LDW status [0|7] "LdwActvIntns_D_Req": 0, # LDW intensity [0|3], shake alert strength } return packer.make_can_msg("Lane_Assist_Data1", CANBUS.main, values) def create_tja_command(packer, lca_rq: int, ramp_type: int, precision: int, path_offset: float, path_angle: float, curvature_rate: float, curvature: float): """ Creates a CAN message for the Ford TJA/LCA Command. This command can apply "Lane Centering" manoeuvres: continuous lane centering for traffic jam assist and highway driving. It is not subject to the PSCM lockout. The PSCM should be configured to accept TJA/LCA commands before these commands will be processed. This can be done using tools such as Forscan. Frequency is 20Hz. """ values = { "LatCtlRng_L_Max": 0, # Unknown [0|126] meter "HandsOffCnfm_B_Rq": 0, # Unknown: 0=Inactive, 1=Active [0|1] "LatCtl_D_Rq": lca_rq, # Mode: 0=None, 1=ContinuousPathFollowing, 2=InterventionLeft, 3=InterventionRight, 4-7=NotUsed [0|7] "LatCtlRampType_D_Rq": ramp_type, # Ramp speed: 0=Slow, 1=Medium, 2=Fast, 3=Immediate [0|3] "LatCtlPrecision_D_Rq": precision, # Precision: 0=Comfortable, 1=Precise, 2/3=NotUsed [0|3] "LatCtlPathOffst_L_Actl": path_offset, # Path offset [-5.12|5.11] meter "LatCtlPath_An_Actl": path_angle, # Path angle [-0.4995|0.5240] radians "LatCtlCurv_NoRate_Actl": curvature_rate, # Curvature rate [-0.001024|0.00102375] 1/meter^2 "LatCtlCurv_No_Actl": curvature, # Curvature [-0.02|0.02094] 1/meter } return packer.make_can_msg("LateralMotionControl", CANBUS.main, values) def create_lkas_ui_command(packer, main_on: bool, enabled: bool, steer_alert: bool, hud_control, stock_values: dict): """ Creates a CAN message for the Ford IPC IPMA/LKAS status. Show the LKAS status with the "driver assist" lines in the IPC. Stock functionality is maintained by passing through unmodified signals. Frequency is 1Hz. """ # LaActvStats_D_Dsply # R Intvn Warn Supprs Avail No # L # Intvn 24 19 14 9 4 # Warn 23 18 13 8 3 # Supprs 22 17 12 7 2 # Avail 21 16 11 6 1 # No 20 15 10 5 0 # # TODO: test suppress state if enabled: lines = 0 # NoLeft_NoRight if hud_control.leftLaneDepart: lines += 4 elif hud_control.leftLaneVisible: lines += 1 if hud_control.rightLaneDepart: lines += 20 elif hud_control.rightLaneVisible: lines += 5 elif main_on: lines = 0 else: if hud_control.leftLaneDepart: lines = 3 # WarnLeft_NoRight elif hud_control.rightLaneDepart: lines = 15 # NoLeft_WarnRight else: lines = 30 # LA_Off # TODO: use level 1 for no sound when less severe? hands_on_wheel_dsply = 2 if steer_alert else 0 values = { **stock_values, "LaActvStats_D_Dsply": lines, # LKAS status (lines) [0|31] "LaHandsOff_D_Dsply": hands_on_wheel_dsply, # 0=HandsOn, 1=Level1 (w/o chime), 2=Level2 (w/ chime), 3=Suppressed } return packer.make_can_msg("IPMA_Data", CANBUS.main, values) def create_acc_ui_command(packer, main_on: bool, enabled: bool, hud_control, stock_values: dict): """ Creates a CAN message for the Ford IPC adaptive cruise, forward collision warning and traffic jam assist status. Stock functionality is maintained by passing through unmodified signals. Frequency is 20Hz. """ # Tja_D_Stat if enabled: if hud_control.leftLaneDepart: status = 3 # ActiveInterventionLeft elif hud_control.rightLaneDepart: status = 4 # ActiveInterventionRight else: status = 2 # Active elif main_on: if hud_control.leftLaneDepart: status = 5 # ActiveWarningLeft elif hud_control.rightLaneDepart: status = 6 # ActiveWarningRight else: status = 1 # Standby else: status = 0 # Off values = { **stock_values, "Tja_D_Stat": status, } return packer.make_can_msg("ACCDATA_3", CANBUS.main, values) def create_button_command(packer, stock_values: dict, cancel = False, resume = False, tja_toggle = False, bus = CANBUS.camera): """ Creates a CAN message for the Ford SCCM buttons/switches. Includes cruise control buttons, turn lights and more. """ values = { **stock_values, "CcAslButtnCnclPress": 1 if cancel else 0, # CC cancel button "CcAsllButtnResPress": 1 if resume else 0, # CC resume button "TjaButtnOnOffPress": 1 if tja_toggle else 0, # TJA toggle button } return packer.make_can_msg("Steering_Data_FD1", bus, values)