parent
							
								
									8f6e36f426
								
							
						
					
					
						commit
						285c52eb69
					
				
				 32 changed files with 972 additions and 157 deletions
			
			
		| @ -1,4 +1,26 @@ | ||||
| # functions common among cars | ||||
| from common.numpy_fast import clip | ||||
| 
 | ||||
| 
 | ||||
| def dbc_dict(pt_dbc, radar_dbc, chassis_dbc=None): | ||||
|   return {'pt': pt_dbc, 'radar': radar_dbc, 'chassis': chassis_dbc} | ||||
| 
 | ||||
| 
 | ||||
| def apply_std_steer_torque_limits(apply_torque, apply_torque_last, driver_torque, LIMITS): | ||||
| 
 | ||||
|   # limits due to driver torque | ||||
|   driver_max_torque = LIMITS.STEER_MAX + (LIMITS.STEER_DRIVER_ALLOWANCE + driver_torque * LIMITS.STEER_DRIVER_FACTOR) * LIMITS.STEER_DRIVER_MULTIPLIER | ||||
|   driver_min_torque = -LIMITS.STEER_MAX + (-LIMITS.STEER_DRIVER_ALLOWANCE + driver_torque * LIMITS.STEER_DRIVER_FACTOR) * LIMITS.STEER_DRIVER_MULTIPLIER | ||||
|   max_steer_allowed = max(min(LIMITS.STEER_MAX, driver_max_torque), 0) | ||||
|   min_steer_allowed = min(max(-LIMITS.STEER_MAX, driver_min_torque), 0) | ||||
|   apply_torque = clip(apply_torque, min_steer_allowed, max_steer_allowed) | ||||
| 
 | ||||
|   # slow rate if steer torque increases in magnitude | ||||
|   if apply_torque_last > 0: | ||||
|     apply_torque = clip(apply_torque, max(apply_torque_last - LIMITS.STEER_DELTA_DOWN, -LIMITS.STEER_DELTA_UP), | ||||
|                                     apply_torque_last + LIMITS.STEER_DELTA_UP) | ||||
|   else: | ||||
|     apply_torque = clip(apply_torque, apply_torque_last - LIMITS.STEER_DELTA_UP, | ||||
|                                     min(apply_torque_last + LIMITS.STEER_DELTA_DOWN, LIMITS.STEER_DELTA_UP)) | ||||
| 
 | ||||
|   return int(round(apply_torque)) | ||||
|  | ||||
| @ -0,0 +1,76 @@ | ||||
| from selfdrive.car import apply_std_steer_torque_limits | ||||
| from selfdrive.boardd.boardd import can_list_to_can_capnp | ||||
| from selfdrive.car.hyundai.hyundaican import create_lkas11, create_lkas12, \ | ||||
|                                              create_1191, create_1156, \ | ||||
|                                              create_clu11 | ||||
| from selfdrive.car.hyundai.values import Buttons | ||||
| from selfdrive.can.packer import CANPacker | ||||
| 
 | ||||
| 
 | ||||
| # Steer torque limits | ||||
| 
 | ||||
| class SteerLimitParams: | ||||
|   STEER_MAX = 250   # 409 is the max | ||||
|   STEER_DELTA_UP = 3 | ||||
|   STEER_DELTA_DOWN = 7 | ||||
|   STEER_DRIVER_ALLOWANCE = 50 | ||||
|   STEER_DRIVER_MULTIPLIER = 2 | ||||
|   STEER_DRIVER_FACTOR = 1 | ||||
| 
 | ||||
| class CarController(object): | ||||
|   def __init__(self, dbc_name, car_fingerprint, enable_camera): | ||||
|     self.apply_steer_last = 0 | ||||
|     self.car_fingerprint = car_fingerprint | ||||
|     self.lkas11_cnt = 0 | ||||
|     self.cnt = 0 | ||||
|     self.last_resume_cnt = 0 | ||||
|     self.enable_camera = enable_camera | ||||
|     # True when giraffe switch 2 is low and we need to replace all the camera messages | ||||
|     # otherwise we forward the camera msgs and we just replace the lkas cmd signals | ||||
|     self.camera_disconnected = False | ||||
| 
 | ||||
|     self.packer = CANPacker(dbc_name) | ||||
| 
 | ||||
|   def update(self, sendcan, enabled, CS, actuators, pcm_cancel_cmd, hud_alert): | ||||
| 
 | ||||
|     if not self.enable_camera: | ||||
|       return | ||||
| 
 | ||||
|     ### Steering Torque | ||||
|     apply_steer = actuators.steer * SteerLimitParams.STEER_MAX | ||||
| 
 | ||||
|     apply_steer = apply_std_steer_torque_limits(apply_steer, self.apply_steer_last, CS.steer_torque_driver, SteerLimitParams) | ||||
| 
 | ||||
|     if not enabled: | ||||
|       apply_steer = 0 | ||||
| 
 | ||||
|     steer_req = 1 if enabled else 0 | ||||
| 
 | ||||
|     self.apply_steer_last = apply_steer | ||||
| 
 | ||||
|     can_sends = [] | ||||
| 
 | ||||
|     self.lkas11_cnt = self.cnt % 0x10 | ||||
|     self.clu11_cnt = self.cnt % 0x10 | ||||
| 
 | ||||
