Skip to content

Commit d77b72d

Browse files
Safety Test Refactor: Nissan (#510)
* start nissan * packer
1 parent 4c7755c commit d77b72d

File tree

2 files changed

+50
-109
lines changed

2 files changed

+50
-109
lines changed

tests/safety/common.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def make_can_msg_panda(self, name_or_addr, bus, values, counter=-1):
4444
class PandaSafetyTest(unittest.TestCase):
4545
TX_MSGS = None
4646
STANDSTILL_THRESHOLD = None
47+
GAS_PRESSED_THRESHOLD = 0
4748
RELAY_MALFUNCTION_ADDR = None
4849
RELAY_MALFUNCTION_BUS = None
4950
FWD_BLACKLISTED_ADDRS = {} # {bus: [addr]}
@@ -119,11 +120,9 @@ def test_manually_enable_controls_allowed(self):
119120

120121
def test_prev_gas(self):
121122
self.assertFalse(self.safety.get_gas_pressed_prev())
122-
for pressed in [True, False]:
123-
self._rx(self._gas_msg(not pressed))
124-
self.assertEqual(not pressed, self.safety.get_gas_pressed_prev())
123+
for pressed in [self.GAS_PRESSED_THRESHOLD+1, 0]:
125124
self._rx(self._gas_msg(pressed))
126-
self.assertEqual(pressed, self.safety.get_gas_pressed_prev())
125+
self.assertEqual(bool(pressed), self.safety.get_gas_pressed_prev())
127126

128127
def test_allow_engage_with_gas_pressed(self):
129128
self._rx(self._gas_msg(1))
@@ -136,14 +135,14 @@ def test_allow_engage_with_gas_pressed(self):
136135
def test_disengage_on_gas(self):
137136
self._rx(self._gas_msg(0))
138137
self.safety.set_controls_allowed(True)
139-
self._rx(self._gas_msg(1))
138+
self._rx(self._gas_msg(self.GAS_PRESSED_THRESHOLD+1))
140139
self.assertFalse(self.safety.get_controls_allowed())
141140

142141
def test_unsafe_mode_no_disengage_on_gas(self):
143142
self._rx(self._gas_msg(0))
144143
self.safety.set_controls_allowed(True)
145144
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
146-
self._rx(self._gas_msg(1))
145+
self._rx(self._gas_msg(self.GAS_PRESSED_THRESHOLD+1))
147146
self.assertTrue(self.safety.get_controls_allowed())
148147

149148
def test_prev_brake(self):

tests/safety/test_nissan.py

+45-103
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,37 @@
33
import numpy as np
44
from panda import Panda
55
from panda.tests.safety import libpandasafety_py
6-
from panda.tests.safety.common import StdTest, make_msg, UNSAFE_MODE
6+
import panda.tests.safety.common as common
7+
from panda.tests.safety.common import CANPackerPanda
78

89
ANGLE_DELTA_BP = [0., 5., 15.]
910
ANGLE_DELTA_V = [5., .8, .15] # windup limit
1011
ANGLE_DELTA_VU = [5., 3.5, 0.4] # unwind limit
1112

12-
TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2], [0x280, 2]]
13-
14-
def twos_comp(val, bits):
15-
if val >= 0:
16-
return val
17-
else:
18-
return (2**bits) + val
1913

2014
def sign(a):
21-
if a > 0:
22-
return 1
23-
else:
24-
return -1
15+
return 1 if a > 0 else -1
2516

2617

27-
class TestNissanSafety(unittest.TestCase):
28-
@classmethod
29-
def setUp(cls):
30-
cls.safety = libpandasafety_py.libpandasafety
31-
cls.safety.set_safety_hooks(Panda.SAFETY_NISSAN, 0)
32-
cls.safety.init_tests_nissan()
18+
class TestNissanSafety(common.PandaSafetyTest):
3319

