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