|     if self.camera_disconnected: | ||||
|       if (self.cnt % 10) == 0: | ||||
|         can_sends.append(create_lkas12()) | ||||
|       if (self.cnt % 50) == 0: | ||||
|         can_sends.append(create_1191()) | ||||
|       if (self.cnt % 7) == 0: | ||||
|         can_sends.append(create_1156()) | ||||
| 
 | ||||
|     can_sends.append(create_lkas11(self.packer, apply_steer, steer_req, self.lkas11_cnt, | ||||
|                                    enabled, CS.lkas11, hud_alert, keep_stock=(not self.camera_disconnected))) | ||||
| 
 | ||||
|     if pcm_cancel_cmd: | ||||
|       can_sends.append(create_clu11(self.packer, CS.clu11, Buttons.CANCEL)) | ||||
|     elif CS.stopped and (self.cnt - self.last_resume_cnt) > 5: | ||||
|       self.last_resume_cnt = self.cnt | ||||
|       can_sends.append(create_clu11(self.packer, CS.clu11, Buttons.RES_ACCEL)) | ||||
| 
 | ||||
|     ### Send messages to canbus | ||||
|     sendcan.send(can_list_to_can_capnp(can_sends, msgtype='sendcan').to_bytes()) | ||||
| 
 | ||||
|     self.cnt += 1 | ||||
| @ -0,0 +1,220 @@ | ||||
| from selfdrive.car.hyundai.values import DBC | ||||
| from selfdrive.can.parser import CANParser | ||||
| from selfdrive.config import Conversions as CV | ||||
| from common.kalman.simple_kalman import KF1D | ||||
| import numpy as np | ||||
| 
 | ||||
| 
 | ||||
| def get_can_parser(CP): | ||||
| 
 | ||||
|   signals = [ | ||||
|     # sig_name, sig_address, default | ||||
|     ("WHL_SPD_FL", "WHL_SPD11", 0), | ||||
|     ("WHL_SPD_FR", "WHL_SPD11", 0), | ||||
|     ("WHL_SPD_RL", "WHL_SPD11", 0), | ||||
|     ("WHL_SPD_RR", "WHL_SPD11", 0), | ||||
| 
 | ||||
|     ("YAW_RATE", "ESP12", 0), | ||||
| 
 | ||||
|     ("CF_Gway_DrvSeatBeltInd", "CGW4", 1), | ||||
|     ("CF_Gway_DrvSeatBeltSw", "CGW1", 0), | ||||
|     ("CF_Gway_TSigLHSw", "CGW1", 0), | ||||
|     ("CF_Gway_TurnSigLh", "CGW1", 0), | ||||
|     ("CF_Gway_TSigRHSw", "CGW1", 0), | ||||
|     ("CF_Gway_TurnSigRh", "CGW1", 0), | ||||
| 
 | ||||
|     ("BRAKE_ACT", "EMS12", 0), | ||||
|     ("PV_AV_CAN", "EMS12", 0), | ||||
|     ("TPS", "EMS12", 0), | ||||
| 
 | ||||
|     ("CYL_PRES", "ESP12", 0), | ||||
| 
 | ||||
|     ("CF_Clu_CruiseSwState", "CLU11", 0), | ||||
|     ("CF_Clu_CruiseSwMain" , "CLU11", 0), | ||||
|     ("CF_Clu_SldMainSW", "CLU11", 0), | ||||
|     ("CF_Clu_ParityBit1", "CLU11", 0), | ||||
|     ("CF_Clu_VanzDecimal" , "CLU11", 0), | ||||
|     ("CF_Clu_Vanz", "CLU11", 0), | ||||
|     ("CF_Clu_SPEED_UNIT", "CLU11", 0), | ||||
|     ("CF_Clu_DetentOut", "CLU11", 0), | ||||
|     ("CF_Clu_RheostatLevel", "CLU11", 0), | ||||
|     ("CF_Clu_CluInfo", "CLU11", 0), | ||||
|     ("CF_Clu_AmpInfo", "CLU11", 0), | ||||
|     ("CF_Clu_AliveCnt1", "CLU11", 0), | ||||
| 
 | ||||
|     ("CF_Lvr_Gear","LVR12",0), | ||||
| 
 | ||||
|     ("ACCEnable", "TCS13", 0), | ||||
|     ("ACC_REQ", "TCS13", 0), | ||||
|     ("DriverBraking", "TCS13", 0), | ||||
|     ("DriverOverride", "TCS13", 0), | ||||
| 
 | ||||
|     ("ESC_Off_Step", "TCS15", 0), | ||||
| 
 | ||||
|     ("CF_Lvr_GearInf", "LVR11", 0),        #Transmission Gear (0 = N or P, 1-8 = Fwd, 14 = Rev) | ||||
| 
 | ||||
|     ("CR_Mdps_DrvTq", "MDPS11", 0), | ||||
| 
 | ||||
|     ("CR_Mdps_StrColTq", "MDPS12", 0), | ||||
|     ("CF_Mdps_ToiActive", "MDPS12", 0), | ||||
|     ("CF_Mdps_ToiUnavail", "MDPS12", 0), | ||||
|     ("CF_Mdps_FailStat", "MDPS12", 0), | ||||
|     ("CR_Mdps_OutTq", "MDPS12", 0), | ||||
| 
 | ||||
|     ("VSetDis", "SCC11", 0), | ||||
|     ("SCCInfoDisplay", "SCC11", 0), | ||||
|     ("ACCMode", "SCC12", 1), | ||||
| 
 | ||||
|     ("SAS_Angle", "SAS11", 0), | ||||
|     ("SAS_Speed", "SAS11", 0), | ||||
|   ] | ||||
| 
 | ||||
