diff --git a/board/safety/safety_chrysler.h b/board/safety/safety_chrysler.h index 648cd0d3..1d5e0c34 100644 --- a/board/safety/safety_chrysler.h +++ b/board/safety/safety_chrysler.h @@ -1,30 +1,77 @@ const int CHRYSLER_MAX_STEER = 261; -const int CHRYSLER_MAX_RT_DELTA = 112; // max delta torque allowed for real time checks +const int CHRYSLER_MAX_RT_DELTA = 112; // max delta torque allowed for real time checks const uint32_t CHRYSLER_RT_INTERVAL = 250000; // 250ms between real time checks const int CHRYSLER_MAX_RATE_UP = 3; const int CHRYSLER_MAX_RATE_DOWN = 3; -const int CHRYSLER_MAX_TORQUE_ERROR = 80; // max torque cmd in excess of torque motor -const int CHRYSLER_STANDSTILL_THRSLD = 10; // about 1m/s -const CanMsg CHRYSLER_TX_MSGS[] = {{571, 0, 3}, {658, 0, 6}, {678, 0, 8}}; +const int CHRYSLER_MAX_TORQUE_ERROR = 80; // max torque cmd in excess of torque motor +const int CHRYSLER_STANDSTILL_THRSLD = 10; // about 1m/s +const int CHRYSLER_RAM_STANDSTILL_THRSLD = 3; // about 1m/s changed from wheel rpm to km/h + +// CAN messages for Chrysler/Jeep platforms +#define EPS_2 544 // EPS driver input torque +#define ESP_1 320 // Brake pedal and vehicle speed +#define ESP_8 284 // Brake pedal and vehicle speed +#define ECM_5 559 // Throttle position sensor +#define DAS_3 500 // ACC engagement states from DASM +#define DAS_6 678 // LKAS HUD and auto headlight control from DASM +#define LKAS_COMMAND 658 // LKAS controls from DASM +#define CRUISE_BUTTONS 571 // Cruise control buttons + +// CAN messages for the 5h gen RAM DT platform +#define EPS_2_RAM 49 // EPS driver input torque +#define ESP_1_RAM 131 // Brake pedal and vehicle speed +#define ESP_8_RAM 121 // Brake pedal and vehicle speed +#define ECM_5_RAM 157 // Throttle position sensor +#define DAS_3_RAM 153 // ACC engagement states from DASM +#define DAS_6_RAM 250 // LKAS HUD and auto headlight control from DASM +#define LKAS_COMMAND_RAM 166 // LKAS controls from DASM +#define CRUISE_BUTTONS_RAM 177 // Cruise control buttons + +const CanMsg CHRYSLER_TX_MSGS[] = { + {CRUISE_BUTTONS, 0, 3}, + {LKAS_COMMAND, 0, 6}, + {DAS_6, 0, 8}, +}; + +const CanMsg CHRYSLER_RAM_TX_MSGS[] = { + {CRUISE_BUTTONS_RAM, 2, 3}, + {LKAS_COMMAND_RAM, 0, 8}, + {DAS_6_RAM, 0, 8}, +}; AddrCheckStruct chrysler_addr_checks[] = { - {.msg = {{544, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, + {.msg = {{EPS_2, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, // EPS module + {.msg = {{ESP_1, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // brake pressed + //{.msg = {{ESP_8, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}}}, // vehicle Speed {.msg = {{514, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, - {.msg = {{500, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, - {.msg = {{559, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, - {.msg = {{320, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, + {.msg = {{ECM_5, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // gas pedal + {.msg = {{DAS_3, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // cruise state }; #define CHRYSLER_ADDR_CHECK_LEN (sizeof(chrysler_addr_checks) / sizeof(chrysler_addr_checks[0])) + +AddrCheckStruct chrysler_ram_addr_checks[] = { + {.msg = {{EPS_2_RAM, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, // EPS module + {.msg = {{ESP_1_RAM, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // brake pressed + {.msg = {{ESP_8_RAM, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // vehicle Speed + {.msg = {{ECM_5_RAM, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // gas pedal + {.msg = {{DAS_3_RAM, 2, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // cruise state +}; +#define CHRYSLER_RAM_ADDR_CHECK_LEN (sizeof(chrysler_ram_addr_checks) / sizeof(chrysler_ram_addr_checks[0])) + addr_checks chrysler_rx_checks = {chrysler_addr_checks, CHRYSLER_ADDR_CHECK_LEN}; +const uint32_t CHRYSLER_PARAM_RAM_DT = 1U; // set for Ram DT platform + +bool chrysler_ram = false; + static uint32_t chrysler_get_checksum(CANPacket_t *to_push) { int checksum_byte = GET_LEN(to_push) - 1U; return (uint8_t)(GET_BYTE(to_push, checksum_byte)); } static uint32_t chrysler_compute_checksum(CANPacket_t *to_push) { - /* This function does not want the checksum byte in the input data. - jeep chrysler canbus checksum from http://illmatics.com/Remote%20Car%20Hacking.pdf */ + // TODO: clean this up + // http://illmatics.com/Remote%20Car%20Hacking.pdf uint8_t checksum = 0xFFU; int len = GET_LEN(to_push); for (int j = 0; j < (len - 1); j++) { @@ -56,7 +103,6 @@ static uint32_t chrysler_compute_checksum(CANPacket_t *to_push) { } static uint8_t chrysler_get_counter(CANPacket_t *to_push) { - // Well defined counter only for 8 bytes messages return (uint8_t)(GET_BYTE(to_push, 6) >> 4); } @@ -66,19 +112,22 @@ static int chrysler_rx_hook(CANPacket_t *to_push) { chrysler_get_checksum, chrysler_compute_checksum, chrysler_get_counter); - if (valid && (GET_BUS(to_push) == 0U)) { - int addr = GET_ADDR(to_push); + const int bus = GET_BUS(to_push); + const int addr = GET_ADDR(to_push); - // Measured eps torque - if (addr == 544) { + if (valid) { + + // Measured EPS torque + const int eps_2 = chrysler_ram ? EPS_2_RAM : EPS_2; + if ((bus == 0) && (addr == eps_2)) { int torque_meas_new = ((GET_BYTE(to_push, 4) & 0x7U) << 8) + GET_BYTE(to_push, 5) - 1024U; - - // update array of samples update_sample(&torque_meas, torque_meas_new); } // enter controls on rising edge of ACC, exit controls on ACC off - if (addr == 500) { + const int das_3 = chrysler_ram ? DAS_3_RAM : DAS_3; + const int das_3_bus = chrysler_ram ? 2 : 0; + if ((bus == das_3_bus) && (addr == das_3)) { int cruise_engaged = GET_BIT(to_push, 21U) == 1U; if (cruise_engaged && !cruise_engaged_prev) { controls_allowed = 1; @@ -89,8 +138,13 @@ static int chrysler_rx_hook(CANPacket_t *to_push) { cruise_engaged_prev = cruise_engaged; } + // TODO: use the same message for both // update speed - if (addr == 514) { + if (chrysler_ram && (bus == 0) && (addr == ESP_8_RAM)) { + vehicle_speed = (((GET_BYTE(to_push, 4) & 0x3U) << 8) + GET_BYTE(to_push, 5))*0.0078125; + vehicle_moving = (int)vehicle_speed > CHRYSLER_RAM_STANDSTILL_THRSLD; + } + if (!chrysler_ram && (bus == 0) && (addr == 514)) { int speed_l = (GET_BYTE(to_push, 0) << 4) + (GET_BYTE(to_push, 1) >> 4); int speed_r = (GET_BYTE(to_push, 2) << 4) + (GET_BYTE(to_push, 3) >> 4); vehicle_speed = (speed_l + speed_r) / 2; @@ -98,16 +152,19 @@ static int chrysler_rx_hook(CANPacket_t *to_push) { } // exit controls on rising edge of gas press - if (addr == 559) { + const int ecm_5 = chrysler_ram ? ECM_5_RAM : ECM_5; + if ((bus == 0) && (addr == ecm_5)) { gas_pressed = GET_BYTE(to_push, 0U) != 0U; } // exit controls on rising edge of brake press - if (addr == 320) { + const int esp_1 = chrysler_ram ? ESP_1_RAM : ESP_1; + if ((bus == 0) && (addr == esp_1)) { brake_pressed = ((GET_BYTE(to_push, 0U) & 0xFU) >> 2U) == 1U; } - generic_rx_checks((addr == 0x292)); + const int lkas_command = chrysler_ram ? LKAS_COMMAND_RAM : LKAS_COMMAND; + generic_rx_checks((bus == 0) && (addr == lkas_command)); } return valid; } @@ -118,18 +175,23 @@ static int chrysler_tx_hook(CANPacket_t *to_send, bool longitudinal_allowed) { int tx = 1; int addr = GET_ADDR(to_send); - if (!msg_allowed(to_send, CHRYSLER_TX_MSGS, sizeof(CHRYSLER_TX_MSGS) / sizeof(CHRYSLER_TX_MSGS[0]))) { - tx = 0; + if (chrysler_ram) { + tx = msg_allowed(to_send, CHRYSLER_RAM_TX_MSGS, sizeof(CHRYSLER_RAM_TX_MSGS) / sizeof(CHRYSLER_RAM_TX_MSGS[0])); + } else { + tx = msg_allowed(to_send, CHRYSLER_TX_MSGS, sizeof(CHRYSLER_TX_MSGS) / sizeof(CHRYSLER_TX_MSGS[0])); } - // LKA STEER - if (addr == 0x292) { - int desired_torque = ((GET_BYTE(to_send, 0) & 0x7U) << 8) + GET_BYTE(to_send, 1) - 1024U; + // STEERING + const int lkas_addr = chrysler_ram ? LKAS_COMMAND_RAM : LKAS_COMMAND; + if (tx && (addr == lkas_addr)) { + int start_byte = chrysler_ram ? 1 : 0; + int desired_torque = ((GET_BYTE(to_send, start_byte) & 0x7U) << 8) | GET_BYTE(to_send, start_byte + 1); + desired_torque -= 1024; + uint32_t ts = microsecond_timer_get(); bool violation = 0; if (controls_allowed) { - // *** global torque limit check *** violation |= max_limit_check(desired_torque, CHRYSLER_MAX_STEER, -CHRYSLER_MAX_STEER); @@ -169,7 +231,7 @@ static int chrysler_tx_hook(CANPacket_t *to_send, bool longitudinal_allowed) { } // FORCE CANCEL: only the cancel button press is allowed - if (addr == 571) { + if ((addr == CRUISE_BUTTONS) || (addr == CRUISE_BUTTONS_RAM)) { if ((GET_BYTE(to_send, 0) != 1U) || ((GET_BYTE(to_send, 1) & 1U) == 1U)) { tx = 0; } @@ -179,17 +241,18 @@ static int chrysler_tx_hook(CANPacket_t *to_send, bool longitudinal_allowed) { } static int chrysler_fwd_hook(int bus_num, CANPacket_t *to_fwd) { - int bus_fwd = -1; int addr = GET_ADDR(to_fwd); - // forward CAN 0 -> 2 so stock LKAS camera sees messages + // forward to camera if (bus_num == 0) { bus_fwd = 2; } - // forward all messages from camera except LKAS_COMMAND and LKAS_HUD - if ((bus_num == 2) && (addr != 658) && (addr != 678)) { + // forward all messages from camera except LKAS messages + const bool is_lkas = (!chrysler_ram && ((addr == LKAS_COMMAND) || (addr == DAS_6))) || + (chrysler_ram && ((addr == LKAS_COMMAND_RAM) || (addr == DAS_6_RAM))); + if ((bus_num == 2) && !is_lkas){ bus_fwd = 0; } @@ -197,7 +260,14 @@ static int chrysler_fwd_hook(int bus_num, CANPacket_t *to_fwd) { } static const addr_checks* chrysler_init(uint16_t param) { - UNUSED(param); + chrysler_ram = GET_FLAG(param, CHRYSLER_PARAM_RAM_DT); + + if (chrysler_ram) { + chrysler_rx_checks = (addr_checks){chrysler_ram_addr_checks, CHRYSLER_RAM_ADDR_CHECK_LEN}; + } else { + chrysler_rx_checks = (addr_checks){chrysler_addr_checks, CHRYSLER_ADDR_CHECK_LEN}; + } + return &chrysler_rx_checks; } diff --git a/python/__init__.py b/python/__init__.py index 3f9887db..3b3ecd80 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -198,6 +198,8 @@ class Panda: FLAG_TESLA_POWERTRAIN = 1 FLAG_TESLA_LONG_CONTROL = 2 + FLAG_CHRYSLER_RAM_DT = 1 + def __init__(self, serial: Optional[str] = None, claim: bool = True): self._serial = serial self._handle = None diff --git a/tests/safety/common.py b/tests/safety/common.py index 79546c90..00c01213 100644 --- a/tests/safety/common.py +++ b/tests/safety/common.py @@ -570,7 +570,6 @@ class PandaSafetyTest(PandaSafetyTestBase): # No point in comparing different Tesla safety modes if 'Tesla' in attr and 'Tesla' in current_test: continue - if {attr, current_test}.issubset({'TestToyotaSafety', 'TestToyotaAltBrakeSafety', 'TestToyotaStockLongitudinal'}): continue diff --git a/tests/safety/test_chrysler.py b/tests/safety/test_chrysler.py index 3d624b15..ed559794 100755 --- a/tests/safety/test_chrysler.py +++ b/tests/safety/test_chrysler.py @@ -21,6 +21,8 @@ class TestChryslerSafety(common.PandaSafetyTest, common.MotorTorqueSteeringSafet RT_INTERVAL = 250000 MAX_TORQUE_ERROR = 80 + DAS_BUS = 0 + def setUp(self): self.packer = CANPackerPanda("chrysler_pacifica_2017_hybrid_generated") self.safety = libpandasafety_py.libpandasafety @@ -29,11 +31,11 @@ class TestChryslerSafety(common.PandaSafetyTest, common.MotorTorqueSteeringSafet def _button_msg(self, cancel): values = {"ACC_Cancel": cancel} - return self.packer.make_can_msg_panda("CRUISE_BUTTONS", 0, values) + return self.packer.make_can_msg_panda("CRUISE_BUTTONS", self.DAS_BUS, values) def _pcm_status_msg(self, enable): values = {"ACC_ACTIVE": enable} - return self.packer.make_can_msg_panda("DAS_3", 0, values, counter=True) + return self.packer.make_can_msg_panda("DAS_3", self.DAS_BUS, values, counter=True) def _speed_msg(self, speed): values = {"SPEED_LEFT": speed, "SPEED_RIGHT": speed} @@ -60,5 +62,25 @@ class TestChryslerSafety(common.PandaSafetyTest, common.MotorTorqueSteeringSafet self.assertEqual(cancel, self._tx(self._button_msg(cancel))) +class TestChryslerRamSafety(TestChryslerSafety): + TX_MSGS = [[177, 2], [166, 0], [250, 0]] + STANDSTILL_THRESHOLD = 3 + RELAY_MALFUNCTION_ADDR = 166 + FWD_BLACKLISTED_ADDRS = {2: [166, 250]} + + DAS_BUS = 2 + + def setUp(self): + self.packer = CANPackerPanda("chrysler_ram_dt_generated") + self.safety = libpandasafety_py.libpandasafety + self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, Panda.FLAG_CHRYSLER_RAM_DT) + self.safety.init_tests() + + def _speed_msg(self, speed): + values = {"Vehicle_Speed": speed} + return self.packer.make_can_msg_panda("ESP_8", 0, values, counter=True) + + + if __name__ == "__main__": unittest.main() diff --git a/tests/safety_replay/replay_drive.py b/tests/safety_replay/replay_drive.py index 35e419ac..65254654 100755 --- a/tests/safety_replay/replay_drive.py +++ b/tests/safety_replay/replay_drive.py @@ -83,7 +83,7 @@ if __name__ == "__main__": logs = r.log_paths()[s.segment_num:s.segment_num+1] if s.segment_num >= 0 else r.log_paths() lr = MultiLogIterator(logs) - if None in (args.mode, args.param): + if None in (args.mode, args.param, args.alternative_experience): for msg in lr: if msg.which() == 'carParams': if args.mode is None: