Skip to content

Commit 7d21acb

Browse files
authored
added steer override check when IPAS is in control (#106)
* added steer override check when IPAS is in control * same override threshold as carController * added initial safety tests for angle control * cleaned up safety tests and added ipas state override check * ipas_override is an unnecessary global variable * bump panda version
1 parent 1c88caf commit 7d21acb

File tree

3 files changed

+127
-6
lines changed

3 files changed

+127
-6
lines changed

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.1.0
1+
v1.1.1

board/safety/safety_toyota.h

+51-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1+
int cruise_engaged_last = 0; // cruise state
2+
int ipas_state = 0;
3+
14
// track the torque measured for limiting
25
int16_t torque_meas[3] = {0, 0, 0}; // last 3 motor torques produced by the eps
36
int16_t torque_meas_min = 0, torque_meas_max = 0;
7+
int16_t torque_driver[3] = {0, 0, 0}; // last 3 driver steering torque
8+
int16_t torque_driver_min = 0, torque_driver_max = 0;
9+
10+
// IPAS override
11+
const int32_t IPAS_OVERRIDE_THRESHOLD = 200; // disallow controls when user torque exceeds this value
12+
int angle_control = 0; // 1 if direct angle control packets are seen
413

514
// global torque limit
615
const int32_t MAX_TORQUE = 1500; // max torque cmd allowed ever
@@ -30,8 +39,10 @@ int16_t rt_torque_last = 0; // last desired torque for real time chec
3039
uint32_t ts_last = 0;
3140

3241
static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
33-
// get eps motor torque (0.66 factor in dbc)
42+
43+
// EPS torque sensor
3444
if ((to_push->RIR>>21) == 0x260) {
45+
// get eps motor torque (see dbc_eps_torque_factor in dbc)
3546
int16_t torque_meas_new_16 = (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF));
3647

3748
// increase torque_meas by 1 to be conservative on rounding
@@ -49,16 +60,46 @@ static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
4960
if (torque_meas[i] < torque_meas_min) torque_meas_min = torque_meas[i];
5061
if (torque_meas[i] > torque_meas_max) torque_meas_max = torque_meas[i];
5162
}
63+
64+
// get driver steering torque
65+
int16_t torque_driver_new = (((to_push->RDLR) & 0xFF00) | ((to_push->RDLR >> 16) & 0xFF));
66+
67+
// shift the array
68+
for (int i = sizeof(torque_driver)/sizeof(torque_driver[0]) - 1; i > 0; i--) {
69+
torque_driver[i] = torque_driver[i-1];
70+
}
71+
torque_driver[0] = torque_driver_new;
72+
73+
// get the minimum and maximum driver torque over the last 3 frames
74+
torque_driver_min = torque_driver_max = torque_driver[0];
75+
for (int i = 1; i < sizeof(torque_driver)/sizeof(torque_driver[0]); i++) {
76+
if (torque_driver[i] < torque_driver_min) torque_driver_min = torque_driver[i];
77+
if (torque_driver[i] > torque_driver_max) torque_driver_max = torque_driver[i];
78+
}
5279
}
5380

54-
// exit controls on ACC off
81+
// enter controls on rising edge of ACC, exit controls on ACC off
5582
if ((to_push->RIR>>21) == 0x1D2) {
5683
// 4 bits: 55-52
57-
if (to_push->RDHR & 0xF00000) {
84+
int cruise_engaged = to_push->RDHR & 0xF00000;
85+
if (cruise_engaged && (!cruise_engaged_last)) {
5886
controls_allowed = 1;
59-
} else {
87+
} else if (!cruise_engaged) {
6088
controls_allowed = 0;
6189
}
90+
cruise_engaged_last = cruise_engaged;
91+
}
92+
93+
// get ipas state
94+
if ((to_push->RIR>>21) == 0x262) {
95+
ipas_state = (to_push->RDLR & 0xf);
96+
}
97+
98+
// exit controls on high steering override
99+
if (angle_control && ((torque_driver_min > IPAS_OVERRIDE_THRESHOLD) ||
100+
(torque_driver_max < -IPAS_OVERRIDE_THRESHOLD) ||
101+
(ipas_state==5))) {
102+
controls_allowed = 0;
62103
}
63104
}
64105

@@ -79,7 +120,12 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
79120
}
80121
}
81122

