293fa33 Honda: fixed message forwarding addresses from can2 to can0 799c338 Chrysler safety controls (#130) c05b15b Toyota frc on (#141) 8291971 Toyota: using a more generalized CRUISE_ACTIVE bit that works on all cars 6f157aa Toyota frc on (#140) 8d2470c bumped panda version 915ee4f Honda: forwarding CAN0 to camera, so camera can stay on (#139) git-subtree-dir: panda git-subtree-split: 293fa33f830f0c7cdfad31f621c4bdc016aa7d41pull/438/head
parent
a51a60b598
commit
c10a755516
10 changed files with 289 additions and 23 deletions
@ -0,0 +1,136 @@ |
||||
// board enforces
|
||||
// in-state
|
||||
// ACC is active (green)
|
||||
// out-state
|
||||
// brake pressed
|
||||
// stock LKAS ECU is online
|
||||
// ACC is not active (white or disabled)
|
||||
|
||||
// chrysler_: namespacing
|
||||
int chrysler_speed = 0; |
||||
|
||||
// silence everything if stock ECUs are still online
|
||||
int chrysler_lkas_detected = 0; |
||||
int chrysler_desired_torque_last = 0; |
||||
|
||||
static void chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { |
||||
int bus_number = (to_push->RDTR >> 4) & 0xFF; |
||||
uint32_t addr; |
||||
if (to_push->RIR & 4) { |
||||
// Extended
|
||||
// Not looked at, but have to be separated
|
||||
// to avoid address collision
|
||||
addr = to_push->RIR >> 3; |
||||
} else { |
||||
// Normal
|
||||
addr = to_push->RIR >> 21; |
||||
} |
||||
|
||||
if (addr == 0x144 && bus_number == 0) { |
||||
chrysler_speed = ((to_push->RDLR & 0xFF000000) >> 16) | (to_push->RDHR & 0xFF); |
||||
} |
||||
|
||||
// check if stock LKAS ECU is still online
|
||||
if (addr == 0x292 && bus_number == 0) { |
||||
chrysler_lkas_detected = 1; |
||||
controls_allowed = 0; |
||||
} |
||||
|
||||
// ["ACC_2"]['ACC_STATUS_2'] == 7 for active (green) Adaptive Cruise Control
|
||||
if (addr == 0x1f4 && bus_number == 0) { |
||||
if (((to_push->RDLR & 0x380000) >> 19) == 7) { |
||||
controls_allowed = 1; |
||||
} else { |
||||
controls_allowed = 0; |
||||
} |
||||
} |
||||
|
||||
// exit controls on brake press by human
|
||||
if (addr == 0x140) { |
||||
if (to_push->RDLR & 0x4) { |
||||
controls_allowed = 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// if controls_allowed
|
||||
// allow steering up to limit
|
||||
// else
|
||||
// block all commands that produce actuation
|
||||
static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { |
||||
// There can be only one! (LKAS)
|
||||
if (chrysler_lkas_detected) { |
||||
return 0; |
||||
} |
||||
|
||||
uint32_t addr; |
||||
if (to_send->RIR & 4) { |
||||
// Extended
|
||||
addr = to_send->RIR >> 3; |
||||
} else { |
||||
// Normal
|
||||
addr = to_send->RIR >> 21; |
||||
} |
||||
|
||||
// LKA STEER: Too large of values cause the steering actuator ECU to silently
|
||||
// fault and no longer actuate the wheel until the car is rebooted.
|
||||
if (addr == 0x292) { |
||||
int rdlr = to_send->RDLR; |
||||
int straight = 1024; |
||||
int steer = ((rdlr & 0x7) << 8) + ((rdlr & 0xFF00) >> 8) - straight; |
||||
int max_steer = 230; |
||||
int max_rate = 50; // ECU is fine with 100, but 3 is typical.
|
||||
if (steer > max_steer) { |
||||
return false; |
||||
} |
||||
if (steer < -max_steer) { |
||||
return false; |
||||
} |
||||
if (!controls_allowed && steer != 0) { |
||||
// If controls not allowed, only allow steering to move closer to 0.
|
||||
if (chrysler_desired_torque_last == 0) { |
||||
return false; |
||||
} |
||||
if ((chrysler_desired_torque_last > 0) && (steer >= chrysler_desired_torque_last)) { |
||||
return false; |
||||
} |
||||
if ((chrysler_desired_torque_last < 0) && (steer <= chrysler_desired_torque_last)) { |
||||
return false; |
||||
} |
||||
} |
||||
if (steer < (chrysler_desired_torque_last - max_rate)) { |
||||
return false; |
||||
} |
||||
if (steer > (chrysler_desired_torque_last + max_rate)) { |
||||
return false; |
||||
} |
||||
|
||||
chrysler_desired_torque_last = steer; |
||||
} |
||||
|
||||
// 1 allows the message through
|
||||
return true; |
||||
} |
||||
|
||||
static int chrysler_tx_lin_hook(int lin_num, uint8_t *data, int len) { |
||||
// LIN is not used.
|
||||
return false; |
||||
} |
||||
|
||||
static void chrysler_init(int16_t param) { |
||||
controls_allowed = 0; |
||||
} |
||||
|
||||
static int chrysler_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { |
||||
return -1; |
||||
} |
||||
|
||||
const safety_hooks chrysler_hooks = { |
||||
.init = chrysler_init, |
||||
.rx = chrysler_rx_hook, |
||||
.tx = chrysler_tx_hook, |
||||
.tx_lin = chrysler_tx_lin_hook, |
||||
.ignition = default_ign_hook, |
||||
.fwd = chrysler_fwd_hook, |
||||
}; |
||||
|
@ -0,0 +1,88 @@ |
||||
#!/usr/bin/env python2 |
||||
import unittest |
||||
import numpy as np |
||||
import libpandasafety_py |
||||
|
||||
|
||||
class TestChryslerSafety(unittest.TestCase): |
||||
@classmethod |
||||
def setUp(cls): |
||||
cls.safety = libpandasafety_py.libpandasafety |
||||
cls.safety.chrysler_init(0) |
||||
cls.safety.init_tests_chrysler() |
||||
|
||||
def _acc_msg(self, active): |
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') |
||||
to_send[0].RIR = 0x1f4 << 21 |
||||
to_send[0].RDLR = 0xfe3fff1f if active else 0xfe0fff1f |
||||
return to_send |
||||
|
||||
|
||||
def _brake_msg(self, brake): |
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') |
||||
to_send[0].RIR = 0x140 << 21 |
||||
to_send[0].RDLR = 0x485 if brake else 0x480 |
||||
return to_send |
||||
|
||||
def _steer_msg(self, angle): |
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') |
||||
to_send[0].RIR = 0x292 << 21 |
||||
c_angle = (1024 + angle) |
||||
to_send[0].RDLR = 0x10 | ((c_angle & 0xf00) >> 8) | ((c_angle & 0xff) << 8) |
||||
return to_send |
||||
|
||||
def test_default_controls_not_allowed(self): |
||||
self.assertFalse(self.safety.get_controls_allowed()) |
||||
|
||||
def test_acc_enables_controls(self): |
||||
self.safety.set_controls_allowed(0) |
||||
self.safety.chrysler_rx_hook(self._acc_msg(0)) |
||||
self.assertFalse(self.safety.get_controls_allowed()) |
||||
self.safety.chrysler_rx_hook(self._acc_msg(1)) |
||||
self.assertTrue(self.safety.get_controls_allowed()) |
||||
self.safety.chrysler_rx_hook(self._acc_msg(0)) |
||||
self.assertFalse(self.safety.get_controls_allowed()) |
||||
|
||||
def test_disengage_on_brake(self): |
||||
self.safety.set_controls_allowed(1) |
||||
self.safety.chrysler_rx_hook(self._brake_msg(0)) |
||||
self.assertTrue(self.safety.get_controls_allowed()) |
||||
self.safety.chrysler_rx_hook(self._brake_msg(1)) |
||||
self.assertFalse(self.safety.get_controls_allowed()) |
||||
|
||||
def test_steer_calculation(self): |
||||
self.assertEqual(0x14, self._steer_msg(0)[0].RDLR) # straight, no steering |
||||
|
||||
def test_steer_tx(self): |
||||
self.safety.set_controls_allowed(1) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(0))) |
||||
self.safety.set_chrysler_desired_torque_last(227) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(230))) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(231))) |
||||
self.safety.set_chrysler_desired_torque_last(-227) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(-231))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(-230))) |
||||
# verify max change |
||||
self.safety.set_chrysler_desired_torque_last(0) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(230))) |
||||
|
||||
self.safety.set_controls_allowed(0) |
||||
self.safety.set_chrysler_desired_torque_last(0) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(3))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(0))) |
||||
# verify when controls not allowed we can still go back towards 0 |
||||
self.safety.set_chrysler_desired_torque_last(10) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(10))) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(11))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(7))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(4))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(0))) |
||||
self.safety.set_chrysler_desired_torque_last(-10) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(-10))) |
||||
self.assertFalse(self.safety.chrysler_tx_hook(self._steer_msg(-11))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(-7))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(-4))) |
||||
self.assertTrue(self.safety.chrysler_tx_hook(self._steer_msg(0))) |
||||
|
||||
if __name__ == "__main__": |
||||
unittest.main() |
Loading…
Reference in new issue