34-
def _angle_meas_msg(self, angle):
35-
to_send = make_msg(0, 0x2)
36-
angle = int(angle * -10)
37-
t = twos_comp(angle, 16)
38-
to_send[0].RDLR = t & 0xFFFF
20+
TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2], [0x280, 2]]
21+
STANDSTILL_THRESHOLD = 0
22+
GAS_PRESSED_THRESHOLD = 1
23+
RELAY_MALFUNCTION_ADDR = 0x169
24+
RELAY_MALFUNCTION_BUS = 0
25+
FWD_BLACKLISTED_ADDRS = {0: [0x280], 2: [0x169, 0x2b1, 0x4cc]}
26+
FWD_BUS_LOOKUP = {0: 2, 2: 0}
27+
28+
def setUp(self):
29+
self.packer = CANPackerPanda("nissan_x_trail_2017")
30+
self.safety = libpandasafety_py.libpandasafety
31+
self.safety.set_safety_hooks(Panda.SAFETY_NISSAN, 0)
32+
self.safety.init_tests_nissan()
3933

40-
return to_send
34+
def _angle_meas_msg(self, angle):
35+
values = {"STEER_ANGLE": angle}
36+
return self.packer.make_can_msg_panda("STEER_ANGLE_SENSOR", 0, values)
4137

4238
def _set_prev_angle(self, t):
4339
t = int(t * -100)
@@ -47,47 +43,33 @@ def _angle_meas_msg_array(self, angle):
4743
for i in range(6):
4844
self.safety.safety_rx_hook(self._angle_meas_msg(angle))
4945

50-
def _lkas_state_msg(self, state):
51-
to_send = make_msg(1, 0x30f)
52-
to_send[0].RDHR = (state & 0x1) << 3
53-
54-
return to_send
46+
def _pcm_status_msg(self, enabled):
47+
values = {"CRUISE_ENABLED": enabled}
48+
return self.packer.make_can_msg_panda("CRUISE_STATE", 2, values)
5549

5650
def _lkas_control_msg(self, angle, state):
57-
to_send = make_msg(0, 0x169)
58-
angle = int((angle - 1310) * -100)
59-
to_send[0].RDLR = ((angle & 0x3FC00) >> 10) | ((angle & 0x3FC) << 6) | ((angle & 0x3) << 16)
60-
to_send[0].RDHR = ((state & 0x1) << 20)
61-
62-
return to_send
51+
values = {"DESIRED_ANGLE": angle, "LKA_ACTIVE": state}
52+
return self.packer.make_can_msg_panda("LKAS", 0, values)
6353

6454
def _speed_msg(self, speed):
65-
to_send = make_msg(0, 0x285)
66-
speed = int(speed / 0.005 * 3.6)
67-
to_send[0].RDLR = ((speed & 0xFF) << 24) | ((speed & 0xFF00) << 8)
68-
69-
return to_send
55+
# TODO: why the 3.6? m/s to kph? not in dbc
56+
values = {"WHEEL_SPEED_%s"%s: speed*3.6 for s in ["RR", "RL"]}
57+
return self.packer.make_can_msg_panda("WHEEL_SPEEDS_REAR", 0, values)
7058

7159
def _brake_msg(self, brake):
72-
to_send = make_msg(1, 0x454)
73-
to_send[0].RDLR = ((brake & 0x1) << 23)
74-
75-
return to_send
76-
77-
def _send_gas_cmd(self, gas):
78-
to_send = make_msg(0, 0x15c)
79-
to_send[0].RDHR = ((gas & 0x3fc) << 6) | ((gas & 0x3) << 22)
80-
81-
return to_send
82-
83-
def _acc_button_cmd(self, buttons):
84-
to_send = make_msg(2, 0x20b)
85-
to_send[0].RDLR = (buttons << 8)
60+
values = {"USER_BRAKE_PRESSED": brake}
61+
return self.packer.make_can_msg_panda("DOORS_LIGHTS", 1, values)
8662

87-
return to_send
63+
def _gas_msg(self, gas):
64+
values = {"GAS_PEDAL": gas}
65+
return self.packer.make_can_msg_panda("GAS_PEDAL", 0, values)
8866

89-
def test_spam_can_buses(self):
90-
StdTest.test_spam_can_buses(self, TX_MSGS)
67+
def _acc_button_cmd(self, cancel=0, propilot=0, flw_dist=0, _set=0, res=0):
68+
no_button = not any([cancel, propilot, flw_dist, _set, res])
69+
values = {"CANCEL_BUTTON": cancel, "PROPILOT_BUTTON": propilot, \
70+
"FOLLOW_DISTANCE_BUTTON": flw_dist, "SET_BUTTON": _set, \
71+
"RES_BUTTON": res, "NO_BUTTON_PRESSED": no_button}
72+
return self.packer.make_can_msg_panda("CRUISE_THROTTLE", 2, values)
9173

