Skip to content

Commit 211883a

Browse files
committed
Add panda safety code
1 parent 1353695 commit 211883a

File tree

3 files changed

+77
-8
lines changed

3 files changed

+77
-8
lines changed

opendbc/car/subaru/values.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class SubaruSafetyFlags(IntFlag):
5757
GEN2 = 1
5858
LONG = 2
5959
PREGLOBAL_REVERSED_DRIVER_TORQUE = 4
60+
ANGLE = 8
6061

6162

6263
class SubaruFlags(IntFlag):

opendbc/safety/safety/safety_subaru.h

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define MSG_SUBARU_Wheel_Speeds 0x13a
2828

2929
#define MSG_SUBARU_ES_LKAS 0x122
30+
#define MSG_SUBARU_ES_LKAS_ANGLE 0x124
3031
#define MSG_SUBARU_ES_Brake 0x220
3132
#define MSG_SUBARU_ES_Distance 0x221
3233
#define MSG_SUBARU_ES_Status 0x222
@@ -70,6 +71,7 @@
7071

7172
static bool subaru_gen2 = false;
7273
static bool subaru_longitudinal = false;
74+
static bool subaru_lkas_angle = false;
7375

7476
static uint32_t subaru_get_checksum(const CANPacket_t *to_push) {
7577
return (uint8_t)GET_BYTE(to_push, 0);
@@ -91,7 +93,8 @@ static uint32_t subaru_compute_checksum(const CANPacket_t *to_push) {
9193

9294
static void subaru_rx_hook(const CANPacket_t *to_push) {
9395
const int bus = GET_BUS(to_push);
94-
const int alt_main_bus = subaru_gen2 ? SUBARU_ALT_BUS : SUBARU_MAIN_BUS;
96+
const int alt_main_bus = (subaru_gen2 || subaru_lkas_angle) ? SUBARU_ALT_BUS : SUBARU_MAIN_BUS;
97+
const int stock_lkas_msg = subaru_lkas_angle ? MSG_SUBARU_ES_LKAS_ANGLE : MSG_SUBARU_ES_LKAS;
9598

9699
int addr = GET_ADDR(to_push);
97100
if ((addr == MSG_SUBARU_Steering_Torque) && (bus == SUBARU_MAIN_BUS)) {
@@ -107,9 +110,16 @@ static void subaru_rx_hook(const CANPacket_t *to_push) {
107110
}
108111

109112
// enter controls on rising edge of ACC, exit controls on ACC off
110-
if ((addr == MSG_SUBARU_CruiseControl) && (bus == alt_main_bus)) {
111-
bool cruise_engaged = GET_BIT(to_push, 41U);
112-
pcm_cruise_check(cruise_engaged);
113+
if (subaru_lkas_angle) {
114+
if ((addr == MSG_SUBARU_ES_DashStatus) && (bus == SUBARU_CAM_BUS)) {
115+
bool cruise_engaged = GET_BIT(to_push, 36U);
116+
pcm_cruise_check(cruise_engaged);
117+
}
118+
} else {
119+
if ((addr == MSG_SUBARU_CruiseControl) && (bus == alt_main_bus)) {
120+
bool cruise_engaged = GET_BIT(to_push, 41U);
121+
pcm_cruise_check(cruise_engaged);
122+
}
113123
}
114124

115125
// update vehicle moving with any non-zero wheel speed
@@ -132,13 +142,25 @@ static void subaru_rx_hook(const CANPacket_t *to_push) {
132142
gas_pressed = GET_BYTE(to_push, 4) != 0U;
133143
}
134144

135-
generic_rx_checks((addr == MSG_SUBARU_ES_LKAS) && (bus == SUBARU_MAIN_BUS));
145+
generic_rx_checks((addr == stock_lkas_msg) && (bus == SUBARU_MAIN_BUS));
136146
}
137147

138148
static bool subaru_tx_hook(const CANPacket_t *to_send) {
139149
const SteeringLimits SUBARU_STEERING_LIMITS = SUBARU_STEERING_LIMITS_GENERATOR(2047, 50, 70);
140150
const SteeringLimits SUBARU_GEN2_STEERING_LIMITS = SUBARU_STEERING_LIMITS_GENERATOR(1000, 40, 40);
141151

152+
const SteeringLimits SUBARU_ANGLE_STEERING_LIMITS = {
153+
.angle_deg_to_can = 100.,
154+
.angle_rate_up_lookup = {
155+
{0., 15., 15.},
156+
{5., .8, .8}
157+
},
158+
.angle_rate_down_lookup = {
159+
{0., 15., 15.},
160+
{5., .4, .4}
161+
},
162+
};
163+
142164
const LongitudinalLimits SUBARU_LONG_LIMITS = {
143165
.min_gas = 808, // appears to be engine braking
144166
.max_gas = 3400, // approx 2 m/s^2 when maxing cruise_rpm and cruise_throttle
@@ -164,6 +186,14 @@ static bool subaru_tx_hook(const CANPacket_t *to_send) {
164186
violation |= steer_torque_cmd_checks(desired_torque, steer_req, limits);
165187
}
166188

189+
if (addr == MSG_SUBARU_ES_LKAS_ANGLE) {
190+
int desired_angle = GET_BYTES(to_send, 5, 3) & 0x1FFFFU;
191+
desired_angle = -1 * to_signed(desired_angle, 17);
192+
bool lkas_request = GET_BIT(to_send, 12U);
193+
194+
violation |= steer_angle_cmd_checks(desired_angle, lkas_request, SUBARU_ANGLE_STEERING_LIMITS);
195+
}
196+
167197
// check es_brake brake_pressure limits
168198
if (addr == MSG_SUBARU_ES_Brake) {
169199
int es_brake_pressure = GET_BYTES(to_send, 2, 2);
@@ -210,13 +240,15 @@ static bool subaru_tx_hook(const CANPacket_t *to_send) {
210240
static int subaru_fwd_hook(int bus_num, int addr) {
211241
int bus_fwd = -1;
212242

243+
const int stock_lkas_msg = subaru_lkas_angle ? MSG_SUBARU_ES_LKAS_ANGLE : MSG_SUBARU_ES_LKAS;
244+
213245
if (bus_num == SUBARU_MAIN_BUS) {
214246
bus_fwd = SUBARU_CAM_BUS; // to the eyesight camera
215247
}
216248

217249
if (bus_num == SUBARU_CAM_BUS) {
218250
// Global platform
219-
bool block_lkas = ((addr == MSG_SUBARU_ES_LKAS) ||
251+
bool block_lkas = ((addr == stock_lkas_msg) ||
220252
(addr == MSG_SUBARU_ES_DashStatus) ||
221253
(addr == MSG_SUBARU_ES_LKAS_State) ||
222254
(addr == MSG_SUBARU_ES_Infotainment));
@@ -254,6 +286,11 @@ static safety_config subaru_init(uint16_t param) {
254286
SUBARU_GEN2_LONG_ADDITIONAL_TX_MSGS()
255287
};
256288

289+
static const CanMsg SUBARU_LKAS_ANGLE_TX_MSGS[] = {
290+
SUBARU_COMMON_TX_MSGS(SUBARU_ALT_BUS, MSG_SUBARU_ES_LKAS_ANGLE)
291+
SUBARU_COMMON_TX_MSGS(SUBARU_ALT_BUS, MSG_SUBARU_ES_LKAS)
292+
};
293+
257294
static RxCheck subaru_rx_checks[] = {
258295
SUBARU_COMMON_RX_CHECKS(SUBARU_MAIN_BUS)
259296
};
@@ -263,16 +300,20 @@ static safety_config subaru_init(uint16_t param) {
263300
};
264301

265302
const uint16_t SUBARU_PARAM_GEN2 = 1;
303+
const uint16_t SUBARU_PARAM_LONGITUDINAL = 2;
304+
const uint16_t SUBARU_PARAM_LKAS_ANGLE = 8;
266305

267306
subaru_gen2 = GET_FLAG(param, SUBARU_PARAM_GEN2);
307+
subaru_lkas_angle = GET_FLAG(param, SUBARU_PARAM_LKAS_ANGLE);
268308

269309
#ifdef ALLOW_DEBUG
270-
const uint16_t SUBARU_PARAM_LONGITUDINAL = 2;
271310
subaru_longitudinal = GET_FLAG(param, SUBARU_PARAM_LONGITUDINAL);
272311
#endif
273312

274313
safety_config ret;
275-
if (subaru_gen2) {
314+
if (subaru_lkas_angle) {
315+
ret = BUILD_SAFETY_CFG(subaru_gen2_rx_checks, SUBARU_LKAS_ANGLE_TX_MSGS);
316+
} else if (subaru_gen2) {
276317
ret = subaru_longitudinal ? BUILD_SAFETY_CFG(subaru_gen2_rx_checks, SUBARU_GEN2_LONG_TX_MSGS) : \
277318
BUILD_SAFETY_CFG(subaru_gen2_rx_checks, SUBARU_GEN2_TX_MSGS);
278319
} else {

opendbc/safety/tests/test_subaru.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,33 @@ def _torque_cmd_msg(self, torque, steer_req=1):
169169
return self.packer.make_can_msg_panda("ES_LKAS", SUBARU_MAIN_BUS, values)
170170

171171

172+
class TestSubaruAngleSafetyBase(TestSubaruSafetyBase, common.AngleSteeringSafetyTest):
173+
ALT_MAIN_BUS = SUBARU_ALT_BUS
174+
175+
TX_MSGS = lkas_tx_msgs(SUBARU_MAIN_BUS, SubaruMsg.ES_LKAS_ANGLE)
176+
RELAY_MALFUNCTION_ADDRS = {SUBARU_MAIN_BUS: (SubaruMsg.ES_LKAS_ANGLE, SubaruMsg.ES_LKAS,)}
177+
FWD_BLACKLISTED_ADDRS = fwd_blacklisted_addr(SubaruMsg.ES_LKAS_ANGLE)
178+
179+
FLAGS = SubaruSafetyFlags.ANGLE
180+
181+
ANGLE_RATE_BP = [0, 15]
182+
ANGLE_RATE_UP = [5, 0.15]
183+
ANGLE_RATE_DOWN = [5, 0.4]
184+
185+
def _angle_cmd_msg(self, angle, enabled=1):
186+
values = {"LKAS_Output": angle, "LKAS_Request": enabled}
187+
return self.packer.make_can_msg_panda("ES_LKAS_ANGLE", 0, values)
188+
189+
def _angle_meas_msg(self, angle):
190+
values = {"Steering_Angle": angle}
191+
return self.packer.make_can_msg_panda("Steering_Torque", 0, values)
192+
193+
# need to use ES_DashStatus Message
194+
def _pcm_status_msg(self, enable):
195+
values = {"Cruise_Activated": enable}
196+
return self.packer.make_can_msg_panda("ES_DashStatus", self.ALT_CAM_BUS, values)
197+
198+
172199
class TestSubaruGen1TorqueStockLongitudinalSafety(TestSubaruStockLongitudinalSafetyBase, TestSubaruTorqueSafetyBase):
173200
FLAGS = 0
174201
TX_MSGS = lkas_tx_msgs(SUBARU_MAIN_BUS)

0 commit comments

Comments
 (0)