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.
191 lines
6.1 KiB
191 lines
6.1 KiB
#pragma once
|
|
|
|
#include "opendbc/safety/safety_declarations.h"
|
|
|
|
static uint8_t rivian_get_counter(const CANPacket_t *msg) {
|
|
uint8_t cnt = 0;
|
|
if ((msg->addr == 0x208U) || (msg->addr == 0x150U)) {
|
|
// Signal: ESP_Status_Counter, VDM_PropStatus_Counter
|
|
cnt = msg->data[1] & 0xFU;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
static uint32_t rivian_get_checksum(const CANPacket_t *msg) {
|
|
uint8_t chksum = 0;
|
|
if ((msg->addr == 0x208U) || (msg->addr == 0x150U)) {
|
|
// Signal: ESP_Status_Checksum, VDM_PropStatus_Checksum
|
|
chksum = msg->data[0];
|
|
} else {
|
|
}
|
|
return chksum;
|
|
}
|
|
|
|
static uint8_t _rivian_compute_checksum(const CANPacket_t *msg, uint8_t poly, uint8_t xor_output) {
|
|
int len = GET_LEN(msg);
|
|
|
|
uint8_t crc = 0;
|
|
// Skip the checksum byte
|
|
for (int i = 1; i < len; i++) {
|
|
crc ^= msg->data[i];
|
|
for (int j = 0; j < 8; j++) {
|
|
if ((crc & 0x80U) != 0U) {
|
|
crc = (crc << 1) ^ poly;
|
|
} else {
|
|
crc <<= 1;
|
|
}
|
|
}
|
|
}
|
|
return crc ^ xor_output;
|
|
}
|
|
|
|
static uint32_t rivian_compute_checksum(const CANPacket_t *msg) {
|
|
uint8_t chksum = 0;
|
|
if (msg->addr == 0x208U) {
|
|
chksum = _rivian_compute_checksum(msg, 0x1D, 0xB1);
|
|
} else if (msg->addr == 0x150U) {
|
|
chksum = _rivian_compute_checksum(msg, 0x1D, 0x9A);
|
|
} else {
|
|
}
|
|
return chksum;
|
|
}
|
|
|
|
static bool rivian_get_quality_flag_valid(const CANPacket_t *msg) {
|
|
bool valid = false;
|
|
if (msg->addr == 0x208U) {
|
|
valid = ((msg->data[3] >> 3) & 0x3U) == 0x1U; // ESP_Vehicle_Speed_Q
|
|
} else if (msg->addr == 0x150U) {
|
|
valid = (msg->data[1] >> 6) == 0x1U; // VDM_VehicleSpeedQ
|
|
} else {
|
|
}
|
|
return valid;
|
|
}
|
|
|
|
static void rivian_rx_hook(const CANPacket_t *msg) {
|
|
|
|
if (msg->bus == 0U) {
|
|
// Vehicle speed
|
|
if (msg->addr == 0x208U) {
|
|
float speed = ((msg->data[6] << 8) | msg->data[7]) * 0.01;
|
|
vehicle_moving = speed > 0.0;
|
|
UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS);
|
|
}
|
|
|
|
// Gas pressed and second speed source for variable torque limit
|
|
if (msg->addr == 0x150U) {
|
|
gas_pressed = msg->data[3] | (msg->data[4] & 0xC0U);
|
|
|
|
// Disable controls if speeds from VDM and ESP ECUs are too far apart.
|
|
float vdm_speed = ((msg->data[5] << 8) | msg->data[6]) * 0.01 * KPH_TO_MS;
|
|
speed_mismatch_check(vdm_speed);
|
|
}
|
|
|
|
// Driver torque
|
|
if (msg->addr == 0x380U) {
|
|
int torque_driver_new = (((msg->data[2] << 4) | (msg->data[3] >> 4))) - 2050U;
|
|
update_sample(&torque_driver, torque_driver_new);
|
|
}
|
|
|
|
// Brake pressed
|
|
if (msg->addr == 0x38fU) {
|
|
brake_pressed = (msg->data[2] >> 7) & 1U;
|
|
}
|
|
}
|
|
|
|
if (msg->bus == 2U) {
|
|
// Cruise state
|
|
if (msg->addr == 0x100U) {
|
|
const int feature_status = msg->data[2] >> 5U;
|
|
pcm_cruise_check(feature_status == 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool rivian_tx_hook(const CANPacket_t *msg) {
|
|
// Rivian utilizes more torque at low speed to maintain the same lateral accel
|
|
const TorqueSteeringLimits RIVIAN_STEERING_LIMITS = {
|
|
.max_torque = 350,
|
|
.dynamic_max_torque = true,
|
|
.max_torque_lookup = {
|
|
{9., 17., 17.},
|
|
{350, 250, 250},
|
|
},
|
|
.max_rate_up = 3,
|
|
.max_rate_down = 5,
|
|
.max_rt_delta = 125,
|
|
.driver_torque_multiplier = 2,
|
|
.driver_torque_allowance = 100,
|
|
.type = TorqueDriverLimited,
|
|
};
|
|
|
|
const LongitudinalLimits RIVIAN_LONG_LIMITS = {
|
|
.max_accel = 200,
|
|
.min_accel = -350,
|
|
.inactive_accel = 0,
|
|
};
|
|
|
|
bool tx = true;
|
|
|
|
if (msg->bus == 0U) {
|
|
// Steering control
|
|
if (msg->addr == 0x120U) {
|
|
int desired_torque = ((msg->data[2] << 3U) | (msg->data[3] >> 5U)) - 1024U;
|
|
bool steer_req = (msg->data[3] >> 4) & 1U;
|
|
|
|
if (steer_torque_cmd_checks(desired_torque, steer_req, RIVIAN_STEERING_LIMITS)) {
|
|
tx = false;
|
|
}
|
|
}
|
|
|
|
// Longitudinal control
|
|
if (msg->addr == 0x160U) {
|
|
int raw_accel = ((msg->data[2] << 3) | (msg->data[3] >> 5)) - 1024U;
|
|
if (longitudinal_accel_checks(raw_accel, RIVIAN_LONG_LIMITS)) {
|
|
tx = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return tx;
|
|
}
|
|
|
|
static safety_config rivian_init(uint16_t param) {
|
|
// SCCM_WheelTouch: for hiding hold wheel alert
|
|
// VDM_AdasSts: for canceling stock ACC
|
|
// 0x120 = ACM_lkaHbaCmd, 0x321 = SCCM_WheelTouch, 0x162 = VDM_AdasSts
|
|
static const CanMsg RIVIAN_TX_MSGS[] = {{0x120, 0, 8, .check_relay = true}, {0x321, 2, 7, .check_relay = true}, {0x162, 2, 8, .check_relay = true}};
|
|
// 0x160 = ACM_longitudinalRequest
|
|
static const CanMsg RIVIAN_LONG_TX_MSGS[] = {{0x120, 0, 8, .check_relay = true}, {0x321, 2, 7, .check_relay = true}, {0x160, 0, 5, .check_relay = true}};
|
|
|
|
static RxCheck rivian_rx_checks[] = {
|
|
{.msg = {{0x208, 0, 8, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // ESP_Status (speed)
|
|
{.msg = {{0x150, 0, 7, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // VDM_PropStatus (gas pedal & 2nd speed)
|
|
{.msg = {{0x380, 0, 5, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPAS_SystemStatus (driver torque)
|
|
{.msg = {{0x38f, 0, 6, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // iBESP2 (brakes)
|
|
{.msg = {{0x100, 2, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ACM_Status (cruise state)
|
|
};
|
|
|
|
bool rivian_longitudinal = false;
|
|
|
|
UNUSED(param);
|
|
#ifdef ALLOW_DEBUG
|
|
const int FLAG_RIVIAN_LONG_CONTROL = 1;
|
|
rivian_longitudinal = GET_FLAG(param, FLAG_RIVIAN_LONG_CONTROL);
|
|
#endif
|
|
|
|
// FIXME: cppcheck thinks that rivian_longitudinal is always false. This is not true
|
|
// if ALLOW_DEBUG is defined but cppcheck is run without ALLOW_DEBUG
|
|
// cppcheck-suppress knownConditionTrueFalse
|
|
return rivian_longitudinal ? BUILD_SAFETY_CFG(rivian_rx_checks, RIVIAN_LONG_TX_MSGS) : \
|
|
BUILD_SAFETY_CFG(rivian_rx_checks, RIVIAN_TX_MSGS);
|
|
}
|
|
|
|
const safety_hooks rivian_hooks = {
|
|
.init = rivian_init,
|
|
.rx = rivian_rx_hook,
|
|
.tx = rivian_tx_hook,
|
|
.get_counter = rivian_get_counter,
|
|
.get_checksum = rivian_get_checksum,
|
|
.compute_checksum = rivian_compute_checksum,
|
|
.get_quality_flag_valid = rivian_get_quality_flag_valid,
|
|
};
|
|
|