openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

211 lines
7.1 KiB

int toyota_giraffe_switch_1 = 0; // is giraffe switch 1 high?
int toyota_camera_forwarded = 0; // should we forward the camera bus?
// global torque limit
const int TOYOTA_MAX_TORQUE = 1500; // max torque cmd allowed ever
// rate based torque limit + stay within actually applied
// packet is sent at 100hz, so this limit is 1000/sec
const int TOYOTA_MAX_RATE_UP = 10; // ramp up slow
const int TOYOTA_MAX_RATE_DOWN = 25; // ramp down fast
const int TOYOTA_MAX_TORQUE_ERROR = 350; // max torque cmd in excess of torque motor
// real time torque limit to prevent controls spamming
// the real time limit is 1500/sec
const int TOYOTA_MAX_RT_DELTA = 375; // max delta torque allowed for real time checks
const int TOYOTA_RT_INTERVAL = 250000; // 250ms between real time checks
// longitudinal limits
const int TOYOTA_MAX_ACCEL = 1500; // 1.5 m/s2
const int TOYOTA_MIN_ACCEL = -3000; // 3.0 m/s2
// global actuation limit state
int toyota_actuation_limits = 1; // by default steer limits are imposed
int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
// state of torque limits
int toyota_desired_torque_last = 0; // last desired steer torque
int toyota_rt_torque_last = 0; // last desired torque for real time check
uint32_t toyota_ts_last = 0;
int toyota_cruise_engaged_last = 0; // cruise state
struct sample_t toyota_torque_meas; // last 3 motor torques produced by the eps
static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// get eps motor torque (0.66 factor in dbc)
if ((to_push->RIR>>21) == 0x260) {
int torque_meas_new = (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF));
torque_meas_new = to_signed(torque_meas_new, 16);
// scale by dbc_factor
torque_meas_new = (torque_meas_new * toyota_dbc_eps_torque_factor) / 100;
// increase torque_meas by 1 to be conservative on rounding
torque_meas_new += (torque_meas_new > 0 ? 1 : -1);
// update array of sample
update_sample(&toyota_torque_meas, torque_meas_new);
}
// enter controls on rising edge of ACC, exit controls on ACC off
if ((to_push->RIR>>21) == 0x1D2) {
// 5th bit is CRUISE_ACTIVE
int cruise_engaged = to_push->RDLR & 0x20;
if (cruise_engaged && !toyota_cruise_engaged_last) {
controls_allowed = 1;
} else if (!cruise_engaged) {
controls_allowed = 0;
}
toyota_cruise_engaged_last = cruise_engaged;
}
int bus = (to_push->RDTR >> 4) & 0xF;
// msgs are only on bus 2 if panda is connected to frc
if (bus == 2) {
toyota_camera_forwarded = 1;
}
// 0x2E4 is lkas cmd. If it is on bus 0, then giraffe switch 1 is high
if ((to_push->RIR>>21) == 0x2E4 && (bus == 0)) {
toyota_giraffe_switch_1 = 1;
}
}
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) {
// no IPAS in non IPAS mode
if (((to_send->RIR>>21) == 0x266) || ((to_send->RIR>>21) == 0x167)) return false;
// GAS PEDAL: safety check
if ((to_send->RIR>>21) == 0x200) {
if (controls_allowed && toyota_actuation_limits) {
// all messages are fine here
} else {
if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0;
}
}
// ACCEL: safety check on byte 1-2
if ((to_send->RIR>>21) == 0x343) {
int desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF);
desired_accel = to_signed(desired_accel, 16);
if (controls_allowed && toyota_actuation_limits) {
int violation = max_limit_check(desired_accel, TOYOTA_MAX_ACCEL, TOYOTA_MIN_ACCEL);
if (violation) return 0;
} else if (!controls_allowed && (desired_accel != 0)) {
return 0;
}
}
// STEER: safety check on bytes 2-3
if ((to_send->RIR>>21) == 0x2E4) {
int desired_torque = (to_send->RDLR & 0xFF00) | ((to_send->RDLR >> 16) & 0xFF);
desired_torque = to_signed(desired_torque, 16);
int violation = 0;
uint32_t ts = TIM2->CNT;
// only check if controls are allowed and actuation_limits are imposed
if (controls_allowed && toyota_actuation_limits) {
// *** global torque limit check ***
violation |= max_limit_check(desired_torque, TOYOTA_MAX_TORQUE, -TOYOTA_MAX_TORQUE);
// *** torque rate limit check ***
violation |= dist_to_meas_check(desired_torque, toyota_desired_torque_last,
&toyota_torque_meas, TOYOTA_MAX_RATE_UP, TOYOTA_MAX_RATE_DOWN, TOYOTA_MAX_TORQUE_ERROR);
// used next time
toyota_desired_torque_last = desired_torque;
// *** torque real time rate limit check ***
violation |= rt_rate_limit_check(desired_torque, toyota_rt_torque_last, TOYOTA_MAX_RT_DELTA);
// every RT_INTERVAL set the new limits
uint32_t ts_elapsed = get_ts_elapsed(ts, toyota_ts_last);
if (ts_elapsed > TOYOTA_RT_INTERVAL) {
toyota_rt_torque_last = desired_torque;
toyota_ts_last = ts;
}
}
// no torque if controls is not allowed
if (!controls_allowed && (desired_torque != 0)) {
violation = 1;
}
// reset to 0 if either controls is not allowed or there's a violation
if (violation || !controls_allowed) {
toyota_desired_torque_last = 0;
toyota_rt_torque_last = 0;
toyota_ts_last = ts;
}
if (violation) {
return false;
}
}
}
// 1 allows the message through
return true;
}
static void toyota_init(int16_t param) {
controls_allowed = 0;
toyota_actuation_limits = 1;
toyota_giraffe_switch_1 = 0;
toyota_camera_forwarded = 0;
toyota_dbc_eps_torque_factor = param;
#ifdef PANDA
lline_relay_release();
#endif
}
static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
// forward cam to radar and viceversa if car, except lkas cmd and hud
// don't forward when switch 1 is high
if ((bus_num == 0 || bus_num == 2) && toyota_camera_forwarded && !toyota_giraffe_switch_1) {
int addr = to_fwd->RIR>>21;
bool is_lkas_msg = (addr == 0x2E4 || addr == 0x412) && bus_num == 2;
// in TSSP 2.0 the camera does ACC as well, so filter 0x343
bool is_acc_msg = (addr == 0x343 && bus_num == 2);
return (is_lkas_msg || is_acc_msg)? -1 : (uint8_t)(~bus_num & 0x2);
}
return -1;
}
const safety_hooks toyota_hooks = {
.init = toyota_init,
.rx = toyota_rx_hook,
.tx = toyota_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.ignition = default_ign_hook,
.fwd = toyota_fwd_hook,
.relay = nooutput_relay_hook,
};
static void toyota_nolimits_init(int16_t param) {
controls_allowed = 0;
toyota_actuation_limits = 0;
toyota_giraffe_switch_1 = 0;
toyota_camera_forwarded = 0;
toyota_dbc_eps_torque_factor = param;
#ifdef PANDA
lline_relay_release();
#endif
}
const safety_hooks toyota_nolimits_hooks = {
.init = toyota_nolimits_init,
.rx = toyota_rx_hook,
.tx = toyota_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.ignition = default_ign_hook,
.fwd = toyota_fwd_hook,
.relay = nooutput_relay_hook,
};