diff --git a/common/fingerprints.py b/common/fingerprints.py index 4bf10bf7decced..952528560d0e55 100644 --- a/common/fingerprints.py +++ b/common/fingerprints.py @@ -16,6 +16,9 @@ # sent messages 0x194: 4, 0x1fa: 8, 0x30c: 8, 0x33d: 5, }, + "HONDA ODYSSEY 2018 EX-L": { + 57L: 3, 148L: 8, 228L: 5, 229L: 4, 316L: 8, 342L: 6, 344L: 8, 380L: 8, 399L: 7, 411L: 5, 419L: 8, 420L: 8, 427L: 3, 432L: 7, 450L: 8, 463L: 8, 464L: 8, 476L: 4, 490L: 8, 506L: 8, 542L: 7, 545L: 6, 597L: 8, 662L: 4, 773L: 7, 777L: 8, 780L: 8, 795L: 8, 800L: 8, 804L: 8, 806L: 8, 808L: 8, 817L: 4, 819L: 7, 821L: 5, 825L: 4, 829L: 5, 837L: 5, 856L: 7, 862L: 8, 871L: 8, 881L: 8, 882L: 4, 884L: 8, 891L: 8, 892L: 8, 905L: 8, 923L: 2, 927L: 8, 929L: 8, 963L: 8, 965L: 8, 966L: 8, 967L: 8, 983L: 8, 985L: 3, 1029L: 8, 1036L: 8, 1052L: 8, 1064L: 7, 1088L: 8, 1089L: 8, 1092L: 1, 1108L: 8, 1110L: 8, 1125L: 8, 1296L: 8, 1302L: 8, 1600L: 5, 1601L: 8, 1612L: 5, 1613L: 5, 1614L: 5, 1615L: 8, 1616L: 5, 1619L: 5, 1623L: 5, 1668L: 5 + }, "TOYOTA RAV4 2017": { 36L: 8, 37L: 8, 170L: 8, 180L: 8, 186L: 4, 426L: 6, 452L: 8, 464L: 8, 466L: 8, 467L: 8, 547L: 8, 548L: 8, 552L: 4, 562L: 4, 608L: 8, 610L: 5, 643L: 7, 705L: 8, 725L: 2, 740L: 5, 800L: 8, 835L: 8, 836L: 8, 849L: 4, 869L: 7, 870L: 7, 871L: 2, 896L: 8, 897L: 8, 900L: 6, 902L: 6, 905L: 8, 911L: 8, 916L: 3, 918L: 7, 921L: 8, 933L: 8, 944L: 8, 945L: 8, 951L: 8, 955L: 4, 956L: 8, 979L: 2, 998L: 5, 999L: 7, 1000L: 8, 1001L: 8, 1008L: 2, 1014L: 8, 1017L: 8, 1041L: 8, 1042L: 8, 1043L: 8, 1044L: 8, 1056L: 8, 1059L: 1, 1114L: 8, 1161L: 8, 1162L: 8, 1163L: 8, 1176L: 8, 1177L: 8, 1178L: 8, 1179L: 8, 1180L: 8, 1181L: 8, 1190L: 8, 1191L: 8, 1192L: 8, 1196L: 8, 1227L: 8, 1228L: 8, 1235L: 8, 1237L: 8, 1263L: 8, 1279L: 8, 1408L: 8, 1409L: 8, 1410L: 8, 1552L: 8, 1553L: 8, 1554L: 8, 1555L: 8, 1556L: 8, 1557L: 8, 1561L: 8, 1562L: 8, 1568L: 8, 1569L: 8, 1570L: 8, 1571L: 8, 1572L: 8, 1584L: 8, 1589L: 8, 1592L: 8, 1593L: 8, 1595L: 8, 1596L: 8, 1597L: 8, 1600L: 8, 1656L: 8, 1664L: 8, 1728L: 8, 1745L: 8, 1779L: 8, 1904L: 8, 1912L: 8, 1990L: 8, 1998L: 8 }, @@ -59,4 +62,3 @@ def eliminate_incompatible_cars(msg, candidate_cars): def all_known_cars(): """Returns a list of all known car strings.""" return _FINGERPRINTS.keys() - diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 4526d35c405e8c..76916cb5b49d60 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -26,6 +26,7 @@ "ACURA ILX 2016 ACURAWATCH PLUS": HondaInterface, "HONDA ACCORD 2016 TOURING": HondaInterface, "HONDA CR-V 2016 TOURING": HondaInterface, + "HONDA ODYSSEY 2018 EX-L": HondaInterface, "TOYOTA PRIUS 2017": ToyotaInterface, "TOYOTA RAV4 2017": ToyotaInterface, "TOYOTA RAV4 2017 HYBRID": ToyotaInterface, @@ -59,7 +60,7 @@ def fingerprint(logcan, timeout): candidate_cars = eliminate_incompatible_cars(can, candidate_cars) ts = sec_since_boot() - # if we only have one car choice and the time_fingerprint since we got our first + # if we only have one car choice and the time_fingerprint since we got our first # message has elapsed, exit. Toyota needs higher time_fingerprint, since DSU does not # broadcast immediately if len(candidate_cars) == 1 and st is not None: diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py index 1ee7e2c8089afa..d2f69936e55e29 100644 --- a/selfdrive/car/honda/carcontroller.py +++ b/selfdrive/car/honda/carcontroller.py @@ -12,7 +12,7 @@ from .values import AH -def actuator_hystereses(brake, braking, brake_steady, v_ego, civic): +def actuator_hystereses(brake, braking, brake_steady, v_ego, civic, odyssey): # hyst params... TODO: move these to VehicleParams brake_hyst_on = 0.02 # to activate brakes exceed this value brake_hyst_off = 0.005 # to deactivate brakes below this value @@ -32,7 +32,7 @@ def actuator_hystereses(brake, braking, brake_steady, v_ego, civic): brake_steady = brake + brake_hyst_gap brake = brake_steady - if not civic and brake > 0.0: + if (not civic and not odyssey) and brake > 0.0: brake += 0.15 return brake, braking, brake_steady @@ -78,7 +78,7 @@ def update(self, sendcan, enabled, CS, frame, actuators, \ return # *** apply brake hysteresis *** - brake, self.braking, self.brake_steady = actuator_hystereses(actuators.brake, self.braking, self.brake_steady, CS.v_ego, CS.civic) + brake, self.braking, self.brake_steady = actuator_hystereses(actuators.brake, self.braking, self.brake_steady, CS.v_ego, CS.civic, CS.odyssey) # *** no output if not enabled *** if not enabled and CS.pcm_acc_status: @@ -121,7 +121,7 @@ def update(self, sendcan, enabled, CS, frame, actuators, \ tt = sec_since_boot() GAS_MAX = 1004 BRAKE_MAX = 1024/4 - if CS.civic: + if CS.civic or CS.odyssey: is_fw_modified = os.getenv("DONGLE_ID") in ['b0f5a01cf604185c'] STEER_MAX = 0x1FFF if is_fw_modified else 0x1000 elif CS.crv: @@ -165,16 +165,16 @@ def update(self, sendcan, enabled, CS, frame, actuators, \ # Send dashboard UI commands. if (frame % 10) == 0: idx = (frame/10) % 4 - can_sends.extend(hondacan.create_ui_commands(pcm_speed, hud, CS.civic, CS.accord, CS.crv, idx)) + can_sends.extend(hondacan.create_ui_commands(pcm_speed, hud, CS.civic, CS.accord, CS.crv, CS.odyssey, idx)) # radar at 20Hz, but these msgs need to be sent at 50Hz on ilx (seems like an Acura bug) - if CS.civic or CS.accord or CS.crv: - radar_send_step = 5 - else: + if CS.acura: radar_send_step = 2 + else: + radar_send_step = 5 if (frame % radar_send_step) == 0: idx = (frame/radar_send_step) % 4 - can_sends.extend(hondacan.create_radar_commands(CS.v_ego, CS.civic, CS.accord, CS.crv, idx)) + can_sends.extend(hondacan.create_radar_commands(CS.v_ego, CS.civic, CS.accord, CS.crv, CS.odyssey, idx)) sendcan.send(can_list_to_can_capnp(can_sends, msgtype='sendcan').to_bytes()) diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py index 015ff7c5737920..d056b146ec99db 100644 --- a/selfdrive/car/honda/carstate.py +++ b/selfdrive/car/honda/carstate.py @@ -6,14 +6,14 @@ from selfdrive.config import Conversions as CV import numpy as np -def parse_gear_shifter(can_gear_shifter, is_acura): +def parse_gear_shifter(can_gear_shifter, is_acura, is_odyssey): if can_gear_shifter == 0x1: return "park" elif can_gear_shifter == 0x2: return "reverse" - if is_acura: + if is_acura or is_odyssey: if can_gear_shifter == 0x3: return "neutral" elif can_gear_shifter == 0x4: @@ -261,6 +261,62 @@ def get_can_signals(CP): (0x324, 10), (0x405, 3), ] + elif CP.carFingerprint == "HONDA ODYSSEY 2018 EX-L": + dbc_f = 'honda_odyssey_exl_2018.dbc' + signals = [ + ("XMISSION_SPEED", 0x158, 0), + ("WHEEL_SPEED_FL", 0x1d0, 0), + ("WHEEL_SPEED_FR", 0x1d0, 0), + ("WHEEL_SPEED_RL", 0x1d0, 0), + ("WHEEL_SPEED_RR", 0x1d0, 0), + ("STEER_ANGLE", 0x156, 0), + ("STEER_ANGLE_RATE", 0x156, 0), + ("STEER_TORQUE_SENSOR", 0x18f, 0), + ("GEAR", 0x1a3, 0), + ("WHEELS_MOVING", 0x1b0, 1), + ("DOOR_OPEN_FL", 0x405, 1), + ("DOOR_OPEN_FR", 0x405, 1), + ("DOOR_OPEN_RL", 0x405, 1), + ("DOOR_OPEN_RR", 0x405, 1), + ("CRUISE_SPEED_PCM", 0x324, 0), + ("SEATBELT_DRIVER_LAMP", 0x305, 1), + ("SEATBELT_DRIVER_LATCHED", 0x305, 0), + ("BRAKE_PRESSED", 0x17c, 0), + ("BRAKE_SWITCH", 0x17c, 0), + ("CRUISE_BUTTONS", 0x296, 0), + ("ESP_DISABLED", 0x1a4, 1), + ("HUD_LEAD", 0x30c, 0), + ("USER_BRAKE", 0x1a4, 0), + ("STEER_STATUS", 0x18f, 5), + ("BRAKE_ERROR_1", 0x1b0, 1), + ("BRAKE_ERROR_2", 0x1b0, 1), + ("GEAR_SHIFTER", 0x1a3, 0), + ("MAIN_ON", 0x326, 0), + ("ACC_STATUS", 0x17c, 0), + ("PEDAL_GAS", 0x17c, 0), + ("CRUISE_SETTING", 0x296, 0), + ("LEFT_BLINKER", 0x326, 0), + ("RIGHT_BLINKER", 0x326, 0), + ("CRUISE_SPEED_OFFSET", 0x37c, 0), + ("EPB_STATE", 0x1c2, 0), + ("BRAKE_HOLD_ACTIVE", 0x1a4, 0), + ] + checks = [ + (0x156, 100), + (0x158, 100), + (0x17c, 100), + (0x1a3, 50), + (0x1a4, 50), + (0x1b0, 50), + (0x1c2, 50), + (0x1d0, 50), + (0x296, 25), + (0x305, 10), + (0x324, 10), + (0x326, 10), + (0x37c, 10), + (0x405, 3), + ] # add gas interceptor reading if we are using it if CP.enableGas: signals.append(("INTERCEPTOR_GAS", 0x201, 0)) @@ -278,6 +334,7 @@ def __init__(self, CP): self.civic = False self.accord = False self.crv = False + self.odyssey = False if CP.carFingerprint == "HONDA CIVIC 2016 TOURING": self.civic = True elif CP.carFingerprint == "ACURA ILX 2016 ACURAWATCH PLUS": @@ -286,6 +343,8 @@ def __init__(self, CP): self.accord = True elif CP.carFingerprint == "HONDA CR-V 2016 TOURING": self.crv = True + elif CP.carFingerprint == "HONDA ODYSSEY 2018 EX-L": + self.odyssey = True else: raise ValueError("unsupported car %s" % CP.carFingerprint) @@ -418,6 +477,20 @@ def update(self, cp): self.cruise_speed_offset = -0.3 self.park_brake = 0 # TODO self.brake_hold = 0 # TODO + elif self.odyssey: + can_gear_shifter = cp.vl[0x1A3]['GEAR_SHIFTER'] + self.angle_steers = cp.vl[0x156]['STEER_ANGLE'] + self.angle_steers_rate = cp.vl[0x156]['STEER_ANGLE_RATE'] + self.gear = cp.vl[0x1A3]['GEAR'] + self.cruise_setting = cp.vl[0x296]['CRUISE_SETTING'] + self.cruise_buttons = cp.vl[0x296]['CRUISE_BUTTONS'] + self.main_on = cp.vl[0x326]['MAIN_ON'] + self.blinker_on = cp.vl[0x326]['LEFT_BLINKER'] or cp.vl[0x326]['RIGHT_BLINKER'] + self.left_blinker_on = cp.vl[0x326]['LEFT_BLINKER'] + self.right_blinker_on = cp.vl[0x326]['RIGHT_BLINKER'] + self.cruise_speed_offset = calc_cruise_offset(cp.vl[0x37c]['CRUISE_SPEED_OFFSET'], self.v_ego) + self.park_brake = cp.vl[0x1c2]['EPB_STATE'] != 0 + self.brake_hold = cp.vl[0x1a4]['BRAKE_HOLD_ACTIVE'] elif self.acura: can_gear_shifter = cp.vl[0x1A3]['GEAR_SHIFTER'] self.angle_steers = cp.vl[0x156]['STEER_ANGLE'] @@ -431,15 +504,15 @@ def update(self, cp): self.right_blinker_on = cp.vl[0x294]['RIGHT_BLINKER'] self.cruise_speed_offset = calc_cruise_offset(cp.vl[0x37c]['CRUISE_SPEED_OFFSET'], self.v_ego) self.park_brake = 0 # TODO - self.brake_hold = 0 + self.brake_hold = 0 # TODO - self.gear_shifter = parse_gear_shifter(can_gear_shifter, self.acura) + self.gear_shifter = parse_gear_shifter(can_gear_shifter, self.acura, self.odyssey) if self.accord: # on the accord, this doesn't seem to include cruise control self.car_gas = cp.vl[0x17C]['PEDAL_GAS'] self.steer_override = False - elif self.crv: + elif self.crv or self.odyssey: # like accord, crv doesn't include cruise control self.car_gas = cp.vl[0x17C]['PEDAL_GAS'] self.steer_override = abs(cp.vl[0x18F]['STEER_TORQUE_SENSOR']) > 1200 diff --git a/selfdrive/car/honda/hondacan.py b/selfdrive/car/honda/hondacan.py index 31615a8cbbe0b2..0c53f243d92759 100644 --- a/selfdrive/car/honda/hondacan.py +++ b/selfdrive/car/honda/hondacan.py @@ -79,7 +79,7 @@ def create_steering_control(apply_steer, crv, idx): commands.append(make_can_msg(0xe4, msg_0xe4, idx, 0)) return commands -def create_ui_commands(pcm_speed, hud, civic, accord, crv, idx): +def create_ui_commands(pcm_speed, hud, civic, accord, crv, odyssey, idx): """Creates an iterable of CAN messages for the UIs.""" commands = [] pcm_speed_real = np.clip(int(round(pcm_speed / 0.002759506)), 0, @@ -90,17 +90,17 @@ def create_ui_commands(pcm_speed, hud, civic, accord, crv, idx): msg_0x33d = chr(hud.X5) + chr(hud.lanes) + chr(hud.beep) + chr(hud.X8) commands.append(make_can_msg(0x33d, msg_0x33d, idx, 0)) - if civic: # 2 more msgs + if civic or odyssey: # 2 more msgs msg_0x35e = chr(0) * 7 commands.append(make_can_msg(0x35e, msg_0x35e, idx, 0)) - if civic or accord: + if civic or accord or odyssey: msg_0x39f = ( chr(0) * 2 + chr(hud.acc_alert) + chr(0) + chr(0xff) + chr(0x7f) + chr(0) ) commands.append(make_can_msg(0x39f, msg_0x39f, idx, 0)) return commands -def create_radar_commands(v_ego, civic, accord, crv, idx): +def create_radar_commands(v_ego, civic, accord, crv, odyssey, idx): """Creates an iterable of CAN messages for the radar system.""" commands = [] v_ego_kph = np.clip(int(round(v_ego * CV.MS_TO_KPH)), 0, 255) @@ -122,6 +122,9 @@ def create_radar_commands(v_ego, civic, accord, crv, idx): elif crv: msg_0x301 = "\x00\x00\x50\x02\x51\x00\x00" commands.append(make_can_msg(0x300, msg_0x300, idx, 1)) + elif odyssey: + msg_0x301 = "\x00\x00\x56\x02\x55\x00\x00" + commands.append(make_can_msg(0x300, msg_0x300, idx, 1)) else: msg_0x301 = "\x0f\x18\x51\x02\x5a\x00\x00" commands.append(make_can_msg(0x300, msg_0x300, idx, 1)) diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 7879a9ef1e51f4..c443740926d325 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -104,7 +104,7 @@ def __init__(self, CP, sendcan=None): # self.accord_msg = [] raise NotImplementedError - if not self.CS.civic: + if not self.CS.civic and not self.CS.odyssey: self.compute_gb = get_compute_gb_acura() else: self.compute_gb = compute_gb_honda @@ -205,6 +205,18 @@ def get_params(candidate, fingerprint): ret.steerRatio = 15.3 ret.steerKp, ret.steerKi = 0.8, 0.24 + ret.longitudinalKpBP = [0., 5., 35.] + ret.longitudinalKpV = [1.2, 0.8, 0.5] + ret.longitudinalKiBP = [0., 35.] + ret.longitudinalKiV = [0.18, 0.12] + elif candidate == "HONDA ODYSSEY 2018 EX-L": + stop_and_go = False + ret.mass = 4354./2.205 + std_cargo + ret.wheelbase = 3.00 + ret.centerToFront = ret.wheelbase * 0.41 + ret.steerRatio = 14.35 + ret.steerKp, ret.steerKi = 0.6, 0.18 + ret.longitudinalKpBP = [0., 5., 35.] ret.longitudinalKpV = [1.2, 0.8, 0.5] ret.longitudinalKiBP = [0., 35.]