|   checks = [ | ||||
|     # address, frequency | ||||
|     ("MDPS12", 50), | ||||
|     ("MDPS11", 100), | ||||
|     ("TCS15", 10), | ||||
|     ("TCS13", 50), | ||||
|     ("CLU11", 50), | ||||
|     ("ESP12", 100), | ||||
|     ("EMS12", 100), | ||||
|     ("CGW1", 10), | ||||
|     ("CGW4", 5), | ||||
|     ("WHL_SPD11", 50), | ||||
|     ("SCC11", 50), | ||||
|     ("SCC12", 50), | ||||
|     ("SAS11", 100) | ||||
|   ] | ||||
| 
 | ||||
|   return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0) | ||||
| 
 | ||||
| def get_camera_parser(CP): | ||||
| 
 | ||||
|   signals = [ | ||||
|     # sig_name, sig_address, default | ||||
|     ("CF_Lkas_LdwsSysState", "LKAS11", 0), | ||||
|     ("CF_Lkas_SysWarning", "LKAS11", 0), | ||||
|     ("CF_Lkas_LdwsLHWarning", "LKAS11", 0), | ||||
|     ("CF_Lkas_LdwsRHWarning", "LKAS11", 0), | ||||
|     ("CF_Lkas_HbaLamp", "LKAS11", 0), | ||||
|     ("CF_Lkas_FcwBasReq", "LKAS11", 0), | ||||
|     ("CF_Lkas_ToiFlt", "LKAS11", 0), | ||||
|     ("CF_Lkas_HbaSysState", "LKAS11", 0), | ||||
|     ("CF_Lkas_FcwOpt", "LKAS11", 0), | ||||
|     ("CF_Lkas_HbaOpt", "LKAS11", 0), | ||||
|     ("CF_Lkas_FcwSysState", "LKAS11", 0), | ||||
|     ("CF_Lkas_FcwCollisionWarning", "LKAS11", 0), | ||||
|     ("CF_Lkas_FusionState", "LKAS11", 0), | ||||
|     ("CF_Lkas_FcwOpt_USM", "LKAS11", 0), | ||||
|     ("CF_Lkas_LdwsOpt_USM", "LKAS11", 0) | ||||
|   ] | ||||
| 
 | ||||
|   checks = [] | ||||
| 
 | ||||
|   return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2) | ||||
| 
 | ||||
| class CarState(object): | ||||
|   def __init__(self, CP): | ||||
| 
 | ||||
|     self.CP = CP | ||||
| 
 | ||||
|     # initialize can parser | ||||
|     self.car_fingerprint = CP.carFingerprint | ||||
| 
 | ||||
|     # vEgo kalman filter | ||||
|     dt = 0.01 | ||||
|     # Q = np.matrix([[10.0, 0.0], [0.0, 100.0]]) | ||||
|     # R = 1e3 | ||||
|     self.v_ego_kf = KF1D(x0=np.matrix([[0.0], [0.0]]), | ||||
|                          A=np.matrix([[1.0, dt], [0.0, 1.0]]), | ||||
|                          C=np.matrix([1.0, 0.0]), | ||||
|                          K=np.matrix([[0.12287673], [0.29666309]])) | ||||
|     self.v_ego = 0.0 | ||||
|     self.left_blinker_on = 0 | ||||
|     self.left_blinker_flash = 0 | ||||
|     self.right_blinker_on = 0 | ||||
|     self.right_blinker_flash = 0 | ||||
| 
 | ||||
|   def update(self, cp, cp_cam): | ||||
|     # copy can_valid | ||||
|     self.can_valid = cp.can_valid | ||||
| 
 | ||||
|     # update prevs, update must run once per Loop | ||||
|     self.prev_left_blinker_on = self.left_blinker_on | ||||
|     self.prev_right_blinker_on = self.right_blinker_on | ||||
| 
 | ||||
|     self.door_all_closed = True | ||||
|     self.seatbelt = cp.vl["CGW1"]['CF_Gway_DrvSeatBeltSw'] | ||||
| 
 | ||||
|     self.brake_pressed = cp.vl["TCS13"]['DriverBraking'] | ||||
|     self.esp_disabled = cp.vl["TCS15"]['ESC_Off_Step'] | ||||
| 
 | ||||
|     self.park_brake = False | ||||
|     self.main_on = True | ||||
|     self.acc_active = cp.vl["SCC12"]['ACCMode'] != 0 | ||||
|     self.pcm_acc_status = int(self.acc_active) | ||||
| 
 | ||||
|     # calc best v_ego estimate, by averaging two opposite corners | ||||
|     self.v_wheel_fl = cp.vl["WHL_SPD11"]['WHL_SPD_FL'] * CV.KPH_TO_MS | ||||
|     self.v_wheel_fr = cp.vl["WHL_SPD11"]['WHL_SPD_FR'] * CV.KPH_TO_MS | ||||
|     self.v_wheel_rl = cp.vl["WHL_SPD11"]['WHL_SPD_RL'] * CV.KPH_TO_MS | ||||
|     self.v_wheel_rr = cp.vl["WHL_SPD11"]['WHL_SPD_RR'] * CV.KPH_TO_MS | ||||
|     self.v_wheel = (self.v_wheel_fl + self.v_wheel_fr + self.v_wheel_rl + self.v_wheel_rr) / 4. | ||||
| 
 | ||||
