panda/board/safety/safety_toyota.h

235 lines
8.0 KiB
C
Raw Normal View History

int cruise_engaged_last = 0; // cruise state
int ipas_state = 0;
2017-10-28 17:22:32 -06:00
// track the torque measured for limiting
int16_t torque_meas[3] = {0, 0, 0}; // last 3 motor torques produced by the eps
2017-10-28 17:22:32 -06:00
int16_t torque_meas_min = 0, torque_meas_max = 0;
int16_t torque_driver[3] = {0, 0, 0}; // last 3 driver steering torque
int16_t torque_driver_min = 0, torque_driver_max = 0;
// IPAS override
const int32_t IPAS_OVERRIDE_THRESHOLD = 200; // disallow controls when user torque exceeds this value
int angle_control = 0; // 1 if direct angle control packets are seen
2017-10-28 17:22:32 -06:00
// global torque limit
const int32_t MAX_TORQUE = 1500; // max torque cmd allowed ever
// rate based torque limit + stay within actually applied
2017-10-28 21:50:04 -06:00
// packet is sent at 100hz, so this limit is 1000/sec
2017-10-28 21:12:13 -06:00
const int32_t MAX_RATE_UP = 10; // ramp up slow
2017-11-03 22:24:14 -06:00
const int32_t MAX_RATE_DOWN = 25; // ramp down fast
const int32_t MAX_TORQUE_ERROR = 350; // max torque cmd in excess of torque motor
2017-10-28 17:22:32 -06:00
// real time torque limit to prevent controls spamming
2017-10-28 17:29:23 -06:00
// the real time limit is 1500/sec
const int32_t MAX_RT_DELTA = 375; // max delta torque allowed for real time checks
2017-10-28 17:22:32 -06:00
const int32_t RT_INTERVAL = 250000; // 250ms between real time checks
// longitudinal limits
const int16_t MAX_ACCEL = 1500; // 1.5 m/s2
const int16_t MIN_ACCEL = -3000; // 3.0 m/s2
2017-10-28 17:22:32 -06:00
// global actuation limit state
int actuation_limits = 1; // by default steer limits are imposed
2018-01-26 01:14:34 -07:00
int16_t dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
2017-10-28 17:22:32 -06:00
// state of torque limits
int16_t desired_torque_last = 0; // last desired steer torque
int16_t rt_torque_last = 0; // last desired torque for real time check
uint32_t ts_last = 0;
2017-08-24 23:31:34 -06:00
static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// EPS torque sensor
if ((to_push->RIR>>21) == 0x260) {
// get eps motor torque (see dbc_eps_torque_factor in dbc)
2018-03-13 21:33:47 -06:00
int16_t torque_meas_new_16 = (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF));
2017-10-28 17:22:32 -06:00
// increase torque_meas by 1 to be conservative on rounding
2018-03-13 21:33:47 -06:00
int torque_meas_new = ((int)(torque_meas_new_16) * dbc_eps_torque_factor / 100) + (torque_meas_new_16 > 0 ? 1 : -1);
2017-10-28 17:22:32 -06:00
// shift the array
2017-10-28 17:46:17 -06:00
for (int i = sizeof(torque_meas)/sizeof(torque_meas[0]) - 1; i > 0; i--) {
torque_meas[i] = torque_meas[i-1];
}
torque_meas[0] = torque_meas_new;
2017-10-28 17:22:32 -06:00
// get the minimum and maximum measured torque over the last 3 frames
torque_meas_min = torque_meas_max = torque_meas[0];
2017-10-28 17:46:17 -06:00
for (int i = 1; i < sizeof(torque_meas)/sizeof(torque_meas[0]); i++) {
2017-10-28 17:22:32 -06:00
if (torque_meas[i] < torque_meas_min) torque_meas_min = torque_meas[i];
if (torque_meas[i] > torque_meas_max) torque_meas_max = torque_meas[i];
}
// get driver steering torque
int16_t torque_driver_new = (((to_push->RDLR) & 0xFF00) | ((to_push->RDLR >> 16) & 0xFF));
// shift the array
for (int i = sizeof(torque_driver)/sizeof(torque_driver[0]) - 1; i > 0; i--) {
torque_driver[i] = torque_driver[i-1];
}
torque_driver[0] = torque_driver_new;
// get the minimum and maximum driver torque over the last 3 frames
torque_driver_min = torque_driver_max = torque_driver[0];
for (int i = 1; i < sizeof(torque_driver)/sizeof(torque_driver[0]); i++) {
if (torque_driver[i] < torque_driver_min) torque_driver_min = torque_driver[i];
if (torque_driver[i] > torque_driver_max) torque_driver_max = torque_driver[i];
}
2017-10-28 17:22:32 -06:00
}
// enter controls on rising edge of ACC, exit controls on ACC off
2017-08-24 23:31:34 -06:00
if ((to_push->RIR>>21) == 0x1D2) {
// 4 bits: 55-52
int cruise_engaged = to_push->RDHR & 0xF00000;
if (cruise_engaged && (!cruise_engaged_last)) {
2017-08-24 23:31:34 -06:00
controls_allowed = 1;
} else if (!cruise_engaged) {
2017-08-24 23:31:34 -06:00
controls_allowed = 0;
}
cruise_engaged_last = cruise_engaged;
}
// get ipas state
if ((to_push->RIR>>21) == 0x262) {
ipas_state = (to_push->RDLR & 0xf);
}
// exit controls on high steering override
if (angle_control && ((torque_driver_min > IPAS_OVERRIDE_THRESHOLD) ||
(torque_driver_max < -IPAS_OVERRIDE_THRESHOLD) ||
(ipas_state==5))) {
controls_allowed = 0;
2017-08-24 23:31:34 -06:00
}
}
static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
// Check if msg is sent on BUS 0
if (((to_send->RDTR >> 4) & 0xF) == 0) {
// ACCEL: safety check on byte 1-2
if ((to_send->RIR>>21) == 0x343) {
int16_t desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF);
if (controls_allowed && actuation_limits) {
if ((desired_accel > MAX_ACCEL) || (desired_accel < MIN_ACCEL)) {
return 0;
}
} else if (!controls_allowed && (desired_accel != 0)) {
return 0;
}
}
// STEER ANGLE
if ((to_send->RIR>>21) == 0x266) {
angle_control = 1;
}
// STEER TORQUE: safety check on bytes 2-3
if ((to_send->RIR>>21) == 0x2E4) {
int16_t desired_torque = (to_send->RDLR & 0xFF00) | ((to_send->RDLR >> 16) & 0xFF);
int16_t violation = 0;
2017-10-28 17:32:36 -06:00
uint32_t ts = TIM2->CNT;
// only check if controls are allowed and actuation_limits are imposed
if (controls_allowed && actuation_limits) {
2017-10-28 17:22:32 -06:00
// *** global torque limit check ***
if (desired_torque < -MAX_TORQUE) violation = 1;
if (desired_torque > MAX_TORQUE) violation = 1;
// *** torque rate limit check ***
int16_t highest_allowed_torque = max(desired_torque_last, 0) + MAX_RATE_UP;
int16_t lowest_allowed_torque = min(desired_torque_last, 0) - MAX_RATE_UP;
// if we've exceeded the applied torque, we must start moving toward 0
highest_allowed_torque = min(highest_allowed_torque, max(desired_torque_last - MAX_RATE_DOWN, max(torque_meas_max, 0) + MAX_TORQUE_ERROR));
2017-10-28 20:05:28 -06:00
lowest_allowed_torque = max(lowest_allowed_torque, min(desired_torque_last + MAX_RATE_DOWN, min(torque_meas_min, 0) - MAX_TORQUE_ERROR));
2017-10-28 17:22:32 -06:00
// check for violation
if ((desired_torque < lowest_allowed_torque) || (desired_torque > highest_allowed_torque)) {
violation = 1;
}
2017-10-28 17:31:10 -06:00
// used next time
desired_torque_last = desired_torque;
2017-10-28 17:22:32 -06:00
// *** torque real time rate limit check ***
int16_t highest_rt_torque = max(rt_torque_last, 0) + MAX_RT_DELTA;
int16_t lowest_rt_torque = min(rt_torque_last, 0) - MAX_RT_DELTA;
// check for violation
if ((desired_torque < lowest_rt_torque) || (desired_torque > highest_rt_torque)) {
violation = 1;
}
2017-10-28 17:22:32 -06:00
// every RT_INTERVAL set the new limits
uint32_t ts_elapsed = ts > ts_last ? ts - ts_last : (0xFFFFFFFF - ts_last) + 1 + ts;
if (ts_elapsed > RT_INTERVAL) {
rt_torque_last = desired_torque;
ts_last = ts;
}
2017-10-28 17:22:32 -06:00
}
// no torque if controls is not allowed
if (!controls_allowed && (desired_torque != 0)) {
violation = 1;
}
2017-10-28 17:22:32 -06:00
// reset to 0 if either controls is not allowed or there's a violation
if (violation || !controls_allowed) {
desired_torque_last = 0;
rt_torque_last = 0;
2017-10-28 17:32:36 -06:00
ts_last = ts;
2017-10-28 17:22:32 -06:00
}
if (violation) {
2017-10-28 17:22:32 -06:00
return false;
}
2017-08-24 23:31:34 -06:00
}
}
// 1 allows the message through
return true;
}
static int toyota_tx_lin_hook(int lin_num, uint8_t *data, int len) {
// TODO: add safety if using LIN
return true;
}
2018-01-26 01:35:33 -07:00
static void toyota_init(int16_t param) {
2017-08-24 23:31:34 -06:00
controls_allowed = 0;
actuation_limits = 1;
2018-01-26 01:35:33 -07:00
dbc_eps_torque_factor = param;
2017-08-24 23:31:34 -06:00
}
static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
return -1;
}
2017-08-24 23:31:34 -06:00
const safety_hooks toyota_hooks = {
.init = toyota_init,
.rx = toyota_rx_hook,
.tx = toyota_tx_hook,
.tx_lin = toyota_tx_lin_hook,
.fwd = toyota_fwd_hook,
2017-08-24 23:31:34 -06:00
};
2018-01-26 01:35:33 -07:00
static void toyota_nolimits_init(int16_t param) {
controls_allowed = 0;
actuation_limits = 0;
2018-01-26 01:35:33 -07:00
dbc_eps_torque_factor = param;
}
const safety_hooks toyota_nolimits_hooks = {
.init = toyota_nolimits_init,
.rx = toyota_rx_hook,
.tx = toyota_tx_hook,
.tx_lin = toyota_tx_lin_hook,
.fwd = toyota_fwd_hook,
};