dragonpilot - 基於 openpilot 的開源駕駛輔助系統
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

#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,
};