|     self.low_speed_lockout = self.v_wheel < 1.0 | ||||
| 
 | ||||
|     # Kalman filter, even though Hyundai raw wheel speed is heaviliy filtered by default | ||||
|     if abs(self.v_wheel - self.v_ego) > 2.0:  # Prevent large accelerations when car starts at non zero speed | ||||
|       self.v_ego_x = np.matrix([[self.v_wheel], [0.0]]) | ||||
| 
 | ||||
|     self.v_ego_raw = self.v_wheel | ||||
|     v_ego_x = self.v_ego_kf.update(self.v_wheel) | ||||
|     self.v_ego = float(v_ego_x[0]) | ||||
|     self.a_ego = float(v_ego_x[1]) | ||||
|     is_set_speed_in_mph = int(cp.vl["CLU11"]["CF_Clu_SPEED_UNIT"]) | ||||
|     speed_conv = CV.MPH_TO_MS if is_set_speed_in_mph else CV.KPH_TO_MS | ||||
|     self.cruise_set_speed = cp.vl["SCC11"]['VSetDis'] * speed_conv | ||||
|     self.standstill = not self.v_wheel > 0.1 | ||||
| 
 | ||||
|     self.angle_steers = cp.vl["SAS11"]['SAS_Angle'] | ||||
|     self.angle_steers_rate = cp.vl["SAS11"]['SAS_Speed'] | ||||
|     self.yaw_rate = cp.vl["ESP12"]['YAW_RATE'] | ||||
|     self.main_on = True | ||||
|     self.left_blinker_on = cp.vl["CGW1"]['CF_Gway_TSigLHSw'] | ||||
|     self.left_blinker_flash = cp.vl["CGW1"]['CF_Gway_TurnSigLh'] | ||||
|     self.right_blinker_on = cp.vl["CGW1"]['CF_Gway_TSigRHSw'] | ||||
|     self.right_blinker_flash = cp.vl["CGW1"]['CF_Gway_TurnSigRh'] | ||||
|     self.steer_override = abs(cp.vl["MDPS11"]['CR_Mdps_DrvTq']) > 100. | ||||
|     self.steer_state = cp.vl["MDPS12"]['CF_Mdps_ToiActive'] #0 NOT ACTIVE, 1 ACTIVE | ||||
|     self.steer_error = cp.vl["MDPS12"]['CF_Mdps_ToiUnavail'] | ||||
|     self.brake_error = 0 | ||||
|     self.steer_torque_driver = cp.vl["MDPS11"]['CR_Mdps_DrvTq'] | ||||
|     self.steer_torque_motor = cp.vl["MDPS12"]['CR_Mdps_OutTq'] | ||||
|     self.stopped = cp.vl["SCC11"]['SCCInfoDisplay'] == 4. | ||||
| 
 | ||||
|     self.user_brake = 0 | ||||
| 
 | ||||
|     self.brake_pressed = cp.vl["TCS13"]['DriverBraking'] | ||||
|     self.brake_lights = bool(self.brake_pressed) | ||||
|     if (cp.vl["TCS13"]["DriverOverride"] == 0 and cp.vl["TCS13"]['ACC_REQ'] == 1): | ||||
|       self.pedal_gas = 0 | ||||
|     else: | ||||
|       self.pedal_gas = cp.vl["EMS12"]['TPS'] | ||||
|     self.car_gas = cp.vl["EMS12"]['TPS'] | ||||
| 
 | ||||
|     # Gear Selecton - This should be compatible with all Kia/Hyundai with Auto's | ||||
|     gear = cp.vl["LVR12"]["CF_Lvr_Gear"] | ||||
|     if gear == 5: | ||||
|       self.gear_shifter = "drive" | ||||
|     elif gear == 6: | ||||
|       self.gear_shifter = "neutral" | ||||
|     elif gear == 0: | ||||
|       self.gear_shifter = "park" | ||||
|     elif gear == 7: | ||||
|       self.gear_shifter = "reverse" | ||||
|     else: | ||||
|       self.gear_shifter = "unknown" | ||||
| 
 | ||||
|     # save the entire LKAS11 and CLU11 | ||||
|     self.lkas11 = cp_cam.vl["LKAS11"] | ||||
|     self.clu11 = cp.vl["CLU11"] | ||||
| @ -0,0 +1,67 @@ | ||||
| import crcmod | ||||
| 
 | ||||
| hyundai_checksum = crcmod.mkCrcFun(0x11D, initCrc=0xFD, rev=False, xorOut=0xdf) | ||||
| 
 | ||||
| def make_can_msg(addr, dat, alt): | ||||
|   return [addr, 0, dat, alt] | ||||
| 
 | ||||
