open source driving agent
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.

216 lines
6.8 KiB

// include first, needed by safety policies
#include "safety_declarations.h"
// Include the actual safety policies.
#include "safety/safety_defaults.h"
#include "safety/safety_honda.h"
#include "safety/safety_toyota.h"
#include "safety/safety_toyota_ipas.h"
#include "safety/safety_tesla.h"
#include "safety/safety_gm_ascm.h"
#include "safety/safety_gm.h"
#include "safety/safety_ford.h"
#include "safety/safety_cadillac.h"
#include "safety/safety_hyundai.h"
#include "safety/safety_chrysler.h"
#include "safety/safety_subaru.h"
#include "safety/safety_elm327.h"
const safety_hooks *current_hooks = &nooutput_hooks;
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push){
current_hooks->rx(to_push);
}
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return current_hooks->tx(to_send);
}
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len){
return current_hooks->tx_lin(lin_num, data, len);
}
// -1 = Disabled (Use GPIO to determine ignition)
// 0 = Off (not started)
// 1 = On (started)
int safety_ignition_hook() {
return current_hooks->ignition();
}
int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
return current_hooks->fwd(bus_num, to_fwd);
}
typedef struct {
uint16_t id;
const safety_hooks *hooks;
} safety_hook_config;
Squashed 'panda/' changes from ae816c104..45d0d286f 45d0d286f remove whitespace (#255) e49d0dbbd Pedal: use avg between tracks (#253) c597dcc89 VERSION update after health packet changes and minor misra test change 01072bec0 Misra 11.x: pointer usage. (#250) fd68c26ab Propagate can_push errors (#249) ce1daf206 Misra check only done for EON config 70d4fd7f6 cleanup docker container on failure 04756a037 Turning back Misra check: unvoluntarily change fcb1208e1 fix weird code in USB_ReadPacket b983cc8fe Re-wrote test_misra.sh 0b1920636 Misra 17.7: The value returned by a function having non-void return type shall be used. We should hang on initial failed safety_set_mode 06ee8bd2d Ignore Misra 5.4 until cppcheck bug (?) is fixed 4be858224 Update cppcheck commit and pass predefined params to avoid impossible combinations of configs f45dd04c6 cppcheck: ignore redundantAssignment and selfAssignment for registers in llcan.h 9ce631155 Misra 12.1 (operator order) and 10.4 (incompatible essential types) fixes, arised after properly checking UID_BASE config 1cd34e564 Explicitly set the define and undefine for unknown configs in misra checks 5a024999d remove esp flash from run_automated_tests.sh 23e3684d7 Cppcheck unused functions (#247) c97d60be6 Removed bad language b031480a7 Missed adding Dockerfile 91ff6bb21 Run language checker in CI 205ec342a Improved language checker f7bbab072 Language checker test d9d0a62f2 Misra 5.5: missed this change from previous PR 85fa3c02a Misra 5.5: Identifiers shall be distinct from macro names (#246) 190d604a0 Pedal: 2 minor fixes to Misra 15.7 (else needed) and 17.7 (non-void output must be used) 8ea01ff12 Pedal: no built-in functions to avoid puts and putc re-definitions 1f40d1e6a Misra pedal (#245) a4554e3e6 Ignore advisory Misra 19.2: the union keyword should not be used e6dc4172b Minor indent error 247e128b4 Fix strict compiler on bootstub build ba6856921 Removed build strict test and enabled -Werror flag da11f0fa0 safety replay: update openpilot-tools after logreader fix fc8b9e49b Cppcheck: also check pedal f7bd2c2f3 Misra 10.4: fix last 2 violations (#242) 9be5fdead finished misra 17.8 (#241) 3c3aba3db Misra 10.4: Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category (#240) f2a3a177b Misra 15_7: fix what seems to be a false positive of cppcheck 812ace538 Misra 15_7: if … else if constructs should be terminated with an else clause (#230) 79e9735ae rename 5_wifi_udp.py 3c3ff0c03 Update Jenkinsfile (#239) 1bd928437 Misra 17.7: the value returned by a function having non-void return shall be used (#237) 18c9e88bc Merge pull request #238 from commaai/misra_17_8 7ac321de4 Merge pull request #235 from commaai/memxxx 004e543cc Jenkins: run EON test first 4bff28620 Merge branch 'memxxx' of github.com:commaai/panda into memxxx 7cd80de23 typo 385e33b32 12.1 regression 955842bae WIP ea908cbb7 10_1 violations: Operands shall not be of an inappropriate essential type (#233) fa3303805 Fix Misra 5.3: An identifier declared in an inner scope shall not hide an identifier declared in an outer scope (#236) ebfe1c512 Merge branch 'master' of github.com:commaai/panda into memxxx 8c11470ef Fix EON test case 64e18e841 fix inverted logic to differentiate between dev and EON panda builds 36755a0fd Merge branch 'master' of github.com:commaai/panda into memxxx e2981d612 skip wifi tests for EON panda build db2eec98c Merge branch 'master' of github.com:commaai/panda into memxxx 11257e79a Ignore test 5_wifi_udp.py_ignore: too unreliable for now 6973c2a81 fix wifi tests cf6985ad1 memxxx function changes to be Misra compliant 3a6cd2930 wifi threshold perc back to 20%. Problem wasn't this. d92a03528 faster docker build for safety replay 3e9469b3e Fixing tests after min->MIN change ecb9b6c01 Revert "Misra 10 1: Operands shall not be of an inappropriate essential type (#232)" 8732e4faf Misra 10 1: Operands shall not be of an inappropriate essential type (#232) git-subtree-dir: panda git-subtree-split: 45d0d286f4b5c893590a98ec1438b8a143b9605d old-commit-hash: 1ff59baea717f88e8038c01ead864ad5acb85f35
6 years ago
#define SAFETY_NOOUTPUT 0U
#define SAFETY_HONDA 1U
#define SAFETY_TOYOTA 2U
#define SAFETY_GM 3U
#define SAFETY_HONDA_BOSCH 4U
#define SAFETY_FORD 5U
#define SAFETY_CADILLAC 6U
#define SAFETY_HYUNDAI 7U
#define SAFETY_TESLA 8U
#define SAFETY_CHRYSLER 9U
#define SAFETY_SUBARU 10U
#define SAFETY_GM_ASCM 0x1334U
#define SAFETY_TOYOTA_IPAS 0x1335U
#define SAFETY_ALLOUTPUT 0x1337U
#define SAFETY_ELM327 0xE327U
const safety_hook_config safety_hook_registry[] = {
{SAFETY_NOOUTPUT, &nooutput_hooks},
{SAFETY_HONDA, &honda_hooks},
{SAFETY_HONDA_BOSCH, &honda_bosch_hooks},
{SAFETY_TOYOTA, &toyota_hooks},
{SAFETY_GM, &gm_hooks},
{SAFETY_FORD, &ford_hooks},
{SAFETY_CADILLAC, &cadillac_hooks},
{SAFETY_HYUNDAI, &hyundai_hooks},
{SAFETY_CHRYSLER, &chrysler_hooks},
{SAFETY_SUBARU, &subaru_hooks},
{SAFETY_TOYOTA_IPAS, &toyota_ipas_hooks},
{SAFETY_GM_ASCM, &gm_ascm_hooks},
{SAFETY_TESLA, &tesla_hooks},
{SAFETY_ALLOUTPUT, &alloutput_hooks},
{SAFETY_ELM327, &elm327_hooks},
};
int safety_set_mode(uint16_t mode, int16_t param) {
int set_status = -1; // not set
int hook_config_count = sizeof(safety_hook_registry) / sizeof(safety_hook_config);
for (int i = 0; i < hook_config_count; i++) {
if (safety_hook_registry[i].id == mode) {
current_hooks = safety_hook_registry[i].hooks;
set_status = 0; // set
break;
}
}
if ((set_status == 0) && (current_hooks->init != NULL)) {
current_hooks->init(param);
}
return set_status;
}
// compute the time elapsed (in microseconds) from 2 counter samples
// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
return ts - ts_last;
}
// convert a trimmed integer to signed 32 bit int
int to_signed(int d, int bits) {
int d_signed = d;
if (d >= (1 << MAX((bits - 1), 0))) {
d_signed = d - (1 << MAX(bits, 0));
}
return d_signed;
}
// given a new sample, update the smaple_t struct
void update_sample(struct sample_t *sample, int sample_new) {
int sample_size = sizeof(sample->values) / sizeof(sample->values[0]);
for (int i = sample_size - 1; i > 0; i--) {
sample->values[i] = sample->values[i-1];
}
sample->values[0] = sample_new;
// get the minimum and maximum measured samples
sample->min = sample->values[0];
sample->max = sample->values[0];
for (int i = 1; i < sample_size; i++) {
if (sample->values[i] < sample->min) {
sample->min = sample->values[i];
}
if (sample->values[i] > sample->max) {
sample->max = sample->values[i];
}
}
}
bool max_limit_check(int val, const int MAX_VAL, const int MIN_VAL) {
return (val > MAX_VAL) || (val < MIN_VAL);
}
// check that commanded value isn't too far from measured
bool dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR) {
// *** val rate limit check ***
int highest_allowed_rl = MAX(val_last, 0) + MAX_RATE_UP;
int lowest_allowed_rl = MIN(val_last, 0) - MAX_RATE_UP;
// if we've exceeded the meas val, we must start moving toward 0
int highest_allowed = MIN(highest_allowed_rl, MAX(val_last - MAX_RATE_DOWN, MAX(val_meas->max, 0) + MAX_ERROR));
int lowest_allowed = MAX(lowest_allowed_rl, MIN(val_last + MAX_RATE_DOWN, MIN(val_meas->min, 0) - MAX_ERROR));
// check for violation
return (val < lowest_allowed) || (val > highest_allowed);
}
// check that commanded value isn't fighting against driver
bool driver_limit_check(int val, int val_last, struct sample_t *val_driver,
const int MAX_VAL, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
const int MAX_ALLOWANCE, const int DRIVER_FACTOR) {
int highest_allowed_rl = MAX(val_last, 0) + MAX_RATE_UP;
int lowest_allowed_rl = MIN(val_last, 0) - MAX_RATE_UP;
int driver_max_limit = MAX_VAL + (MAX_ALLOWANCE + val_driver->max) * DRIVER_FACTOR;
int driver_min_limit = -MAX_VAL + (-MAX_ALLOWANCE + val_driver->min) * DRIVER_FACTOR;
// if we've exceeded the applied torque, we must start moving toward 0
int highest_allowed = MIN(highest_allowed_rl, MAX(val_last - MAX_RATE_DOWN,
MAX(driver_max_limit, 0)));
int lowest_allowed = MAX(lowest_allowed_rl, MIN(val_last + MAX_RATE_DOWN,
MIN(driver_min_limit, 0)));
// check for violation
return (val < lowest_allowed) || (val > highest_allowed);
}
// real time check, mainly used for steer torque rate limiter
bool rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) {
// *** torque real time rate limit check ***
int highest_val = MAX(val_last, 0) + MAX_RT_DELTA;
int lowest_val = MIN(val_last, 0) - MAX_RT_DELTA;
// check for violation
return (val < lowest_val) || (val > highest_val);
}
// interp function that holds extreme values
float interpolate(struct lookup_t xy, float x) {
int size = sizeof(xy.x) / sizeof(xy.x[0]);
float ret = xy.y[size - 1]; // default output is last point
// x is lower than the first point in the x array. Return the first point
if (x <= xy.x[0]) {
ret = xy.y[0];
} else {
// find the index such that (xy.x[i] <= x < xy.x[i+1]) and linearly interp
for (int i=0; i < (size - 1); i++) {
if (x < xy.x[i+1]) {
float x0 = xy.x[i];
float y0 = xy.y[i];
float dx = xy.x[i+1] - x0;
float dy = xy.y[i+1] - y0;
// dx should not be zero as xy.x is supposed ot be monotonic
if (dx <= 0.) {
dx = 0.0001;
}
ret = (dy * (x - x0) / dx) + y0;
break;
}
}
}
return ret;
}