mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-06-23 23:12:04 +08:00
Merge branch 'devel-i18n' into devel-zht
This commit is contained in:
@@ -57,3 +57,9 @@ panda_jungle
|
||||
htmlcov
|
||||
pandaextra
|
||||
|
||||
apk/cn.dragonpilot.gpsservice.apk
|
||||
apk/com.autonavi.amapauto.apk
|
||||
apk/com.mixplorer.apk
|
||||
apk/com.tomtom.speedcams.android.map.apk
|
||||
apk/com.waze.apk
|
||||
apk/tw.com.ainvest.outpack.apk
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -6,7 +6,7 @@ import shutil
|
||||
from common.basedir import BASEDIR
|
||||
from selfdrive.swaglog import cloudlog
|
||||
|
||||
android_packages = ("ai.comma.plus.offroad", "tw.com.ainvest.outpack", "cn.dragonpilot.gpsservice", "com.autonavi.amapauto", "com.mixplorer", "com.tomtom.speedcams.android.map")
|
||||
android_packages = ("ai.comma.plus.offroad",)
|
||||
|
||||
def get_installed_apks():
|
||||
dat = subprocess.check_output(["pm", "list", "packages", "-f"], encoding='utf8').strip().split("\n")
|
||||
|
||||
+2
-2
@@ -174,12 +174,12 @@ keys = {
|
||||
"DragonLastModified": [TxType.PERSISTENT],
|
||||
"DragonEnableRegistration": [TxType.PERSISTENT],
|
||||
"DragonDynamicFollow": [TxType.PERSISTENT],
|
||||
"DragonEnableDoorCheck": [TxType.PERSISTENT],
|
||||
"DragonEnableSeatBeltCheck": [TxType.PERSISTENT],
|
||||
"DragonEnableGearCheck": [TxType.PERSISTENT],
|
||||
"DragonEnableTempMonitor": [TxType.PERSISTENT],
|
||||
"DragonEnableCurvatureLearner": [TxType.PERSISTENT],
|
||||
"DragonCurvatureLearnerOffset": [TxType.PERSISTENT],
|
||||
"DragonAppAutoUpdate": [TxType.PERSISTENT],
|
||||
"DragonUpdating": [TxType.CLEAR_ON_MANAGER_START],
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
v1.7.3
|
||||
v1.7.5
|
||||
@@ -28,6 +28,7 @@ void can_set_forwarding(int from, int to);
|
||||
|
||||
void can_init(uint8_t can_number);
|
||||
void can_init_all(void);
|
||||
bool can_tx_check_min_slots_free(uint32_t min);
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook);
|
||||
bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
|
||||
|
||||
@@ -107,6 +108,20 @@ bool can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t can_slots_empty(can_ring *q) {
|
||||
uint32_t ret = 0;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
if (q->w_ptr >= q->r_ptr) {
|
||||
ret = q->fifo_size - 1U - q->w_ptr + q->r_ptr;
|
||||
} else {
|
||||
ret = q->r_ptr - q->w_ptr - 1U;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_clear(can_ring *q) {
|
||||
ENTER_CRITICAL();
|
||||
q->w_ptr = 0;
|
||||
@@ -317,6 +332,10 @@ void process_can(uint8_t can_number) {
|
||||
CAN->sTxMailBox[0].TDHR = to_send.RDHR;
|
||||
CAN->sTxMailBox[0].TDTR = to_send.RDTR;
|
||||
CAN->sTxMailBox[0].TIR = to_send.RIR;
|
||||
|
||||
if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
|
||||
usb_outep3_resume_if_paused();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,6 +424,14 @@ void CAN3_TX_IRQ_Handler(void) { process_can(2); }
|
||||
void CAN3_RX0_IRQ_Handler(void) { can_rx(2); }
|
||||
void CAN3_SCE_IRQ_Handler(void) { can_sce(CAN3); }
|
||||
|
||||
bool can_tx_check_min_slots_free(uint32_t min) {
|
||||
return
|
||||
(can_slots_empty(&can_tx1_q) >= min) &&
|
||||
(can_slots_empty(&can_tx2_q) >= min) &&
|
||||
(can_slots_empty(&can_tx3_q) >= min) &&
|
||||
(can_slots_empty(&can_txgmlan_q) >= min);
|
||||
}
|
||||
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook) {
|
||||
if (skip_tx_hook || safety_tx_hook(to_push) != 0) {
|
||||
if (bus_number < BUS_MAX) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define GET_BUS(msg) (((msg)->RDTR >> 4) & 0xFF)
|
||||
#define GET_LEN(msg) ((msg)->RDTR & 0xF)
|
||||
#define GET_ADDR(msg) ((((msg)->RIR & 4) != 0) ? ((msg)->RIR >> 3) : ((msg)->RIR >> 21))
|
||||
#define GET_BYTE(msg, b) (((int)(b) > 3) ? (((msg)->RDHR >> (8U * ((unsigned int)(b) % 4U))) & 0XFFU) : (((msg)->RDLR >> (8U * (unsigned int)(b))) & 0xFFU))
|
||||
#define GET_BYTE(msg, b) (((int)(b) > 3) ? (((msg)->RDHR >> (8U * ((unsigned int)(b) % 4U))) & 0xFFU) : (((msg)->RDLR >> (8U * (unsigned int)(b))) & 0xFFU))
|
||||
#define GET_BYTES_04(msg) ((msg)->RDLR)
|
||||
#define GET_BYTES_48(msg) ((msg)->RDHR)
|
||||
|
||||
|
||||
@@ -23,12 +23,16 @@ typedef union _USB_Setup {
|
||||
}
|
||||
USB_Setup_TypeDef;
|
||||
|
||||
#define MAX_CAN_MSGS_PER_BULK_TRANSFER 4U
|
||||
|
||||
void usb_init(void);
|
||||
int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired);
|
||||
int usb_cb_ep1_in(void *usbdata, int len, bool hardwired);
|
||||
void usb_cb_ep2_out(void *usbdata, int len, bool hardwired);
|
||||
void usb_cb_ep3_out(void *usbdata, int len, bool hardwired);
|
||||
void usb_cb_ep3_out_complete(void);
|
||||
void usb_cb_enumeration_complete(void);
|
||||
void usb_outep3_resume_if_paused(void);
|
||||
|
||||
// **** supporting defines ****
|
||||
|
||||
@@ -380,6 +384,7 @@ USB_Setup_TypeDef setup;
|
||||
uint8_t usbdata[0x100];
|
||||
uint8_t* ep0_txdata = NULL;
|
||||
uint16_t ep0_txlen = 0;
|
||||
bool outep3_processing = false;
|
||||
|
||||
// Store the current interface alt setting.
|
||||
int current_int0_alt_setting = 0;
|
||||
@@ -744,6 +749,7 @@ void usb_irqhandler(void) {
|
||||
}
|
||||
|
||||
if (endpoint == 3) {
|
||||
outep3_processing = true;
|
||||
usb_cb_ep3_out(usbdata, len, 1);
|
||||
}
|
||||
} else if (status == STS_SETUP_UPDT) {
|
||||
@@ -816,15 +822,17 @@ void usb_irqhandler(void) {
|
||||
#ifdef DEBUG_USB
|
||||
puts(" OUT3 PACKET XFRC\n");
|
||||
#endif
|
||||
USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
|
||||
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
// NAK cleared by process_can (if tx buffers have room)
|
||||
outep3_processing = false;
|
||||
usb_cb_ep3_out_complete();
|
||||
} else if ((USBx_OUTEP(3)->DOEPINT & 0x2000) != 0) {
|
||||
#ifdef DEBUG_USB
|
||||
puts(" OUT3 PACKET WTF\n");
|
||||
#endif
|
||||
// if NAK was set trigger this, unknown interrupt
|
||||
USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
|
||||
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
// TODO: why was this here? fires when TX buffers when we can't clear NAK
|
||||
// USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
|
||||
// USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
} else if ((USBx_OUTEP(3)->DOEPINT) != 0) {
|
||||
puts("OUTEP3 error ");
|
||||
puth(USBx_OUTEP(3)->DOEPINT);
|
||||
@@ -932,6 +940,15 @@ void usb_irqhandler(void) {
|
||||
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
|
||||
}
|
||||
|
||||
void usb_outep3_resume_if_paused() {
|
||||
ENTER_CRITICAL();
|
||||
if (!outep3_processing && (USBx_OUTEP(3)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) != 0) {
|
||||
USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
|
||||
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void OTG_FS_IRQ_Handler(void) {
|
||||
NVIC_DisableIRQ(OTG_FS_IRQn);
|
||||
//__disable_irq();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
# Need formula for gcc
|
||||
sudo easy_install pip
|
||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
brew tap ArmMbed/homebrew-formulae
|
||||
brew install python dfu-util arm-none-eabi-gcc
|
||||
pip install --user libusb1 pycrypto requests
|
||||
|
||||
@@ -235,6 +235,12 @@ void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
|
||||
}
|
||||
}
|
||||
|
||||
void usb_cb_ep3_out_complete() {
|
||||
if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
|
||||
usb_outep3_resume_if_paused();
|
||||
}
|
||||
}
|
||||
|
||||
void usb_cb_enumeration_complete() {
|
||||
puts("USB enumeration complete\n");
|
||||
is_enumerated = 1;
|
||||
@@ -469,6 +475,15 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w));
|
||||
}
|
||||
break;
|
||||
// **** 0xdf: set unsafe mode
|
||||
case 0xdf:
|
||||
// you can only set this if you are in a non car safety mode
|
||||
if ((current_safety_mode == SAFETY_SILENT) ||
|
||||
(current_safety_mode == SAFETY_NOOUTPUT) ||
|
||||
(current_safety_mode == SAFETY_ELM327)) {
|
||||
unsafe_mode = setup->b.wValue.w;
|
||||
}
|
||||
break;
|
||||
// **** 0xe0: uart read
|
||||
case 0xe0:
|
||||
ur = get_ring_by_number(setup->b.wValue.w);
|
||||
|
||||
@@ -76,6 +76,7 @@ void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
|
||||
UNUSED(len);
|
||||
UNUSED(hardwired);
|
||||
}
|
||||
void usb_cb_ep3_out_complete(void) {}
|
||||
void usb_cb_enumeration_complete(void) {}
|
||||
|
||||
int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#define SAFETY_GM_ASCM 18U
|
||||
#define SAFETY_NOOUTPUT 19U
|
||||
#define SAFETY_HONDA_BOSCH_HARNESS 20U
|
||||
#define SAFETY_VOLKSWAGEN_PQ 21U
|
||||
#define SAFETY_SUBARU_LEGACY 22U
|
||||
|
||||
uint16_t current_safety_mode = SAFETY_SILENT;
|
||||
@@ -183,6 +184,15 @@ bool addr_safety_check(CAN_FIFOMailBox_TypeDef *to_push,
|
||||
return is_msg_valid(rx_checks, index);
|
||||
}
|
||||
|
||||
void relay_malfunction_set(void) {
|
||||
relay_malfunction = true;
|
||||
fault_occurred(FAULT_RELAY_MALFUNCTION);
|
||||
}
|
||||
|
||||
void relay_malfunction_reset(void) {
|
||||
relay_malfunction = false;
|
||||
fault_recovered(FAULT_RELAY_MALFUNCTION);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
@@ -203,6 +213,7 @@ const safety_hook_config safety_hook_registry[] = {
|
||||
{SAFETY_SUBARU_LEGACY, &subaru_legacy_hooks},
|
||||
{SAFETY_MAZDA, &mazda_hooks},
|
||||
{SAFETY_VOLKSWAGEN_MQB, &volkswagen_mqb_hooks},
|
||||
{SAFETY_VOLKSWAGEN_PQ, &volkswagen_pq_hooks},
|
||||
{SAFETY_NOOUTPUT, &nooutput_hooks},
|
||||
#ifdef ALLOW_DEBUG
|
||||
{SAFETY_CADILLAC, &cadillac_hooks},
|
||||
|
||||
@@ -74,6 +74,8 @@ static int chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
chrysler_get_checksum, chrysler_compute_checksum,
|
||||
chrysler_get_counter);
|
||||
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (valid && (GET_BUS(to_push) == 0)) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -107,7 +109,7 @@ static int chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 308) {
|
||||
bool gas_pressed = (GET_BYTE(to_push, 5) & 0x7F) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev && (chrysler_speed > CHRYSLER_GAS_THRSLD)) {
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev && (chrysler_speed > CHRYSLER_GAS_THRSLD)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
@@ -124,7 +126,7 @@ static int chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
// check if stock camera ECU is on bus 0
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == 0x292)) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
|
||||
@@ -8,7 +8,7 @@ int default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static void nooutput_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
}
|
||||
|
||||
static int nooutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -42,7 +42,7 @@ const safety_hooks nooutput_hooks = {
|
||||
static void alloutput_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = true;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
}
|
||||
|
||||
static int alloutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
@@ -13,6 +13,7 @@ static int ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
int addr = GET_ADDR(to_push);
|
||||
int bus = GET_BUS(to_push);
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (addr == 0x217) {
|
||||
// wheel speeds are 14 bits every 16
|
||||
@@ -47,14 +48,14 @@ static int ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 0x204) {
|
||||
bool gas_pressed = ((GET_BYTE(to_push, 0) & 0x03) | GET_BYTE(to_push, 1)) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev) {
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 0x3CA)) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -72,7 +73,11 @@ static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
int pedal_pressed = gas_pressed_prev || (brake_pressed_prev && ford_moving);
|
||||
int pedal_pressed = brake_pressed_prev && ford_moving;
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
if (!unsafe_allow_gas) {
|
||||
pedal_pressed = pedal_pressed || gas_pressed_prev;
|
||||
}
|
||||
bool current_controls_allowed = controls_allowed && !(pedal_pressed);
|
||||
|
||||
if (relay_malfunction) {
|
||||
|
||||
@@ -44,6 +44,8 @@ static int gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
bool valid = addr_safety_check(to_push, gm_rx_checks, GM_RX_CHECK_LEN,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (valid && (GET_BUS(to_push) == 0)) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -91,8 +93,8 @@ static int gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 417) {
|
||||
bool gas_pressed = GET_BYTE(to_push, 6) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 1;
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
@@ -110,7 +112,7 @@ static int gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// 384 = ASCMLKASteeringCmd
|
||||
// 715 = ASCMGasRegenCmd
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && ((addr == 384) || (addr == 715))) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
@@ -138,8 +140,11 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
//int pedal_pressed = gas_pressed_prev || (brake_pressed_prev && gm_moving);
|
||||
int pedal_pressed = brake_pressed_prev && gm_moving;
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
if (!unsafe_allow_gas) {
|
||||
pedal_pressed = pedal_pressed || gas_pressed_prev;
|
||||
}
|
||||
bool current_controls_allowed = controls_allowed && !pedal_pressed;
|
||||
|
||||
// BRAKE: safety check
|
||||
|
||||
@@ -72,6 +72,8 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
honda_get_checksum, honda_compute_checksum, honda_get_counter);
|
||||
}
|
||||
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (valid) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
int len = GET_LEN(to_push);
|
||||
@@ -121,9 +123,9 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if ((addr == 0x201) && (len == 6)) {
|
||||
gas_interceptor_detected = 1;
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
if (!unsafe_allow_gas && (gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
(gas_interceptor_prev <= HONDA_GAS_INTERCEPTOR_THRESHOLD)) {
|
||||
controls_allowed = 1;
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
@@ -132,24 +134,28 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if (!gas_interceptor_detected) {
|
||||
if (addr == 0x17C) {
|
||||
bool gas_pressed = GET_BYTE(to_push, 0) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 1;
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
}
|
||||
if ((bus == 2) && (addr == 0x1FA)) {
|
||||
bool honda_stock_aeb = GET_BYTE(to_push, 3) & 0x20;
|
||||
int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) + ((GET_BYTE(to_push, 1) >> 6) & 0x3);
|
||||
|
||||
// Forward AEB when stock braking is higher than openpilot braking
|
||||
// only stop forwarding when AEB event is over
|
||||
if (!honda_stock_aeb) {
|
||||
honda_fwd_brake = false;
|
||||
} else if (honda_stock_brake >= honda_brake) {
|
||||
honda_fwd_brake = true;
|
||||
} else {
|
||||
// Leave Honda forward brake as is
|
||||
// disable stock Honda AEB in unsafe mode
|
||||
if ( !(unsafe_mode & UNSAFE_DISABLE_STOCK_AEB) ) {
|
||||
if ((bus == 2) && (addr == 0x1FA)) {
|
||||
bool honda_stock_aeb = GET_BYTE(to_push, 3) & 0x20;
|
||||
int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) + ((GET_BYTE(to_push, 1) >> 6) & 0x3);
|
||||
|
||||
// Forward AEB when stock braking is higher than openpilot braking
|
||||
// only stop forwarding when AEB event is over
|
||||
if (!honda_stock_aeb) {
|
||||
honda_fwd_brake = false;
|
||||
} else if (honda_stock_brake >= honda_brake) {
|
||||
honda_fwd_brake = true;
|
||||
} else {
|
||||
// Leave Honda forward brake as is
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +165,7 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && ((addr == 0xE4) || (addr == 0x194))) {
|
||||
if (((honda_hw != HONDA_N_HW) && (bus == bus_rdr_car)) ||
|
||||
((honda_hw == HONDA_N_HW) && (bus == 0))) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,9 +198,11 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
//int pedal_pressed = gas_pressed_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD) ||
|
||||
// (brake_pressed_prev && honda_moving);
|
||||
int pedal_pressed = brake_pressed_prev && honda_moving;
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
if (!unsafe_allow_gas) {
|
||||
pedal_pressed = pedal_pressed || gas_pressed_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD);
|
||||
}
|
||||
bool current_controls_allowed = controls_allowed && !(pedal_pressed);
|
||||
|
||||
// BRAKE: safety check
|
||||
@@ -249,14 +257,14 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
static void honda_nidec_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
honda_hw = HONDA_N_HW;
|
||||
honda_alt_brake_msg = false;
|
||||
}
|
||||
|
||||
static void honda_bosch_giraffe_init(int16_t param) {
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
honda_hw = HONDA_BG_HW;
|
||||
// Checking for alternate brake override from safety parameter
|
||||
honda_alt_brake_msg = (param == 1) ? true : false;
|
||||
@@ -264,7 +272,7 @@ static void honda_bosch_giraffe_init(int16_t param) {
|
||||
|
||||
static void honda_bosch_harness_init(int16_t param) {
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
honda_hw = HONDA_BH_HW;
|
||||
// Checking for alternate brake override from safety parameter
|
||||
honda_alt_brake_msg = (param == 1) ? true : false;
|
||||
@@ -343,4 +351,4 @@ const safety_hooks honda_bosch_harness_hooks = {
|
||||
.fwd = honda_bosch_fwd_hook,
|
||||
.addr_check = honda_bh_rx_checks,
|
||||
.addr_check_len = sizeof(honda_bh_rx_checks) / sizeof(honda_bh_rx_checks[0]),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -30,6 +30,8 @@ static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
bool valid = addr_safety_check(to_push, hyundai_rx_checks, HYUNDAI_RX_CHECK_LEN,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (valid && GET_BUS(to_push) == 0) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -55,8 +57,8 @@ static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 608) {
|
||||
bool gas_pressed = (GET_BYTE(to_push, 7) >> 6) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 1;
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
@@ -79,7 +81,7 @@ static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
// check if stock camera ECU is on bus 0
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == 832)) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
|
||||
@@ -55,7 +55,7 @@ static int mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
// if we see wheel speed msgs on MAZDA_CAM bus then relay is closed
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == MAZDA_CAM) && (addr == MAZDA_WHEEL_SPEED)) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -9,18 +9,16 @@ const struct lookup_t NISSAN_LOOKUP_ANGLE_RATE_DOWN = {
|
||||
{2., 7., 17.},
|
||||
{5., 3.5, .5}};
|
||||
|
||||
const struct lookup_t NISSAN_LOOKUP_MAX_ANGLE = {
|
||||
{3.3, 12, 32},
|
||||
{540., 120., 23.}};
|
||||
|
||||
const int NISSAN_DEG_TO_CAN = 100;
|
||||
|
||||
const AddrBus NISSAN_TX_MSGS[] = {{0x169, 0}, {0x2b1, 0}, {0x4cc, 0}, {0x20b, 2}};
|
||||
const AddrBus NISSAN_TX_MSGS[] = {{0x169, 0}, {0x2b1, 0}, {0x4cc, 0}, {0x20b, 2}, {0x280, 2}};
|
||||
|
||||
AddrCheckStruct nissan_rx_checks[] = {
|
||||
{.addr = {0x2}, .bus = 0, .expected_timestep = 10000U},
|
||||
{.addr = {0x29a}, .bus = 0, .expected_timestep = 20000U},
|
||||
{.addr = {0x1b6}, .bus = 1, .expected_timestep = 10000U},
|
||||
{.addr = {0x2}, .bus = 0, .expected_timestep = 10000U}, // STEER_ANGLE_SENSOR (100Hz)
|
||||
{.addr = {0x285}, .bus = 0, .expected_timestep = 20000U}, // WHEEL_SPEEDS_REAR (50Hz)
|
||||
{.addr = {0x30f}, .bus = 2, .expected_timestep = 100000U}, // CRUISE_STATE (10Hz)
|
||||
{.addr = {0x15c, 0x239}, .bus = 0, .expected_timestep = 20000U}, // GAS_PEDAL (100Hz / 50Hz)
|
||||
{.addr = {0x454, 0x1cc}, .bus = 0, .expected_timestep = 100000U}, // DOORS_LIGHTS (10Hz) / BRAKE (100Hz)
|
||||
};
|
||||
const int NISSAN_RX_CHECK_LEN = sizeof(nissan_rx_checks) / sizeof(nissan_rx_checks[0]);
|
||||
|
||||
@@ -38,6 +36,8 @@ static int nissan_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
bool valid = addr_safety_check(to_push, nissan_rx_checks, NISSAN_RX_CHECK_LEN,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (valid) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
@@ -54,47 +54,62 @@ static int nissan_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
update_sample(&nissan_angle_meas, angle_meas_new);
|
||||
}
|
||||
|
||||
if (addr == 0x29a) {
|
||||
if (addr == 0x285) {
|
||||
// Get current speed
|
||||
// Factor 0.00555
|
||||
nissan_speed = ((GET_BYTE(to_push, 2) << 8) | (GET_BYTE(to_push, 3))) * 0.00555 / 3.6;
|
||||
// Factor 0.005
|
||||
nissan_speed = ((GET_BYTE(to_push, 2) << 8) | (GET_BYTE(to_push, 3))) * 0.005 / 3.6;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 0x15c) {
|
||||
bool gas_pressed = ((GET_BYTE(to_push, 5) << 2) | ((GET_BYTE(to_push, 6) >> 6) & 0x3));
|
||||
if (gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 1;
|
||||
// X-Trail 0x15c, Leaf 0x239
|
||||
if ((addr == 0x15c) || (addr == 0x239)) {
|
||||
bool gas_pressed = true;
|
||||
if (addr == 0x15c){
|
||||
gas_pressed = ((GET_BYTE(to_push, 5) << 2) | ((GET_BYTE(to_push, 6) >> 6) & 0x3)) > 1;
|
||||
} else {
|
||||
gas_pressed = GET_BYTE(to_push, 0) > 3;
|
||||
}
|
||||
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
|
||||
// 0x169 is lkas cmd. If it is on bus 0, then relay is unexpectedly closed
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == 0x169)) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
|
||||
if (bus == 1) {
|
||||
if (addr == 0x1b6) {
|
||||
int cruise_engaged = (GET_BYTE(to_push, 4) >> 6) & 1;
|
||||
if (cruise_engaged && !nissan_cruise_engaged_last) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
if (!cruise_engaged) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
nissan_cruise_engaged_last = cruise_engaged;
|
||||
// exit controls on rising edge of brake press, or if speed > 0 and brake
|
||||
// X-trail 0x454, Leaf 0x1cc
|
||||
if ((addr == 0x454) || (addr == 0x1cc)) {
|
||||
bool brake_pressed = true;
|
||||
if (addr == 0x454){
|
||||
brake_pressed = (GET_BYTE(to_push, 2) & 0x80) != 0;
|
||||
} else {
|
||||
brake_pressed = GET_BYTE(to_push, 0) > 3;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of brake press, or if speed > 0 and brake
|
||||
if (addr == 0x454) {
|
||||
bool brake_pressed = (GET_BYTE(to_push, 2) & 0x80) != 0;
|
||||
if (brake_pressed && (!brake_pressed_prev || (nissan_speed > 0.))) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
brake_pressed_prev = brake_pressed;
|
||||
if (brake_pressed && (!brake_pressed_prev || (nissan_speed > 0.))) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
brake_pressed_prev = brake_pressed;
|
||||
}
|
||||
|
||||
|
||||
// Handle cruise enabled
|
||||
if ((bus == 2) && (addr == 0x30f)) {
|
||||
bool cruise_engaged = (GET_BYTE(to_push, 0) >> 3) & 1;
|
||||
|
||||
if (cruise_engaged && !nissan_cruise_engaged_last) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
if (!cruise_engaged) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
nissan_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
@@ -133,16 +148,6 @@ static int nissan_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int highest_desired_angle = nissan_desired_angle_last + ((nissan_desired_angle_last > 0) ? delta_angle_up : delta_angle_down);
|
||||
int lowest_desired_angle = nissan_desired_angle_last - ((nissan_desired_angle_last >= 0) ? delta_angle_down : delta_angle_up);
|
||||
|
||||
// Limit maximum steering angle at current speed
|
||||
int maximum_angle = ((int)interpolate(NISSAN_LOOKUP_MAX_ANGLE, nissan_speed));
|
||||
|
||||
if (highest_desired_angle > (maximum_angle * NISSAN_DEG_TO_CAN)) {
|
||||
highest_desired_angle = (maximum_angle * NISSAN_DEG_TO_CAN);
|
||||
}
|
||||
if (lowest_desired_angle < (-maximum_angle * NISSAN_DEG_TO_CAN)) {
|
||||
lowest_desired_angle = (-maximum_angle * NISSAN_DEG_TO_CAN);
|
||||
}
|
||||
|
||||
// check for violation;
|
||||
violation |= max_limit_check(desired_angle, highest_desired_angle, lowest_desired_angle);
|
||||
|
||||
@@ -183,7 +188,10 @@ static int nissan_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2; // ADAS
|
||||
int block_msg = (addr == 0x280); // CANCEL_MSG
|
||||
if (!block_msg) {
|
||||
bus_fwd = 2; // ADAS
|
||||
}
|
||||
}
|
||||
|
||||
if (bus_num == 2) {
|
||||
|
||||
@@ -67,6 +67,8 @@ static int subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (valid && (GET_BUS(to_push) == 0)) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
if (((addr == 0x119) && subaru_global) ||
|
||||
@@ -116,15 +118,15 @@ static int subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
((addr == 0x140) && !subaru_global)) {
|
||||
int byte = subaru_global ? 4 : 0;
|
||||
bool gas_pressed = GET_BYTE(to_push, byte) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 1;
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) &&
|
||||
(((addr == 0x122) && subaru_global) || ((addr == 0x164) && !subaru_global))) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
@@ -226,14 +228,14 @@ static int subaru_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
static void subaru_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
subaru_global = true;
|
||||
}
|
||||
|
||||
static void subaru_legacy_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
subaru_global = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,10 @@ const uint32_t 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
|
||||
const int TOYOTA_MIN_ACCEL = -3000; // -3.0 m/s2
|
||||
|
||||
const int TOYOTA_ISO_MAX_ACCEL = 2000; // 2.0 m/s2
|
||||
const int TOYOTA_ISO_MIN_ACCEL = -3500; // -3.5 m/s2
|
||||
|
||||
const int TOYOTA_STANDSTILL_THRSLD = 100; // 1kph
|
||||
const int TOYOTA_GAS_INTERCEPTOR_THRSLD = 475; // ratio between offset and gain from dbc file
|
||||
@@ -63,6 +66,8 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
bool valid = addr_safety_check(to_push, toyota_rx_checks, TOYOTA_RX_CHECKS_LEN,
|
||||
toyota_get_checksum, toyota_compute_checksum, NULL);
|
||||
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
||||
|
||||
if (valid && (GET_BUS(to_push) == 0)) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -83,6 +88,7 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
}
|
||||
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 0x1D2) {
|
||||
// 5th bit is CRUISE_ACTIVE
|
||||
int cruise_engaged = GET_BYTE(to_push, 0) & 0x20;
|
||||
@@ -93,6 +99,13 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
toyota_cruise_engaged_last = cruise_engaged;
|
||||
|
||||
// handle gas_pressed
|
||||
bool gas_pressed = ((GET_BYTE(to_push, 0) >> 4) & 1) == 0;
|
||||
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev && !gas_interceptor_detected) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
|
||||
// sample speed
|
||||
@@ -121,25 +134,16 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if (addr == 0x201) {
|
||||
gas_interceptor_detected = 1;
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRSLD) &&
|
||||
if (!unsafe_allow_gas && (gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRSLD) &&
|
||||
(gas_interceptor_prev <= TOYOTA_GAS_INTERCEPTOR_THRSLD)) {
|
||||
controls_allowed = 1;
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 0x2C1) {
|
||||
bool gas_pressed = GET_BYTE(to_push, 6) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev && !gas_interceptor_detected) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
|
||||
// 0x2E4 is lkas cmd. If it is on bus 0, then relay is unexpectedly closed
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == 0x2E4)) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
@@ -180,7 +184,10 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
bool violation = max_limit_check(desired_accel, TOYOTA_MAX_ACCEL, TOYOTA_MIN_ACCEL);
|
||||
bool violation = (unsafe_mode & UNSAFE_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX)?
|
||||
max_limit_check(desired_accel, TOYOTA_ISO_MAX_ACCEL, TOYOTA_ISO_MIN_ACCEL) :
|
||||
max_limit_check(desired_accel, TOYOTA_MAX_ACCEL, TOYOTA_MIN_ACCEL);
|
||||
|
||||
if (violation) {
|
||||
tx = 0;
|
||||
}
|
||||
@@ -240,7 +247,7 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
static void toyota_init(int16_t param) {
|
||||
controls_allowed = 0;
|
||||
relay_malfunction = 0;
|
||||
relay_malfunction_reset();
|
||||
toyota_dbc_eps_torque_factor = param;
|
||||
}
|
||||
|
||||
@@ -275,4 +282,4 @@ const safety_hooks toyota_hooks = {
|
||||
.fwd = toyota_fwd_hook,
|
||||
.addr_check = toyota_rx_checks,
|
||||
.addr_check_len = sizeof(toyota_rx_checks)/sizeof(toyota_rx_checks[0]),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -30,6 +30,26 @@ AddrCheckStruct volkswagen_mqb_rx_checks[] = {
|
||||
};
|
||||
const int VOLKSWAGEN_MQB_RX_CHECKS_LEN = sizeof(volkswagen_mqb_rx_checks) / sizeof(volkswagen_mqb_rx_checks[0]);
|
||||
|
||||
// Safety-relevant CAN messages for the Volkswagen PQ35/PQ46/NMS platforms
|
||||
#define MSG_LENKHILFE_3 0x0D0 // RX from EPS, for steering angle and driver steering torque
|
||||
#define MSG_HCA_1 0x0D2 // TX by OP, Heading Control Assist steering torque
|
||||
#define MSG_MOTOR_2 0x288 // RX from ECU, for CC state and brake switch state
|
||||
#define MSG_MOTOR_3 0x380 // RX from ECU, for driver throttle input
|
||||
#define MSG_GRA_NEU 0x38A // TX by OP, ACC control buttons for cancel/resume
|
||||
#define MSG_BREMSE_3 0x4A0 // RX from ABS, for wheel speeds
|
||||
#define MSG_LDW_1 0x5BE // TX by OP, Lane line recognition and text alerts
|
||||
|
||||
// Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration
|
||||
const AddrBus VOLKSWAGEN_PQ_TX_MSGS[] = {{MSG_HCA_1, 0}, {MSG_GRA_NEU, 0}, {MSG_GRA_NEU, 2}, {MSG_LDW_1, 0}};
|
||||
const int VOLKSWAGEN_PQ_TX_MSGS_LEN = sizeof(VOLKSWAGEN_PQ_TX_MSGS) / sizeof(VOLKSWAGEN_PQ_TX_MSGS[0]);
|
||||
|
||||
AddrCheckStruct volkswagen_pq_rx_checks[] = {
|
||||
{.addr = {MSG_LENKHILFE_3}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U},
|
||||
{.addr = {MSG_MOTOR_2}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 20000U},
|
||||
{.addr = {MSG_MOTOR_3}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U},
|
||||
{.addr = {MSG_BREMSE_3}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U},
|
||||
};
|
||||
const int VOLKSWAGEN_PQ_RX_CHECKS_LEN = sizeof(volkswagen_pq_rx_checks) / sizeof(volkswagen_pq_rx_checks[0]);
|
||||
|
||||
struct sample_t volkswagen_torque_driver; // Last few driver torques measured
|
||||
int volkswagen_rt_torque_last = 0;
|
||||
@@ -45,10 +65,17 @@ static uint8_t volkswagen_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
return (uint8_t)GET_BYTE(to_push, 0);
|
||||
}
|
||||
|
||||
static uint8_t volkswagen_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static uint8_t volkswagen_mqb_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// MQB message counters are consistently found at LSB 8.
|
||||
return (uint8_t)GET_BYTE(to_push, 1) & 0xFU;
|
||||
}
|
||||
|
||||
static uint8_t volkswagen_pq_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// Few PQ messages have counters, and their offsets are inconsistent. This
|
||||
// function works only for Lenkhilfe_3 at this time.
|
||||
return (uint8_t)(GET_BYTE(to_push, 1) & 0xF0U) >> 4;
|
||||
}
|
||||
|
||||
static uint8_t volkswagen_mqb_compute_crc(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
int len = GET_LEN(to_push);
|
||||
@@ -62,7 +89,7 @@ static uint8_t volkswagen_mqb_compute_crc(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
crc = volkswagen_crc8_lut_8h2f[crc];
|
||||
}
|
||||
|
||||
uint8_t counter = volkswagen_get_counter(to_push);
|
||||
uint8_t counter = volkswagen_mqb_get_counter(to_push);
|
||||
switch(addr) {
|
||||
case MSG_EPS_01:
|
||||
crc ^= (uint8_t[]){0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5}[counter];
|
||||
@@ -84,20 +111,40 @@ static uint8_t volkswagen_mqb_compute_crc(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
return crc ^ 0xFFU;
|
||||
}
|
||||
|
||||
static uint8_t volkswagen_pq_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int len = GET_LEN(to_push);
|
||||
uint8_t checksum = 0U;
|
||||
|
||||
for (int i = 1; i < len; i++) {
|
||||
checksum ^= (uint8_t)GET_BYTE(to_push, i);
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
static void volkswagen_mqb_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
relay_malfunction_reset();
|
||||
volkswagen_torque_msg = MSG_HCA_01;
|
||||
volkswagen_lane_msg = MSG_LDW_02;
|
||||
gen_crc_lookup_table(0x2F, volkswagen_crc8_lut_8h2f);
|
||||
}
|
||||
|
||||
static void volkswagen_pq_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
controls_allowed = false;
|
||||
relay_malfunction_reset();
|
||||
volkswagen_torque_msg = MSG_HCA_1;
|
||||
volkswagen_lane_msg = MSG_LDW_1;
|
||||
}
|
||||
|
||||
static int volkswagen_mqb_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
bool valid = addr_safety_check(to_push, volkswagen_mqb_rx_checks, VOLKSWAGEN_MQB_RX_CHECKS_LEN,
|
||||
volkswagen_get_checksum, volkswagen_mqb_compute_crc, volkswagen_get_counter);
|
||||
volkswagen_get_checksum, volkswagen_mqb_compute_crc, volkswagen_mqb_get_counter);
|
||||
|
||||
if (valid && (GET_BUS(to_push) == 0)) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
@@ -136,8 +183,8 @@ static int volkswagen_mqb_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// Signal: Motor_20.MO_Fahrpedalrohwert_01
|
||||
if (addr == MSG_MOTOR_20) {
|
||||
bool gas_pressed = ((GET_BYTES_04(to_push) >> 12) & 0xFF) != 0;
|
||||
if (gas_pressed && !gas_pressed_prev) {
|
||||
controls_allowed = 1;
|
||||
if (gas_pressed && !gas_pressed_prev && !(unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
@@ -154,7 +201,74 @@ static int volkswagen_mqb_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
// If there are HCA messages on bus 0 not sent by OP, there's a relay problem
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == MSG_HCA_01)) {
|
||||
relay_malfunction = true;
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
static int volkswagen_pq_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
bool valid = addr_safety_check(to_push, volkswagen_pq_rx_checks, VOLKSWAGEN_PQ_RX_CHECKS_LEN,
|
||||
volkswagen_get_checksum, volkswagen_pq_compute_checksum, volkswagen_pq_get_counter);
|
||||
|
||||
if (valid) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
// Update in-motion state by sampling front wheel speeds
|
||||
// Signal: Bremse_3.Radgeschw__VL_4_1 (front left)
|
||||
// Signal: Bremse_3.Radgeschw__VR_4_1 (front right)
|
||||
if ((bus == 0) && (addr == MSG_BREMSE_3)) {
|
||||
int wheel_speed_fl = (GET_BYTE(to_push, 0) | (GET_BYTE(to_push, 1) << 8)) >> 1;
|
||||
int wheel_speed_fr = (GET_BYTE(to_push, 2) | (GET_BYTE(to_push, 3) << 8)) >> 1;
|
||||
// Check for average front speed in excess of 0.3m/s, 1.08km/h
|
||||
// DBC speed scale 0.01: 0.3m/s = 108, sum both wheels to compare
|
||||
volkswagen_moving = (wheel_speed_fl + wheel_speed_fr) > 216;
|
||||
}
|
||||
|
||||
// Update driver input torque samples
|
||||
// Signal: Lenkhilfe_3.LH3_LM (absolute torque)
|
||||
// Signal: Lenkhilfe_3.LH3_LMSign (direction)
|
||||
if ((bus == 0) && (addr == MSG_LENKHILFE_3)) {
|
||||
int torque_driver_new = GET_BYTE(to_push, 2) | ((GET_BYTE(to_push, 3) & 0x3) << 8);
|
||||
int sign = (GET_BYTE(to_push, 3) & 0x4) >> 2;
|
||||
if (sign == 1) {
|
||||
torque_driver_new *= -1;
|
||||
}
|
||||
update_sample(&volkswagen_torque_driver, torque_driver_new);
|
||||
}
|
||||
|
||||
// Update ACC status from ECU for controls-allowed state
|
||||
// Signal: Motor_2.GRA_Status
|
||||
if ((bus == 0) && (addr == MSG_MOTOR_2)) {
|
||||
int acc_status = (GET_BYTE(to_push, 2) & 0xC0) >> 6;
|
||||
controls_allowed = ((acc_status == 1) || (acc_status == 2)) ? 1 : 0;
|
||||
}
|
||||
|
||||
// Exit controls on rising edge of gas press
|
||||
// Signal: Motor_3.Fahrpedal_Rohsignal
|
||||
if ((bus == 0) && (addr == MSG_MOTOR_3)) {
|
||||
int gas_pressed = (GET_BYTE(to_push, 2));
|
||||
if (gas_pressed && !gas_pressed_prev && !(unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gas_pressed_prev = gas_pressed;
|
||||
}
|
||||
|
||||
// Exit controls on rising edge of brake press
|
||||
// Signal: Motor_2.Bremslichtschalter
|
||||
if ((bus == 0) && (addr == MSG_MOTOR_2)) {
|
||||
bool brake_pressed = (GET_BYTE(to_push, 2) & 0x1);
|
||||
if (brake_pressed && (!(brake_pressed_prev) || volkswagen_moving)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
brake_pressed_prev = brake_pressed;
|
||||
}
|
||||
|
||||
// If there are HCA messages on bus 0 not sent by OP, there's a relay problem
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == MSG_HCA_1)) {
|
||||
relay_malfunction_set();
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
@@ -237,6 +351,44 @@ static int volkswagen_mqb_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
static int volkswagen_pq_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
int tx = 1;
|
||||
|
||||
if (!msg_allowed(addr, bus, VOLKSWAGEN_PQ_TX_MSGS, VOLKSWAGEN_PQ_TX_MSGS_LEN) || relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// Safety check for HCA_1 Heading Control Assist torque
|
||||
// Signal: HCA_1.LM_Offset (absolute torque)
|
||||
// Signal: HCA_1.LM_Offsign (direction)
|
||||
if (addr == MSG_HCA_1) {
|
||||
int desired_torque = GET_BYTE(to_send, 2) | ((GET_BYTE(to_send, 3) & 0x7F) << 8);
|
||||
desired_torque = desired_torque / 32; // DBC scale from PQ network to centi-Nm
|
||||
int sign = (GET_BYTE(to_send, 3) & 0x80) >> 7;
|
||||
if (sign == 1) {
|
||||
desired_torque *= -1;
|
||||
}
|
||||
|
||||
if (volkswagen_steering_check(desired_torque)) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FORCE CANCEL: ensuring that only the cancel button press is sent when controls are off.
|
||||
// This avoids unintended engagements while still allowing resume spam
|
||||
if ((addr == MSG_GRA_NEU) && !controls_allowed) {
|
||||
// disallow resume and set: bits 16 and 17
|
||||
if ((GET_BYTE(to_send, 2) & 0x3) != 0) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 allows the message through
|
||||
return tx;
|
||||
}
|
||||
|
||||
static int volkswagen_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
int bus_fwd = -1;
|
||||
@@ -275,3 +427,14 @@ const safety_hooks volkswagen_mqb_hooks = {
|
||||
.addr_check = volkswagen_mqb_rx_checks,
|
||||
.addr_check_len = sizeof(volkswagen_mqb_rx_checks) / sizeof(volkswagen_mqb_rx_checks[0]),
|
||||
};
|
||||
|
||||
// Volkswagen PQ35/PQ46/NMS platforms
|
||||
const safety_hooks volkswagen_pq_hooks = {
|
||||
.init = volkswagen_pq_init,
|
||||
.rx = volkswagen_pq_rx_hook,
|
||||
.tx = volkswagen_pq_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = volkswagen_fwd_hook,
|
||||
.addr_check = volkswagen_pq_rx_checks,
|
||||
.addr_check_len = sizeof(volkswagen_pq_rx_checks) / sizeof(volkswagen_pq_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -61,6 +61,8 @@ bool addr_safety_check(CAN_FIFOMailBox_TypeDef *to_push,
|
||||
uint8_t (*get_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
|
||||
uint8_t (*compute_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
|
||||
uint8_t (*get_counter)(CAN_FIFOMailBox_TypeDef *to_push));
|
||||
void relay_malfunction_set(void);
|
||||
void relay_malfunction_reset(void);
|
||||
|
||||
typedef void (*safety_hook_init)(int16_t param);
|
||||
typedef int (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
@@ -88,6 +90,24 @@ int gas_interceptor_prev = 0;
|
||||
bool gas_pressed_prev = false;
|
||||
bool brake_pressed_prev = false;
|
||||
|
||||
// This can be set with a USB command
|
||||
// It enables features we consider to be unsafe, but understand others may have different opinions
|
||||
// It is always 0 on mainline comma.ai openpilot
|
||||
|
||||
// If using this flag, be very careful about what happens if your fork wants to brake while the
|
||||
// user is pressing the gas. Tesla is careful with this.
|
||||
#define UNSAFE_DISABLE_DISENGAGE_ON_GAS 1
|
||||
|
||||
// If using this flag, make sure to communicate to your users that a stock safety feature is now disabled.
|
||||
#define UNSAFE_DISABLE_STOCK_AEB 2
|
||||
|
||||
// If using this flag, be aware that harder braking is more likely to lead to rear endings,
|
||||
// and that alone this flag doesn't make braking compliant because there's also a time element.
|
||||
// See ISO 15622:2018 for more information.
|
||||
#define UNSAFE_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX 8
|
||||
|
||||
int unsafe_mode = 0;
|
||||
|
||||
// time since safety mode has been changed
|
||||
uint32_t safety_mode_cnt = 0U;
|
||||
// allow 1s of transition timeout after relay changes state before assessing malfunctioning
|
||||
|
||||
@@ -110,6 +110,7 @@ void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
|
||||
UNUSED(len);
|
||||
UNUSED(hardwired);
|
||||
}
|
||||
void usb_cb_ep3_out_complete(void) {}
|
||||
|
||||
int is_enumerated = 0;
|
||||
void usb_cb_enumeration_complete(void) {
|
||||
|
||||
@@ -129,6 +129,7 @@ class Panda(object):
|
||||
SAFETY_GM_ASCM = 18
|
||||
SAFETY_NOOUTPUT = 19
|
||||
SAFETY_HONDA_BOSCH_HARNESS = 20
|
||||
SAFETY_VOLKSWAGEN_PQ = 21
|
||||
SAFETY_SUBARU_LEGACY = 22
|
||||
|
||||
SERIAL_DEBUG = 0
|
||||
@@ -187,6 +188,7 @@ class Panda(object):
|
||||
self.bootstub = device.getProductID() == 0xddee
|
||||
self.legacy = (device.getbcdDevice() != 0x2300)
|
||||
self._handle = device.open()
|
||||
self._handle.setAutoDetachKernelDriver(True)
|
||||
if claim:
|
||||
self._handle.claimInterface(0)
|
||||
#self._handle.setInterfaceAltSetting(0, 0) #Issue in USB stack
|
||||
@@ -476,7 +478,12 @@ class Panda(object):
|
||||
|
||||
# ******************* can *******************
|
||||
|
||||
def can_send_many(self, arr):
|
||||
# The panda will NAK CAN writes when there is CAN congestion.
|
||||
# libusb will try to send it again, with a max timeout.
|
||||
# Timeout is in ms. If set to 0, the timeout is infinite.
|
||||
CAN_SEND_TIMEOUT_MS = 10
|
||||
|
||||
def can_send_many(self, arr, timeout=CAN_SEND_TIMEOUT_MS):
|
||||
snds = []
|
||||
transmit = 1
|
||||
extended = 4
|
||||
@@ -499,13 +506,13 @@ class Panda(object):
|
||||
for s in snds:
|
||||
self._handle.bulkWrite(3, s)
|
||||
else:
|
||||
self._handle.bulkWrite(3, b''.join(snds))
|
||||
self._handle.bulkWrite(3, b''.join(snds), timeout=timeout)
|
||||
break
|
||||
except (usb1.USBErrorIO, usb1.USBErrorOverflow):
|
||||
print("CAN: BAD SEND MANY, RETRYING")
|
||||
|
||||
def can_send(self, addr, dat, bus):
|
||||
self.can_send_many([[addr, None, dat, bus]])
|
||||
def can_send(self, addr, dat, bus, timeout=CAN_SEND_TIMEOUT_MS):
|
||||
self.can_send_many([[addr, None, dat, bus]], timeout=timeout)
|
||||
|
||||
def can_recv(self):
|
||||
dat = bytearray()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import time
|
||||
import random
|
||||
import threading
|
||||
from panda import Panda
|
||||
from nose.tools import assert_equal, assert_less, assert_greater
|
||||
from .helpers import panda_jungle, start_heartbeat_thread, reset_pandas, time_many_sends, test_all_pandas, test_all_gen2_pandas, clear_can_buffers, panda_connect_and_init
|
||||
@@ -200,3 +201,44 @@ def test_gen2_loopback(p):
|
||||
finally:
|
||||
# Set back to silent mode
|
||||
p.set_safety_mode(Panda.SAFETY_SILENT)
|
||||
|
||||
@test_all_pandas
|
||||
@panda_connect_and_init
|
||||
def test_bulk_write(p):
|
||||
# The TX buffers on pandas is 0x100 in length.
|
||||
NUM_MESSAGES_PER_BUS = 10000
|
||||
|
||||
def flood_tx(panda):
|
||||
print('Sending!')
|
||||
msg = b"\xaa"*4
|
||||
packet = [[0xaa, None, msg, 0], [0xaa, None, msg, 1], [0xaa, None, msg, 2]] * NUM_MESSAGES_PER_BUS
|
||||
|
||||
# Disable timeout
|
||||
panda.can_send_many(packet, timeout=0)
|
||||
print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!")
|
||||
|
||||
# Start heartbeat
|
||||
start_heartbeat_thread(p)
|
||||
|
||||
# Set safety mode and power saving
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
p.set_power_save(False)
|
||||
|
||||
# Start transmisson
|
||||
threading.Thread(target=flood_tx, args=(p,)).start()
|
||||
|
||||
# Receive as much as we can in a few second time period
|
||||
rx = []
|
||||
old_len = 0
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 2 or len(rx) > old_len:
|
||||
old_len = len(rx)
|
||||
rx.extend(panda_jungle.can_recv())
|
||||
print(f"Received {len(rx)} messages")
|
||||
|
||||
# All messages should have been received
|
||||
if len(rx) != 3*NUM_MESSAGES_PER_BUS:
|
||||
Exception("Did not receive all messages!")
|
||||
|
||||
# Set back to silent mode
|
||||
p.set_safety_mode(Panda.SAFETY_SILENT)
|
||||
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
import time
|
||||
import threading
|
||||
|
||||
from panda import Panda
|
||||
|
||||
# The TX buffers on pandas is 0x100 in length.
|
||||
NUM_MESSAGES_PER_BUS = 10000
|
||||
|
||||
def flood_tx(panda):
|
||||
print('Sending!')
|
||||
msg = b"\xaa"*4
|
||||
packet = [[0xaa, None, msg, 0], [0xaa, None, msg, 1], [0xaa, None, msg, 2]] * NUM_MESSAGES_PER_BUS
|
||||
panda.can_send_many(packet)
|
||||
print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
serials = Panda.list()
|
||||
if len(serials) != 2:
|
||||
raise Exception("Connect two pandas to perform this test!")
|
||||
|
||||
sender = Panda(serials[0])
|
||||
receiver = Panda(serials[1])
|
||||
|
||||
sender.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
receiver.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# Start transmisson
|
||||
threading.Thread(target=flood_tx, args=(sender,)).start()
|
||||
|
||||
# Receive as much as we can in a few second time period
|
||||
rx = []
|
||||
old_len = 0
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 2 or len(rx) > old_len:
|
||||
old_len = len(rx)
|
||||
rx.extend(receiver.can_recv())
|
||||
print(f"Received {len(rx)} messages")
|
||||
@@ -2,6 +2,12 @@ from panda.tests.safety import libpandasafety_py
|
||||
|
||||
MAX_WRONG_COUNTERS = 5
|
||||
|
||||
class UNSAFE_MODE:
|
||||
DEFAULT = 0
|
||||
DISABLE_DISENGAGE_ON_GAS = 1
|
||||
DISABLE_STOCK_AEB = 2
|
||||
RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX = 8
|
||||
|
||||
def make_msg(bus, addr, length=8):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
if addr >= 0x800:
|
||||
|
||||
@@ -32,6 +32,8 @@ typedef struct
|
||||
|
||||
void set_controls_allowed(bool c);
|
||||
bool get_controls_allowed(void);
|
||||
void set_unsafe_mode(int mode);
|
||||
int get_unsafe_mode(void);
|
||||
void set_relay_malfunction(bool c);
|
||||
bool get_relay_malfunction(void);
|
||||
void set_gas_interceptor_detected(bool c);
|
||||
|
||||
@@ -62,6 +62,13 @@ uint8_t hw_type = HW_TYPE_UNKNOWN;
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
(_a > 0) ? _a : (-_a); })
|
||||
|
||||
// from faults.h
|
||||
#define FAULT_RELAY_MALFUNCTION (1U << 0)
|
||||
void fault_occurred(uint32_t fault) {
|
||||
}
|
||||
void fault_recovered(uint32_t fault) {
|
||||
}
|
||||
|
||||
// from llcan.h
|
||||
#define GET_BUS(msg) (((msg)->RDTR >> 4) & 0xFF)
|
||||
#define GET_LEN(msg) ((msg)->RDTR & 0xf)
|
||||
@@ -72,7 +79,9 @@ uint8_t hw_type = HW_TYPE_UNKNOWN;
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
#ifndef PANDA
|
||||
#define PANDA
|
||||
#endif
|
||||
#define NULL ((void*)0)
|
||||
#define static
|
||||
#include "safety.h"
|
||||
@@ -81,6 +90,10 @@ void set_controls_allowed(bool c){
|
||||
controls_allowed = c;
|
||||
}
|
||||
|
||||
void set_unsafe_mode(int mode){
|
||||
unsafe_mode = mode;
|
||||
}
|
||||
|
||||
void set_relay_malfunction(bool c){
|
||||
relay_malfunction = c;
|
||||
}
|
||||
@@ -93,6 +106,10 @@ bool get_controls_allowed(void){
|
||||
return controls_allowed;
|
||||
}
|
||||
|
||||
int get_unsafe_mode(void){
|
||||
return unsafe_mode;
|
||||
}
|
||||
|
||||
bool get_relay_malfunction(void){
|
||||
return relay_malfunction;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg
|
||||
from panda.tests.safety.common import StdTest, make_msg, UNSAFE_MODE
|
||||
|
||||
MAX_RATE_UP = 3
|
||||
MAX_RATE_DOWN = 3
|
||||
@@ -149,6 +149,14 @@ class TestChryslerSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_brake_disengage(self):
|
||||
StdTest.test_allow_brake_at_zero_speed(self)
|
||||
StdTest.test_not_allow_brake_when_moving(self, 0)
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg
|
||||
from panda.tests.safety.common import StdTest, make_msg, UNSAFE_MODE
|
||||
|
||||
MAX_RATE_UP = 7
|
||||
MAX_RATE_DOWN = 17
|
||||
@@ -126,6 +126,14 @@ class TestGmSafety(unittest.TestCase):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._gas_msg(False))
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(False))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._gas_msg(True))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(True))
|
||||
self.safety.set_controls_allowed(1)
|
||||
@@ -252,6 +260,59 @@ class TestGmSafety(unittest.TestCase):
|
||||
# assume len 8
|
||||
self.assertEqual(-1, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
|
||||
def test_tx_hook_on_pedal_pressed(self):
|
||||
for pedal in ['brake', 'gas']:
|
||||
if pedal == 'brake':
|
||||
# brake_pressed_prev and honda_moving
|
||||
self.safety.safety_rx_hook(self._speed_msg(100))
|
||||
self.safety.safety_rx_hook(self._brake_msg(MAX_BRAKE))
|
||||
elif pedal == 'gas':
|
||||
# gas_pressed_prev
|
||||
self.safety.safety_rx_hook(self._gas_msg(MAX_GAS))
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_gas_msg(MAX_GAS)))
|
||||
|
||||
# reset status
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.safety_tx_hook(self._send_brake_msg(0))
|
||||
self.safety.safety_tx_hook(self._torque_msg(0))
|
||||
if pedal == 'brake':
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._brake_msg(0))
|
||||
elif pedal == 'gas':
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
|
||||
def test_tx_hook_on_pedal_pressed_on_unsafe_gas_mode(self):
|
||||
for pedal in ['brake', 'gas']:
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
if pedal == 'brake':
|
||||
# brake_pressed_prev and honda_moving
|
||||
self.safety.safety_rx_hook(self._speed_msg(100))
|
||||
self.safety.safety_rx_hook(self._brake_msg(MAX_BRAKE))
|
||||
allow_ctrl = False
|
||||
elif pedal == 'gas':
|
||||
# gas_pressed_prev
|
||||
self.safety.safety_rx_hook(self._gas_msg(MAX_GAS))
|
||||
allow_ctrl = True
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._send_gas_msg(MAX_GAS)))
|
||||
|
||||
# reset status
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
self.safety.safety_tx_hook(self._send_brake_msg(0))
|
||||
self.safety.safety_tx_hook(self._torque_msg(0))
|
||||
if pedal == 'brake':
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._brake_msg(0))
|
||||
elif pedal == 'gas':
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg, MAX_WRONG_COUNTERS
|
||||
from panda.tests.safety.common import StdTest, make_msg, MAX_WRONG_COUNTERS, UNSAFE_MODE
|
||||
|
||||
MAX_BRAKE = 255
|
||||
|
||||
@@ -189,6 +189,14 @@ class TestHondaSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.safety.set_controls_allowed(1)
|
||||
@@ -205,6 +213,17 @@ class TestHondaSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas_interceptor(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(g, 0x201))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
self.safety.set_controls_allowed(False)
|
||||
|
||||
def test_allow_engage_with_gas_interceptor_pressed(self):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
|
||||
self.safety.set_controls_allowed(1)
|
||||
@@ -335,6 +354,79 @@ class TestHondaSafety(unittest.TestCase):
|
||||
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
|
||||
def test_tx_hook_on_pedal_pressed(self):
|
||||
for pedal in ['brake', 'gas', 'interceptor']:
|
||||
if pedal == 'brake':
|
||||
# brake_pressed_prev and honda_moving
|
||||
self.safety.safety_rx_hook(self._speed_msg(100))
|
||||
self.safety.safety_rx_hook(self._brake_msg(1))
|
||||
elif pedal == 'gas':
|
||||
# gas_pressed_prev
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
elif pedal == 'interceptor':
|
||||
# gas_interceptor_prev > INTERCEPTOR_THRESHOLD
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
hw = self.safety.get_honda_hw()
|
||||
if hw == HONDA_N_HW:
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_interceptor_msg(INTERCEPTOR_THRESHOLD, 0x200)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_steer_msg(0x1000)))
|
||||
|
||||
# reset status
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.safety_tx_hook(self._send_brake_msg(0))
|
||||
self.safety.safety_tx_hook(self._send_steer_msg(0))
|
||||
self.safety.safety_tx_hook(self._send_interceptor_msg(0, 0x200))
|
||||
if pedal == 'brake':
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._brake_msg(0))
|
||||
elif pedal == 'gas':
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
elif pedal == 'interceptor':
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_tx_hook_on_pedal_pressed_on_unsafe_gas_mode(self):
|
||||
for pedal in ['brake', 'gas', 'interceptor']:
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
if pedal == 'brake':
|
||||
# brake_pressed_prev and honda_moving
|
||||
self.safety.safety_rx_hook(self._speed_msg(100))
|
||||
self.safety.safety_rx_hook(self._brake_msg(1))
|
||||
allow_ctrl = False
|
||||
elif pedal == 'gas':
|
||||
# gas_pressed_prev
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
allow_ctrl = True
|
||||
elif pedal == 'interceptor':
|
||||
# gas_interceptor_prev > INTERCEPTOR_THRESHOLD
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
allow_ctrl = True
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
hw = self.safety.get_honda_hw()
|
||||
if hw == HONDA_N_HW:
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._send_interceptor_msg(INTERCEPTOR_THRESHOLD, 0x200)))
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._send_steer_msg(0x1000)))
|
||||
# reset status
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
self.safety.safety_tx_hook(self._send_brake_msg(0))
|
||||
self.safety.safety_tx_hook(self._send_steer_msg(0))
|
||||
self.safety.safety_tx_hook(self._send_interceptor_msg(0, 0x200))
|
||||
if pedal == 'brake':
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._brake_msg(0))
|
||||
elif pedal == 'gas':
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
elif pedal == 'interceptor':
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
class TestHondaBoschGiraffeSafety(TestHondaSafety):
|
||||
@classmethod
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg
|
||||
from panda.tests.safety.common import StdTest, make_msg, UNSAFE_MODE
|
||||
|
||||
MAX_RATE_UP = 3
|
||||
MAX_RATE_DOWN = 7
|
||||
@@ -114,6 +114,14 @@ class TestHyundaiSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_brake_disengage(self):
|
||||
StdTest.test_allow_brake_at_zero_speed(self)
|
||||
StdTest.test_not_allow_brake_when_moving(self, SPEED_THRESHOLD)
|
||||
|
||||
@@ -3,15 +3,13 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg
|
||||
from panda.tests.safety.common import StdTest, make_msg, UNSAFE_MODE
|
||||
|
||||
ANGLE_MAX_BP = [1.3, 10., 30.]
|
||||
ANGLE_MAX_V = [540., 120., 23.]
|
||||
ANGLE_DELTA_BP = [0., 5., 15.]
|
||||
ANGLE_DELTA_V = [5., .8, .15] # windup limit
|
||||
ANGLE_DELTA_VU = [5., 3.5, 0.4] # unwind limit
|
||||
|
||||
TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2]]
|
||||
TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2], [0x280, 2]]
|
||||
|
||||
def twos_comp(val, bits):
|
||||
if val >= 0:
|
||||
@@ -50,8 +48,8 @@ class TestNissanSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._angle_meas_msg(angle))
|
||||
|
||||
def _lkas_state_msg(self, state):
|
||||
to_send = make_msg(0, 0x1b6)
|
||||
to_send[0].RDHR = (state & 0x1) << 6
|
||||
to_send = make_msg(1, 0x30f)
|
||||
to_send[0].RDHR = (state & 0x1) << 3
|
||||
|
||||
return to_send
|
||||
|
||||
@@ -64,8 +62,8 @@ class TestNissanSafety(unittest.TestCase):
|
||||
return to_send
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
to_send = make_msg(0, 0x29a)
|
||||
speed = int(speed / 0.00555 * 3.6)
|
||||
to_send = make_msg(0, 0x285)
|
||||
speed = int(speed / 0.005 * 3.6)
|
||||
to_send[0].RDLR = ((speed & 0xFF) << 24) | ((speed & 0xFF00) << 8)
|
||||
|
||||
return to_send
|
||||
@@ -92,46 +90,48 @@ class TestNissanSafety(unittest.TestCase):
|
||||
StdTest.test_spam_can_buses(self, TX_MSGS)
|
||||
|
||||
def test_angle_cmd_when_enabled(self):
|
||||
|
||||
# when controls are allowed, angle cmd rate limit is enforced
|
||||
# test 1: no limitations if we stay within limits
|
||||
speeds = [0., 1., 5., 10., 15., 100.]
|
||||
speeds = [0., 1., 5., 10., 15., 50.]
|
||||
angles = [-300, -100, -10, 0, 10, 100, 300]
|
||||
for a in angles:
|
||||
for s in speeds:
|
||||
max_delta_up = np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_V)
|
||||
max_delta_down = np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_VU)
|
||||
angle_lim = np.interp(s, ANGLE_MAX_BP, ANGLE_MAX_V)
|
||||
|
||||
# first test against false positives
|
||||
self._angle_meas_msg_array(a)
|
||||
self.safety.safety_rx_hook(self._speed_msg(s))
|
||||
|
||||
self._set_prev_angle(np.clip(a, -angle_lim, angle_lim))
|
||||
self._set_prev_angle(a)
|
||||
self.safety.set_controls_allowed(1)
|
||||
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(self._lkas_control_msg(
|
||||
np.clip(a + sign(a) * max_delta_up, -angle_lim, angle_lim), 1)))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(
|
||||
self._lkas_control_msg(np.clip(a, -angle_lim, angle_lim), 1)))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(self._lkas_control_msg(
|
||||
np.clip(a - sign(a) * max_delta_down, -angle_lim, angle_lim), 1)))
|
||||
# Stay within limits
|
||||
# Up
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(self._lkas_control_msg(a + sign(a) * max_delta_up, 1)))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
# now inject too high rates
|
||||
self.assertEqual(False, self.safety.safety_tx_hook(self._lkas_control_msg(a + sign(a) *
|
||||
(max_delta_up + 1), 1)))
|
||||
# Don't change
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(self._lkas_control_msg(a, 1)))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
# Down
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(self._lkas_control_msg(a - sign(a) * max_delta_down, 1)))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
# Inject too high rates
|
||||
# Up
|
||||
self.assertEqual(False, self.safety.safety_tx_hook(self._lkas_control_msg(a + sign(a) * (max_delta_up + 1), 1)))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# Don't change
|
||||
self.safety.set_controls_allowed(1)
|
||||
self._set_prev_angle(np.clip(a, -angle_lim, angle_lim))
|
||||
self._set_prev_angle(a)
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(
|
||||
self._lkas_control_msg(np.clip(a, -angle_lim, angle_lim), 1)))
|
||||
self.assertEqual(True, self.safety.safety_tx_hook(self._lkas_control_msg(a, 1)))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.assertEqual(False, self.safety.safety_tx_hook(self._lkas_control_msg(a - sign(a) *
|
||||
(max_delta_down + 1), 1)))
|
||||
|
||||
# Down
|
||||
self.assertEqual(False, self.safety.safety_tx_hook(self._lkas_control_msg(a - sign(a) * (max_delta_down + 1), 1)))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# Check desired steer should be the same as steer angle when controls are off
|
||||
@@ -154,6 +154,14 @@ class TestNissanSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._send_gas_cmd(100))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._send_gas_cmd(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._send_gas_cmd(100))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_acc_buttons(self):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_tx_hook(self._acc_button_cmd(0x2)) # Cancel button
|
||||
@@ -181,7 +189,7 @@ class TestNissanSafety(unittest.TestCase):
|
||||
buss = list(range(0x0, 0x3))
|
||||
msgs = list(range(0x1, 0x800))
|
||||
|
||||
blocked_msgs = [0x169,0x2b1,0x4cc]
|
||||
blocked_msgs = [(2, 0x169), (2, 0x2b1), (2, 0x4cc), (0, 0x280)]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == 0:
|
||||
@@ -189,7 +197,10 @@ class TestNissanSafety(unittest.TestCase):
|
||||
elif b == 1:
|
||||
fwd_bus = -1
|
||||
elif b == 2:
|
||||
fwd_bus = -1 if m in blocked_msgs else 0
|
||||
fwd_bus = 0
|
||||
|
||||
if (b, m) in blocked_msgs:
|
||||
fwd_bus = -1
|
||||
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg
|
||||
from panda.tests.safety.common import StdTest, make_msg, UNSAFE_MODE
|
||||
|
||||
MAX_RATE_UP = 50
|
||||
MAX_RATE_DOWN = 70
|
||||
@@ -155,6 +155,14 @@ class TestSubaruSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_brake_disengage(self):
|
||||
if (self.safety.get_subaru_global()):
|
||||
StdTest.test_allow_brake_at_zero_speed(self)
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg
|
||||
from panda.tests.safety.common import StdTest, make_msg, UNSAFE_MODE
|
||||
|
||||
MAX_RATE_UP = 10
|
||||
MAX_RATE_DOWN = 25
|
||||
@@ -12,6 +12,9 @@ MAX_TORQUE = 1500
|
||||
MAX_ACCEL = 1500
|
||||
MIN_ACCEL = -3000
|
||||
|
||||
ISO_MAX_ACCEL = 2000
|
||||
ISO_MIN_ACCEL = -3500
|
||||
|
||||
MAX_RT_DELTA = 375
|
||||
RT_INTERVAL = 250000
|
||||
|
||||
@@ -94,9 +97,10 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
to_send[0].RDHR |= toyota_checksum(to_send[0], 0x226, 8) << 24
|
||||
return to_send
|
||||
|
||||
def _send_gas_msg(self, gas):
|
||||
to_send = make_msg(0, 0x2C1)
|
||||
to_send[0].RDHR = (gas & 0xFF) << 16
|
||||
def _gas_pressed_msg(self, pressed, enable_cruise=False):
|
||||
to_send = make_msg(0, 0x1D2)
|
||||
to_send[0].RDLR = ((1*(not pressed)) << 4) | (1*enable_cruise << 5)
|
||||
to_send[0].RDHR = (toyota_checksum(to_send[0], 0x1D2, 8) << 24)
|
||||
return to_send
|
||||
|
||||
def _send_interceptor_msg(self, gas, addr):
|
||||
@@ -136,9 +140,9 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_prev_gas(self):
|
||||
for g in range(0, 256):
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(g))
|
||||
self.assertEqual(True if g > 0 else False, self.safety.get_gas_pressed_prev())
|
||||
for pressed in [True, False]:
|
||||
self.safety.safety_rx_hook(self._gas_pressed_msg(pressed))
|
||||
self.assertEqual(pressed, self.safety.get_gas_pressed_prev())
|
||||
|
||||
def test_prev_gas_interceptor(self):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0x0, 0x201))
|
||||
@@ -149,18 +153,27 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(0))
|
||||
self.safety.safety_rx_hook(self._gas_pressed_msg(False))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(1))
|
||||
self.safety.safety_rx_hook(self._gas_pressed_msg(True, enable_cruise=True))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(1))
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_pressed_msg(False))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(1))
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._gas_pressed_msg(True, enable_cruise=True))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._gas_pressed_msg(True))
|
||||
self.safety.set_controls_allowed(True)
|
||||
for _ in range(2):
|
||||
# since cruise msg is used for gas pedal state, cruise bit must
|
||||
# also be set for this test or else it will set controls_allowed
|
||||
self.safety.safety_rx_hook(self._gas_pressed_msg(True, enable_cruise=True))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disengage_on_gas_interceptor(self):
|
||||
for g in range(0, 0x1000):
|
||||
@@ -172,6 +185,17 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas_interceptor(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(g, 0x201))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
self.safety.set_controls_allowed(False)
|
||||
|
||||
def test_brake_disengage(self):
|
||||
StdTest.test_allow_brake_at_zero_speed(self)
|
||||
StdTest.test_not_allow_brake_when_moving(self, STANDSTILL_THRESHOLD)
|
||||
@@ -194,6 +218,18 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
send = accel == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._accel_msg(accel)))
|
||||
|
||||
def test_unsafe_iso_accel_actuation_limits(self):
|
||||
for accel in np.arange(ISO_MIN_ACCEL - 1000, ISO_MAX_ACCEL + 1000, 100):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX)
|
||||
if controls_allowed:
|
||||
send = ISO_MIN_ACCEL <= accel <= ISO_MAX_ACCEL
|
||||
else:
|
||||
send = accel == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._accel_msg(accel)))
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_torque_absolute_limits(self):
|
||||
for controls_allowed in [True, False]:
|
||||
for torque in np.arange(-MAX_TORQUE - 1000, MAX_TORQUE + 1000, MAX_RATE_UP):
|
||||
|
||||
@@ -4,7 +4,7 @@ import numpy as np
|
||||
import crcmod
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg, MAX_WRONG_COUNTERS
|
||||
from panda.tests.safety.common import StdTest, make_msg, MAX_WRONG_COUNTERS, UNSAFE_MODE
|
||||
|
||||
MAX_RATE_UP = 4
|
||||
MAX_RATE_DOWN = 10
|
||||
@@ -198,6 +198,14 @@ class TestVolkswagenMqbSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._motor_20_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._motor_20_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._motor_20_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._motor_20_msg(1))
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
#!/usr/bin/env python3
|
||||
import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg, MAX_WRONG_COUNTERS, UNSAFE_MODE
|
||||
|
||||
MAX_RATE_UP = 4
|
||||
MAX_RATE_DOWN = 10
|
||||
MAX_STEER = 300
|
||||
MAX_RT_DELTA = 75
|
||||
RT_INTERVAL = 250000
|
||||
|
||||
DRIVER_TORQUE_ALLOWANCE = 80
|
||||
DRIVER_TORQUE_FACTOR = 3
|
||||
|
||||
MSG_LENKHILFE_3 = 0x0D0 # RX from EPS, for steering angle and driver steering torque
|
||||
MSG_HCA_1 = 0x0D2 # TX by OP, Heading Control Assist steering torque
|
||||
MSG_MOTOR_2 = 0x288 # RX from ECU, for CC state and brake switch state
|
||||
MSG_MOTOR_3 = 0x380 # RX from ECU, for driver throttle input
|
||||
MSG_GRA_NEU = 0x38A # TX by OP, ACC control buttons for cancel/resume
|
||||
MSG_BREMSE_3 = 0x4A0 # RX from ABS, for wheel speeds
|
||||
MSG_LDW_1 = 0x5BE # TX by OP, Lane line recognition and text alerts
|
||||
|
||||
# Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration
|
||||
TX_MSGS = [[MSG_HCA_1, 0], [MSG_GRA_NEU, 0], [MSG_GRA_NEU, 2], [MSG_LDW_1, 0]]
|
||||
|
||||
def sign(a):
|
||||
if a > 0:
|
||||
return 1
|
||||
else:
|
||||
return -1
|
||||
|
||||
def volkswagen_pq_checksum(msg, addr, len_msg):
|
||||
msg_bytes = msg.RDLR.to_bytes(4, 'little') + msg.RDHR.to_bytes(4, 'little')
|
||||
msg_bytes = msg_bytes[1:len_msg]
|
||||
|
||||
checksum = 0
|
||||
for i in msg_bytes:
|
||||
checksum ^= i
|
||||
return checksum
|
||||
|
||||
class TestVolkswagenPqSafety(unittest.TestCase):
|
||||
cruise_engaged = False
|
||||
brake_pressed = False
|
||||
cnt_lenkhilfe_3 = 0
|
||||
cnt_hca_1 = 0
|
||||
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_VOLKSWAGEN_PQ, 0)
|
||||
cls.safety.init_tests_volkswagen()
|
||||
|
||||
def _set_prev_torque(self, t):
|
||||
self.safety.set_volkswagen_desired_torque_last(t)
|
||||
self.safety.set_volkswagen_rt_torque_last(t)
|
||||
|
||||
# Wheel speeds (Bremse_3)
|
||||
def _speed_msg(self, speed):
|
||||
wheel_speed_scaled = int(speed / 0.01)
|
||||
to_send = make_msg(0, MSG_BREMSE_3)
|
||||
to_send[0].RDLR = (wheel_speed_scaled | (wheel_speed_scaled << 16)) << 1
|
||||
to_send[0].RDHR = (wheel_speed_scaled | (wheel_speed_scaled << 16)) << 1
|
||||
return to_send
|
||||
|
||||
# Brake light switch (shared message Motor_2)
|
||||
def _brake_msg(self, brake):
|
||||
self.__class__.brake_pressed = brake
|
||||
return self._motor_2_msg()
|
||||
|
||||
# ACC engaged status (shared message Motor_2)
|
||||
def _cruise_msg(self, cruise):
|
||||
self.__class__.cruise_engaged = cruise
|
||||
return self._motor_2_msg()
|
||||
|
||||
# Driver steering input torque
|
||||
def _lenkhilfe_3_msg(self, torque):
|
||||
to_send = make_msg(0, MSG_LENKHILFE_3)
|
||||
t = abs(torque)
|
||||
to_send[0].RDLR = ((t & 0x3FF) << 16)
|
||||
if torque < 0:
|
||||
to_send[0].RDLR |= 0x1 << 26
|
||||
to_send[0].RDLR |= (self.cnt_lenkhilfe_3 % 16) << 12
|
||||
to_send[0].RDLR |= volkswagen_pq_checksum(to_send[0], MSG_LENKHILFE_3, 8)
|
||||
self.__class__.cnt_lenkhilfe_3 += 1
|
||||
return to_send
|
||||
|
||||
# openpilot steering output torque
|
||||
def _hca_1_msg(self, torque):
|
||||
to_send = make_msg(0, MSG_HCA_1)
|
||||
t = abs(torque) << 5 # DBC scale from centi-Nm to PQ network (approximated)
|
||||
to_send[0].RDLR = (t & 0x7FFF) << 16
|
||||
if torque < 0:
|
||||
to_send[0].RDLR |= 0x1 << 31
|
||||
to_send[0].RDLR |= (self.cnt_hca_1 % 16) << 8
|
||||
to_send[0].RDLR |= volkswagen_pq_checksum(to_send[0], MSG_HCA_1, 8)
|
||||
self.__class__.cnt_hca_1 += 1
|
||||
return to_send
|
||||
|
||||
# ACC engagement and brake light switch status
|
||||
# Called indirectly for compatibility with common.py tests
|
||||
def _motor_2_msg(self):
|
||||
to_send = make_msg(0, MSG_MOTOR_2)
|
||||
to_send[0].RDLR = (0x1 << 16) if self.__class__.brake_pressed else 0
|
||||
to_send[0].RDLR |= (self.__class__.cruise_engaged & 0x3) << 22
|
||||
return to_send
|
||||
|
||||
# Driver throttle input
|
||||
def _motor_3_msg(self, gas):
|
||||
to_send = make_msg(0, MSG_MOTOR_3)
|
||||
to_send[0].RDLR = (gas & 0xFF) << 16
|
||||
return to_send
|
||||
|
||||
# Cruise control buttons
|
||||
def _gra_neu_msg(self, bit):
|
||||
to_send = make_msg(2, MSG_GRA_NEU)
|
||||
to_send[0].RDLR = 1 << bit
|
||||
to_send[0].RDLR |= volkswagen_pq_checksum(to_send[0], MSG_GRA_NEU, 8)
|
||||
return to_send
|
||||
|
||||
def test_spam_can_buses(self):
|
||||
StdTest.test_spam_can_buses(self, TX_MSGS)
|
||||
|
||||
def test_relay_malfunction(self):
|
||||
StdTest.test_relay_malfunction(self, MSG_HCA_1)
|
||||
|
||||
def test_prev_gas(self):
|
||||
for g in range(0, 256):
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(g))
|
||||
self.assertEqual(True if g > 0 else False, self.safety.get_gas_pressed_prev())
|
||||
|
||||
def test_default_controls_not_allowed(self):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_enable_control_allowed_from_cruise(self):
|
||||
self.safety.safety_rx_hook(self._brake_msg(False))
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.safety_rx_hook(self._cruise_msg(True))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disable_control_allowed_from_cruise(self):
|
||||
self.safety.safety_rx_hook(self._brake_msg(False))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._cruise_msg(False))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_sample_speed(self):
|
||||
# Stationary
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.assertEqual(0, self.safety.get_volkswagen_moving())
|
||||
# 1 km/h, just under 0.3 m/s safety grace threshold
|
||||
self.safety.safety_rx_hook(self._speed_msg(1))
|
||||
self.assertEqual(0, self.safety.get_volkswagen_moving())
|
||||
# 2 km/h, just over 0.3 m/s safety grace threshold
|
||||
self.safety.safety_rx_hook(self._speed_msg(2))
|
||||
self.assertEqual(1, self.safety.get_volkswagen_moving())
|
||||
# 144 km/h, openpilot V_CRUISE_MAX
|
||||
self.safety.safety_rx_hook(self._speed_msg(144))
|
||||
self.assertEqual(1, self.safety.get_volkswagen_moving())
|
||||
|
||||
def test_prev_brake(self):
|
||||
self.assertFalse(self.safety.get_brake_pressed_prev())
|
||||
self.safety.safety_rx_hook(self._brake_msg(True))
|
||||
self.assertTrue(self.safety.get_brake_pressed_prev())
|
||||
self.safety.safety_rx_hook(self._brake_msg(False))
|
||||
|
||||
def test_brake_disengage(self):
|
||||
self.__class__.cruise_engaged = True # Hack due to brake and ACC signals being in the same message
|
||||
StdTest.test_allow_brake_at_zero_speed(self)
|
||||
StdTest.test_not_allow_brake_when_moving(self, 1)
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(1))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._motor_3_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_steer_safety_check(self):
|
||||
for enabled in [0, 1]:
|
||||
for t in range(-500, 500):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
self._set_prev_torque(t)
|
||||
if abs(t) > MAX_STEER or (not enabled and abs(t) > 0):
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._hca_1_msg(t)))
|
||||
else:
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(t)))
|
||||
|
||||
def test_manually_enable_controls_allowed(self):
|
||||
StdTest.test_manually_enable_controls_allowed(self)
|
||||
|
||||
def test_spam_cancel_safety_check(self):
|
||||
BIT_CANCEL = 9
|
||||
BIT_SET = 16
|
||||
BIT_RESUME = 17
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._gra_neu_msg(BIT_CANCEL)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._gra_neu_msg(BIT_RESUME)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._gra_neu_msg(BIT_SET)))
|
||||
# do not block resume if we are engaged already
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._gra_neu_msg(BIT_RESUME)))
|
||||
|
||||
def test_non_realtime_limit_up(self):
|
||||
self.safety.set_volkswagen_torque_driver(0, 0)
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
self._set_prev_torque(0)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(MAX_RATE_UP)))
|
||||
self._set_prev_torque(0)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(-MAX_RATE_UP)))
|
||||
|
||||
self._set_prev_torque(0)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._hca_1_msg(MAX_RATE_UP + 1)))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._set_prev_torque(0)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._hca_1_msg(-MAX_RATE_UP - 1)))
|
||||
|
||||
def test_non_realtime_limit_down(self):
|
||||
self.safety.set_volkswagen_torque_driver(0, 0)
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
def test_against_torque_driver(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
for sign in [-1, 1]:
|
||||
for t in np.arange(0, DRIVER_TORQUE_ALLOWANCE + 1, 1):
|
||||
t *= -sign
|
||||
self.safety.set_volkswagen_torque_driver(t, t)
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(MAX_STEER * sign)))
|
||||
|
||||
self.safety.set_volkswagen_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._hca_1_msg(-MAX_STEER)))
|
||||
|
||||
# spot check some individual cases
|
||||
for sign in [-1, 1]:
|
||||
driver_torque = (DRIVER_TORQUE_ALLOWANCE + 10) * sign
|
||||
torque_desired = (MAX_STEER - 10 * DRIVER_TORQUE_FACTOR) * sign
|
||||
delta = 1 * sign
|
||||
self._set_prev_torque(torque_desired)
|
||||
self.safety.set_volkswagen_torque_driver(-driver_torque, -driver_torque)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(torque_desired)))
|
||||
self._set_prev_torque(torque_desired + delta)
|
||||
self.safety.set_volkswagen_torque_driver(-driver_torque, -driver_torque)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._hca_1_msg(torque_desired + delta)))
|
||||
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.safety.set_volkswagen_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.safety.set_volkswagen_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(0)))
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.safety.set_volkswagen_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._hca_1_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
|
||||
|
||||
def test_realtime_limits(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
for sign in [-1, 1]:
|
||||
self.safety.init_tests_volkswagen()
|
||||
self._set_prev_torque(0)
|
||||
self.safety.set_volkswagen_torque_driver(0, 0)
|
||||
for t in np.arange(0, MAX_RT_DELTA, 1):
|
||||
t *= sign
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(t)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._hca_1_msg(sign * (MAX_RT_DELTA + 1))))
|
||||
|
||||
self._set_prev_torque(0)
|
||||
for t in np.arange(0, MAX_RT_DELTA, 1):
|
||||
t *= sign
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(t)))
|
||||
|
||||
# Increase timer to update rt_torque_last
|
||||
self.safety.set_timer(RT_INTERVAL + 1)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(sign * (MAX_RT_DELTA - 1))))
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._hca_1_msg(sign * (MAX_RT_DELTA + 1))))
|
||||
|
||||
def test_torque_measurements(self):
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(50))
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(-50))
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
|
||||
self.assertEqual(-50, self.safety.get_volkswagen_torque_driver_min())
|
||||
self.assertEqual(50, self.safety.get_volkswagen_torque_driver_max())
|
||||
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
self.assertEqual(0, self.safety.get_volkswagen_torque_driver_max())
|
||||
self.assertEqual(-50, self.safety.get_volkswagen_torque_driver_min())
|
||||
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
self.assertEqual(0, self.safety.get_volkswagen_torque_driver_max())
|
||||
self.assertEqual(0, self.safety.get_volkswagen_torque_driver_min())
|
||||
|
||||
def test_rx_hook(self):
|
||||
# checksum checks
|
||||
# TODO: Would be ideal to check non-checksum non-counter messages as well,
|
||||
# but I'm not sure if we can easily validate Panda's simple temporal
|
||||
# reception-rate check here.
|
||||
for msg in [MSG_LENKHILFE_3]:
|
||||
self.safety.set_controls_allowed(1)
|
||||
if msg == MSG_LENKHILFE_3:
|
||||
to_push = self._lenkhilfe_3_msg(0)
|
||||
self.assertTrue(self.safety.safety_rx_hook(to_push))
|
||||
to_push[0].RDHR ^= 0xFF
|
||||
self.assertFalse(self.safety.safety_rx_hook(to_push))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# counter
|
||||
# reset wrong_counters to zero by sending valid messages
|
||||
for i in range(MAX_WRONG_COUNTERS + 1):
|
||||
self.__class__.cnt_lenkhilfe_3 += 1
|
||||
if i < MAX_WRONG_COUNTERS:
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
else:
|
||||
self.assertFalse(self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0)))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# restore counters for future tests with a couple of good messages
|
||||
for i in range(2):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._lenkhilfe_3_msg(0))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_fwd_hook(self):
|
||||
buss = list(range(0x0, 0x3))
|
||||
msgs = list(range(0x1, 0x800))
|
||||
blocked_msgs_0to2 = []
|
||||
blocked_msgs_2to0 = [MSG_HCA_1, MSG_LDW_1]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == 0:
|
||||
fwd_bus = -1 if m in blocked_msgs_0to2 else 2
|
||||
elif b == 1:
|
||||
fwd_bus = -1
|
||||
elif b == 2:
|
||||
fwd_bus = -1 if m in blocked_msgs_2to0 else 0
|
||||
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,6 +1,21 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y make clang python python-pip git libarchive-dev libusb-1.0-0 locales curl zlib1g-dev libffi-dev bzip2 libssl-dev libbz2-dev
|
||||
RUN apt-get update && apt-get install -y \
|
||||
bzip2 \
|
||||
clang \
|
||||
curl \
|
||||
git \
|
||||
libarchive-dev \
|
||||
libbz2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libffi-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0 \
|
||||
locales \
|
||||
make \
|
||||
python \
|
||||
python-pip \
|
||||
zlib1g-dev
|
||||
|
||||
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
|
||||
ENV LANG en_US.UTF-8
|
||||
@@ -21,15 +36,11 @@ RUN pip install -r requirements_extra.txt
|
||||
COPY tests/safety_replay/install_capnp.sh install_capnp.sh
|
||||
RUN ./install_capnp.sh
|
||||
|
||||
RUN mkdir /openpilot
|
||||
RUN git clone https://github.com/commaai/openpilot.git || true
|
||||
WORKDIR /openpilot
|
||||
RUN git clone https://github.com/commaai/cereal.git || true
|
||||
WORKDIR /openpilot/cereal
|
||||
RUN git pull
|
||||
RUN git checkout bb2cc7572de99becce1bfbae63f3b38d5464e162
|
||||
RUN git pull && git checkout f9257fc75f68c673f9e433985fbe739f23310bb4
|
||||
RUN git submodule update --init cereal
|
||||
|
||||
COPY . /openpilot/panda
|
||||
|
||||
WORKDIR /openpilot/panda/tests/safety_replay
|
||||
RUN git clone https://github.com/commaai/openpilot-tools.git tools || true
|
||||
WORKDIR tools
|
||||
RUN git checkout d69c6bc85f221766305ec53956e9a1d3bf283160
|
||||
|
||||
@@ -2,3 +2,6 @@ aenum
|
||||
subprocess32
|
||||
libarchive
|
||||
pycapnp
|
||||
pycurl
|
||||
tenacity
|
||||
atomicwrites
|
||||
|
||||
@@ -18,7 +18,8 @@ logs = [
|
||||
("02ec6bea180a4d36|2019-04-17--11-21-35.bz2", Panda.SAFETY_HYUNDAI, 0), # HYUNDAI.SANTA_FE
|
||||
("6fb4948a7ebe670e|2019-11-12--00-35-53.bz2", Panda.SAFETY_CHRYSLER, 0), # CHRYSLER.PACIFICA_2018_HYBRID
|
||||
("791340bc01ed993d|2019-04-08--10-26-00.bz2", Panda.SAFETY_SUBARU, 0), # SUBARU.IMPREZA
|
||||
("76b83eb0245de90e|2020-03-05--19-16-05.bz2", Panda.SAFETY_VOLKSWAGEN_MQB, 0), # VOLKSWAGEN.GOLF
|
||||
("76b83eb0245de90e|2020-03-05--19-16-05.bz2", Panda.SAFETY_VOLKSWAGEN_MQB, 0), # VOLKSWAGEN.GOLF (MK7)
|
||||
("d12cd943127f267b|2020-03-27--15-57-18.bz2", Panda.SAFETY_VOLKSWAGEN_PQ, 0), # 2009 VW Passat R36 (B6), supporting OP port not yet upstreamed
|
||||
("fbbfa6af821552b9|2020-03-03--08-09-43.bz2", Panda.SAFETY_NISSAN, 0), # NISSAN.XTRAIL
|
||||
]
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
|
||||
export HOME=/data/data/com.termux/files/home
|
||||
export PATH=/usr/local/bin:/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/sbin:/data/data/com.termux/files/usr/bin/applets:/bin:/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin:/data/data/com.termux/files/usr/bin/git
|
||||
printf %s "1" > /data/params/d/DragonUpdating
|
||||
cd /data/openpilot && git reset --hard @{u} && git clean -xdf && git pull && scons --clean && reboot
|
||||
@@ -133,6 +133,9 @@ void *safety_setter_thread(void *s) {
|
||||
capnp::FlatArrayMessageReader cmsg(amsg);
|
||||
cereal::CarParams::Reader car_params = cmsg.getRoot<cereal::CarParams>();
|
||||
|
||||
LOGW("setting unsafety mode");
|
||||
libusb_control_transfer(dev_handle, 0x40, 0xdf, 9, 0, NULL, 0, TIMEOUT);
|
||||
|
||||
int safety_model = int(car_params.getSafetyModel());
|
||||
auto safety_param = car_params.getSafetyParam();
|
||||
LOGW("setting safety model: %d with param %d", safety_model, safety_param);
|
||||
|
||||
@@ -44,8 +44,6 @@ class CarInterfaceBase():
|
||||
self.ts_last_check = 0.
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
self.dp_door_check = True
|
||||
self.dp_seatbelt_check = True
|
||||
self.dp_gear_check = True
|
||||
|
||||
@staticmethod
|
||||
@@ -116,8 +114,6 @@ class CarInterfaceBase():
|
||||
self.dragon_toyota_stock_dsu = False
|
||||
if not self.dragon_toyota_stock_dsu:
|
||||
self.dragon_allow_gas = True if params.get("DragonAllowGas", encoding='utf8') == "1" else False
|
||||
self.dp_door_check = False if params.get("DragonEnableDoorCheck", encoding='utf8') == "0" else True
|
||||
self.dp_seatbelt_check = False if params.get("DragonEnableSeatBeltCheck", encoding='utf8') == "0" else True
|
||||
self.dp_gear_check = False if params.get("DragonEnableGearCheck", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
self.ts_last_check = ts
|
||||
@@ -125,9 +121,9 @@ class CarInterfaceBase():
|
||||
def create_common_events(self, cs_out, extra_gears=[], gas_resume_speed=-1):
|
||||
events = []
|
||||
|
||||
if self.dp_door_check and cs_out.doorOpen:
|
||||
if cs_out.doorOpen:
|
||||
events.append(create_event('doorOpen', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
|
||||
if self.dp_seatbelt_check and cs_out.seatbeltUnlatched:
|
||||
if cs_out.seatbeltUnlatched:
|
||||
events.append(create_event('seatbeltNotLatched', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
|
||||
if self.dp_gear_check:
|
||||
if cs_out.gearShifter != GearShifter.drive and cs_out.gearShifter not in extra_gears:
|
||||
|
||||
@@ -136,8 +136,6 @@ class CarState(CarStateBase):
|
||||
enable_acc = False
|
||||
if ret.seatbeltUnlatched or ret.doorOpen:
|
||||
enable_acc = False
|
||||
if ret.brakePressed:
|
||||
enable_acc = False
|
||||
ret.cruiseState.enabled = enable_acc
|
||||
|
||||
return ret
|
||||
|
||||
@@ -77,7 +77,7 @@ def events_to_bytes(events):
|
||||
return ret
|
||||
|
||||
|
||||
def data_sample(CI, CC, sm, can_sock, state, mismatch_counter, can_error_counter, params):
|
||||
def data_sample(CI, CC, sm, can_sock, state, mismatch_counter, can_error_counter, params, dragon_toyota_stock_dsu):
|
||||
"""Receive data from sockets and create events for battery, temperature and disk space"""
|
||||
|
||||
# Update carstate from CAN and create events
|
||||
@@ -131,11 +131,12 @@ def data_sample(CI, CC, sm, can_sock, state, mismatch_counter, can_error_counter
|
||||
if not enabled:
|
||||
mismatch_counter = 0
|
||||
|
||||
controls_allowed = sm['health'].controlsAllowed
|
||||
if not controls_allowed and enabled:
|
||||
mismatch_counter += 1
|
||||
if mismatch_counter >= 200:
|
||||
events.append(create_event('controlsMismatch', [ET.IMMEDIATE_DISABLE]))
|
||||
if not dragon_toyota_stock_dsu:
|
||||
controls_allowed = sm['health'].controlsAllowed
|
||||
if not controls_allowed and enabled:
|
||||
mismatch_counter += 1
|
||||
if mismatch_counter >= 200:
|
||||
events.append(create_event('controlsMismatch', [ET.IMMEDIATE_DISABLE]))
|
||||
|
||||
return CS, events, cal_perc, mismatch_counter, can_error_counter
|
||||
|
||||
@@ -566,7 +567,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None):
|
||||
prof.checkpoint("Ratekeeper", ignore=True)
|
||||
|
||||
# Sample data and compute car events
|
||||
CS, events, cal_perc, mismatch_counter, can_error_counter = data_sample(CI, CC, sm, can_sock, state, mismatch_counter, can_error_counter, params)
|
||||
CS, events, cal_perc, mismatch_counter, can_error_counter = data_sample(CI, CC, sm, can_sock, state, mismatch_counter, can_error_counter, params, dragon_toyota_stock_dsu)
|
||||
prof.checkpoint("Sample")
|
||||
|
||||
# Create alerts
|
||||
|
||||
@@ -10,6 +10,12 @@ from common.params import Params, put_nonblocking
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
from math import floor
|
||||
import re
|
||||
import os
|
||||
|
||||
is_gitee_src = "gitee" in subprocess.check_output(["git", "-C", "/data/openpilot", "config", "--get", "remote.origin.url"]).decode('utf8').rstrip()
|
||||
is_offline = subprocess.call(["ping", "-W", "4", "-c", "1", "117.28.245.92"])
|
||||
auto_update = params.get("DragonAppAutoUpdate", encoding='utf8') == "1"
|
||||
|
||||
class App():
|
||||
|
||||
@@ -56,19 +62,93 @@ class App():
|
||||
# app options
|
||||
self.opts = opts
|
||||
|
||||
self.is_enabled = False
|
||||
self.is_installed = False
|
||||
self.is_enabled = True if params.get(self.enable_param, encoding='utf8') == "1" else False
|
||||
self.last_is_enabled = False
|
||||
self.is_auto_runnable = False
|
||||
self.is_running = False
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
self.manually_ctrled = False
|
||||
|
||||
self.set_package_permissions()
|
||||
self.system("pm disable %s" % self.app)
|
||||
if self.is_enabled:
|
||||
local_version = self.get_local_version()
|
||||
if local_version is not None:
|
||||
self.is_installed = True
|
||||
|
||||
if not is_offline:
|
||||
remote_version = local_version
|
||||
if local_version is not None and auto_update:
|
||||
remote_version = self.get_remote_version()
|
||||
if local_version is None or (remote_version is not None and local_version != remote_version):
|
||||
self.update_app()
|
||||
if self.is_installed:
|
||||
self.set_package_permissions()
|
||||
else:
|
||||
self.uninstall_app()
|
||||
|
||||
if self.manual_ctrl_param is not None:
|
||||
put_nonblocking(self.manual_ctrl_param, '0')
|
||||
self.last_ts = sec_since_boot()
|
||||
|
||||
def get_remote_version(self):
|
||||
apk = self.app + ".apk"
|
||||
try:
|
||||
if is_gitee_src:
|
||||
url = "https://gitee.com/dragonpilot/apps/raw/%s/VERSION" % apk
|
||||
else:
|
||||
url = "https://raw.githubusercontent.com/dragonpilot-community/apps/%s/VERSION" % apk
|
||||
return subprocess.check_output(["curl", "-H", "'Cache-Control: no-cache'", "-s", url], stderr=subprocess.STDOUT, shell=True).decode('utf8').rstrip()
|
||||
except subprocess.CalledProcessError as e:
|
||||
pass
|
||||
return None
|
||||
|
||||
def uninstall_app(self):
|
||||
try:
|
||||
local_version = self.get_local_version()
|
||||
if local_version is not None:
|
||||
subprocess.check_output(["pm","uninstall", self.app])
|
||||
self.is_installed = False
|
||||
except subprocess.CalledProcessError as e:
|
||||
pass
|
||||
|
||||
def update_app(self):
|
||||
apk = self.app + ".apk"
|
||||
apk_path = "/sdcard/" + apk
|
||||
try:
|
||||
os.remove(apk_path)
|
||||
except (OSError, FileNotFoundError) as e:
|
||||
pass
|
||||
|
||||
self.uninstall_app()
|
||||
# if local_version is not None:
|
||||
# try:
|
||||
# subprocess.check_output(["pm","uninstall", self.app], stderr=subprocess.STDOUT, shell=True)
|
||||
# except subprocess.CalledProcessError as e:
|
||||
# pass
|
||||
try:
|
||||
put_nonblocking('DragonUpdating', '1')
|
||||
url = "https://raw.githubusercontent.com/dragonpilot-community/apps/%s/%s" % (apk, apk)
|
||||
subprocess.check_output(["curl","-o", apk_path,"-LJO", url])
|
||||
subprocess.check_output(["pm","install","-r",apk_path])
|
||||
self.is_installed = True
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.is_installed = False
|
||||
put_nonblocking('DragonUpdating', '0')
|
||||
try:
|
||||
os.remove(apk_path)
|
||||
except (OSError, FileNotFoundError) as e:
|
||||
pass
|
||||
|
||||
def get_local_version(self):
|
||||
try:
|
||||
result = subprocess.check_output(["dumpsys", "package", self.app, "|", "grep", "versionName"], encoding='utf8')
|
||||
if len(result) > 12:
|
||||
return re.findall(r"versionName=(.*)", result)[0]
|
||||
except subprocess.CalledProcessError as e:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def read_params(self):
|
||||
self.last_is_enabled = self.is_enabled
|
||||
if self.enable_param is None:
|
||||
@@ -76,29 +156,35 @@ class App():
|
||||
else:
|
||||
self.is_enabled = True if params.get(self.enable_param, encoding='utf8') == "1" else False
|
||||
|
||||
if self.is_enabled:
|
||||
# a service app should run automatically and not manual controllable.
|
||||
if self.app_type in [App.TYPE_SERVICE, App.TYPE_GPS_SERVICE]:
|
||||
self.is_auto_runnable = True
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
else:
|
||||
if self.manual_ctrl_param is None:
|
||||
if self.is_installed:
|
||||
if self.is_enabled:
|
||||
# a service app should run automatically and not manual controllable.
|
||||
if self.app_type in [App.TYPE_SERVICE, App.TYPE_GPS_SERVICE]:
|
||||
self.is_auto_runnable = True
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
else:
|
||||
self.manual_ctrl_status = params.get(self.manual_ctrl_param, encoding='utf8')
|
||||
|
||||
if self.manual_ctrl_status == self.MANUAL_IDLE:
|
||||
if self.auto_run_param is None:
|
||||
self.is_auto_runnable = False
|
||||
if self.manual_ctrl_param is None:
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
else:
|
||||
self.is_auto_runnable = True if params.get(self.auto_run_param, encoding='utf8') == "1" else False
|
||||
self.manual_ctrl_status = params.get(self.manual_ctrl_param, encoding='utf8')
|
||||
|
||||
if self.manual_ctrl_status == self.MANUAL_IDLE:
|
||||
if self.auto_run_param is None:
|
||||
self.is_auto_runnable = False
|
||||
else:
|
||||
self.is_auto_runnable = True if params.get(self.auto_run_param, encoding='utf8') == "1" else False
|
||||
else:
|
||||
if self.last_is_enabled:
|
||||
self.uninstall_app()
|
||||
self.is_auto_runnable = False
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
self.manually_ctrled = False
|
||||
else:
|
||||
self.is_auto_runnable = False
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
self.manually_ctrled = False
|
||||
if not self.last_is_enabled and self.is_enabled:
|
||||
self.update_app()
|
||||
|
||||
def run(self, force = False):
|
||||
if force or self.is_enabled:
|
||||
if self.is_installed and (force or self.is_enabled):
|
||||
# app is manually ctrl, we record that
|
||||
if self.manual_ctrl_param is not None and self.manual_ctrl_status == self.MANUAL_ON:
|
||||
put_nonblocking(self.manual_ctrl_param, '0')
|
||||
@@ -120,7 +206,7 @@ class App():
|
||||
self.is_running = True
|
||||
|
||||
def kill(self, force = False):
|
||||
if force or self.is_enabled:
|
||||
if self.is_installed and (force or self.is_enabled):
|
||||
# app is manually ctrl, we record that
|
||||
if self.manual_ctrl_param is not None and self.manual_ctrl_status == self.MANUAL_OFF:
|
||||
put_nonblocking(self.manual_ctrl_param, '0')
|
||||
@@ -156,7 +242,19 @@ def init_apps(apps):
|
||||
[],
|
||||
))
|
||||
apps.append(App(
|
||||
# v1.16.2
|
||||
"com.mixplorer",
|
||||
"com.mixplorer.activities.BrowseActivity",
|
||||
"DragonEnableMixplorer",
|
||||
None,
|
||||
"DragonRunMixplorer",
|
||||
App.TYPE_UTIL,
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[],
|
||||
))
|
||||
apps.append(App(
|
||||
"com.tomtom.speedcams.android.map",
|
||||
"com.tomtom.speedcams.android.activities.SpeedCamActivity",
|
||||
"DragonEnableTomTom",
|
||||
@@ -174,7 +272,22 @@ def init_apps(apps):
|
||||
]
|
||||
))
|
||||
apps.append(App(
|
||||
# v4.5.0.600053
|
||||
"tw.com.ainvest.outpack",
|
||||
"tw.com.ainvest.outpack.ui.MainActivity",
|
||||
"DragonEnableAegis",
|
||||
"DragonBootAegis",
|
||||
"DragonRunAegis",
|
||||
App.TYPE_GPS,
|
||||
[
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[
|
||||
"SYSTEM_ALERT_WINDOW",
|
||||
]
|
||||
))
|
||||
apps.append(App(
|
||||
"com.autonavi.amapauto",
|
||||
"com.autonavi.amapauto.MainMapActivity",
|
||||
"DragonEnableAutonavi",
|
||||
@@ -192,38 +305,6 @@ def init_apps(apps):
|
||||
]
|
||||
))
|
||||
apps.append(App(
|
||||
# v6.40.3
|
||||
"com.mixplorer",
|
||||
"com.mixplorer.activities.BrowseActivity",
|
||||
"DragonEnableMixplorer",
|
||||
None,
|
||||
"DragonRunMixplorer",
|
||||
App.TYPE_UTIL,
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[],
|
||||
))
|
||||
apps.append(App(
|
||||
# v2.9.5 build 74
|
||||
"tw.com.ainvest.outpack",
|
||||
"tw.com.ainvest.outpack.ui.MainActivity",
|
||||
"DragonEnableAegis",
|
||||
"DragonBootAegis",
|
||||
"DragonRunAegis",
|
||||
App.TYPE_GPS,
|
||||
[
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[
|
||||
"SYSTEM_ALERT_WINDOW",
|
||||
]
|
||||
))
|
||||
apps.append(App(
|
||||
# v4.57.2.0
|
||||
"com.waze",
|
||||
"com.waze.MainActivity",
|
||||
"DragonWazeMode",
|
||||
@@ -267,11 +348,11 @@ def main():
|
||||
last_modified = None
|
||||
|
||||
while 1: #has_enabled_apps:
|
||||
if not init_done and sec_since_boot() - start_ts >= 10:
|
||||
init_apps(apps)
|
||||
init_done = True
|
||||
|
||||
if init_done:
|
||||
if not init_done:
|
||||
if sec_since_boot() - start_ts >= 10:
|
||||
init_apps(apps)
|
||||
init_done = True
|
||||
else:
|
||||
enabled_apps = []
|
||||
has_fullscreen_apps = False
|
||||
modified = dp_get_last_modified()
|
||||
@@ -354,7 +435,7 @@ def main():
|
||||
|
||||
last_started = started
|
||||
frame += 3
|
||||
time.sleep(3)
|
||||
time.sleep(3)
|
||||
|
||||
def system(cmd):
|
||||
try:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
from common.params import Params, put_nonblocking
|
||||
import time
|
||||
from math import floor
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
default_conf = {
|
||||
'DragonEnableDashcam': '0',
|
||||
@@ -72,12 +74,12 @@ default_conf = {
|
||||
'DragonLastModified': str(floor(time.time())),
|
||||
'DragonEnableRegistration': '1',
|
||||
'DragonDynamicFollow': '-2', # OFF = -2, LONG = -1, NORMAL = 0, SHORT = 1
|
||||
'DragonEnableDoorCheck': '1',
|
||||
'DragonEnableSeatBeltCheck': '1',
|
||||
'DragonEnableGearCheck': '1',
|
||||
'DragonEnableTempMonitor': '1',
|
||||
'DragonEnableCurvatureLearner': '0',
|
||||
'DragonCurvatureLearnerOffset': '0.0',
|
||||
'DragonAppAutoUpdate': '1',
|
||||
'DragonUpdating': '0',
|
||||
}
|
||||
|
||||
deprecated_conf = {
|
||||
@@ -94,7 +96,15 @@ deprecated_conf_invert = {
|
||||
def dp_get_last_modified():
|
||||
return Params().get('DragonLastModified', encoding='utf-8')
|
||||
|
||||
def run_patcher():
|
||||
if os.path.isfile("/sdcard/dp_patcher.py"):
|
||||
try:
|
||||
subprocess.call(["python", "/sdcard/dp_patcher.py"])
|
||||
except subprocess.CalledProcessError as e:
|
||||
pass
|
||||
|
||||
def dragonpilot_set_params(params):
|
||||
run_patcher()
|
||||
# # remove deprecated params
|
||||
# for old, new in deprecated_conf.items():
|
||||
# if params.get(old) is not None:
|
||||
|
||||
@@ -42,6 +42,26 @@ static void ui_draw_sidebar_home_button(UIState *s, bool hasSidebar) {
|
||||
nvgRect(s->vg, home_btn_xr, home_btn_y, home_btn_w, home_btn_h);
|
||||
nvgFillPaint(s->vg, imgPaint);
|
||||
nvgFill(s->vg);
|
||||
|
||||
if (s->dragon_updating) {
|
||||
nvgBeginPath(s->vg);
|
||||
nvgCircle(s->vg, home_btn_xr + home_btn_w/2, home_btn_y + home_btn_h/2+2, 72);
|
||||
// nvgRoundedRect(s->vg, home_btn_xr, home_btn_y + home_btn_h/2-5, home_btn_w, 20, 5);
|
||||
nvgFillColor(s->vg, nvgRGBA(255, 255, 255, s->scene.alert_rate));
|
||||
nvgFill(s->vg);
|
||||
|
||||
nvgFillColor(s->vg, nvgRGBA(0, 0, 0, s->scene.alert_rate));
|
||||
nvgFontSize(s->vg, 30);
|
||||
nvgFontFace(s->vg, "sans-bold");
|
||||
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
|
||||
nvgTextBox(s->vg, home_btn_xr, home_btn_y + home_btn_h/2+5, home_btn_w, "UPDATING", NULL);
|
||||
|
||||
s->scene.alert_rate += 5*s->scene.alert_type;
|
||||
|
||||
if (s->scene.alert_rate == 0 || s->scene.alert_rate == 255) {
|
||||
s->scene.alert_type *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_draw_sidebar_network_strength(UIState *s, bool hasSidebar) {
|
||||
|
||||
+5
-1
@@ -248,6 +248,7 @@ static void ui_init_vision(UIState *s, const VisionStreamBufs back_bufs,
|
||||
// dragonpilot
|
||||
read_param_float(&s->dragon_ui_volume_boost, "DragonUIVolumeBoost");
|
||||
read_param_bool(&s->dragon_waze_mode, "DragonWazeMode");
|
||||
read_param_bool(&s->dragon_updating, "DragonUpdating");
|
||||
if (s->dragon_waze_mode) {
|
||||
s->dragon_ui_speed = false;
|
||||
s->dragon_ui_event = false;
|
||||
@@ -300,6 +301,7 @@ static void ui_init_vision(UIState *s, const VisionStreamBufs back_bufs,
|
||||
s->dragon_ui_blinker_timeout = UI_FREQ * 6.3;
|
||||
s->dragon_waze_mode_timeout = UI_FREQ * 6.4;
|
||||
s->dragon_ui_dm_view_timeout = UI_FREQ * 6.5;
|
||||
s->dragon_updating_timeout = UI_FREQ * 10;
|
||||
}
|
||||
|
||||
static PathData read_path(cereal_ModelData_PathData_ptr pathp) {
|
||||
@@ -960,7 +962,8 @@ int main(int argc, char* argv[]) {
|
||||
int draws = 0;
|
||||
|
||||
s->scene.satelliteCount = -1;
|
||||
|
||||
s->scene.alert_rate = 0;
|
||||
s->scene.alert_type = 1;
|
||||
while (!do_exit) {
|
||||
bool should_swap = false;
|
||||
if (!s->vision_connected) {
|
||||
@@ -1090,6 +1093,7 @@ int main(int argc, char* argv[]) {
|
||||
// dragonpilot
|
||||
read_param_float_timeout(&s->dragon_ui_volume_boost, "DragonUIVolumeBoost", &s->dragon_ui_volume_boost_timeout);
|
||||
read_param_bool_timeout(&s->dragon_waze_mode, "DragonWazeMode", &s->dragon_waze_mode_timeout);
|
||||
read_param_bool_timeout(&s->dragon_updating, "DragonUpdating", &s->dragon_updating_timeout);
|
||||
|
||||
if (s->dragon_waze_mode) {
|
||||
s->dragon_ui_speed = false;
|
||||
|
||||
@@ -162,6 +162,8 @@ typedef struct UIScene {
|
||||
float angleSteersDes;
|
||||
float angleSteers;
|
||||
char ipAddr[20];
|
||||
int alert_rate;
|
||||
int alert_type;
|
||||
|
||||
// for blinker, from kegman
|
||||
bool leftBlinker;
|
||||
@@ -315,6 +317,7 @@ typedef struct UIState {
|
||||
int dragon_ui_blinker_timeout;
|
||||
int dragon_waze_mode_timeout;
|
||||
int dragon_ui_dm_view_timeout;
|
||||
int dragon_updating_timeout;
|
||||
|
||||
bool dragon_ui_speed;
|
||||
bool dragon_ui_event;
|
||||
@@ -331,6 +334,7 @@ typedef struct UIState {
|
||||
bool dragon_ui_blinker;
|
||||
bool dragon_waze_mode;
|
||||
bool dragon_ui_dm_view;
|
||||
bool dragon_updating;
|
||||
} UIState;
|
||||
|
||||
// API
|
||||
|
||||
@@ -4,5 +4,5 @@ export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
|
||||
export HOME=/data/data/com.termux/files/home
|
||||
export PATH=/usr/local/bin:/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/sbin:/data/data/com.termux/files/usr/bin/applets:/bin:/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin:/data/data/com.termux/files/usr/bin/python
|
||||
export PYTHONPATH=/data/openpilot
|
||||
|
||||
printf %s "1" > /data/params/d/DragonUpdating
|
||||
cd /data/openpilot/panda ; pkill -f boardd ; python -c "from panda import Panda; Panda().flash()" && reboot
|
||||
Reference in New Issue
Block a user