| def create_lkas11(packer, apply_steer, steer_req, cnt, enabled, lkas11, hud_alert, keep_stock=False): | ||||
|   values = { | ||||
|     "CF_Lkas_Icon": 3 if enabled else 0, | ||||
|     "CF_Lkas_LdwsSysState": lkas11["CF_Lkas_LdwsSysState"] if keep_stock else 1, | ||||
|     "CF_Lkas_SysWarning": hud_alert, | ||||
|     "CF_Lkas_LdwsLHWarning": lkas11["CF_Lkas_LdwsLHWarning"] if keep_stock else 0, | ||||
|     "CF_Lkas_LdwsRHWarning": lkas11["CF_Lkas_LdwsRHWarning"] if keep_stock else 0, | ||||
|     "CF_Lkas_HbaLamp": lkas11["CF_Lkas_HbaLamp"] if keep_stock else 0, | ||||
|     "CF_Lkas_FcwBasReq": lkas11["CF_Lkas_FcwBasReq"] if keep_stock else 0, | ||||
|     "CR_Lkas_StrToqReq": apply_steer, | ||||
|     "CF_Lkas_ActToi": steer_req, | ||||
|     "CF_Lkas_ToiFlt": lkas11["CF_Lkas_ToiFlt"] if keep_stock else 0, | ||||
|     "CF_Lkas_HbaSysState": lkas11["CF_Lkas_HbaSysState"] if keep_stock else 1, | ||||
|     "CF_Lkas_FcwOpt": lkas11["CF_Lkas_FcwOpt"] if keep_stock else 0, | ||||
|     "CF_Lkas_HbaOpt": lkas11["CF_Lkas_HbaOpt"] if keep_stock else 3, | ||||
|     "CF_Lkas_MsgCount": cnt, | ||||
|     "CF_Lkas_FcwSysState": lkas11["CF_Lkas_FcwSysState"] if keep_stock else 0, | ||||
|     "CF_Lkas_FcwCollisionWarning": lkas11["CF_Lkas_FcwCollisionWarning"] if keep_stock else 0, | ||||
|     "CF_Lkas_FusionState": lkas11["CF_Lkas_FusionState"] if keep_stock else 0, | ||||
|     "CF_Lkas_Chksum": 0, | ||||
|     "CF_Lkas_FcwOpt_USM": 2 if enabled else 1, | ||||
|     "CF_Lkas_LdwsOpt_USM": lkas11["CF_Lkas_LdwsOpt_USM"] if keep_stock else 3, | ||||
|   } | ||||
| 
 | ||||
|   dat = packer.make_can_msg("LKAS11", 0, values)[2] | ||||
|   dat = dat[:6] + dat[7] | ||||
|   checksum = hyundai_checksum(dat) | ||||
| 
 | ||||
|   values["CF_Lkas_Chksum"] = checksum | ||||
| 
 | ||||
|   return packer.make_can_msg("LKAS11", 0, values) | ||||
| 
 | ||||
| def create_lkas12(): | ||||
|   return make_can_msg(1342, "\x00\x00\x00\x00\x60\x05", 0) | ||||
| 
 | ||||
| 
 | ||||
| def create_1191(): | ||||
|   return make_can_msg(1191, "\x01\x00", 0) | ||||
| 
 | ||||
| 
 | ||||
| def create_1156(): | ||||
|   return make_can_msg(1156, "\x08\x20\xfe\x3f\x00\xe0\xfd\x3f", 0) | ||||
| 
 | ||||
| def create_clu11(packer, clu11, button): | ||||
|   values = { | ||||
|     "CF_Clu_CruiseSwState": button, | ||||
|     "CF_Clu_CruiseSwMain": clu11["CF_Clu_CruiseSwMain"], | ||||
|     "CF_Clu_SldMainSW": clu11["CF_Clu_SldMainSW"], | ||||
|     "CF_Clu_ParityBit1": clu11["CF_Clu_ParityBit1"], | ||||
|     "CF_Clu_VanzDecimal": clu11["CF_Clu_VanzDecimal"], | ||||
|     "CF_Clu_Vanz": clu11["CF_Clu_Vanz"], | ||||
|     "CF_Clu_SPEED_UNIT": clu11["CF_Clu_SPEED_UNIT"], | ||||
|     "CF_Clu_DetentOut": clu11["CF_Clu_DetentOut"], | ||||
|     "CF_Clu_RheostatLevel": clu11["CF_Clu_RheostatLevel"], | ||||
|     "CF_Clu_CluInfo": clu11["CF_Clu_CluInfo"], | ||||
|     "CF_Clu_AmpInfo": clu11["CF_Clu_AmpInfo"], | ||||
|     "CF_Clu_AliveCnt1": 0, | ||||
|   } | ||||
| 
 | ||||
|   return packer.make_can_msg("CLU11", 0, values) | ||||
| @ -0,0 +1,259 @@ | ||||
| #!/usr/bin/env python | ||||
| from cereal import car, log | ||||
| from common.realtime import sec_since_boot | ||||
| from selfdrive.config import Conversions as CV | ||||
| from selfdrive.controls.lib.drive_helpers import EventTypes as ET, create_event | ||||
| from selfdrive.controls.lib.vehicle_model import VehicleModel | ||||
| from selfdrive.car.hyundai.carstate import CarState, get_can_parser, get_camera_parser | ||||
| from selfdrive.car.hyundai.values import CAMERA_MSGS, get_hud_alerts | ||||
| 
 | ||||
| try: | ||||
|   from selfdrive.car.hyundai.carcontroller import CarController | ||||
| except ImportError: | ||||
|   CarController = None | ||||
| 
 | ||||
| 
 | ||||
| class CarInterface(object): | ||||
|   def __init__(self, CP, sendcan=None): | ||||
|     self.CP = CP | ||||
|     self.VM = VehicleModel(CP) | ||||
|     self.idx = 0 | ||||
|     self.lanes = 0 | ||||
|     self.lkas_request = 0 | ||||
| 
 | ||||
