mirror of
https://github.com/infiniteCable2/opendbc.git
synced 2026-02-18 13:03:52 +08:00
Merge branch 'upstream/opendbc/master' into sync-20250529-new
# Conflicts: # .github/workflows/tests.yml # opendbc/car/car_helpers.py # opendbc/car/docs.py # opendbc/car/tests/test_car_interfaces.py # opendbc/safety/modes/chrysler.h # opendbc/safety/modes/ford.h # opendbc/safety/modes/hyundai.h # opendbc/safety/modes/nissan.h # opendbc/safety/modes/subaru.h # opendbc/safety/modes/tesla.h # opendbc/safety/modes/toyota.h
This commit is contained in:
9
.github/workflows/cache/action.yaml
vendored
Normal file
9
.github/workflows/cache/action.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
name: 'Restore cache'
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Restore cached cppcheck
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: opendbc/safety/tests/misra/cppcheck/
|
||||
key: cppcheck-cache-${{ runner.os }}-${{ hashFiles('opendbc/safety/tests/misra/install.sh') }}
|
||||
60
.github/workflows/tests.yml
vendored
60
.github/workflows/tests.yml
vendored
@@ -16,63 +16,18 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- os: ${{ github.repository == 'commaai/opendbc' && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
||||
flags: ''
|
||||
- os: ${{ github.repository == 'commaai/opendbc' && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
|
||||
flags: '--ubsan'
|
||||
- os: ${{ github.repository == 'commaai/opendbc' && 'namespace-profile-macos-8x14' || 'macos-latest' }}
|
||||
flags: ''
|
||||
steps:
|
||||
- uses: commaai/timeout@v1
|
||||
with:
|
||||
timeout: '240'
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore cached cppcheck
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: opendbc/safety/tests/misra/cppcheck/
|
||||
key: cppcheck-cache-${{ runner.os }}-${{ hashFiles('opendbc/safety/tests/misra/install.sh') }}
|
||||
- run: ./test.sh
|
||||
- name: Save cppcheck cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: opendbc/safety/tests/misra/cppcheck/
|
||||
key: cppcheck-cache-${{ runner.os }}-${{ hashFiles('opendbc/safety/tests/misra/install.sh') }}
|
||||
|
||||
safety_tests:
|
||||
name: safety
|
||||
runs-on: ${{ github.repository == 'commaai/opendbc' && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flags: ['--ubsan']
|
||||
steps:
|
||||
- uses: commaai/timeout@v1
|
||||
with:
|
||||
timeout: '240'
|
||||
timeout: ${{ github.repository == 'commaai/opendbc' && '60' || '999' }}
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run safety tests
|
||||
run: ./opendbc/safety/tests/test.sh ${{ matrix.flags }}
|
||||
|
||||
misra_mutation:
|
||||
name: MISRA C:2012 Mutation
|
||||
runs-on: ${{ github.repository == 'commaai/opendbc' && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore cached cppcheck
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: opendbc/safety/tests/misra/cppcheck/
|
||||
key: cppcheck-cache-${{ runner.os }}-${{ hashFiles('opendbc/safety/tests/misra/install.sh') }}
|
||||
- name: MISRA mutation tests
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
source setup.sh
|
||||
scons -j8
|
||||
cd opendbc/safety/tests/misra
|
||||
./install.sh # cppcheck
|
||||
pytest -s -n8 --randomly-seed $RANDOM test_mutation.py
|
||||
- name: Save cppcheck cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: opendbc/safety/tests/misra/cppcheck/
|
||||
key: cppcheck-cache-${{ runner.os }}-${{ hashFiles('opendbc/safety/tests/misra/install.sh') }}
|
||||
- uses: ./.github/workflows/cache
|
||||
- run: ./test.sh ${{ matrix.flags }}
|
||||
|
||||
mutation:
|
||||
name: Safety mutation tests
|
||||
@@ -84,6 +39,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # need master to get diff
|
||||
- uses: ./.github/workflows/cache
|
||||
- name: Run mutation tests
|
||||
timeout-minutes: 60
|
||||
run: |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# pytest attempts to execute shell scripts while collecting
|
||||
collect_ignore_glob = [
|
||||
"opendbc/safety/tests/misra/*",
|
||||
"opendbc/safety/tests/misra/*.sh",
|
||||
"opendbc/safety/tests/misra/cppcheck/",
|
||||
]
|
||||
|
||||
@@ -4,7 +4,7 @@ output:
|
||||
- empty_summary # Print summary heading when there are no steps to run
|
||||
- success # Print successful steps
|
||||
- failure # Print failed steps printing
|
||||
#- execution # Print any execution logs
|
||||
- execution # Print any execution logs
|
||||
#- execution_out # Print execution output
|
||||
#- execution_info # Print `EXECUTE > ...` logging
|
||||
- skips # Print "skip" (i.e. no files matched)
|
||||
|
||||
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.notCar = True
|
||||
ret.brand = "body"
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.body)]
|
||||
|
||||
@@ -152,7 +152,7 @@ def fingerprint(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_mu
|
||||
|
||||
|
||||
def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, alpha_long_allowed: bool,
|
||||
num_pandas: int = 1, cached_params: CarParamsT | None = None, fixed_fingerprint: str | None = None):
|
||||
is_release: bool, num_pandas: int = 1, cached_params: CarParamsT | None = None, fixed_fingerprint: str | None = None):
|
||||
candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params,
|
||||
fixed_fingerprint)
|
||||
|
||||
@@ -161,7 +161,7 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip
|
||||
candidate = "MOCK"
|
||||
|
||||
CarInterface = interfaces[candidate]
|
||||
CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, docs=False)
|
||||
CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, docs=False)
|
||||
CP.carVin = vin
|
||||
CP.carFw = car_fw
|
||||
CP.fingerprintSource = source
|
||||
|
||||
@@ -13,7 +13,7 @@ class CarInterface(CarInterfaceBase):
|
||||
RadarInterface = RadarInterface
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "chrysler"
|
||||
ret.dashcamOnly = candidate in RAM_HD
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ def get_params_for_docs(platform) -> tuple[CarParams, CarParamsSP]:
|
||||
cp_platform = platform if platform in interfaces else MOCK.MOCK
|
||||
CP: CarParams = interfaces[cp_platform].get_params(cp_platform, fingerprint=gen_empty_fingerprint(),
|
||||
car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)],
|
||||
alpha_long=True, docs=True)
|
||||
alpha_long=True, is_release=False, docs=True)
|
||||
|
||||
CP_SP: CarParamsSP = interfaces[cp_platform].get_params_sp(CP, cp_platform, fingerprint=gen_empty_fingerprint(),
|
||||
car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)],
|
||||
|
||||
@@ -26,7 +26,7 @@ class CarInterface(CarInterfaceBase):
|
||||
return CarControllerParams.ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS)
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "ford"
|
||||
|
||||
ret.radarUnavailable = Bus.radar not in DBC[candidate]
|
||||
|
||||
@@ -85,7 +85,7 @@ class CarInterface(CarInterfaceBase):
|
||||
return self.torque_from_lateral_accel_linear
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "gm"
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.gm)]
|
||||
ret.autoResumeSng = False
|
||||
|
||||
@@ -31,7 +31,7 @@ class CarInterface(CarInterfaceBase):
|
||||
return CarControllerParams.NIDEC_ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS)
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "honda"
|
||||
|
||||
CAN = CanBus(ret, fingerprint)
|
||||
|
||||
@@ -27,7 +27,7 @@ class CarInterface(CarInterfaceBase):
|
||||
RadarInterface = RadarInterface
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "hyundai"
|
||||
|
||||
cam_can = CanBus(None, fingerprint).CAM
|
||||
|
||||
@@ -51,7 +51,7 @@ class TestHyundaiFingerprint:
|
||||
if lka_steering:
|
||||
cam_can = CanBus(None, fingerprint).CAM
|
||||
fingerprint[cam_can] = [0x50, 0x110] # LKA steering messages
|
||||
CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False)
|
||||
CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False)
|
||||
assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEERING) == lka_steering
|
||||
|
||||
# radar available
|
||||
@@ -59,14 +59,14 @@ class TestHyundaiFingerprint:
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if radar:
|
||||
fingerprint[1][RADAR_START_ADDR] = 8
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False)
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False)
|
||||
assert CP.radarUnavailable != radar
|
||||
|
||||
def test_alternate_limits(self):
|
||||
# Alternate lateral control limits, for high torque cars, verify Panda safety mode flag is set
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
for car_model in CAR:
|
||||
CP = CarInterface.get_params(car_model, fingerprint, [], False, False)
|
||||
CP = CarInterface.get_params(car_model, fingerprint, [], False, False, False)
|
||||
assert bool(CP.flags & HyundaiFlags.ALT_LIMITS) == bool(CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.ALT_LIMITS)
|
||||
|
||||
def test_can_features(self):
|
||||
|
||||
@@ -138,7 +138,7 @@ class CarInterfaceBase(ABC):
|
||||
"""
|
||||
Parameters essential to controlling the car may be incomplete or wrong without FW versions or fingerprints.
|
||||
"""
|
||||
return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False)
|
||||
return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False, False)
|
||||
|
||||
@classmethod
|
||||
def get_non_essential_params_sp(cls, car_params, candidate: str) -> structs.CarParamsSP:
|
||||
@@ -146,7 +146,7 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
@classmethod
|
||||
def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_fw: list[structs.CarParams.CarFw],
|
||||
alpha_long: bool, docs: bool) -> structs.CarParams:
|
||||
alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams:
|
||||
ret = CarInterfaceBase.get_std_params(candidate)
|
||||
|
||||
platform = PLATFORMS[candidate]
|
||||
@@ -159,7 +159,7 @@ class CarInterfaceBase(ABC):
|
||||
ret.tireStiffnessFactor = platform.config.specs.tireStiffnessFactor
|
||||
ret.flags |= int(platform.config.flags)
|
||||
|
||||
ret = cls._get_params(ret, candidate, fingerprint, car_fw, alpha_long, docs)
|
||||
ret = cls._get_params(ret, candidate, fingerprint, car_fw, alpha_long, is_release, docs)
|
||||
|
||||
# Vehicle mass is published curb weight plus assumed payload such as a human driver; notCars have no assumed payload
|
||||
if not ret.notCar:
|
||||
@@ -181,7 +181,7 @@ class CarInterfaceBase(ABC):
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint: dict[int, dict[int, int]],
|
||||
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, docs: bool) -> structs.CarParams:
|
||||
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams:
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -12,7 +12,7 @@ class CarInterface(CarInterfaceBase):
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "mazda"
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.mazda)]
|
||||
ret.radarUnavailable = True
|
||||
|
||||
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "mock"
|
||||
ret.mass = 1700.
|
||||
ret.wheelbase = 2.70
|
||||
|
||||
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "nissan"
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.nissan)]
|
||||
ret.autoResumeSng = False
|
||||
|
||||
@@ -13,7 +13,7 @@ class PandaRunner(AbstractContextManager):
|
||||
|
||||
# setup + fingerprinting
|
||||
self.p.set_safety_mode(CarParams.SafetyModel.elm327, 1)
|
||||
self.CI = get_car(self._can_recv, self.p.can_send_many, self.p.set_obd, True)
|
||||
self.CI = get_car(self._can_recv, self.p.can_send_many, self.p.set_obd, True, False)
|
||||
assert self.CI.CP.carFingerprint.lower() != "mock", "Unable to identify car. Check connections and ensure car is supported."
|
||||
|
||||
safety_model = self.CI.CP.safetyConfigs[0].safetyModel
|
||||
|
||||
@@ -54,7 +54,7 @@ class CarState(CarStateBase):
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
ret.cruiseState.speed = -1
|
||||
ret.cruiseState.available = True # cp.vl["VDM_AdasSts"]["VDM_AdasInterfaceStatus"] == 1
|
||||
ret.cruiseState.standstill = cp.vl["VDM_AdasSts"]["VDM_AdasAccelRequestAcknowledged"] == 1
|
||||
ret.cruiseState.standstill = cp.vl["VDM_AdasSts"]["VDM_AdasVehicleHoldStatus"] == 1
|
||||
|
||||
# TODO: log ACM_Unkown2=3 as a fault. need to filter it at the start and end of routes though
|
||||
# ACM_FaultStatus hasn't been seen yet
|
||||
|
||||
@@ -12,7 +12,7 @@ class CarInterface(CarInterfaceBase):
|
||||
RadarInterface = RadarInterface
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "rivian"
|
||||
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.rivian)]
|
||||
|
||||
@@ -85,10 +85,10 @@ def create_adas_status(packer, vdm_adas_status, interface_status):
|
||||
"VDM_AdasFaultStatus",
|
||||
"VDM_AdasAccelLimit",
|
||||
"VDM_AdasDriverModeStatus",
|
||||
"VDM_AdasAccelRequest",
|
||||
"VDM_AdasUnkown1",
|
||||
"VDM_AdasInterfaceStatus",
|
||||
"VDM_AdasAccelRequestAcknowledged",
|
||||
"VDM_AdasVehicleHoldStatus",
|
||||
"VDM_UserAdasRequest",
|
||||
)}
|
||||
|
||||
if interface_status is not None:
|
||||
|
||||
@@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase):
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "subaru"
|
||||
ret.radarUnavailable = True
|
||||
# for HYBRID CARS to be upstreamed, we need:
|
||||
|
||||
@@ -31,6 +31,7 @@ FW_VERSIONS = {
|
||||
b'TeMYG4_Legacy3Y_0.0.0 (2),Y4003.02.0',
|
||||
b'TeMYG4_Legacy3Y_0.0.0 (5),Y4003.03.2',
|
||||
b'TeMYG4_Legacy3Y_0.0.0 (2),Y4P003.02.0',
|
||||
b'TeMYG4_SingleECU_0.0.0 (28),Y4S002.23.0',
|
||||
b'TeMYG4_SingleECU_0.0.0 (33),Y4S002.26',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase):
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "tesla"
|
||||
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.tesla)]
|
||||
|
||||
@@ -59,7 +59,7 @@ class TestCarInterfaces:
|
||||
args = get_fuzzy_car_interface_args(data.draw)
|
||||
|
||||
car_params = CarInterface.get_params(car_name, args['fingerprints'], args['car_fw'],
|
||||
alpha_long=args['alpha_long'], docs=False)
|
||||
alpha_long=args['alpha_long'], is_release=False, docs=False)
|
||||
car_params_sp = CarInterface.get_params_sp(car_params, car_name, args['fingerprints'], args['car_fw'],
|
||||
alpha_long=args['alpha_long'], docs=False)
|
||||
car_interface = CarInterface(car_params, car_params_sp)
|
||||
|
||||
@@ -22,7 +22,7 @@ class CarInterface(CarInterfaceBase):
|
||||
return CarControllerParams(CP).ACCEL_MIN, CarControllerParams(CP).ACCEL_MAX
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "toyota"
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.toyota)]
|
||||
ret.safetyConfigs[0].safetyParam = EPS_SCALE[candidate]
|
||||
@@ -34,6 +34,7 @@ class CarInterface(CarInterfaceBase):
|
||||
if ret.flags & ToyotaFlags.SECOC.value:
|
||||
ret.secOcRequired = True
|
||||
ret.safetyConfigs[0].safetyParam |= ToyotaSafetyFlags.SECOC.value
|
||||
ret.dashcamOnly = is_release
|
||||
|
||||
if candidate in ANGLE_CONTROL_CAR:
|
||||
ret.steerControlType = SteerControlType.angle
|
||||
|
||||
@@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase):
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, docs) -> structs.CarParams:
|
||||
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "volkswagen"
|
||||
ret.radarUnavailable = True
|
||||
|
||||
|
||||
@@ -182,15 +182,15 @@ BO_ 352 ACM_longitudinalRequest: 5 ACM
|
||||
BO_ 354 VDM_AdasSts: 8 VDM
|
||||
SG_ VDM_AdasStatus_Checksum : 7|8@0+ (1,0) [0|0] "" ACM
|
||||
SG_ VDM_AdasStatus_Counter : 11|4@0+ (1,0) [0|0] "" ACM
|
||||
SG_ VDM_AdasDecelLimit : 17|10@0+ (0.01,0) [0|10.23] "m/s^2" ACM
|
||||
SG_ VDM_AdasDecelLimit : 17|10@0+ (0.01,0) [0|-10.23] "m/s^2" ACM
|
||||
SG_ VDM_AdasDriverAccelPriorityStatus : 19|2@0+ (1,0) [0|3] "" ACM
|
||||
SG_ VDM_AdasFaultStatus : 23|4@0+ (1,0) [0|15] "" ACM
|
||||
SG_ VDM_AdasAccelLimit : 33|10@0+ (0.01,0) [0|10.23] "m/s^2" ACM
|
||||
SG_ VDM_AdasDriverModeStatus : 36|3@0+ (1,0) [0|7] "" ACM
|
||||
SG_ VDM_AdasAccelRequest : 50|11@0+ (0.01,-10.24) [-10.24|10.23] "m/s^2" ACM
|
||||
SG_ VDM_AdasUnkown1 : 50|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ VDM_AdasInterfaceStatus : 52|2@0+ (1,0) [0|3] "" ACM
|
||||
SG_ VDM_AdasAccelRequestAcknowledged : 54|2@0+ (1,0) [0|3] "" ACM
|
||||
SG_ VDM_AdasVehicleHoldStatus : 55|1@0+ (1,0) [0|1] "" ACM
|
||||
SG_ VDM_AdasVehicleHoldStatus : 55|3@0+ (1,0) [0|7] "" ACM
|
||||
SG_ VDM_UserAdasRequest : 58|3@0+ (1,0) [0|7] "" ACM
|
||||
|
||||
BO_ 357 VDM_AdasStalk: 4 VDM
|
||||
SG_ VDM_AdasStalk_Checksum : 7|8@0+ (1,0) [0|255] "Unitless" ACM
|
||||
@@ -615,7 +615,6 @@ CM_ SG_ 354 VDM_AdasStatus_Checksum "VDM_AdasSts message j1850 checksum.";
|
||||
CM_ SG_ 354 VDM_AdasStatus_Counter "VDM_AdasSts message counter.";
|
||||
CM_ SG_ 354 VDM_AdasFaultStatus "Fault status of ADAS requests from VDM.";
|
||||
CM_ SG_ 354 VDM_AdasDriverModeStatus "Signal which describes who is commanding the torque - Human or ADAS";
|
||||
CM_ SG_ 354 VDM_AdasAccelRequestAcknowledged "An acknowleddge signal to the ADAS system to show that TQM is honoring their request";
|
||||
CM_ SG_ 432 ESP_Torque_Front_MinQ "Indication of whether signal with corresponding name is valid";
|
||||
CM_ SG_ 432 ESP_Torque_Front_MaxQ "Indication of whether signal with corresponding name is valid";
|
||||
CM_ SG_ 432 ESP_Torque_Front_Max "ESP intervention, ESP tractive torque limit per axle.";
|
||||
@@ -878,7 +877,6 @@ VAL_ 354 VDM_AdasDriverAccelPriorityStatus 0 "VDM_AdasDriverAccelPriorityStatus_
|
||||
VAL_ 354 VDM_AdasFaultStatus 0 "VDM_AdasFlaultStatus_No_Fault" 1 "VDM_AdasFaultStatus_Brk_Intv" 2 "VDM_AdasFlaultStatus_Cntr_Fault" 3 "VDM_AdasFlaultStatus_Imps_Cmd" 15 "VDM_AdasFlaultStatus_Sna";
|
||||
VAL_ 354 VDM_AdasDriverModeStatus 0 "VDM_AdasDriverModeStatus_Human" 1 "VDM_AdasDriverModeStatus_Adas" 2 "VDM_AdasDriverModeStatus_Reserved" 3 "VDM_AdasDriverModeStatus_Sna";
|
||||
VAL_ 354 VDM_AdasInterfaceStatus 0 "VDM_AdasInterfaceStatus_Unavailable" 1 "VDM_AdasInterfaceStatus_Available" 2 "VDM_AdasInterfaceStatus_Enabled" 3 "VDM_AdasInterfaceStatus_Faulted";
|
||||
VAL_ 354 VDM_AdasAccelRequestAcknowledged 0 "VDM_AdasAccelRequestAcknowledged_Not_Acknowledged" 1 "VDM_AdasAccelRequestAcknowledged_Acknowledged" 2 "VDM_AdasAccelRequestAcknowledged_Fault_Ignored" 3 "VDM_AdasAccelRequestAcknowledged_Sna";
|
||||
VAL_ 354 VDM_AdasVehicleHoldStatus 0 "VDM_AdasVehicleHoldStatus_NotHold" 1 "VDM_AdasVehicleHoldStatus_Hold";
|
||||
VAL_ 357 VDM_AdasStalkGapAdjust 0 "VDM_AdasStalkGapAdjust_No_Required" 1 "VDM_AdasStalkGapAdjust_GapDecrement" 2 "VDM_AdasStalkGapAdjust_GapIncrement";
|
||||
VAL_ 357 VDM_AdasStalkAccCancelRes 0 "VDM_AdasStalkAccCancelRes_NoRequired" 1 "VDM_AdasStalkAccCancelRes_Cancel" 2 "VDM_AdasStalkAccCancelRes_Resume";
|
||||
|
||||
@@ -31,7 +31,7 @@ static bool body_tx_hook(const CANPacket_t *to_send) {
|
||||
|
||||
static safety_config body_init(uint16_t param) {
|
||||
static RxCheck body_rx_checks[] = {
|
||||
{.msg = {{0x201, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{0x201, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
static const CanMsg BODY_TX_MSGS[] = {{0x250, 0, 8, .check_relay = false}, {0x250, 0, 6, .check_relay = false}, {0x251, 0, 5, .check_relay = false}, // body
|
||||
|
||||
@@ -207,22 +207,22 @@ static safety_config chrysler_init(uint16_t param) {
|
||||
};
|
||||
|
||||
static RxCheck chrysler_ram_dt_rx_checks[] = {
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.EPS_2, 0, 8, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_1, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_8, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.ECM_5, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.DAS_3, 2, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.Center_Stack_2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 1U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.EPS_2, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_1, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_8, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.ECM_5, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.DAS_3, 2, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_DT_ADDRS.Center_Stack_2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 1U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
static RxCheck chrysler_rx_checks[] = {
|
||||
{.msg = {{CHRYSLER_ADDRS.EPS_2, 0, 8, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.ESP_1, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
//{.msg = {{ESP_8, 0, 8, .max_counter = 15U, .frequency = 50U}}},
|
||||
{.msg = {{514, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.ECM_5, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.DAS_3, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.TRACTION_BUTTON, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 1U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.EPS_2, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.ESP_1, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
//{.msg = {{ESP_8, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}}},
|
||||
{.msg = {{514, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.ECM_5, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.DAS_3, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_ADDRS.TRACTION_BUTTON, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 1U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
static const CanMsg CHRYSLER_TX_MSGS[] = {
|
||||
@@ -253,12 +253,12 @@ static safety_config chrysler_init(uint16_t param) {
|
||||
};
|
||||
|
||||
static RxCheck chrysler_ram_hd_rx_checks[] = {
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.EPS_2, 0, 8, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_1, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_8, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.ECM_5, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.DAS_3, 2, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.Center_Stack_2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 1U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.EPS_2, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_1, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_8, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.ECM_5, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.DAS_3, 2, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{CHRYSLER_RAM_HD_ADDRS.Center_Stack_2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 1U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
static const CanMsg CHRYSLER_RAM_HD_TX_MSGS[] = {
|
||||
|
||||
@@ -94,8 +94,6 @@ static bool ford_get_quality_flag_valid(const CANPacket_t *to_push) {
|
||||
|
||||
#define FORD_CANFD_INACTIVE_CURVATURE_RATE 1024U
|
||||
|
||||
#define FORD_MAX_SPEED_DELTA 2.0 // m/s
|
||||
|
||||
// Curvature rate limits
|
||||
#define FORD_LIMITS(limit_lateral_acceleration) { \
|
||||
.max_angle = 1000, /* 0.02 curvature */ \
|
||||
@@ -133,19 +131,15 @@ static void ford_rx_hook(const CANPacket_t *to_push) {
|
||||
// Update vehicle speed
|
||||
if (addr == FORD_BrakeSysFeatures) {
|
||||
// Signal: Veh_V_ActlBrk
|
||||
UPDATE_VEHICLE_SPEED(((GET_BYTE(to_push, 0) << 8) | GET_BYTE(to_push, 1)) * 0.01 / 3.6);
|
||||
UPDATE_VEHICLE_SPEED(((GET_BYTE(to_push, 0) << 8) | GET_BYTE(to_push, 1)) * 0.01 * KPH_TO_MS);
|
||||
}
|
||||
|
||||
// Check vehicle speed against a second source
|
||||
if (addr == FORD_EngVehicleSpThrottle2) {
|
||||
// Disable controls if speeds from ABS and PCM ECUs are too far apart.
|
||||
// Signal: Veh_V_ActlEng
|
||||
float filtered_pcm_speed = ((GET_BYTE(to_push, 6) << 8) | GET_BYTE(to_push, 7)) * 0.01 / 3.6;
|
||||
bool is_invalid_speed = ABS(filtered_pcm_speed - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) > FORD_MAX_SPEED_DELTA;
|
||||
// TODO: this should generically cause rx valid to fall until re-enable
|
||||
if (is_invalid_speed) {
|
||||
controls_allowed = false;
|
||||
}
|
||||
float filtered_pcm_speed = ((GET_BYTE(to_push, 6) << 8) | GET_BYTE(to_push, 7)) * 0.01 * KPH_TO_MS;
|
||||
speed_mismatch_check(filtered_pcm_speed);
|
||||
}
|
||||
|
||||
// Update vehicle yaw rate
|
||||
@@ -176,7 +170,7 @@ static void ford_rx_hook(const CANPacket_t *to_push) {
|
||||
pcm_cruise_check(cruise_engaged);
|
||||
acc_main_on = (cruise_state == 3U) || cruise_engaged;
|
||||
}
|
||||
|
||||
|
||||
if (addr == FORD_Steering_Data_FD1) {
|
||||
mads_button_press = GET_BIT(to_push, 40U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED;
|
||||
}
|
||||
@@ -309,17 +303,17 @@ static safety_config ford_init(uint16_t param) {
|
||||
// warning: quality flags are not yet checked in openpilot's CAN parser,
|
||||
// this may be the cause of blocked messages
|
||||
static RxCheck ford_rx_checks[] = {
|
||||
{.msg = {{FORD_BrakeSysFeatures, 0, 8, .max_counter = 15U, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_BrakeSysFeatures, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
// FORD_EngVehicleSpThrottle2 has a counter that either randomly skips or by 2, likely ECU bug
|
||||
// Some hybrid models also experience a bug where this checksum mismatches for one or two frames under heavy acceleration with ACC
|
||||
// It has been confirmed that the Bronco Sport's camera only disallows ACC for bad quality flags, not counters or checksums, so we match that
|
||||
{.msg = {{FORD_EngVehicleSpThrottle2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_Yaw_Data_FD1, 0, 8, .max_counter = 255U, .quality_flag=true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_EngVehicleSpThrottle2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_Yaw_Data_FD1, 0, 8, .max_counter = 255U, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
// These messages have no counter or checksum
|
||||
{.msg = {{FORD_EngBrakeData, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_EngVehicleSpThrottle, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_DesiredTorqBrk, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_Steering_Data_FD1, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_EngBrakeData, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_EngVehicleSpThrottle, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_DesiredTorqBrk, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_Steering_Data_FD1, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
#define FORD_COMMON_TX_MSGS \
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
// TODO: do checksum and counter checks. Add correct timestep, 0.1s for now.
|
||||
#define GM_COMMON_RX_CHECKS \
|
||||
{.msg = {{0x184, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x34A, 0, 5, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x1E1, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xBE, 0, 6, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, /* Volt, Silverado, Acadia Denali */ \
|
||||
{0xBE, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, /* Bolt EUV */ \
|
||||
{0xBE, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}}}, /* Escalade */ \
|
||||
{.msg = {{0x1C4, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xC9, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x184, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x34A, 0, 5, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x1E1, 0, 7, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xBE, 0, 6, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, /* Volt, Silverado, Acadia Denali */ \
|
||||
{0xBE, 0, 7, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, /* Bolt EUV */ \
|
||||
{0xBE, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}}}, /* Escalade */ \
|
||||
{.msg = {{0x1C4, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xC9, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static const LongitudinalLimits *gm_long_limits;
|
||||
|
||||
@@ -200,7 +200,7 @@ static safety_config gm_init(uint16_t param) {
|
||||
|
||||
static RxCheck gm_ev_rx_checks[] = {
|
||||
GM_COMMON_RX_CHECKS
|
||||
{.msg = {{0xBD, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 40U}, { 0 }, { 0 }}},
|
||||
{.msg = {{0xBD, 0, 7, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 40U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
static const CanMsg GM_CAM_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, // pt bus
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
#include "opendbc/safety/safety_declarations.h"
|
||||
|
||||
// All common address checks except SCM_BUTTONS which isn't on one Nidec safety configuration
|
||||
#define HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1A6, (pt_bus), 8, .max_counter = 3U, .frequency = 25U}, /* SCM_BUTTONS */ \
|
||||
{0x296, (pt_bus), 4, .max_counter = 3U, .frequency = 25U}, { 0 }}}, \
|
||||
{.msg = {{0x158, (pt_bus), 8, .max_counter = 3U, .frequency = 100U}, { 0 }, { 0 }}}, /* ENGINE_DATA */ \
|
||||
{.msg = {{0x17C, (pt_bus), 8, .max_counter = 3U, .frequency = 100U}, { 0 }, { 0 }}}, /* POWERTRAIN_DATA */ \
|
||||
#define HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1A6, (pt_bus), 8, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 25U}, /* SCM_BUTTONS */ \
|
||||
{0x296, (pt_bus), 4, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 25U}, { 0 }}}, \
|
||||
{.msg = {{0x158, (pt_bus), 8, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, /* ENGINE_DATA */ \
|
||||
{.msg = {{0x17C, (pt_bus), 8, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, /* POWERTRAIN_DATA */ \
|
||||
|
||||
#define HONDA_COMMON_RX_CHECKS(pt_bus) \
|
||||
HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x326, (pt_bus), 8, .max_counter = 3U, .frequency = 10U}, { 0 }, { 0 }}}, /* SCM_FEEDBACK */ \
|
||||
#define HONDA_COMMON_RX_CHECKS(pt_bus) \
|
||||
HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x326, (pt_bus), 8, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, /* SCM_FEEDBACK */ \
|
||||
|
||||
// Alternate brake message is used on some Honda Bosch, and Honda Bosch radarless (where PT bus is 0)
|
||||
#define HONDA_ALT_BRAKE_ADDR_CHECK(pt_bus) \
|
||||
{.msg = {{0x1BE, (pt_bus), 3, .max_counter = 3U, .frequency = 50U}, { 0 }, { 0 }}}, /* BRAKE_MODULE */ \
|
||||
#define HONDA_ALT_BRAKE_ADDR_CHECK(pt_bus) \
|
||||
{.msg = {{0x1BE, (pt_bus), 3, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, /* BRAKE_MODULE */ \
|
||||
|
||||
enum {
|
||||
HONDA_BTN_NONE = 0,
|
||||
@@ -310,7 +310,7 @@ static safety_config honda_nidec_init(uint16_t param) {
|
||||
// For Nidecs with main on signal on an alternate msg (missing 0x326)
|
||||
static RxCheck honda_nidec_alt_rx_checks[] = {
|
||||
HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(0)
|
||||
{.msg = {{0x1FA, 2, 8, .max_counter = 3U, .frequency = 50U}, { 0 }, { 0 }}}, // BRAKE_COMMAND
|
||||
{.msg = {{0x1FA, 2, 8, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, // BRAKE_COMMAND
|
||||
};
|
||||
|
||||
SET_RX_CHECKS(honda_nidec_alt_rx_checks, ret);
|
||||
@@ -318,7 +318,7 @@ static safety_config honda_nidec_init(uint16_t param) {
|
||||
// Nidec includes BRAKE_COMMAND
|
||||
static RxCheck honda_nidec_common_rx_checks[] = {
|
||||
HONDA_COMMON_RX_CHECKS(0)
|
||||
{.msg = {{0x1FA, 2, 8, .max_counter = 3U, .frequency = 50U}, { 0 }, { 0 }}}, // BRAKE_COMMAND
|
||||
{.msg = {{0x1FA, 2, 8, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, // BRAKE_COMMAND
|
||||
};
|
||||
|
||||
SET_RX_CHECKS(honda_nidec_common_rx_checks, ret);
|
||||
|
||||
@@ -38,25 +38,25 @@ const LongitudinalLimits HYUNDAI_LONG_LIMITS = {
|
||||
{0x389, 0, 8, .check_relay = true}, /* SCC14 Bus 0 */ \
|
||||
{0x4A2, 0, 2, .check_relay = false}, /* FRT_RADAR11 Bus 0 */ \
|
||||
|
||||
#define HYUNDAI_COMMON_RX_CHECKS(legacy) \
|
||||
{.msg = {{0x260, 0, 8, .max_counter = 3U, .frequency = 100U}, \
|
||||
{0x371, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }}}, \
|
||||
{.msg = {{0x386, 0, 8, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 15U, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x394, 0, 8, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 7U, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x251, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x4F1, 0, 4, .ignore_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_COMMON_RX_CHECKS(legacy) \
|
||||
{.msg = {{0x260, 0, 8, .max_counter = 3U, .ignore_quality_flag = true, .frequency = 100U}, \
|
||||
{0x371, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }}}, \
|
||||
{.msg = {{0x386, 0, 8, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x394, 0, 8, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 7U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x251, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x4F1, 0, 4, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_SCC11_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x420, (scc_bus), 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_SCC11_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x420, (scc_bus), 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_SCC12_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x421, (scc_bus), 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_SCC12_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x421, (scc_bus), 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_FCEV_GAS_ADDR_CHECK \
|
||||
{.msg = {{0x91, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x91, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_LDA_BUTTON_ADDR_CHECK \
|
||||
{.msg = {{0x391, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x391, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static const CanMsg HYUNDAI_TX_MSGS[] = {
|
||||
HYUNDAI_COMMON_TX_MSGS(0)
|
||||
|
||||
@@ -25,25 +25,25 @@
|
||||
|
||||
// *** Addresses checked in rx hook ***
|
||||
// EV, ICE, HYBRID: ACCELERATOR (0x35), ACCELERATOR_BRAKE_ALT (0x100), ACCELERATOR_ALT (0x105)
|
||||
#define HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x35, (pt_bus), 32, .max_counter = 0xffU, .frequency = 100U}, \
|
||||
{0x100, (pt_bus), 32, .max_counter = 0xffU, .frequency = 100U}, \
|
||||
{0x105, (pt_bus), 32, .max_counter = 0xffU, .frequency = 100U}}}, \
|
||||
{.msg = {{0x175, (pt_bus), 24, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xa0, (pt_bus), 24, .max_counter = 0xffU, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xea, (pt_bus), 24, .max_counter = 0xffU, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x35, (pt_bus), 32, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 100U}, \
|
||||
{0x100, (pt_bus), 32, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 100U}, \
|
||||
{0x105, (pt_bus), 32, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 100U}}}, \
|
||||
{.msg = {{0x175, (pt_bus), 24, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xa0, (pt_bus), 24, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xea, (pt_bus), 24, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(pt_bus) \
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1cf, (pt_bus), 8, .ignore_checksum = true, .max_counter = 0xfU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(pt_bus) \
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1cf, (pt_bus), 8, .ignore_checksum = true, .max_counter = 0xfU, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(pt_bus) \
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1aa, (pt_bus), 16, .ignore_checksum = true, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(pt_bus) \
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1aa, (pt_bus), 16, .ignore_checksum = true, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
// SCC_CONTROL (from ADAS unit or camera)
|
||||
#define HYUNDAI_CANFD_SCC_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x1a0, (scc_bus), 32, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_SCC_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x1a0, (scc_bus), 32, .max_counter = 0xffU, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static bool hyundai_canfd_alt_buttons = false;
|
||||
static bool hyundai_canfd_lka_steering_alt = false;
|
||||
@@ -124,7 +124,7 @@ static void hyundai_canfd_rx_hook(const CANPacket_t *to_push) {
|
||||
(rl > HYUNDAI_STANDSTILL_THRSLD) || (rr > HYUNDAI_STANDSTILL_THRSLD);
|
||||
|
||||
// average of all 4 wheel speeds. Conversion: raw * 0.03125 / 3.6 = m/s
|
||||
UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.03125 / 3.6);
|
||||
UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.03125 * KPH_TO_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,11 +93,11 @@ static safety_config mazda_init(uint16_t param) {
|
||||
static const CanMsg MAZDA_TX_MSGS[] = {{MAZDA_LKAS, 0, 8, .check_relay = true}, {MAZDA_CRZ_BTNS, 0, 8, .check_relay = false}, {MAZDA_LKAS_HUD, 0, 8, .check_relay = true}};
|
||||
|
||||
static RxCheck mazda_rx_checks[] = {
|
||||
{.msg = {{MAZDA_CRZ_CTRL, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_CRZ_BTNS, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_STEER_TORQUE, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 83U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_ENGINE_DATA, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_PEDALS, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_CRZ_CTRL, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_CRZ_BTNS, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_STEER_TORQUE, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 83U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_ENGINE_DATA, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MAZDA_PEDALS, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
UNUSED(param);
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
|
||||
#include "opendbc/safety/safety_declarations.h"
|
||||
|
||||
#define NISSAN_COMMON_RX_CHECKS \
|
||||
{.msg = {{0x2, 0, 5, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, \
|
||||
{0x2, 1, 5, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }}}, /* STEER_ANGLE_SENSOR */ \
|
||||
{.msg = {{0x285, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, \
|
||||
{0x285, 1, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }}}, /* WHEEL_SPEEDS_REAR */ \
|
||||
{.msg = {{0x30f, 2, 3, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, \
|
||||
{0x30f, 1, 3, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }}}, /* CRUISE_STATE */ \
|
||||
{.msg = {{0x15c, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, \
|
||||
{0x15c, 1, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, \
|
||||
{0x239, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}}}, /* GAS_PEDAL */ \
|
||||
{.msg = {{0x454, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, \
|
||||
{0x454, 1, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, \
|
||||
{0x1cc, 0, 4, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}}}, /* DOORS_LIGHTS / BRAKE */ \
|
||||
#define NISSAN_COMMON_RX_CHECKS \
|
||||
{.msg = {{0x2, 0, 5, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, \
|
||||
{0x2, 1, 5, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }}}, /* STEER_ANGLE_SENSOR */ \
|
||||
{.msg = {{0x285, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, \
|
||||
{0x285, 1, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }}}, /* WHEEL_SPEEDS_REAR */ \
|
||||
{.msg = {{0x30f, 2, 3, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, \
|
||||
{0x30f, 1, 3, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }}}, /* CRUISE_STATE */ \
|
||||
{.msg = {{0x15c, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, \
|
||||
{0x15c, 1, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, \
|
||||
{0x239, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}}}, /* GAS_PEDAL */ \
|
||||
{.msg = {{0x454, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, \
|
||||
{0x454, 1, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, \
|
||||
{0x1cc, 0, 4, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}}}, /* DOORS_LIGHTS / BRAKE */ \
|
||||
|
||||
#define NISSAN_PRO_PILOT_RX_CHECKS(alt_eps_bus) \
|
||||
{.msg = {{0x1B6, alt_eps_bus, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
#define NISSAN_PRO_PILOT_RX_CHECKS(alt_eps_bus) \
|
||||
{.msg = {{0x1B6, alt_eps_bus, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static bool nissan_alt_eps = false;
|
||||
|
||||
@@ -42,7 +42,7 @@ static void nissan_rx_hook(const CANPacket_t *to_push) {
|
||||
uint16_t right_rear = (GET_BYTE(to_push, 0) << 8) | (GET_BYTE(to_push, 1));
|
||||
uint16_t left_rear = (GET_BYTE(to_push, 2) << 8) | (GET_BYTE(to_push, 3));
|
||||
vehicle_moving = (right_rear | left_rear) != 0U;
|
||||
UPDATE_VEHICLE_SPEED((right_rear + left_rear) / 2.0 * 0.005 / 3.6);
|
||||
UPDATE_VEHICLE_SPEED((right_rear + left_rear) / 2.0 * 0.005 * KPH_TO_MS);
|
||||
}
|
||||
|
||||
// X-Trail 0x15c, Leaf 0x239
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "opendbc/safety/safety_declarations.h"
|
||||
|
||||
#define RIVIAN_MAX_SPEED_DELTA 2.0 // m/s
|
||||
|
||||
static uint8_t rivian_get_counter(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -81,7 +79,7 @@ static void rivian_rx_hook(const CANPacket_t *to_push) {
|
||||
if (addr == 0x208) {
|
||||
float speed = ((GET_BYTE(to_push, 6) << 8) | GET_BYTE(to_push, 7)) * 0.01;
|
||||
vehicle_moving = speed > 0.0;
|
||||
UPDATE_VEHICLE_SPEED(speed / 3.6);
|
||||
UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS);
|
||||
}
|
||||
|
||||
// Gas pressed and second speed source for variable torque limit
|
||||
@@ -89,12 +87,8 @@ static void rivian_rx_hook(const CANPacket_t *to_push) {
|
||||
gas_pressed = GET_BYTE(to_push, 3) | (GET_BYTE(to_push, 4) & 0xC0U);
|
||||
|
||||
// Disable controls if speeds from VDM and ESP ECUs are too far apart.
|
||||
float vdm_speed = ((GET_BYTE(to_push, 5) << 8) | GET_BYTE(to_push, 6)) * 0.01 / 3.6;
|
||||
bool is_invalid_speed = ABS(vdm_speed - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) > RIVIAN_MAX_SPEED_DELTA;
|
||||
// TODO: this should generically cause rx valid to fall until re-enable
|
||||
if (is_invalid_speed) {
|
||||
controls_allowed = false;
|
||||
}
|
||||
float vdm_speed = ((GET_BYTE(to_push, 5) << 8) | GET_BYTE(to_push, 6)) * 0.01 * KPH_TO_MS;
|
||||
speed_mismatch_check(vdm_speed);
|
||||
}
|
||||
|
||||
// Driver torque
|
||||
@@ -178,11 +172,11 @@ static safety_config rivian_init(uint16_t param) {
|
||||
static const CanMsg RIVIAN_LONG_TX_MSGS[] = {{0x120, 0, 8, .check_relay = true}, {0x321, 2, 7, .check_relay = true}, {0x160, 0, 5, .check_relay = true}};
|
||||
|
||||
static RxCheck rivian_rx_checks[] = {
|
||||
{.msg = {{0x208, 0, 8, .frequency = 50U, .max_counter = 14U, .quality_flag = true}, { 0 }, { 0 }}}, // ESP_Status (speed)
|
||||
{.msg = {{0x150, 0, 7, .frequency = 50U, .max_counter = 14U, .quality_flag = true}, { 0 }, { 0 }}}, // VDM_PropStatus (gas pedal & 2nd speed)
|
||||
{.msg = {{0x380, 0, 5, .frequency = 100U, .ignore_checksum = true, .ignore_counter = true}, { 0 }, { 0 }}}, // EPAS_SystemStatus (driver torque)
|
||||
{.msg = {{0x38f, 0, 6, .frequency = 50U, .ignore_checksum = true, .ignore_counter = true}, { 0 }, { 0 }}}, // iBESP2 (brakes)
|
||||
{.msg = {{0x100, 2, 8, .frequency = 100U, .ignore_checksum = true, .ignore_counter = true}, { 0 }, { 0 }}}, // ACM_Status (cruise state)
|
||||
{.msg = {{0x208, 0, 8, .frequency = 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // ESP_Status (speed)
|
||||
{.msg = {{0x150, 0, 7, .frequency = 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // VDM_PropStatus (gas pedal & 2nd speed)
|
||||
{.msg = {{0x380, 0, 5, .frequency = 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPAS_SystemStatus (driver torque)
|
||||
{.msg = {{0x38f, 0, 6, .frequency = 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // iBESP2 (brakes)
|
||||
{.msg = {{0x100, 2, 8, .frequency = 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ACM_Status (cruise state)
|
||||
};
|
||||
|
||||
bool rivian_longitudinal = false;
|
||||
|
||||
@@ -63,13 +63,13 @@
|
||||
{MSG_SUBARU_ES_STATIC_1, SUBARU_MAIN_BUS, 8, .check_relay = false}, \
|
||||
{MSG_SUBARU_ES_STATIC_2, SUBARU_MAIN_BUS, 8, .check_relay = false}, \
|
||||
|
||||
#define SUBARU_COMMON_RX_CHECKS(alt_bus) \
|
||||
{.msg = {{MSG_SUBARU_Throttle, SUBARU_MAIN_BUS, 8, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_Steering_Torque, SUBARU_MAIN_BUS, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_Wheel_Speeds, alt_bus, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_Brake_Status, alt_bus, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_CruiseControl, alt_bus, 8, .max_counter = 15U, .frequency = 20U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_ES_LKAS_State, SUBARU_CAM_BUS, 8, .max_counter = 15U, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
#define SUBARU_COMMON_RX_CHECKS(alt_bus) \
|
||||
{.msg = {{MSG_SUBARU_Throttle, SUBARU_MAIN_BUS, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_Steering_Torque, SUBARU_MAIN_BUS, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_Wheel_Speeds, alt_bus, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_Brake_Status, alt_bus, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_CruiseControl, alt_bus, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 20U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{MSG_SUBARU_ES_LKAS_State, SUBARU_CAM_BUS, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static bool subaru_gen2 = false;
|
||||
static bool subaru_longitudinal = false;
|
||||
@@ -132,7 +132,7 @@ static void subaru_rx_hook(const CANPacket_t *to_push) {
|
||||
|
||||
vehicle_moving = (fr > 0U) || (rr > 0U) || (rl > 0U) || (fl > 0U);
|
||||
|
||||
UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.057 / 3.6);
|
||||
UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.057 * KPH_TO_MS);
|
||||
}
|
||||
|
||||
if ((addr == MSG_SUBARU_Brake_Status) && (bus == alt_main_bus)) {
|
||||
|
||||
@@ -91,11 +91,11 @@ static safety_config subaru_preglobal_init(uint16_t param) {
|
||||
|
||||
// TODO: do checksum and counter checks after adding the signals to the outback dbc file
|
||||
static RxCheck subaru_preglobal_rx_checks[] = {
|
||||
{.msg = {{MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_Steering_Torque, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_CruiseControl, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_Wheel_Speeds, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_Brake_Pedal, SUBARU_PG_MAIN_BUS, 4, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_Steering_Torque, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_CruiseControl, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_Wheel_Speeds, SUBARU_PG_MAIN_BUS, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_SUBARU_PG_Brake_Pedal, SUBARU_PG_MAIN_BUS, 4, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
const int SUBARU_PG_PARAM_REVERSED_DRIVER_TORQUE = 4;
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
|
||||
#include "opendbc/safety/safety_declarations.h"
|
||||
|
||||
// parameters for lateral accel/jerk angle limiting using a simple vehicle model
|
||||
typedef struct {
|
||||
const float slip_factor;
|
||||
const float steer_ratio;
|
||||
const float wheelbase;
|
||||
} AngleSteeringParams;
|
||||
|
||||
#define TESLA_MAX_SPEED_DELTA 2.0 // m/s
|
||||
|
||||
static bool tesla_longitudinal = false;
|
||||
static bool tesla_stock_aeb = false;
|
||||
|
||||
@@ -23,68 +14,6 @@ static bool tesla_stock_lkas_prev = false;
|
||||
static bool tesla_autopark = false;
|
||||
static bool tesla_autopark_prev = false;
|
||||
|
||||
static float tesla_curvature_factor(const float speed, const AngleSteeringParams params) {
|
||||
return 1. / (1. - (params.slip_factor * (speed * speed))) / params.wheelbase;
|
||||
}
|
||||
|
||||
static bool tesla_steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits,
|
||||
const AngleSteeringParams params) {
|
||||
|
||||
static const float RAD_TO_DEG = 57.29577951308232;
|
||||
static const float ISO_LATERAL_ACCEL = 3.0; // m/s^2
|
||||
|
||||
// Highway curves are rolled in the direction of the turn, add tolerance to compensate
|
||||
static const float EARTH_G = 9.81;
|
||||
static const float AVERAGE_ROAD_ROLL = 0.06; // ~3.4 degrees, 6% superelevation
|
||||
|
||||
static const float MAX_LATERAL_ACCEL = ISO_LATERAL_ACCEL + (EARTH_G * AVERAGE_ROAD_ROLL); // ~3.6 m/s^2
|
||||
static const float MAX_LATERAL_JERK = 3.0 + (EARTH_G * AVERAGE_ROAD_ROLL); // ~3.6 m/s^3
|
||||
|
||||
const float fudged_speed = (vehicle_speed.min / VEHICLE_SPEED_FACTOR) - 1.;
|
||||
const float curvature_factor = tesla_curvature_factor(fudged_speed, params);
|
||||
|
||||
bool violation = false;
|
||||
|
||||
if (is_lat_active() && steer_control_enabled) {
|
||||
// *** ISO lateral jerk limit ***
|
||||
// calculate maximum angle rate per second
|
||||
const float speed = MAX(fudged_speed, 1.0);
|
||||
const float max_curvature_rate_sec = MAX_LATERAL_JERK / (speed * speed);
|
||||
const float max_angle_rate_sec = max_curvature_rate_sec * params.steer_ratio / curvature_factor * RAD_TO_DEG;
|
||||
|
||||
// finally get max angle delta per frame
|
||||
const float max_angle_delta = max_angle_rate_sec * (0.01f * 2.0f); // 50 Hz
|
||||
const int max_angle_delta_can = (max_angle_delta * limits.angle_deg_to_can) + 1.;
|
||||
|
||||
// NOTE: symmetric up and down limits
|
||||
const int highest_desired_angle = desired_angle_last + max_angle_delta_can;
|
||||
const int lowest_desired_angle = desired_angle_last - max_angle_delta_can;
|
||||
|
||||
violation |= max_limit_check(desired_angle, highest_desired_angle, lowest_desired_angle);
|
||||
|
||||
// *** ISO lateral accel limit ***
|
||||
const float max_curvature = MAX_LATERAL_ACCEL / (speed * speed);
|
||||
const float max_angle = max_curvature * params.steer_ratio / curvature_factor * RAD_TO_DEG;
|
||||
const int max_angle_can = (max_angle * limits.angle_deg_to_can) + 1.;
|
||||
|
||||
violation |= max_limit_check(desired_angle, max_angle_can, -max_angle_can);
|
||||
}
|
||||
desired_angle_last = desired_angle;
|
||||
|
||||
// Angle should either be 0 or same as current angle while not steering
|
||||
if (!steer_control_enabled) {
|
||||
const int max_inactive_angle = CLAMP(angle_meas.max, -limits.max_angle, limits.max_angle) + 1;
|
||||
const int min_inactive_angle = CLAMP(angle_meas.min, -limits.max_angle, limits.max_angle) - 1;
|
||||
violation |= (limits.inactive_angle_is_zero ? (desired_angle != 0) :
|
||||
max_limit_check(desired_angle, max_inactive_angle, min_inactive_angle));
|
||||
}
|
||||
|
||||
// No angle control allowed when controls are not allowed
|
||||
violation |= !is_lat_active() && steer_control_enabled;
|
||||
|
||||
return violation;
|
||||
}
|
||||
|
||||
static uint8_t tesla_get_counter(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -158,6 +87,8 @@ static bool tesla_get_quality_flag_valid(const CANPacket_t *to_push) {
|
||||
bool valid = false;
|
||||
if (addr == 0x155) {
|
||||
valid = (GET_BYTE(to_push, 5) & 0x1U) == 0x1U; // ESP_wheelSpeedsQF
|
||||
} else if (addr == 0x39d) {
|
||||
valid = (GET_BYTE(to_push, 2) & 0x03U) != 3U; // IBST_driverBrakeApply=FAULT
|
||||
} else {
|
||||
}
|
||||
return valid;
|
||||
@@ -185,19 +116,15 @@ static void tesla_rx_hook(const CANPacket_t *to_push) {
|
||||
// Vehicle speed (DI_speed)
|
||||
if (addr == 0x257) {
|
||||
// Vehicle speed: ((val * 0.08) - 40) / MS_TO_KPH
|
||||
float speed = ((((GET_BYTE(to_push, 2) << 4) | (GET_BYTE(to_push, 1) >> 4)) * 0.08) - 40.) / 3.6;
|
||||
float speed = ((((GET_BYTE(to_push, 2) << 4) | (GET_BYTE(to_push, 1) >> 4)) * 0.08) - 40.) * KPH_TO_MS;
|
||||
UPDATE_VEHICLE_SPEED(speed);
|
||||
}
|
||||
|
||||
// 2nd vehicle speed (ESP_B)
|
||||
if (addr == 0x155) {
|
||||
// Disable controls if speeds from DI (Drive Inverter) and ESP ECUs are too far apart.
|
||||
float esp_speed = (((GET_BYTE(to_push, 6) & 0x0FU) << 6) | GET_BYTE(to_push, 5) >> 2) * 0.5 / 3.6;
|
||||
bool is_invalid_speed = ABS(esp_speed - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) > TESLA_MAX_SPEED_DELTA;
|
||||
// TODO: this should generically cause rx valid to fall until re-enable
|
||||
if (is_invalid_speed) {
|
||||
controls_allowed = false;
|
||||
}
|
||||
float esp_speed = (((GET_BYTE(to_push, 6) & 0x0FU) << 6) | GET_BYTE(to_push, 5) >> 2) * 0.5 * KPH_TO_MS;
|
||||
speed_mismatch_check(esp_speed);
|
||||
}
|
||||
|
||||
// Gas pressed
|
||||
@@ -303,7 +230,7 @@ static bool tesla_tx_hook(const CANPacket_t *to_send) {
|
||||
bool steer_control_enabled = (steer_control_type == 1) || // ANGLE_CONTROL
|
||||
(steer_control_type == 2); // LANE_KEEP_ASSIST
|
||||
|
||||
if (tesla_steer_angle_cmd_checks(desired_angle, steer_control_enabled, TESLA_STEERING_LIMITS, TESLA_STEERING_PARAMS)) {
|
||||
if (steer_angle_cmd_checks_vm(desired_angle, steer_control_enabled, TESLA_STEERING_LIMITS, TESLA_STEERING_PARAMS)) {
|
||||
violation = true;
|
||||
}
|
||||
|
||||
@@ -420,15 +347,15 @@ static safety_config tesla_init(uint16_t param) {
|
||||
tesla_autopark_prev = false;
|
||||
|
||||
static RxCheck tesla_model3_y_rx_checks[] = {
|
||||
{.msg = {{0x2b9, 2, 8, .max_counter = 7U, .frequency = 25U}, { 0 }, { 0 }}}, // DAS_control
|
||||
{.msg = {{0x488, 2, 4, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, // DAS_steeringControl
|
||||
{.msg = {{0x257, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, // DI_speed (speed in kph)
|
||||
{.msg = {{0x155, 0, 8, .max_counter = 15U, .quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, // ESP_B (2nd speed in kph)
|
||||
{.msg = {{0x370, 0, 8, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, // EPAS3S_sysStatus (steering angle)
|
||||
{.msg = {{0x118, 0, 8, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, // DI_systemStatus (gas pedal)
|
||||
{.msg = {{0x39d, 0, 5, .max_counter = 15U, .frequency = 25U}, { 0 }, { 0 }}}, // IBST_status (brakes)
|
||||
{.msg = {{0x286, 0, 8, .max_counter = 15U, .frequency = 10U}, { 0 }, { 0 }}}, // DI_state (acc state)
|
||||
{.msg = {{0x311, 0, 7, .max_counter = 15U, .frequency = 10U}, { 0 }, { 0 }}}, // UI_warning (blinkers, buckle switch & doors)
|
||||
{.msg = {{0x2b9, 2, 8, .max_counter = 7U, .ignore_quality_flag = true, .frequency = 25U}, { 0 }, { 0 }}}, // DAS_control
|
||||
{.msg = {{0x488, 2, 4, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, // DAS_steeringControl
|
||||
{.msg = {{0x257, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, // DI_speed (speed in kph)
|
||||
{.msg = {{0x155, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, // ESP_B (2nd speed in kph)
|
||||
{.msg = {{0x370, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, // EPAS3S_sysStatus (steering angle)
|
||||
{.msg = {{0x118, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}}, // DI_systemStatus (gas pedal)
|
||||
{.msg = {{0x39d, 0, 5, .max_counter = 15U, .frequency = 25U}, { 0 }, { 0 }}}, // IBST_status (brakes)
|
||||
{.msg = {{0x286, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, // DI_state (acc state)
|
||||
{.msg = {{0x311, 0, 7, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}}, // UI_warning (blinkers, buckle switch & doors)
|
||||
};
|
||||
|
||||
safety_config ret;
|
||||
|
||||
@@ -36,31 +36,31 @@
|
||||
{0x343, 0, 8, .check_relay = true}, /* ACC */ \
|
||||
{0x183, 0, 8, .check_relay = true}, /* ACC_CONTROL_2 */ \
|
||||
|
||||
#define TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
{.msg = {{ 0xaa, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 83U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x260, 0, 8, .ignore_counter = true, .quality_flag = (lta), .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
{.msg = {{ 0xaa, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 83U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x260, 0, 8, .ignore_counter = true, .ignore_quality_flag=!(lta), .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define TOYOTA_RX_CHECKS(lta) \
|
||||
TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
{.msg = {{0x1D2, 0, 8, .ignore_counter = true, .frequency = 33U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x226, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 40U}, { 0 }, { 0 }}}, \
|
||||
#define TOYOTA_RX_CHECKS(lta) \
|
||||
TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
{.msg = {{0x1D2, 0, 8, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 33U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x226, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 40U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define TOYOTA_ALT_BRAKE_RX_CHECKS(lta) \
|
||||
TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
{.msg = {{0x1D2, 0, 8, .ignore_counter = true, .frequency = 33U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x224, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 40U}, { 0 }, { 0 }}}, \
|
||||
#define TOYOTA_ALT_BRAKE_RX_CHECKS(lta) \
|
||||
TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
{.msg = {{0x1D2, 0, 8, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 33U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x224, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 40U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define TOYOTA_SECOC_RX_CHECKS \
|
||||
TOYOTA_COMMON_RX_CHECKS(false) \
|
||||
{.msg = {{0x176, 0, 8, .ignore_counter = true, .frequency = 32U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x116, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 42U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x101, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
#define TOYOTA_SECOC_RX_CHECKS \
|
||||
TOYOTA_COMMON_RX_CHECKS(false) \
|
||||
{.msg = {{0x176, 0, 8, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 32U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x116, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 42U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x101, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define TOYOTA_PCM_CRUISE_2_ADDR_CHECK \
|
||||
{.msg = {{0x1D3, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 33U}, { 0 }, { 0 }}}, \
|
||||
#define TOYOTA_PCM_CRUISE_2_ADDR_CHECK \
|
||||
{.msg = {{0x1D3, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 33U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define TOYOTA_DSU_CRUISE_ADDR_CHECK \
|
||||
{.msg = {{0x365, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 5U}, { 0 }, { 0 }}}, \
|
||||
#define TOYOTA_DSU_CRUISE_ADDR_CHECK \
|
||||
{.msg = {{0x365, 0, 7, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 5U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static bool toyota_secoc = false;
|
||||
static bool toyota_alt_brake = false;
|
||||
@@ -173,7 +173,7 @@ static void toyota_rx_hook(const CANPacket_t *to_push) {
|
||||
// check that all wheel speeds are at zero value
|
||||
vehicle_moving = speed != 0;
|
||||
|
||||
UPDATE_VEHICLE_SPEED(speed / 4.0 * 0.01 / 3.6);
|
||||
UPDATE_VEHICLE_SPEED(speed / 4.0 * 0.01 * KPH_TO_MS);
|
||||
}
|
||||
|
||||
if (addr == 0x1D3) {
|
||||
|
||||
@@ -17,13 +17,13 @@ static safety_config volkswagen_mqb_init(uint16_t param) {
|
||||
{MSG_ACC_02, 0, 8, .check_relay = true}, {MSG_ACC_06, 0, 8, .check_relay = true}, {MSG_ACC_07, 0, 8, .check_relay = true}};
|
||||
|
||||
static RxCheck volkswagen_mqb_rx_checks[] = {
|
||||
{.msg = {{MSG_ESP_19, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_LH_EPS_03, 0, 8, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_ESP_05, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_TSK_06, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_20, 0, 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_14, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_GRA_ACC_01, 0, 8, .max_counter = 15U, .frequency = 33U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_ESP_19, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_LH_EPS_03, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_ESP_05, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_TSK_06, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_20, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_14, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_GRA_ACC_01, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 33U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
UNUSED(param);
|
||||
|
||||
@@ -59,12 +59,12 @@ static safety_config volkswagen_pq_init(uint16_t param) {
|
||||
{MSG_ACC_SYSTEM, 0, 8, .check_relay = true}, {MSG_ACC_GRA_ANZEIGE, 0, 8, .check_relay = true}};
|
||||
|
||||
static RxCheck volkswagen_pq_rx_checks[] = {
|
||||
{.msg = {{MSG_LENKHILFE_3, 0, 6, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_BREMSE_1, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_3, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_5, 0, 8, .ignore_counter = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_GRA_NEU, 0, 4, .max_counter = 15U, .frequency = 30U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_LENKHILFE_3, 0, 6, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_BREMSE_1, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_2, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_3, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_5, 0, 8, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_GRA_NEU, 0, 4, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 30U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
UNUSED(param);
|
||||
|
||||
@@ -180,10 +180,10 @@ static bool rx_msg_safety_check(const CANPacket_t *to_push,
|
||||
}
|
||||
|
||||
// quality flag check
|
||||
if ((safety_hooks->get_quality_flag_valid != NULL) && cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].quality_flag) {
|
||||
if ((safety_hooks->get_quality_flag_valid != NULL) && !cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].ignore_quality_flag) {
|
||||
cfg->rx_checks[index].status.valid_quality_flag = safety_hooks->get_quality_flag_valid(to_push);
|
||||
} else {
|
||||
cfg->rx_checks[index].status.valid_quality_flag = true;
|
||||
cfg->rx_checks[index].status.valid_quality_flag = cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].ignore_quality_flag;
|
||||
}
|
||||
}
|
||||
return is_msg_valid(cfg->rx_checks, index);
|
||||
@@ -525,7 +525,7 @@ void update_sample(struct sample_t *sample, int sample_new) {
|
||||
}
|
||||
}
|
||||
|
||||
bool max_limit_check(int val, const int MAX_VAL, const int MIN_VAL) {
|
||||
static bool max_limit_check(int val, const int MAX_VAL, const int MIN_VAL) {
|
||||
return (val > MAX_VAL) || (val < MIN_VAL);
|
||||
}
|
||||
|
||||
@@ -790,12 +790,8 @@ bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const
|
||||
|
||||
// check not above ISO 11270 lateral accel assuming worst case road roll
|
||||
if (limits.angle_is_curvature) {
|
||||
// ISO 11270
|
||||
static const float ISO_LATERAL_ACCEL = 3.0; // m/s^2
|
||||
|
||||
// Limit to average banked road since safety doesn't have the roll
|
||||
static const float EARTH_G = 9.81;
|
||||
static const float AVERAGE_ROAD_ROLL = 0.06; // ~3.4 degrees, 6% superelevation
|
||||
static const float MAX_LATERAL_ACCEL = ISO_LATERAL_ACCEL - (EARTH_G * AVERAGE_ROAD_ROLL); // ~2.4 m/s^2
|
||||
|
||||
// Allow small tolerance by using minimum speed and rounding curvature up
|
||||
@@ -833,6 +829,67 @@ bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const
|
||||
return violation;
|
||||
}
|
||||
|
||||
static float get_curvature_factor(const float speed, const AngleSteeringParams params) {
|
||||
return 1. / (1. - (params.slip_factor * (speed * speed))) / params.wheelbase;
|
||||
}
|
||||
|
||||
bool steer_angle_cmd_checks_vm(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits,
|
||||
const AngleSteeringParams params) {
|
||||
// This check uses a simple vehicle model to allow for true lateral acceleration and jerk limits.
|
||||
// TODO: remove the inaccurate breakpoint angle limiting function above and always use this one
|
||||
|
||||
static const float RAD_TO_DEG = 57.29577951308232;
|
||||
|
||||
// Highway curves are rolled in the direction of the turn, add tolerance to compensate
|
||||
static const float MAX_LATERAL_ACCEL = ISO_LATERAL_ACCEL + (EARTH_G * AVERAGE_ROAD_ROLL); // ~3.6 m/s^2
|
||||
// Lower than ISO 11270 lateral jerk limit, which is 5.0 m/s^3
|
||||
static const float MAX_LATERAL_JERK = 3.0 + (EARTH_G * AVERAGE_ROAD_ROLL); // ~3.6 m/s^3
|
||||
|
||||
const float fudged_speed = (vehicle_speed.min / VEHICLE_SPEED_FACTOR) - 1.;
|
||||
const float curvature_factor = get_curvature_factor(fudged_speed, params);
|
||||
|
||||
bool violation = false;
|
||||
|
||||
if (is_lat_active() && steer_control_enabled) {
|
||||
// *** ISO lateral jerk limit ***
|
||||
// calculate maximum angle rate per second
|
||||
const float speed = MAX(fudged_speed, 1.0);
|
||||
const float max_curvature_rate_sec = MAX_LATERAL_JERK / (speed * speed);
|
||||
const float max_angle_rate_sec = max_curvature_rate_sec * params.steer_ratio / curvature_factor * RAD_TO_DEG;
|
||||
|
||||
// finally get max angle delta per frame
|
||||
const float max_angle_delta = max_angle_rate_sec * (0.01f * 2.0f); // 50 Hz
|
||||
const int max_angle_delta_can = (max_angle_delta * limits.angle_deg_to_can) + 1.;
|
||||
|
||||
// NOTE: symmetric up and down limits
|
||||
const int highest_desired_angle = desired_angle_last + max_angle_delta_can;
|
||||
const int lowest_desired_angle = desired_angle_last - max_angle_delta_can;
|
||||
|
||||
violation |= max_limit_check(desired_angle, highest_desired_angle, lowest_desired_angle);
|
||||
|
||||
// *** ISO lateral accel limit ***
|
||||
const float max_curvature = MAX_LATERAL_ACCEL / (speed * speed);
|
||||
const float max_angle = max_curvature * params.steer_ratio / curvature_factor * RAD_TO_DEG;
|
||||
const int max_angle_can = (max_angle * limits.angle_deg_to_can) + 1.;
|
||||
|
||||
violation |= max_limit_check(desired_angle, max_angle_can, -max_angle_can);
|
||||
}
|
||||
desired_angle_last = desired_angle;
|
||||
|
||||
// Angle should either be 0 or same as current angle while not steering
|
||||
if (!steer_control_enabled) {
|
||||
const int max_inactive_angle = CLAMP(angle_meas.max, -limits.max_angle, limits.max_angle) + 1;
|
||||
const int min_inactive_angle = CLAMP(angle_meas.min, -limits.max_angle, limits.max_angle) - 1;
|
||||
violation |= (limits.inactive_angle_is_zero ? (desired_angle != 0) :
|
||||
max_limit_check(desired_angle, max_inactive_angle, min_inactive_angle));
|
||||
}
|
||||
|
||||
// No angle control allowed when controls are not allowed
|
||||
violation |= !is_lat_active() && steer_control_enabled;
|
||||
|
||||
return violation;
|
||||
}
|
||||
|
||||
void pcm_cruise_check(bool cruise_engaged) {
|
||||
// Enter controls on rising edge of stock ACC, exit controls if stock ACC disengages
|
||||
if (!cruise_engaged) {
|
||||
@@ -843,3 +900,13 @@ void pcm_cruise_check(bool cruise_engaged) {
|
||||
}
|
||||
cruise_engaged_prev = cruise_engaged;
|
||||
}
|
||||
|
||||
void speed_mismatch_check(const float speed_2) {
|
||||
// Disable controls if speeds from two sources are too far apart.
|
||||
// For safety modes that use speed to adjust torque or angle limits
|
||||
const float MAX_SPEED_DELTA = 2.0; // m/s
|
||||
bool is_invalid_speed = ABS(speed_2 - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) > MAX_SPEED_DELTA;
|
||||
if (is_invalid_speed) {
|
||||
controls_allowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,15 @@ extern const int MAX_WRONG_COUNTERS;
|
||||
#define VEHICLE_SPEED_FACTOR 1000.0
|
||||
#define MAX_TORQUE_RT_INTERVAL 250000U
|
||||
|
||||
// Conversions
|
||||
#define KPH_TO_MS (1.0 / 3.6)
|
||||
|
||||
// Lateral constants
|
||||
// ISO 11270
|
||||
static const float ISO_LATERAL_ACCEL = 3.0; // m/s^2
|
||||
|
||||
static const float EARTH_G = 9.81;
|
||||
static const float AVERAGE_ROAD_ROLL = 0.06; // ~3.4 degrees, 6% superelevation
|
||||
|
||||
// sample struct that keeps 6 samples in memory
|
||||
struct sample_t {
|
||||
@@ -133,6 +142,13 @@ typedef struct {
|
||||
const bool inactive_angle_is_zero; // if false, enforces angle near meas when disabled (default)
|
||||
} AngleSteeringLimits;
|
||||
|
||||
// parameters for lateral accel/jerk angle limiting using a simple vehicle model
|
||||
typedef struct {
|
||||
const float slip_factor;
|
||||
const float steer_ratio;
|
||||
const float wheelbase;
|
||||
} AngleSteeringParams;
|
||||
|
||||
typedef struct {
|
||||
// acceleration cmd limits
|
||||
const int max_accel;
|
||||
@@ -162,7 +178,7 @@ typedef struct {
|
||||
const bool ignore_checksum; // checksum check is not performed when set to true
|
||||
const bool ignore_counter; // counter check is not performed when set to true
|
||||
const uint8_t max_counter; // maximum value of the counter. 0 means that the counter check is skipped
|
||||
const bool quality_flag; // true is quality flag check is performed
|
||||
const bool ignore_quality_flag; // true if quality flag check is skipped
|
||||
const uint32_t frequency; // expected frequency of the message [Hz]
|
||||
} CanMsgCheck;
|
||||
|
||||
@@ -217,7 +233,6 @@ bool safety_rx_hook(const CANPacket_t *to_push);
|
||||
bool safety_tx_hook(CANPacket_t *to_send);
|
||||
int to_signed(int d, int bits);
|
||||
void update_sample(struct sample_t *sample, int sample_new);
|
||||
bool max_limit_check(int val, const int MAX_VAL, const int MIN_VAL);
|
||||
bool get_longitudinal_allowed(void);
|
||||
int ROUND(float val);
|
||||
void gen_crc_lookup_table_8(uint8_t poly, uint8_t crc_lut[]);
|
||||
@@ -226,12 +241,15 @@ void gen_crc_lookup_table_16(uint16_t poly, uint16_t crc_lut[]);
|
||||
#endif
|
||||
bool steer_torque_cmd_checks(int desired_torque, int steer_req, const TorqueSteeringLimits limits);
|
||||
bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits);
|
||||
bool steer_angle_cmd_checks_vm(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits,
|
||||
const AngleSteeringParams params);
|
||||
bool longitudinal_accel_checks(int desired_accel, const LongitudinalLimits limits);
|
||||
bool longitudinal_speed_checks(int desired_speed, const LongitudinalLimits limits);
|
||||
bool longitudinal_gas_checks(int desired_gas, const LongitudinalLimits limits);
|
||||
bool longitudinal_transmission_rpm_checks(int desired_transmission_rpm, const LongitudinalLimits limits);
|
||||
bool longitudinal_brake_checks(int desired_brake, const LongitudinalLimits limits);
|
||||
void pcm_cruise_check(bool cruise_engaged);
|
||||
void speed_mismatch_check(const float speed_2);
|
||||
|
||||
void safety_tick(const safety_config *safety_config);
|
||||
|
||||
|
||||
@@ -115,4 +115,4 @@ extern void m_update_button_state(ButtonStateTracking *button_state);
|
||||
extern void m_update_binary_state(BinaryStateTracking *state);
|
||||
extern void m_update_control_state(void);
|
||||
|
||||
bool is_lat_active(void);
|
||||
extern bool is_lat_active(void);
|
||||
|
||||
@@ -16,6 +16,9 @@ MAX_WRONG_COUNTERS = 5
|
||||
MAX_SAMPLE_VALS = 6
|
||||
VEHICLE_SPEED_FACTOR = 1000
|
||||
|
||||
# Max allowed delta between car speeds
|
||||
MAX_SPEED_DELTA = 2.0 # m/s
|
||||
|
||||
MessageFunction = Callable[[float], libsafety_py.CANPacket]
|
||||
|
||||
|
||||
@@ -920,6 +923,10 @@ class PandaCarSafetyTest(PandaSafetyTest, MadsSafetyTestBase):
|
||||
def _speed_msg(self, speed):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _speed_msg_2(self, speed: float):
|
||||
pass
|
||||
|
||||
# Safety modes can override if vehicle_moving is driven by a different message
|
||||
def _vehicle_moving_msg(self, speed: float):
|
||||
return self._speed_msg(speed)
|
||||
@@ -1060,6 +1067,21 @@ class PandaCarSafetyTest(PandaSafetyTest, MadsSafetyTestBase):
|
||||
self._rx(self._vehicle_moving_msg(self.STANDSTILL_THRESHOLD + 1))
|
||||
self.assertTrue(self.safety.get_vehicle_moving())
|
||||
|
||||
def test_rx_hook_speed_mismatch(self):
|
||||
if self._speed_msg_2(0) is None:
|
||||
raise unittest.SkipTest("No second speed message for this safety mode")
|
||||
|
||||
for speed in np.arange(0, 40, 0.5):
|
||||
for speed_delta in np.arange(-5, 5, 0.1):
|
||||
speed_2 = round(max(speed + speed_delta, 0), 1)
|
||||
# Set controls allowed in between rx since first message can reset it
|
||||
self._rx(self._speed_msg(speed))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._speed_msg_2(speed_2))
|
||||
|
||||
within_delta = abs(speed - speed_2) <= MAX_SPEED_DELTA
|
||||
self.assertEqual(self.safety.get_controls_allowed(), within_delta)
|
||||
|
||||
def test_safety_tick(self):
|
||||
self.safety.set_timer(int(2e6))
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
@@ -4,6 +4,11 @@ set -e
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
: "${CPPCHECK_DIR:=$DIR/cppcheck/}"
|
||||
|
||||
# skip if we're running in parallel with test_mutation.py
|
||||
if [ ! -z "$OPENDBC_ROOT" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -d "$CPPCHECK_DIR" ]; then
|
||||
git clone https://github.com/danmar/cppcheck.git $CPPCHECK_DIR
|
||||
fi
|
||||
|
||||
@@ -14,20 +14,15 @@ NC='\033[0m'
|
||||
: "${CPPCHECK_DIR:=$DIR/cppcheck/}"
|
||||
|
||||
# ensure checked in coverage table is up to date
|
||||
if [ -z "$SKIP_TABLES_DIFF" ]; then
|
||||
python3 $CPPCHECK_DIR/addons/misra.py -generate-table > coverage_table
|
||||
if ! git diff --quiet coverage_table; then
|
||||
echo -e "${YELLOW}MISRA coverage table doesn't match. Update and commit:${NC}"
|
||||
exit 3
|
||||
fi
|
||||
python3 $CPPCHECK_DIR/addons/misra.py -generate-table > coverage_table
|
||||
if ! git diff --quiet coverage_table; then
|
||||
echo -e "${YELLOW}MISRA coverage table doesn't match. Update and commit:${NC}"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
cd $BASEDIR
|
||||
if [ -z "${SKIP_BUILD}" ]; then
|
||||
scons -j8
|
||||
fi
|
||||
|
||||
CHECKLIST=$DIR/checkers.txt
|
||||
CHECKLIST=$(mktemp)
|
||||
echo "Cppcheck checkers list from test_misra.sh:" > $CHECKLIST
|
||||
|
||||
cppcheck() {
|
||||
@@ -35,12 +30,13 @@ cppcheck() {
|
||||
COMMON_DEFINES="-D__GNUC__=9"
|
||||
|
||||
# note that cppcheck build cache results in inconsistent results as of v2.13.0
|
||||
OUTPUT=$DIR/.output.log
|
||||
OUTPUT=$(mktemp)
|
||||
|
||||
echo -e "\n\n\n\n\nTEST variant options:" >> $CHECKLIST
|
||||
echo -e ""${@//$BASEDIR/}"\n\n" >> $CHECKLIST # (absolute path removed)
|
||||
|
||||
$CPPCHECK_DIR/cppcheck --inline-suppr -I $BASEDIR \
|
||||
OPENDBC_ROOT=${OPENDBC_ROOT:-$BASEDIR}
|
||||
$CPPCHECK_DIR/cppcheck --inline-suppr -I $OPENDBC_ROOT \
|
||||
-I "$(gcc -print-file-name=include)" --suppress=*:*gcc*include/* --suppress=*:*clang*include/* \
|
||||
--suppressions-list=$DIR/suppressions.txt \
|
||||
--error-exitcode=2 --check-level=exhaustive --safety \
|
||||
@@ -65,8 +61,11 @@ cppcheck $PANDA_OPTS -DCANFD $BASEDIR/opendbc/safety/main.c
|
||||
printf "\n${GREEN}Success!${NC} took $SECONDS seconds\n"
|
||||
|
||||
# ensure list of checkers is up to date
|
||||
cd $DIR
|
||||
if [ -z "$SKIP_TABLES_DIFF" ] && ! git diff --quiet $CHECKLIST; then
|
||||
echo -e "\n${YELLOW}WARNING: Cppcheck checkers.txt report has changed. Review and commit...${NC}"
|
||||
exit 4
|
||||
if [ -z "$OPENDBC_ROOT" ]; then
|
||||
cd $DIR
|
||||
if ! git diff --quiet $CHECKLIST; then
|
||||
echo -e "\n${YELLOW}WARNING: Cppcheck checkers.txt report has changed. Review and commit...${NC}"
|
||||
mv $CHECKLIST $DIR/checkers.txt
|
||||
exit 4
|
||||
fi
|
||||
fi
|
||||
|
||||
61
opendbc/safety/tests/misra/test_mutation.py
Executable file → Normal file
61
opendbc/safety/tests/misra/test_mutation.py
Executable file → Normal file
@@ -11,38 +11,27 @@ HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
ROOT = os.path.join(HERE, "../../../../")
|
||||
|
||||
IGNORED_PATHS = (
|
||||
'opendbc/safety/main.c',
|
||||
'opendbc/safety/tests/',
|
||||
'opendbc/safety/board/',
|
||||
)
|
||||
|
||||
mutations = [
|
||||
# default
|
||||
(None, None, False),
|
||||
# general safety
|
||||
("opendbc/safety/modes/toyota.h", "s/if (addr == 0x260) {/if (addr == 1 || addr == 2) {/g", True),
|
||||
# no mutation, should pass
|
||||
(None, None, lambda s: s, False),
|
||||
]
|
||||
|
||||
patterns = [
|
||||
# misra-c2012-13.3
|
||||
"$a void test(int tmp) { int tmp2 = tmp++ + 2; if (tmp2) {;}}",
|
||||
# misra-c2012-13.4
|
||||
"$a int test(int x, int y) { return (x=2) && (y=2); }",
|
||||
# misra-c2012-13.5
|
||||
"$a void test(int tmp) { if (true && tmp++) {;} }",
|
||||
# misra-c2012-13.6
|
||||
"$a void test(int tmp) { if (sizeof(tmp++)) {;} }",
|
||||
# misra-c2012-14.1
|
||||
"$a void test(float len) { for (float j = 0; j < len; j++) {;} }",
|
||||
# misra-c2012-14.4
|
||||
"$a void test(int len) { if (len - 8) {;} }",
|
||||
# misra-c2012-16.4
|
||||
r"$a void test(int temp) {switch (temp) { case 1: ; }}\n",
|
||||
# misra-c2012-17.8
|
||||
"$a void test(int cnt) { for (cnt=0;;cnt++) {;} }",
|
||||
# misra-c2012-20.4
|
||||
r"$a #define auto 1\n",
|
||||
# misra-c2012-20.5
|
||||
r"$a #define TEST 1\n#undef TEST\n",
|
||||
("misra-c2012-10.3", lambda s: s + "\nvoid test(float len) { for (float j = 0; j < len; j++) {;} }\n"),
|
||||
("misra-c2012-13.3", lambda s: s + "\nvoid test(int tmp) { int tmp2 = tmp++ + 2; if (tmp2) {;}}\n"),
|
||||
("misra-c2012-13.4", lambda s: s + "\nint test(int x, int y) { return (x=2) && (y=2); }\n"),
|
||||
("misra-c2012-13.5", lambda s: s + "\nvoid test(int tmp) { if (true && tmp++) {;} }\n"),
|
||||
("misra-c2012-13.6", lambda s: s + "\nvoid test(int tmp) { if (sizeof(tmp++)) {;} }\n"),
|
||||
("misra-c2012-14.2", lambda s: s + "\nvoid test(int cnt) { for (cnt=0;;cnt++) {;} }\n"),
|
||||
("misra-c2012-14.4", lambda s: s + "\nvoid test(int len) { if (len - 8) {;} }\n"),
|
||||
("misra-c2012-16.4", lambda s: s + "\nvoid test(int temp) {switch (temp) { case 1: ; }}\n"),
|
||||
("misra-c2012-20.4", lambda s: s + "\n#define auto 1\n"),
|
||||
("misra-c2012-20.5", lambda s: s + "\n#define TEST 1\n#undef TEST\n"),
|
||||
]
|
||||
|
||||
all_files = glob.glob('opendbc/safety/**', root_dir=ROOT, recursive=True)
|
||||
@@ -50,20 +39,28 @@ files = [f for f in all_files if f.endswith(('.c', '.h')) and not f.startswith(I
|
||||
assert len(files) > 20, files
|
||||
|
||||
for p in patterns:
|
||||
mutations.append((random.choice(files), p, True))
|
||||
mutations.append((random.choice(files), *p, True))
|
||||
|
||||
@pytest.mark.parametrize("fn, patch, should_fail", mutations)
|
||||
def test_misra_mutation(fn, patch, should_fail):
|
||||
mutations = random.sample(mutations, 2) # can remove this once cppcheck is faster
|
||||
|
||||
@pytest.mark.parametrize("fn, rule, transform, should_fail", mutations)
|
||||
def test_misra_mutation(fn, rule, transform, should_fail):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
shutil.copytree(ROOT, tmp, dirs_exist_ok=True)
|
||||
shutil.rmtree(os.path.join(tmp, '.venv'), ignore_errors=True)
|
||||
shutil.copytree(ROOT, tmp, dirs_exist_ok=True,
|
||||
ignore=shutil.ignore_patterns('.venv', 'cppcheck', '.git', '*.ctu-info'))
|
||||
|
||||
# apply patch
|
||||
if fn is not None:
|
||||
r = os.system(f"cd {tmp} && sed -i '{patch}' {fn}")
|
||||
assert r == 0
|
||||
with open(os.path.join(tmp, fn), 'r+') as f:
|
||||
content = f.read()
|
||||
f.seek(0)
|
||||
f.write(transform(content))
|
||||
|
||||
# run test
|
||||
r = subprocess.run("SKIP_TABLES_DIFF=1 SKIP_BUILD=1 opendbc/safety/tests/misra/test_misra.sh", cwd=tmp, shell=True)
|
||||
r = subprocess.run(f"OPENDBC_ROOT={tmp} opendbc/safety/tests/misra/test_misra.sh",
|
||||
stdout=subprocess.PIPE, cwd=ROOT, shell=True, encoding='utf8')
|
||||
print(r.stdout) # helpful for debugging failures
|
||||
failed = r.returncode != 0
|
||||
assert failed == should_fail
|
||||
if should_fail:
|
||||
assert rule in r.stdout, "MISRA test failed but not for the correct violation"
|
||||
@@ -13,4 +13,4 @@ echo -e "$MULL_OPS" > $GIT_ROOT/mull.yml
|
||||
scons --mutation -j$(nproc) -D
|
||||
echo -e "timeout: 60000\ngitDiffRef: $GIT_REF\ngitProjectRoot: $GIT_ROOT" >> $GIT_ROOT/mull.yml
|
||||
|
||||
mull-runner-17 --ld-search-path /lib/x86_64-linux-gnu/ ./libsafety/libsafety.so -test-program=pytest -- -n8
|
||||
mull-runner-17 --ld-search-path /lib/x86_64-linux-gnu/ ./libsafety/libsafety.so -test-program=pytest -- -n8 --ignore-glob=misra/*
|
||||
|
||||
@@ -73,9 +73,6 @@ class TestFordSafetyBase(common.PandaCarSafetyTest):
|
||||
FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl,
|
||||
MSG_LateralMotionControl2, MSG_IPMA_Data]}
|
||||
|
||||
# Max allowed delta between car speeds
|
||||
MAX_SPEED_DELTA = 2.0 # m/s
|
||||
|
||||
STEER_MESSAGE = 0
|
||||
|
||||
# Curvature control limits
|
||||
@@ -130,6 +127,7 @@ class TestFordSafetyBase(common.PandaCarSafetyTest):
|
||||
|
||||
# PCM vehicle speed
|
||||
def _speed_msg_2(self, speed: float, quality_flag=True):
|
||||
# Ford relies on speed for driver curvature limiting, so it checks two sources
|
||||
values = {"Veh_V_ActlEng": speed * 3.6, "VehVActlEng_D_Qf": 3 if quality_flag else 0, "VehVActlEng_No_Cnt": self.cnt_speed_2 % 16}
|
||||
self.__class__.cnt_speed_2 += 1
|
||||
return self.packer.make_can_msg_panda("EngVehicleSpThrottle2", 0, values, fix_checksum=checksum)
|
||||
@@ -222,19 +220,6 @@ class TestFordSafetyBase(common.PandaCarSafetyTest):
|
||||
self.assertEqual(should_rx, self._rx(to_push))
|
||||
self.assertEqual(should_rx, self.safety.get_controls_allowed())
|
||||
|
||||
def test_rx_hook_speed_mismatch(self):
|
||||
# Ford relies on speed for driver curvature limiting, so it checks two sources
|
||||
for speed in np.arange(0, 40, 0.5):
|
||||
for speed_delta in np.arange(-5, 5, 0.1):
|
||||
speed_2 = round(max(speed + speed_delta, 0), 1)
|
||||
# Set controls allowed in between rx since first message can reset it
|
||||
self._rx(self._speed_msg(speed))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._speed_msg_2(speed_2))
|
||||
|
||||
within_delta = abs(speed - speed_2) <= self.MAX_SPEED_DELTA
|
||||
self.assertEqual(self.safety.get_controls_allowed(), within_delta)
|
||||
|
||||
def test_angle_measurements(self):
|
||||
"""Tests rx hook correctly parses the curvature measurement from the vehicle speed and yaw rate"""
|
||||
for speed in np.arange(0.5, 40, 0.5):
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import unittest
|
||||
import numpy as np
|
||||
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
@@ -40,9 +39,6 @@ class TestRivianSafetyBase(common.PandaCarSafetyTest, common.DriverTorqueSteerin
|
||||
DRIVER_TORQUE_ALLOWANCE = 100
|
||||
DRIVER_TORQUE_FACTOR = 2
|
||||
|
||||
# Max allowed delta between car speeds
|
||||
MAX_SPEED_DELTA = 2.0 # m/s
|
||||
|
||||
cnt_speed = 0
|
||||
cnt_speed_2 = 0
|
||||
|
||||
@@ -61,6 +57,7 @@ class TestRivianSafetyBase(common.PandaCarSafetyTest, common.DriverTorqueSteerin
|
||||
return self.packer.make_can_msg_panda("ESP_Status", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _speed_msg_2(self, speed, quality_flag=True):
|
||||
# Rivian has a dynamic max torque limit based on speed, so it checks two sources
|
||||
return self._user_gas_msg(0, speed, quality_flag)
|
||||
|
||||
def _user_brake_msg(self, brake):
|
||||
@@ -112,20 +109,6 @@ class TestRivianSafetyBase(common.PandaCarSafetyTest, common.DriverTorqueSteerin
|
||||
self.assertFalse(self._rx(to_push))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_rx_hook_speed_mismatch(self):
|
||||
# TODO: this can be a common test w/ Ford
|
||||
# Rivian has a dynamic max torque limit based on speed, so it checks two sources
|
||||
for speed in np.arange(0, 40, 0.5):
|
||||
for speed_delta in np.arange(-5, 5, 0.1):
|
||||
speed_2 = round(max(speed + speed_delta, 0), 1)
|
||||
# Set controls allowed in between rx since first message can reset it
|
||||
self._rx(self._speed_msg(speed))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._speed_msg_2(speed_2))
|
||||
|
||||
within_delta = abs(speed - speed_2) <= self.MAX_SPEED_DELTA
|
||||
self.assertEqual(self.safety.get_controls_allowed(), within_delta)
|
||||
|
||||
|
||||
class TestRivianStockSafety(TestRivianSafetyBase):
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from opendbc.car.vehicle_model import VehicleModel
|
||||
from opendbc.can.can_define import CANDefine
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
import opendbc.safety.tests.common as common
|
||||
from opendbc.safety.tests.common import CANPackerPanda, MAX_WRONG_COUNTERS, away_round, round_speed
|
||||
from opendbc.safety.tests.common import CANPackerPanda, MAX_SPEED_DELTA, MAX_WRONG_COUNTERS, away_round, round_speed
|
||||
|
||||
MSG_DAS_steeringControl = 0x488
|
||||
MSG_APS_eacMonitor = 0x27d
|
||||
@@ -46,9 +46,6 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
MIN_ACCEL = -3.48
|
||||
INACTIVE_ACCEL = 0.0
|
||||
|
||||
# Max allowed delta between car speeds
|
||||
MAX_SPEED_DELTA = 2.0 # m/s
|
||||
|
||||
cnt_epas = 0
|
||||
|
||||
packer: CANPackerPanda
|
||||
@@ -74,8 +71,10 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
self.__class__.cnt_epas += 1
|
||||
return self.packer.make_can_msg_panda("EPAS3S_sysStatus", 0, values)
|
||||
|
||||
def _user_brake_msg(self, brake):
|
||||
def _user_brake_msg(self, brake, quality_flag: bool = True):
|
||||
values = {"IBST_driverBrakeApply": 2 if brake else 1}
|
||||
if not quality_flag:
|
||||
values["IBST_driverBrakeApply"] = 3 # FAULT
|
||||
return self.packer.make_can_msg_panda("IBST_status", 0, values)
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
@@ -159,7 +158,7 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
self.safety.get_vehicle_speed_min, self.safety.get_vehicle_speed_max)
|
||||
|
||||
def test_rx_hook_speed_mismatch(self):
|
||||
# TODO: this can be a common test w/ Ford
|
||||
# TODO: overridden because of custom rounding
|
||||
# Tesla relies on speed for lateral limits close to ISO 11270, so it checks two sources
|
||||
for speed in np.arange(0, 40, 0.5):
|
||||
# match signal rounding on CAN
|
||||
@@ -173,7 +172,7 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.assertTrue(self._rx(self._speed_msg_2(speed_2)))
|
||||
|
||||
within_delta = abs(speed - speed_2) <= self.MAX_SPEED_DELTA
|
||||
within_delta = abs(speed - speed_2) <= MAX_SPEED_DELTA
|
||||
self.assertEqual(self.safety.get_controls_allowed(), within_delta)
|
||||
|
||||
# Test ESP_B quality flag
|
||||
@@ -183,6 +182,11 @@ class TestTeslaSafetyBase(common.PandaCarSafetyTest, common.AngleSteeringSafetyT
|
||||
self.assertEqual(quality_flag, self._rx(self._speed_msg_2(0, quality_flag=quality_flag)))
|
||||
self.assertEqual(quality_flag, self.safety.get_controls_allowed())
|
||||
|
||||
def test_user_brake_quality_flag(self):
|
||||
for quality_flag in (True, False):
|
||||
to_push = self._user_brake_msg(True, quality_flag=quality_flag)
|
||||
self.assertEqual(quality_flag, self._rx(to_push))
|
||||
|
||||
def test_steering_wheel_disengage(self):
|
||||
# Tesla disengages when the user forcibly overrides the locked-in angle steering control
|
||||
# Either when the hands on level is high, or if there is a high angle rate fault
|
||||
|
||||
Reference in New Issue
Block a user