82-
// STEER: safety check on bytes 2-3
123+
// STEER ANGLE
124+
if ((to_send->RIR>>21) == 0x266) {
125+
angle_control = 1;
126+
}
127+
128+
// STEER TORQUE: safety check on bytes 2-3
83129
if ((to_send->RIR>>21) == 0x2E4) {
84130
int16_t desired_torque = (to_send->RDLR & 0xFF00) | ((to_send->RDLR >> 16) & 0xFF);
85131
int16_t violation = 0;

tests/safety/test_toyota.py

+75
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
MAX_TORQUE_ERROR = 350
1717

18+
IPAS_OVERRIDE_THRESHOLD = 200
19+
1820
def twos_comp(val, bits):
1921
if val >= 0:
2022
return val
@@ -42,6 +44,18 @@ def _torque_meas_msg(self, torque):
4244
to_send[0].RDHR = t | ((t & 0xFF) << 16)
4345
return to_send
4446

47+
def _torque_driver_msg(self, torque):
48+
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
49+
to_send[0].RIR = 0x260 << 21
50+
51+
t = twos_comp(torque, 16)
52+
to_send[0].RDLR = t | ((t & 0xFF) << 16)
53+
return to_send
54+
55+
def _torque_driver_msg_array(self, torque):
56+
for i in range(3):
57+
self.safety.toyota_rx_hook(self._torque_driver_msg(torque))
58+
4559
def _torque_msg(self, torque):
4660
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
4761
to_send[0].RIR = 0x2E4 << 21
@@ -50,6 +64,19 @@ def _torque_msg(self, torque):
5064
to_send[0].RDLR = t | ((t & 0xFF) << 16)
5165
return to_send
5266

67+
def _ipas_state_msg(self, state):
68+
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
69+
to_send[0].RIR = 0x262 << 21
70+
71+
to_send[0].RDLR = state & 0xF
72+
return to_send
73+
74+
def _ipas_control_msg(self):
75+
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
76+
to_send[0].RIR = 0x266 << 21
77+
78+
return to_send
79+
5380
def _accel_msg(self, accel):
5481
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
5582
to_send[0].RIR = 0x343 << 21
@@ -180,6 +207,54 @@ def test_torque_measurements(self):
180207
self.assertEqual(-1, self.safety.get_torque_meas_max())
181208
self.assertEqual(-1, self.safety.get_torque_meas_min())
182209

210+
def test_ipas_override(self):
211+
212+
## angle control is not active
213+
self.safety.set_controls_allowed(1)
214+
215+
# 3 consecutive msgs where driver exceeds threshold but angle_control isn't active
216+
self.safety.set_controls_allowed(1)
217+
self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD + 1)
218+
self.assertTrue(self.safety.get_controls_allowed())
219+
220+
self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD - 1)
221+
self.assertTrue(self.safety.get_controls_allowed())
222+
223+
# ipas state is override
224+
self.safety.toyota_rx_hook(self._ipas_state_msg(5))
225+
self.assertTrue(self.safety.get_controls_allowed())
226+
227+
## now angle control is active
228+
self.safety.toyota_tx_hook(self._ipas_control_msg())
229+
self.safety.toyota_rx_hook(self._ipas_state_msg(0))
230+
231+
# 3 consecutive msgs where driver does exceed threshold
232+
self.safety.set_controls_allowed(1)
233+
self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD + 1)
234+
self.assertFalse(self.safety.get_controls_allowed())
235+
236+
self.safety.set_controls_allowed(1)
237+
self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD - 1)
238+
self.assertFalse(self.safety.get_controls_allowed())
239+
240+
# ipas state is override and torque isn't overriding any more
241+
self.safety.set_controls_allowed(1)
242+
self._torque_driver_msg_array(0)
243+
self.safety.toyota_rx_hook(self._ipas_state_msg(5))
244+
self.assertFalse(self.safety.get_controls_allowed())
245+
246+
# 3 consecutive msgs where driver does not exceed threshold and
247+
# ipas state is not override
248+
self.safety.set_controls_allowed(1)
249+
self.safety.toyota_rx_hook(self._ipas_state_msg(0))
250+
self.assertTrue(self.safety.get_controls_allowed())
251+
252+
self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD)
253+
self.assertTrue(self.safety.get_controls_allowed())
254+
255+
self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD)
256+
self.assertTrue(self.safety.get_controls_allowed())
257+
183258

184259
if __name__ == "__main__":
185260
unittest.main()

0 commit comments

Comments
 (0)