|     self.gas_pressed_prev = False | ||||
|     self.brake_pressed_prev = False | ||||
|     self.can_invalid_count = 0 | ||||
|     self.cruise_enabled_prev = False | ||||
| 
 | ||||
|     # *** init the major players *** | ||||
|     self.CS = CarState(CP) | ||||
|     self.cp = get_can_parser(CP) | ||||
|     self.cp_cam = get_camera_parser(CP) | ||||
| 
 | ||||
|     # sending if read only is False | ||||
|     if sendcan is not None: | ||||
|       self.sendcan = sendcan | ||||
|       self.CC = CarController(self.cp.dbc_name, CP.carFingerprint, CP.enableCamera) | ||||
| 
 | ||||
|   @staticmethod | ||||
|   def compute_gb(accel, speed): | ||||
|     return float(accel) / 3.0 | ||||
| 
 | ||||
|   @staticmethod | ||||
|   def calc_accel_override(a_ego, a_target, v_ego, v_target): | ||||
|     return 1.0 | ||||
| 
 | ||||
|   @staticmethod | ||||
|   def get_params(candidate, fingerprint): | ||||
| 
 | ||||
|     # kg of standard extra cargo to count for drive, gas, etc... | ||||
|     std_cargo = 136 | ||||
| 
 | ||||
|     ret = car.CarParams.new_message() | ||||
| 
 | ||||
|     ret.carName = "hyundai" | ||||
|     ret.carFingerprint = candidate | ||||
|     ret.radarOffCan = True | ||||
| 
 | ||||
|     ret.safetyModel = car.CarParams.SafetyModels.hyundai | ||||
| 
 | ||||
|     ret.enableCruise = True  # stock acc | ||||
| 
 | ||||
|     # FIXME: hardcoding honda civic 2016 touring params so they can be used to | ||||
|     # scale unknown params for other cars | ||||
|     mass_civic = 2923 * CV.LB_TO_KG + std_cargo | ||||
|     wheelbase_civic = 2.70 | ||||
|     centerToFront_civic = wheelbase_civic * 0.4 | ||||
|     centerToRear_civic = wheelbase_civic - centerToFront_civic | ||||
|     rotationalInertia_civic = 2500 | ||||
|     tireStiffnessFront_civic = 192150 | ||||
|     tireStiffnessRear_civic = 202500 | ||||
| 
 | ||||
|     ret.steerActuatorDelay = 0.1  # Default delay, Prius has larger delay | ||||
| 
 | ||||
|     #borrowing a lot from corolla, given similar car size | ||||
|     ret.steerKf = 0.00005   # full torque for 20 deg at 80mph means 0.00007818594 | ||||
|     ret.steerRateCost = 0.5 | ||||
|     ret.mass = 3982 * CV.LB_TO_KG + std_cargo | ||||
|     ret.wheelbase = 2.766 | ||||
|     ret.steerRatio = 13.8 * 1.15   # 15% higher at the center seems reasonable | ||||
|     ret.steerKiBP, ret.steerKpBP = [[0.], [0.]] | ||||
|     ret.steerKpV, ret.steerKiV = [[0.37], [0.1]] | ||||
|     ret.longitudinalKpBP = [0.] | ||||
|     ret.longitudinalKpV = [0.] | ||||
|     ret.longitudinalKiBP = [0.] | ||||
|     ret.longitudinalKiV = [0.] | ||||
|     tire_stiffness_factor = 1. | ||||
| 
 | ||||
|     ret.centerToFront = ret.wheelbase * 0.4 | ||||
| 
 | ||||
|     # min speed to enable ACC. if car can do stop and go, then set enabling speed | ||||
|     # to a negative value, so it won't matter. | ||||
|     ret.minEnableSpeed = -1. | ||||
| 
 | ||||
|     centerToRear = ret.wheelbase - ret.centerToFront | ||||
| 
 | ||||
|     # TODO: get actual value, for now starting with reasonable value for | ||||
|     # civic and scaling by mass and wheelbase | ||||
|     ret.rotationalInertia = rotationalInertia_civic * \ | ||||
|                             ret.mass * ret.wheelbase**2 / (mass_civic * wheelbase_civic**2) | ||||
| 
 | ||||
|     # TODO: start from empirically derived lateral slip stiffness for the civic and scale by | ||||
|     # mass and CG position, so all cars will have approximately similar dyn behaviors | ||||
|     ret.tireStiffnessFront = (tireStiffnessFront_civic * tire_stiffness_factor) * \ | ||||
|                              ret.mass / mass_civic * \ | ||||
|                              (centerToRear / ret.wheelbase) / (centerToRear_civic / wheelbase_civic) | ||||
|     ret.tireStiffnessRear = (tireStiffnessRear_civic * tire_stiffness_factor) * \ | ||||
|                             ret.mass / mass_civic * \ | ||||
|                             (ret.centerToFront / ret.wheelbase) / (centerToFront_civic / wheelbase_civic) | ||||
| 
 | ||||
| 
 | ||||
|     # no rear steering, at least on the listed cars above | ||||
|     ret.steerRatioRear = 0. | ||||
|     ret.steerControlType = car.CarParams.SteerControlType.torque | ||||
| 
 | ||||
