GCC Code Coverage Report


Directory: ./
File: safety/safety_tesla.h
Date: 2025-02-27 09:09:49
Exec Total Coverage
Lines: 80 80 100.0%
Functions: 4 4 100.0%
Branches: 82 86 95.3%

Line Branch Exec Source
1 #pragma once
2
3 #include "safety_declarations.h"
4
5 static bool tesla_longitudinal = false;
6 static bool tesla_stock_aeb = false;
7
8 51614 static void tesla_rx_hook(const CANPacket_t *to_push) {
9 51614 int bus = GET_BUS(to_push);
10 51614 int addr = GET_ADDR(to_push);
11
12
2/2
✓ Branch 0 taken 40348 times.
✓ Branch 1 taken 11266 times.
51614 if (bus == 0) {
13 // Steering angle: (0.1 * val) - 819.2 in deg.
14
2/2
✓ Branch 0 taken 24026 times.
✓ Branch 1 taken 16322 times.
40348 if (addr == 0x370) {
15 // Store it 1/10 deg to match steering request
16 24026 int angle_meas_new = (((GET_BYTE(to_push, 4) & 0x3FU) << 8) | GET_BYTE(to_push, 5)) - 8192U;
17 24026 update_sample(&angle_meas, angle_meas_new);
18 }
19
20 // Vehicle speed
21
2/2
✓ Branch 0 taken 10622 times.
✓ Branch 1 taken 29726 times.
40348 if (addr == 0x257) {
22 // Vehicle speed: ((val * 0.08) - 40) / MS_TO_KPH
23 10622 float speed = ((((GET_BYTE(to_push, 2) << 4) | (GET_BYTE(to_push, 1) >> 4)) * 0.08) - 40) / 3.6;
24 10622 UPDATE_VEHICLE_SPEED(speed);
25 }
26
27 // Gas pressed
28
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 40326 times.
40348 if (addr == 0x118) {
29 22 gas_pressed = (GET_BYTE(to_push, 4) != 0U);
30 }
31
32 // Brake pressed
33
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 40322 times.
40348 if (addr == 0x39d) {
34 26 brake_pressed = (GET_BYTE(to_push, 2) & 0x03U) == 2U;
35 }
36
37 // Cruise state
38
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 40318 times.
40348 if (addr == 0x286) {
39 30 int cruise_state = (GET_BYTE(to_push, 1) >> 4) & 0x07U;
40
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 bool cruise_engaged = (cruise_state == 2) || // ENABLED
41
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 (cruise_state == 3) || // STANDSTILL
42
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 (cruise_state == 4) || // OVERRIDE
43
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
50 (cruise_state == 6) || // PRE_FAULT
44 (cruise_state == 7); // PRE_CANCEL
45
46 30 vehicle_moving = cruise_state != 3; // STANDSTILL
47 30 pcm_cruise_check(cruise_engaged);
48 }
49 }
50
51
2/2
✓ Branch 0 taken 5634 times.
✓ Branch 1 taken 45980 times.
51614 if (bus == 2) {
52
4/4
✓ Branch 0 taken 2818 times.
✓ Branch 1 taken 2816 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2815 times.
5634 if (tesla_longitudinal && (addr == 0x2b9)) {
53 // "AEB_ACTIVE"
54 3 tesla_stock_aeb = (GET_BYTE(to_push, 2) & 0x03U) == 1U;
55 }
56 }
57
58
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 51608 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
51614 generic_rx_checks((addr == 0x488) && (bus == 0)); // DAS_steeringControl
59
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 51608 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
51614 generic_rx_checks((addr == 0x27d) && (bus == 0)); // APS_eacMonitor
60
61
2/2
✓ Branch 0 taken 25808 times.
✓ Branch 1 taken 25806 times.
51614 if (tesla_longitudinal) {
62
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 25803 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
25808 generic_rx_checks((addr == 0x2b9) && (bus == 0));
63 }
64 51614 }
65
66
67 14322 static bool tesla_tx_hook(const CANPacket_t *to_send) {
68 const SteeringLimits TESLA_STEERING_LIMITS = {
69 .angle_deg_to_can = 10,
70 .angle_rate_up_lookup = {
71 {0., 5., 25.},
72 {2.5, 1.5, 0.2}
73 },
74 .angle_rate_down_lookup = {
75 {0., 5., 25.},
76 {5., 2.0, 0.3}
77 },
78 };
79
80 const LongitudinalLimits TESLA_LONG_LIMITS = {
81 .max_accel = 425, // 2 m/s^2
82 .min_accel = 288, // -3.48 m/s^2
83 .inactive_accel = 375, // 0. m/s^2
84 };
85
86 14322 bool tx = true;
87 14322 int addr = GET_ADDR(to_send);
88 14322 bool violation = false;
89
90 // Steering control: (0.1 * val) - 1638.35 in deg.
91
2/2
✓ Branch 0 taken 13052 times.
✓ Branch 1 taken 1270 times.
14322 if (addr == 0x488) {
92 // We use 1/10 deg as a unit here
93 13052 int raw_angle_can = ((GET_BYTE(to_send, 0) & 0x7FU) << 8) | GET_BYTE(to_send, 1);
94 13052 int desired_angle = raw_angle_can - 16384;
95 13052 int steer_control_type = GET_BYTE(to_send, 2) >> 6;
96
3/4
✓ Branch 0 taken 10156 times.
✓ Branch 1 taken 2896 times.
✓ Branch 2 taken 10156 times.
✗ Branch 3 not taken.
13052 bool steer_control_enabled = (steer_control_type != 0) && // NONE
97 (steer_control_type != 3); // DISABLED
98
99
2/2
✓ Branch 1 taken 4994 times.
✓ Branch 2 taken 8058 times.
13052 if (steer_angle_cmd_checks(desired_angle, steer_control_enabled, TESLA_STEERING_LIMITS)) {
100 4994 violation = true;
101 }
102 }
103
104 // DAS_control: longitudinal control message
105
2/2
✓ Branch 0 taken 1270 times.
✓ Branch 1 taken 13052 times.
14322 if (addr == 0x2b9) {
106 // No AEB events may be sent by openpilot
107 1270 int aeb_event = GET_BYTE(to_send, 2) & 0x03U;
108
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1264 times.
1270 if (aeb_event != 0) {
109 6 violation = true;
110 }
111
112 1270 int raw_accel_max = ((GET_BYTE(to_send, 6) & 0x1FU) << 4) | (GET_BYTE(to_send, 5) >> 4);
113 1270 int raw_accel_min = ((GET_BYTE(to_send, 5) & 0x0FU) << 5) | (GET_BYTE(to_send, 4) >> 3);
114 1270 int acc_state = GET_BYTE(to_send, 1) >> 4;
115
116
2/2
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 645 times.
1270 if (tesla_longitudinal) {
117 // Don't send messages when the stock AEB system is active
118
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 624 times.
625 if (tesla_stock_aeb) {
119 1 violation = true;
120 }
121
122 // Prevent both acceleration from being negative, as this could cause the car to reverse after coming to standstill
123
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 619 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
625 if ((raw_accel_max < TESLA_LONG_LIMITS.inactive_accel) && (raw_accel_min < TESLA_LONG_LIMITS.inactive_accel)) {
124 4 violation = true;
125 }
126
127 // Don't allow any acceleration limits above the safety limits
128 625 violation |= longitudinal_accel_checks(raw_accel_max, TESLA_LONG_LIMITS);
129 625 violation |= longitudinal_accel_checks(raw_accel_min, TESLA_LONG_LIMITS);
130 } else {
131 // does allowing cancel here disrupt stock AEB? TODO: find out and add safety or remove comment
132 // Can only send cancel longitudinal messages when not controlling longitudinal
133
2/2
✓ Branch 0 taken 639 times.
✓ Branch 1 taken 6 times.
645 if (acc_state != 13) { // ACC_CANCEL_GENERIC_SILENT
134 639 violation = true;
135 }
136
137 // No actuation is allowed when not controlling longitudinal
138
4/4
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 360 times.
✓ Branch 3 taken 28 times.
645 if ((raw_accel_max != TESLA_LONG_LIMITS.inactive_accel) || (raw_accel_min != TESLA_LONG_LIMITS.inactive_accel)) {
139 617 violation = true;
140 }
141 }
142 }
143
144
2/2
✓ Branch 0 taken 6025 times.
✓ Branch 1 taken 8297 times.
14322 if (violation) {
145 6025 tx = false;
146 }
147
148 14322 return tx;
149 }
150
151 16898 static int tesla_fwd_hook(int bus_num, int addr) {
152 16898 int bus_fwd = -1;
153
154
2/2
✓ Branch 0 taken 5632 times.
✓ Branch 1 taken 11266 times.
16898 if (bus_num == 0) {
155 // Party to autopilot
156 5632 bus_fwd = 2;
157 }
158
159
2/2
✓ Branch 0 taken 5634 times.
✓ Branch 1 taken 11264 times.
16898 if (bus_num == 2) {
160 5634 bool block_msg = false;
161 // DAS_steeringControl, APS_eacMonitor
162
4/4
✓ Branch 0 taken 5632 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5630 times.
5634 if ((addr == 0x488) || (addr == 0x27d)) {
163 4 block_msg = true;
164 }
165
166 // DAS_control
167
6/6
✓ Branch 0 taken 2818 times.
✓ Branch 1 taken 2816 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2815 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
5634 if (tesla_longitudinal && (addr == 0x2b9) && !tesla_stock_aeb) {
168 2 block_msg = true;
169 }
170
171
2/2
✓ Branch 0 taken 5628 times.
✓ Branch 1 taken 6 times.
5634 if (!block_msg) {
172 5628 bus_fwd = 0;
173 }
174 }
175
176 16898 return bus_fwd;
177 }
178
179 2779 static safety_config tesla_init(uint16_t param) {
180
181 static const CanMsg TESLA_M3_Y_TX_MSGS[] = {
182 {0x488, 0, 4}, // DAS_steeringControl
183 {0x2b9, 0, 8}, // DAS_control
184 {0x27D, 0, 3}, // APS_eacMonitor
185 };
186
187 UNUSED(param);
188 #ifdef ALLOW_DEBUG
189 2779 const int TESLA_FLAG_LONGITUDINAL_CONTROL = 1;
190 2779 tesla_longitudinal = GET_FLAG(param, TESLA_FLAG_LONGITUDINAL_CONTROL);
191 #endif
192
193 2779 tesla_stock_aeb = false;
194
195 static RxCheck tesla_model3_y_rx_checks[] = {
196 {.msg = {{0x2b9, 2, 8, .frequency = 25U}, { 0 }, { 0 }}}, // DAS_control
197 {.msg = {{0x257, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, // DI_speed (speed in kph)
198 {.msg = {{0x370, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, // EPAS3S_internalSAS (steering angle)
199 {.msg = {{0x118, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, // DI_systemStatus (gas pedal)
200 {.msg = {{0x39d, 0, 5, .frequency = 25U}, { 0 }, { 0 }}}, // IBST_status (brakes)
201 {.msg = {{0x286, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // DI_state (acc state)
202 {.msg = {{0x311, 0, 7, .frequency = 10U}, { 0 }, { 0 }}}, // UI_warning (blinkers, buckle switch & doors)
203 };
204
205 2779 return BUILD_SAFETY_CFG(tesla_model3_y_rx_checks, TESLA_M3_Y_TX_MSGS);
206 }
207
208 const safety_hooks tesla_hooks = {
209 .init = tesla_init,
210 .rx = tesla_rx_hook,
211 .tx = tesla_tx_hook,
212 .fwd = tesla_fwd_hook,
213 };
214