9274
def test_angle_cmd_when_enabled(self):
9375
# when controls are allowed, angle cmd rate limit is enforced
@@ -145,65 +127,25 @@ def test_angle_cmd_when_disabled(self):
145127
self.assertFalse(self.safety.safety_tx_hook(self._lkas_control_msg(0, 1)))
146128
self.assertFalse(self.safety.get_controls_allowed())
147129

148-
def test_brake_disengage(self):
149-
StdTest.test_allow_brake_at_zero_speed(self)
150-
StdTest.test_not_allow_brake_when_moving(self, 0)
151-
152-
def test_gas_rising_edge(self):
153-
self.safety.set_controls_allowed(1)
154-
self.safety.safety_rx_hook(self._send_gas_cmd(100))
155-
self.assertFalse(self.safety.get_controls_allowed())
156-
157-
def test_unsafe_mode_no_disengage_on_gas(self):
158-
self.safety.safety_rx_hook(self._send_gas_cmd(0))
159-
self.safety.set_controls_allowed(True)
160-
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
161-
self.safety.safety_rx_hook(self._send_gas_cmd(100))
162-
self.assertTrue(self.safety.get_controls_allowed())
163-
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
164-
165130
def test_acc_buttons(self):
166131
self.safety.set_controls_allowed(1)
167-
self.safety.safety_tx_hook(self._acc_button_cmd(0x2)) # Cancel button
132+
self.safety.safety_tx_hook(self._acc_button_cmd(cancel=1))
168133
self.assertTrue(self.safety.get_controls_allowed())
169-
self.safety.safety_tx_hook(self._acc_button_cmd(0x1)) # ProPilot button
134+
self.safety.safety_tx_hook(self._acc_button_cmd(propilot=1))
170135
self.assertFalse(self.safety.get_controls_allowed())
171136
self.safety.set_controls_allowed(1)
172-
self.safety.safety_tx_hook(self._acc_button_cmd(0x4)) # Follow Distance button
137+
self.safety.safety_tx_hook(self._acc_button_cmd(flw_dist=1))
173138
self.assertFalse(self.safety.get_controls_allowed())
174139
self.safety.set_controls_allowed(1)
175-
self.safety.safety_tx_hook(self._acc_button_cmd(0x8)) # Set button
140+
self.safety.safety_tx_hook(self._acc_button_cmd(_set=1))
176141
self.assertFalse(self.safety.get_controls_allowed())
177142
self.safety.set_controls_allowed(1)
178-
self.safety.safety_tx_hook(self._acc_button_cmd(0x10)) # Res button
143+
self.safety.safety_tx_hook(self._acc_button_cmd(res=1))
179144
self.assertFalse(self.safety.get_controls_allowed())
180145
self.safety.set_controls_allowed(1)
181-
self.safety.safety_tx_hook(self._acc_button_cmd(0x20)) # No button pressed
146+
self.safety.safety_tx_hook(self._acc_button_cmd())
182147
self.assertFalse(self.safety.get_controls_allowed())
183148

184-
def test_relay_malfunction(self):
185-
StdTest.test_relay_malfunction(self, 0x169)
186-
187-
def test_fwd_hook(self):
188-
189-
buss = list(range(0x0, 0x3))
190-
msgs = list(range(0x1, 0x800))
191-
192-
blocked_msgs = [(2, 0x169), (2, 0x2b1), (2, 0x4cc), (0, 0x280)]
193-
for b in buss:
194-
for m in msgs:
195-
if b == 0:
196-
fwd_bus = 2
197-
elif b == 1:
198-
fwd_bus = -1
199-
elif b == 2:
200-
fwd_bus = 0
201-
202-
if (b, m) in blocked_msgs:
203-
fwd_bus = -1
204-
205-
# assume len 8
206-
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
207149

208150
if __name__ == "__main__":
209151
unittest.main()

0 commit comments

Comments
 (0)