|     # steer, gas, brake limitations VS speed | ||||
|     ret.steerMaxBP = [0.] | ||||
|     ret.steerMaxV = [1.0] | ||||
|     ret.gasMaxBP = [0.] | ||||
|     ret.gasMaxV = [1.] | ||||
|     ret.brakeMaxBP = [0.] | ||||
|     ret.brakeMaxV = [1.] | ||||
|     ret.longPidDeadzoneBP = [0.] | ||||
|     ret.longPidDeadzoneV = [0.] | ||||
| 
 | ||||
|     ret.enableCamera = not any(x for x in CAMERA_MSGS if x in fingerprint) | ||||
| 
 | ||||
|     ret.steerLimitAlert = False | ||||
|     ret.stoppingControl = False | ||||
|     ret.startAccel = 0.0 | ||||
| 
 | ||||
|     return ret | ||||
| 
 | ||||
|   # returns a car.CarState | ||||
|   def update(self, c): | ||||
|     # ******************* do can recv ******************* | ||||
|     canMonoTimes = [] | ||||
|     self.cp.update(int(sec_since_boot() * 1e9), False) | ||||
|     self.cp_cam.update(int(sec_since_boot() * 1e9), False) | ||||
|     self.CS.update(self.cp, self.cp_cam) | ||||
|     # create message | ||||
|     ret = car.CarState.new_message() | ||||
|     # speeds | ||||
|     ret.vEgo = self.CS.v_ego | ||||
|     ret.vEgoRaw = self.CS.v_ego_raw | ||||
|     ret.aEgo = self.CS.a_ego | ||||
|     ret.yawRate = self.CS.yaw_rate | ||||
|     ret.standstill = self.CS.standstill | ||||
|     ret.wheelSpeeds.fl = self.CS.v_wheel_fl | ||||
|     ret.wheelSpeeds.fr = self.CS.v_wheel_fr | ||||
|     ret.wheelSpeeds.rl = self.CS.v_wheel_rl | ||||
|     ret.wheelSpeeds.rr = self.CS.v_wheel_rr | ||||
| 
 | ||||
|     # gear shifter | ||||
|     ret.gearShifter = self.CS.gear_shifter | ||||
| 
 | ||||
|     # gas pedal | ||||
|     ret.gas = self.CS.car_gas | ||||
|     ret.gasPressed = self.CS.pedal_gas > 1e-3   # tolerance to avoid false press reading | ||||
| 
 | ||||
|     # brake pedal | ||||
|     ret.brake = self.CS.user_brake | ||||
|     ret.brakePressed = self.CS.brake_pressed != 0 | ||||
|     ret.brakeLights = self.CS.brake_lights | ||||
| 
 | ||||
|     # steering wheel | ||||
|     ret.steeringAngle = self.CS.angle_steers | ||||
|     ret.steeringRate = self.CS.angle_steers_rate  # it's unsigned | ||||
| 
 | ||||
|     ret.steeringTorque = self.CS.steer_torque_driver | ||||
|     ret.steeringPressed = self.CS.steer_override | ||||
| 
 | ||||
|     # cruise state | ||||
|     ret.cruiseState.enabled = self.CS.pcm_acc_status != 0 | ||||
|     if self.CS.pcm_acc_status != 0: | ||||
|       ret.cruiseState.speed = self.CS.cruise_set_speed | ||||
|     else: | ||||
|       ret.cruiseState.speed = 0 | ||||
|     ret.cruiseState.available = bool(self.CS.main_on) | ||||
|     ret.cruiseState.standstill = False | ||||
| 
 | ||||
|     # TODO: button presses | ||||
|     buttonEvents = [] | ||||
| 
 | ||||
|     if self.CS.left_blinker_on != self.CS.prev_left_blinker_on: | ||||
|       be = car.CarState.ButtonEvent.new_message() | ||||
|       be.type = 'leftBlinker' | ||||
|       be.pressed = self.CS.left_blinker_on != 0 | ||||
|       buttonEvents.append(be) | ||||
| 
 | ||||
|     if self.CS.right_blinker_on != self.CS.prev_right_blinker_on: | ||||
|       be = car.CarState.ButtonEvent.new_message() | ||||
|       be.type = 'rightBlinker' | ||||
|       be.pressed = self.CS.right_blinker_on != 0 | ||||
|       buttonEvents.append(be) | ||||
| 
 | ||||
|     ret.buttonEvents = buttonEvents | ||||
|     ret.leftBlinker = bool(self.CS.left_blinker_on) | ||||
|     ret.rightBlinker = bool(self.CS.right_blinker_on) | ||||
| 
 | ||||
|     ret.doorOpen = not self.CS.door_all_closed | ||||
|     ret.seatbeltUnlatched = not self.CS.seatbelt | ||||
| 
 | ||||
|     #ret.genericToggle = self.CS.generic_toggle | ||||
| 
 | ||||
|     # events | ||||
|     events = [] | ||||
|     if not self.CS.can_valid: | ||||
|       self.can_invalid_count += 1 | ||||
|       if self.can_invalid_count >= 5: | ||||
|         events.append(create_event('commIssue', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE])) | ||||
|     else: | ||||
|       self.can_invalid_count = 0 | ||||
|     if not ret.gearShifter == 'drive': | ||||
|       events.append(create_event('wrongGear', [ET.NO_ENTRY, ET.SOFT_DISABLE])) | ||||
|     if ret.doorOpen: | ||||
|       events.append(create_event('doorOpen', [ET.NO_ENTRY, ET.SOFT_DISABLE])) | ||||
|     if ret.seatbeltUnlatched: | ||||
|       events.append(create_event('seatbeltNotLatched', [ET.NO_ENTRY, ET.SOFT_DISABLE])) | ||||
|     if self.CS.esp_disabled: | ||||
|       events.append(create_event('espDisabled', [ET.NO_ENTRY, ET.SOFT_DISABLE])) | ||||
|     if not self.CS.main_on: | ||||
|       events.append(create_event('wrongCarMode', [ET.NO_ENTRY, ET.USER_DISABLE])) | ||||
|     if ret.gearShifter == 'reverse': | ||||
|       events.append(create_event('reverseGear', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE])) | ||||
|     if self.CS.steer_error: | ||||
|       events.append(create_event('steerTempUnavailable', [ET.NO_ENTRY, ET.WARNING])) | ||||
| 
 | ||||
|     # enable request in prius is simple, as we activate when Toyota is active (rising edge) | ||||
|     if ret.cruiseState.enabled and not self.cruise_enabled_prev: | ||||
|       events.append(create_event('pcmEnable', [ET.ENABLE])) | ||||
|     elif not ret.cruiseState.enabled: | ||||
|       events.append(create_event('pcmDisable', [ET.USER_DISABLE])) | ||||
| 
 | ||||
|     # disable on pedals rising edge or when brake is pressed and speed isn't zero | ||||
|     if (ret.gasPressed and not self.gas_pressed_prev) or \ | ||||
|       (ret.brakePressed and (not self.brake_pressed_prev or ret.vEgoRaw > 0.1)): | ||||
|       events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE])) | ||||
| 
 | ||||
|     if ret.gasPressed: | ||||
|       events.append(create_event('pedalPressed', [ET.PRE_ENABLE])) | ||||
| 
 | ||||
|     ret.events = events | ||||
|     ret.canMonoTimes = canMonoTimes | ||||
| 
 | ||||
|     self.gas_pressed_prev = ret.gasPressed | ||||
|     self.brake_pressed_prev = ret.brakePressed | ||||
|     self.cruise_enabled_prev = ret.cruiseState.enabled | ||||
| 
 | ||||
|     return ret.as_reader() | ||||
| 
 | ||||
|   def apply(self, c, perception_state=log.Live20Data.new_message()): | ||||
| 
 | ||||
|     hud_alert = get_hud_alerts(c.hudControl.visualAlert, c.hudControl.audibleAlert) | ||||
| 
 | ||||
|     self.CC.update(self.sendcan, c.enabled, self.CS, c.actuators, | ||||
|                    c.cruiseControl.cancel, hud_alert) | ||||
| 
 | ||||
|     return False | ||||
| @ -0,0 +1,24 @@ | ||||
| #!/usr/bin/env python | ||||
| from cereal import car | ||||
| import time | ||||
| 
 | ||||
| 
 | ||||
| class RadarInterface(object): | ||||
|   def __init__(self, CP): | ||||
|     # radar | ||||
|     self.pts = {} | ||||
|     self.delay = 0.1 | ||||
| 
 | ||||
|   def update(self): | ||||
| 
 | ||||
|     ret = car.RadarState.new_message() | ||||
|     time.sleep(0.05)  # radard runs on RI updates | ||||
| 
 | ||||
|     return ret | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|   RI = RadarInterface(None) | ||||
|   while 1: | ||||
|     ret = RI.update() | ||||
|     print(chr(27) + "[2J") | ||||
|     print ret | ||||
| @ -0,0 +1,29 @@ | ||||
| from selfdrive.car import dbc_dict | ||||
| 
 | ||||
| def get_hud_alerts(visual_alert, audble_alert): | ||||
|   if visual_alert == "steerRequired": | ||||
|     return 4 if audble_alert != "none" else 5 | ||||
|   else: | ||||
|     return 0 | ||||
| 
 | ||||
| class CAR: | ||||
|   SANTA_FE = "HYUNDAI SANTA FE LIMITED 2019" | ||||
| 
 | ||||
| class Buttons: | ||||
|   NONE = 0 | ||||
|   RES_ACCEL = 1 | ||||
|   SET_DECEL = 2 | ||||
|   CANCEL = 4 | ||||
| 
 | ||||
| FINGERPRINTS = { | ||||
|   CAR.SANTA_FE: [{ | ||||
|     67: 8, 127: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 8, 593: 8, 608: 8, 688: 6, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 8, 897: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1042: 8, 1056: 8, 1057: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1155: 8, 1156: 8, 1162: 8, 1164: 8, 1168: 7, 1170: 8, 1173: 8, 1183: 8, 1186: 2, 1191: 2, 1227: 8, 1265: 4, 1280: 1, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1363: 8, 1369: 8, 1379: 8, 1384: 8, 1407: 8, 1414: 3, 1419: 8, 1427: 6, 1456: 4, 1470: 8 | ||||
|   }], | ||||
| } | ||||
| 
 | ||||
| CAMERA_MSGS = [832, 1156, 1191, 1342]   # msgs sent by the camera | ||||
| 
 | ||||
| DBC = { | ||||
|   CAR.SANTA_FE: dbc_dict('hyundai_santa_fe_2019_ccan', None), | ||||
| } | ||||
| 
 | ||||
| @ -1 +1 @@ | ||||
| #define COMMA_VERSION "0.5.2-release" | ||||
| #define COMMA_VERSION "0.5.3-release" | ||||
|  | ||||
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
					Loading…
					
					
				
		Reference in new issue