Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot] 7d08d3bcd1 sunnypilot v2026.08.07-4624
version: sunnypilot v2026.003.000 (feature-branch)
date: 2026-08-07T19:37:28
master commit: 5655fb3a6c
2026-08-07 19:37:28 +00:00
443 changed files with 17079 additions and 22916 deletions
-1
View File
@@ -2,6 +2,5 @@ Wen
REGIST
PullRequest
cancelled
indeces
FOF
NoO
Binary file not shown.
-42
View File
@@ -1,42 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach LLDB to Python",
"type": "lldb",
"request": "attach",
"pid": "${command:pickMyProcess}",
"initCommands": [
"script import time; time.sleep(5)"
]
},
{
"name": "Python Launch",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/opendbc/safety/tests/safety_replay/replay_drive.py",
"args": [
"e1107f9d04dfb1e2/0000045c--da2e374469"
],
"console": "integratedTerminal",
"justMyCode": false,
"debugOptions": [
"RedirectOutput"
],
"env": {
"PYTHONPATH": "${workspaceFolder}"
},
"subProcess": true,
"stopOnEntry": false
}
],
"compounds": [
{
"name": "Python + Native (LLDB)",
"configurations": [
"Python Launch",
"Attach LLDB to Python"
]
}
]
}
+1 -1
View File
@@ -18,7 +18,7 @@ test:
ty:
run: ty check
codespell:
run: codespell {files} -L tge,stdio -S "*.dbc,*.ipynb" --ignore-words=.codespellignore
run: codespell {files} -L tge,stdio -S *.dbc --ignore-words=.codespellignore
files: git ls-tree -r HEAD --name-only
cpplint:
run: cpplint --exclude=opendbc/can/*_pyx.cpp --recursive --quiet --counting=detailed --linelength=240 --filter=-build,-legal,-readability,-runtime,-whitespace,+build/include_subdir,+build/forward_decl,+build/include_what_you_use,+build/deprecated,+whitespace/comma,+whitespace/line_length,+whitespace/empty_if_body,+whitespace/empty_loop_body,+whitespace/empty_conditional_body,+whitespace/forcolon,+whitespace/parens,+whitespace/semicolon,+whitespace/tab,+readability/braces opendbc/
@@ -307,14 +307,9 @@ opendbc/dbc/generator/honda/honda_e_advance_2020_can.dbc
opendbc/dbc/generator/honda/honda_insight_ex_2019_can.dbc
opendbc/dbc/generator/honda/honda_odyssey_exl_2018.dbc
opendbc/dbc/generator/honda/honda_odyssey_twn_2018.dbc
opendbc/dbc/generator/hyundai/_20240705_STD_DB_CAR_R2-0_2024_FD_C_v24-05-01_SFA_RWA.dbc
opendbc/dbc/generator/hyundai/_hyundai_canfd_ccnc_og.dbc
opendbc/dbc/generator/hyundai/_hyundai_canfd_common.dbc
opendbc/dbc/generator/hyundai/_hyundai_canfd_hda2_cam_unknown.dbc
opendbc/dbc/generator/hyundai/_hyundai_reversed_ccnc_canfd.dbc
opendbc/dbc/generator/hyundai/hyundai_can.dbc
opendbc/dbc/generator/hyundai/hyundai_canfd.dbc
opendbc/dbc/generator/hyundai/hyundai_canfd_og.dbc
opendbc/dbc/generator/hyundai/hyundai_kia_mando_corner_radar.py
opendbc/dbc/generator/hyundai/hyundai_kia_mando_front_radar.py
opendbc/dbc/generator/hyundai/hyundai_palisade_2023.dbc
@@ -130,7 +130,6 @@ class CarHarness(EnumBase):
hyundai_p = BaseCarHarness("Hyundai P connector")
hyundai_q = BaseCarHarness("Hyundai Q connector")
hyundai_r = BaseCarHarness("Hyundai R connector")
hyundai_s = BaseCarHarness("Hyundai S connector")
custom = BaseCarHarness("Developer connector")
obd_ii = BaseCarHarness("OBD-II connector", parts=[Cable.long_obdc_cable], has_connector=False)
gm = BaseCarHarness("GM connector", parts=[Accessory.harness_box])
-1
View File
@@ -209,7 +209,6 @@ MIGRATION = {
"HYUNDAI SONATA HYBRID 2021": HYUNDAI.HYUNDAI_SONATA_HYBRID,
"HYUNDAI IONIQ 5 2022": HYUNDAI.HYUNDAI_IONIQ_5,
"HYUNDAI IONIQ 6 2023": HYUNDAI.HYUNDAI_IONIQ_6,
"HYUNDAI IONIQ 9 2025": HYUNDAI.HYUNDAI_IONIQ_9,
"HYUNDAI TUCSON 4TH GEN": HYUNDAI.HYUNDAI_TUCSON_4TH_GEN,
"HYUNDAI SANTA CRUZ 1ST GEN": HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN,
"HYUNDAI CUSTIN 1ST GEN": HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN,
@@ -1,50 +0,0 @@
# About Angle Steering, Baseline Model, and ISO Safety Limits
## Overview
The baseline vehicle model serves as our safety reference point for establishing universal control parameters across our entire vehicle fleet. This approach ensures that all vehicles operate within ISO safety standards regardless of their individual physics characteristics.
## How It Works
For any given speed and driving conditions, we query each vehicle model with the question: "What's the maximum steering angle I can apply right now while staying below the ISO standard limits for lateral acceleration and jerk?"
Each vehicle model responds differently based on its unique physics characteristics:
- **Baseline Vehicle Model**: Has the most restrictive limits - requires the smallest steering angles to stay within ISO safety thresholds
- **Current Vehicle Model**: May be able to handle larger steering angles while remaining within the same ISO safety standards, depending on its physical characteristics
## Safety Logic
Both the baseline and current vehicle models target the same ISO safety limits. The key difference is that the baseline vehicle's physics require more conservative steering inputs to stay within those standards.
By applying the baseline vehicle's more restrictive steering limits to all vehicles in the fleet:
- Every model stays well within ISO safety thresholds
- No vehicle will breach safety standards regardless of its individual characteristics
- We maintain a consistent safety margin across the entire fleet
If we instead used a less restrictive model as our baseline, any naturally more restrictive vehicles in the fleet would exceed ISO standards and create unsafe driving conditions.
## Implementation Details
### Two-Layer Validation Process
We use a two-layer validation approach to balance vehicle-specific optimization with baseline safety:
1. **Current Vehicle Model Calculation**: We first calculate the optimal steering limits from the current vehicle model, which determines the best steering angle based on that vehicle's physical characteristics and desired maneuver.
2. **Baseline Model Validation**: We then pass the current vehicle's requested steering command through the baseline model as a final safety filter.
This two-layer approach is essential because while the current vehicle model may generally be more capable, it might sometimes request smaller jerk or lateral acceleration values to achieve specific driving goals. The baseline validation ensures that regardless of what the current vehicle requests, we never exceed the safety limits of our most restrictive vehicle.
### Special Case: Driving the Baseline Vehicle
When actually driving the baseline vehicle itself (e.g., Santa Fe), we apply an additional 80% ISO cap since that vehicle would otherwise operate right at the ISO safety threshold. This extra margin ensures safe operation even for our most restrictive vehicle model.
## Example Implementation
### Baseline Vehicle: Hyundai Santa Fe
Due to its physics characteristics, the Santa Fe requires smaller steering angles to remain within ISO safety limits.
### Current Vehicle: Ioniq 5 PE
Due to different physical characteristics, the Ioniq 5 PE can handle larger steering angles while still remaining within the same ISO safety standards.
By using the Santa Fe's conservative limits across all vehicles, we ensure the Ioniq 5 PE operates well within its capabilities, while preventing the Santa Fe from exceeding its safety thresholds.
@@ -1,10 +1,7 @@
import numpy as np
from opendbc.car.vehicle_model import VehicleModel
from opendbc.car.common.filter_simple import FirstOrderFilter
from opendbc.can import CANPacker
from opendbc.car import Bus, DT_CTRL, make_tester_present_msg, structs, rate_limit
from opendbc.car.lateral import apply_driver_steer_torque_limits, common_fault_avoidance, apply_steer_angle_limits_vm
from opendbc.car import Bus, DT_CTRL, make_tester_present_msg, structs
from opendbc.car.lateral import apply_driver_steer_torque_limits, common_fault_avoidance
from opendbc.car.common.conversions import Conversions as CV
from opendbc.car.hyundai import hyundaicanfd, hyundaican
from opendbc.car.hyundai.hyundaicanfd import CanBus
@@ -32,31 +29,6 @@ MAX_ANGLE_CONSECUTIVE_FRAMES = 2
# naturally on brake press. We send ~100 ms later if it fails to do so, or if we want to cancel for another reason.
CANCEL_BUTTON_DELAY_FRAMES = 10
MAX_ANGLE_RATE = 5
ANGLE_SAFETY_BASELINE_MODEL = "KIA_SPORTAGE_HEV_2026"
def get_baseline_safety_cp():
from opendbc.car.hyundai.interface import CarInterface
return CarInterface.get_non_essential_params(ANGLE_SAFETY_BASELINE_MODEL)
def compute_torque_reduction_gain(steering_torque, v_ego, lat_active, last_gain):
if lat_active:
ceiling = np.interp(v_ego, [0.5, 1.5], [1.0, 0.85])
shelf = np.interp(v_ego, [2, 11], [0.45, 0.6])
floor = np.interp(v_ego, [2, 22], [0.1, 0.3])
bp1 = np.interp(v_ego, [2, 11], [75, 125])
bp2 = np.interp(v_ego, [2, 11], [125, 150])
bp3 = np.interp(v_ego, [2, 11], [175, 275])
bp4 = np.interp(v_ego, [2, 22], [400, 700])
target = np.interp(abs(steering_torque), [bp1, bp2, bp3, bp4], [ceiling, shelf, shelf, floor])
else:
target = 0.0
gain = rate_limit(target, last_gain, -0.014, 0.004)
return round(gain / 0.004) * 0.004
def process_hud_alert(enabled, fingerprint, hud_control):
sys_warning = (hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw))
@@ -82,21 +54,6 @@ def process_hud_alert(enabled, fingerprint, hud_control):
return sys_warning, sys_state, left_lane_warning, right_lane_warning
def parse_tq_rdc_gain(val):
"""
Returns the float value divided by 100 if val is not None, else returns None.
"""
if val is not None:
return float(val) / 100
return None
def parse_scaled_value(val, scale=10):
if val is not None:
return float(val) / scale
return None
class CarController(CarControllerBase, EsccCarController, LeadDataCarController, LongitudinalController, MadsCarController,
IntelligentCruiseButtonManagementInterface):
def __init__(self, dbc_names, CP, CP_SP):
@@ -110,12 +67,6 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
self.params = CarControllerParams(CP)
self.packer = CANPacker(dbc_names[Bus.pt])
self.angle_limit_counter = 0
self.angle_filter = FirstOrderFilter(0.0, 0.2, DT_CTRL)
# Vehicle model used for lateral limiting
self.VM = VehicleModel(CP)
self.BASELINE_VM = VehicleModel(get_baseline_safety_cp())
self.apply_angle_last = 0
self.accel_last = 0
self.apply_torque_last = 0
@@ -123,8 +74,6 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
self.last_button_frame = 0
self.cancel_counter = 0
self.apply_angle_last = 0
def update(self, CC, CC_SP, CS, now_nanos):
EsccCarController.update(self, CS)
LeadDataCarController.update(self, CC_SP)
@@ -136,43 +85,13 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
hud_control = CC.hudControl
# steering torque
if not self.CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
self.angle_limit_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringAngleDeg) >= MAX_ANGLE, CC.latActive,
self.angle_limit_counter, MAX_ANGLE_FRAMES,
MAX_ANGLE_CONSECUTIVE_FRAMES)
new_torque = int(round(actuators.torque * self.params.STEER_MAX))
apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params)
new_torque = int(round(actuators.torque * self.params.STEER_MAX))
apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params)
# angle control
else:
v_ego_raw = CS.out.vEgoRaw
desired_angle = float(np.clip(actuators.steeringAngleDeg, -self.params.ANGLE_LIMITS.STEER_ANGLE_MAX, self.params.ANGLE_LIMITS.STEER_ANGLE_MAX))
self.angle_filter.update_alpha(float(np.interp(CS.out.vEgo, [5, 10, 20], [0.2, 0.1, 0.0])))
desired_angle = self.angle_filter.update(desired_angle)
apply_angle = apply_steer_angle_limits_vm(desired_angle, self.apply_angle_last, v_ego_raw, CS.out.steeringAngleDeg, CC.latActive, self.params, self.VM)
# if we are not the baseline model, we use the baseline model for further limits to prevent a panda block since it is hardcoded for baseline model.
if self.CP.carFingerprint != ANGLE_SAFETY_BASELINE_MODEL:
apply_angle = apply_steer_angle_limits_vm(apply_angle or desired_angle, self.apply_angle_last, v_ego_raw, CS.out.steeringAngleDeg, CC.latActive,
self.params, self.BASELINE_VM)
apply_torque = compute_torque_reduction_gain(CS.out.steeringTorque, v_ego_raw, CC.latActive, self.apply_torque_last)
apply_steer_req = CC.latActive and apply_torque != 0
# Failsafe if we detected we'd violate safety
if apply_angle is None:
apply_torque = 0
apply_angle = CS.out.steeringAngleDeg
apply_steer_req = False
# After we've used the last angle wherever we needed it, we now update it.
self.apply_angle_last = apply_angle
if not CC.latActive:
self.apply_angle_last = float(np.clip(CS.out.steeringAngleDeg, -self.params.ANGLE_LIMITS.STEER_ANGLE_MAX, self.params.ANGLE_LIMITS.STEER_ANGLE_MAX))
self.angle_filter.x = self.apply_angle_last
# >90 degree steering fault prevention
self.angle_limit_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringAngleDeg) >= MAX_ANGLE, CC.latActive,
self.angle_limit_counter, MAX_ANGLE_FRAMES,
MAX_ANGLE_CONSECUTIVE_FRAMES)
if not CC.latActive:
apply_torque = 0
@@ -223,7 +142,6 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
new_actuators = actuators.as_builder()
new_actuators.torque = apply_torque / self.params.STEER_MAX
new_actuators.torqueOutputCan = apply_torque
new_actuators.steeringAngleDeg = self.apply_angle_last
new_actuators.accel = self.tuning.actual_accel
self.frame += 1
@@ -284,8 +202,7 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl
# steering control
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, self.apply_angle_last
, self.lkas_icon))
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, self.lkas_icon))
# prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU
if self.frame % 5 == 0 and lka_steering:
+3 -13
View File
@@ -70,9 +70,6 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
self.cluster_speed_counter = CLUSTER_SAMPLE_RATE
self.params = CarControllerParams(CP)
self.is_canfd_angle_steering = CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING
self.imu_lateral_acceleration = 0.0 # used for CAN FD cars with angle steering
self.hands_on_steering_grip = 0
def recent_button_interaction(self) -> bool:
# On some newer model years, the CANCEL button acts as a pause/resume button based on the PCM state
@@ -253,22 +250,15 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
cp.vl["WHEEL_SPEEDS"]["WHL_SpdRLVal"] <= STANDSTILL_THRESHOLD and cp.vl["WHEEL_SPEEDS"]["WHL_SpdRRVal"] <= STANDSTILL_THRESHOLD
ret.steeringRateDeg = cp.vl["STEERING_SENSORS"]["STEERING_RATE"]
ret.steeringAngleDeg = cp.vl["MDPS"]["MDPS_EstStrAnglVal"]
ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEERING_ANGLE"]
ret.steeringTorque = cp.vl["MDPS"]["MDPS_StrTqSnsrVal"]
ret.steeringTorqueEps = cp.vl["MDPS"]["MDPS_OutTqVal"]
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
ret.steerFaultTemporary = cp.vl["MDPS"]["MDPS_LkaFailSta"] != 0
if self.is_canfd_angle_steering:
ret.steerFaultTemporary = ret.steerFaultTemporary or cp.vl["MDPS"]["MDPS_ADAS_AciFltSig_Lv2"] != 0
self.hands_on_steering_grip = cp.vl["HOD_FD_01_100ms"]["HOD_Dir_Status"]
torque_overriding = abs(ret.steeringTorque) > self.params.STEER_THRESHOLD
ret.steeringPressed = self.update_steering_pressed(torque_overriding, 5)
self.imu_lateral_acceleration = cp.vl["IMU_01_10ms"]["IMU_LatAccelVal"] * 9.81 # m/s^2
else:
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
# TODO: alt signal usage may be described by cp.vl['BLINKERS']['USE_ALT_LAMP']
left_blinker_sig, right_blinker_sig = "LEFT_LAMP", "RIGHT_LAMP"
if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN or self.is_canfd_angle_steering:
if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN:
left_blinker_sig, right_blinker_sig = "LEFT_LAMP_ALT", "RIGHT_LAMP_ALT"
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig],
cp.vl["BLINKERS"][right_blinker_sig])
@@ -41,14 +41,6 @@ FW_VERSIONS = {
b'\xf1\x00IGhe SCC FHCUP 1.00 1.02 99110-M9000 ',
],
},
CAR.HYUNDAI_AZERA_HEV_7TH_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00GN7HMFC AT KOR LHD 1.00 1.01 99211-N1110 240423',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00GN7_ RDR ----- 1.00 1.00 99110-N1100 ',
],
},
CAR.HYUNDAI_GENESIS: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00DH LKAS 1.1 -150210',
@@ -362,16 +354,6 @@ FW_VERSIONS = {
b'\xf1\x00TMP MFC AT USA LHD 1.00 1.06 99211-S1500 220727',
],
},
CAR.HYUNDAI_SANTA_FE_HEV_5TH_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00MX5HMFC AT KOR LHD 1.00 1.07 99211-P6000 231218',
b'\xf1\x00MX5HMFC AT USA LHD 1.00 1.06 99211-R6000 231218',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00MX5_ RDR ----- 1.00 1.01 99110-P6000 ',
b'\xf1\x00MX5_ RDR ----- 1.00 1.01 99110-R6000 ',
],
},
CAR.HYUNDAI_CUSTIN_1ST_GEN: {
(Ecu.abs, 0x7d1, None): [
b'\xf1\x00KU ESC \x01 101!\x02\x03 58910-O3200',
@@ -1056,34 +1038,6 @@ FW_VERSIONS = {
b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.06 99210-CV000 220328',
],
},
CAR.KIA_EV6_2025: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CV__ RDR ----- 1.00 1.00 99110-XG500 ',
b'\xf1\x00CV__ RDR ----- 1.00 1.01 99110-CV500 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00CV MFC AT KOR LHD 1.00 1.01 99210-CV500 240405',
b'\xf1\x00CV MFC AT USA LHD 1.00 1.02 99210-XG500 241223',
],
},
CAR.KIA_EV9: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00MV__ RDR ----- 1.00 1.02 99110-DO000 ',
b'\xf1\x00MV__ RDR ----- 1.00 1.03 99110-DO000 ',
b'\xf1\x00MV__ RDR ----- 1.00 1.04 99110-DO000 ',
b'\xf1\x00MV__ RDR ----- 1.00 1.02 99110-DO700 ',
b'\xf1\x00MV__ RDR ----- 1.00 1.04 99110-DO700 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00MV MFC AT KOR LHD 1.00 1.01 99211-DO000 230419',
b'\xf1\x00MV MFC AT USA LHD 1.00 1.02 99211-DO000 230616',
b'\xf1\x00MV MFC AT EUR LHD 1.00 1.02 99211-DO000 230616',
b'\xf1\x00MV MFC AT CAN LHD 1.00 1.00 99211-DO100 240403',
b'\xf1\x00MV MFC AT USA LHD 1.00 1.01 99211-XA000 241023',
b'\xf1\x00MV MFC AT CAN LHD 1.00 1.01 99211-DO100 241023',
b'\xf1\x00MV MFC AT CAN LHD 1.00 1.02 99211-DO100 241223',
],
},
CAR.HYUNDAI_IONIQ_5: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NE1_ RDR ----- 1.00 1.00 99110-GI000 ',
@@ -1115,18 +1069,6 @@ FW_VERSIONS = {
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110',
],
},
CAR.HYUNDAI_IONIQ_5_PE: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NE__ RDR ----- 1.00 1.00 99110-PI000 ',
b'\xf1\x00NE__ RDR ----- 1.00 1.01 99110-GI500 '
],
(Ecu.fwdCamera, 0x7C4, None): [
b'\xf1\x00NE MFC AT USA LHD 1.00 1.01 99211-PI000 240905',
b'\xf1\x00NE MFC AT EUR LHD 1.00 1.03 99211-GI500 240809',
b'\xf1\x00NE MFC AT USA LHD 1.00 1.00 99211-PI010 250407',
b'\xf1\x00NE MFC AT EUR LHD 1.00 1.00 99211-GI510 250513',
],
},
CAR.HYUNDAI_IONIQ_6: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ',
@@ -1141,16 +1083,6 @@ FW_VERSIONS = {
b'\xf1\x00CE MFC AT CAN LHD 1.00 1.06 99211-KL000 230915',
],
},
CAR.HYUNDAI_IONIQ_9: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00MEev RDR ----- 1.00 1.00 99110-GO000 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00ME MFC AT KOR LHD 1.00 1.00 99211-GO000 241007',
b'\xf1\x00ME MFC AT KOR LHD 1.00 1.01 99211-GO000 250103',
b'\xf1\x00ME MFC AT USA LHD 1.00 1.00 99211-TD000 241007',
],
},
CAR.HYUNDAI_TUCSON_4TH_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N9220 14K',
@@ -1206,14 +1138,6 @@ FW_VERSIONS = {
b'\xf1\x00NQ5__ 1.01 1.03 99110-P1000 ',
],
},
CAR.KIA_SPORTAGE_HEV_2026: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NQ51.011.021.012551000HKP_NQ524_50509099211P1110',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NQ5__ 1.00 1.04 99110CH100 ',
],
},
CAR.GENESIS_GV70_1ST_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00JK1 MFC AT CAN LHD 1.00 1.02 99211-IY000 230627',
@@ -1241,14 +1165,6 @@ FW_VERSIONS = {
b'\xf1\x00JKev SCC ----- 1.00 1.01 99110-DS000 ',
],
},
CAR.GENESIS_GV70_ELECTRIFIED_2ND_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00JK MFC AT USA LHD 1.00 1.03 99211-DS600 241125',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00JK__ RDR ----- 1.00 1.01 99110-DS500 ',
],
},
CAR.GENESIS_GV60_EV_1ST_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00JW1 MFC AT AUS RHD 1.00 1.03 99211-CU100 221118',
@@ -1288,14 +1204,6 @@ FW_VERSIONS = {
b'\xf1\x00MQhe SCC FHCUP 1.00 1.07 99110-P4000 ',
],
},
CAR.KIA_SORENTO_HEV_4TH_GEN_LFA2: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.00 99210-P2600 250617',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-P2500 ',
],
},
CAR.KIA_NIRO_HEV_2ND_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00SG2HMFC AT USA LHD 1.01 1.08 99211-AT000 220531',
@@ -1314,14 +1222,6 @@ FW_VERSIONS = {
b'\xf1\x00JX1_ SCC FHCUP 1.00 1.01 99110-T6100 ',
],
},
CAR.GENESIS_GV80_2025: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00JX__ RDR ----- 1.00 1.03 99110-T6500 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00JX MFC AT USA LHD 1.00 1.03 99211-T6510 240124',
],
},
CAR.KIA_CARNIVAL_4TH_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00KA4 MFC AT EUR LHD 1.00 1.06 99210-R0000 220221',
@@ -36,31 +36,18 @@ class CanBus(CanBusBase):
return self._cam
def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque, apply_angle, lkas_icon):
def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque, lkas_icon):
values = {
"LKA_OptUsmSta": 2,
"LKA_SysIndReq": 2 if enabled else 1,
"LKA_SysIndReq": lkas_icon,
"StrTqReqVal": apply_torque,
"LKA_SysWrn": 0,
"ActToiSta": 1 if lat_active else 0,
"LKA_UsmMod": 0, # hide LKAS settings
"LKA_RcgSta": 0, # lane recognition status (0 for "not recognized")
"LKA_RcgSta": 0,
"Damping_Gain": 100, # can potentially tuned for better perf [3, 200]
}
# Angle control doesn't support using LFA yet
if CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
# LKAS messages take priority over LFA messages on HDA2.
values |= {
"LKA_OptUsmSta": 0, # TODO: not used by the stock system
"StrTqReqVal": 0, # we don't use torque
"ActToiSta": 0, # we don't use torque
"LKA_RcgSta": 3 if lat_active else 0,
"ADAS_StrAnglReqVal": apply_angle,
"LKAS_ANGLE_ACTIVE": 2 if lat_active else 1,
"ADAS_ACIAnglTqRedcGainVal": apply_torque if lat_active else 0,
}
ret = []
if CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG_ALT else "LKAS"
+1 -10
View File
@@ -46,10 +46,6 @@ class CarInterface(CarInterfaceBase):
# this needs to be figured out for cars without an ADAS ECU
ret.alphaLongitudinalAvailable = False
# no longitudinal for all lka_steering angle steering
if lka_steering and ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
ret.alphaLongitudinalAvailable = False
ret.enableBsm = 0x1ba in fingerprint[CAN.ECAN]
# Check if the car is hybrid. Only HEV/PHEV cars have 0xFA on E-CAN.
@@ -89,9 +85,6 @@ class CarInterface(CarInterfaceBase):
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value
if ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
ret.steerControlType = structs.CarParams.SteerControlType.angle
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ANGLE_STEERING.value
else:
# Shared configuration for non CAN-FD cars
@@ -124,9 +117,7 @@ class CarInterface(CarInterfaceBase):
ret.centerToFront = ret.wheelbase * 0.4
ret.steerActuatorDelay = 0.1
ret.steerLimitTimer = 0.4
if not (ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING):
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
if ret.flags & HyundaiFlags.ALT_LIMITS:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.ALT_LIMITS.value
@@ -1,74 +0,0 @@
# CarController Debug Replay Guide
This guide outlines the steps needed to replay a drive and debug `carcontroller.py` using breakpoints in the `card.py` process.
---
## ✅ Step 1: Set Environment Variables
`card.py` requires environment variables to simulate the target vehicle. Set them before launching the process.
Example for KIA EV9:
```sh
export FINGERPRINT=KIA_EV9
export SKIP_FW_QUERY=1
```
You can add these to your shell session or prefix the command launching `card.py`.
---
## 🚀 Step 2: Launch `card.py` Manually
Start `card.py` as a standalone process so you can attach a debugger or use breakpoints.
```sh
cd selfdrive/car
python card.py
```
> 🔑 Make sure your breakpoints are set **in this process**, not in the replay one.
---
## 🔁 Step 3: Run the Replay
Use the `replay` tool to play back a segment, blocking certain publishers to avoid conflicts with the live `card.py`.
### Example:
```sh
./tools/replay/replay "cb6aec3054a67f94/00000273--dae50621b9" \
--block "sendcan,carState,carParams,carOutput,liveTracks,carParamsSP,carStateSP"
```
This prevents `replay` from publishing messages that `card.py` is responsible for generating.
---
## 🔧 Common Issues
| Symptom | Likely Cause |
| ---------------------------------------- | ----------------------------------------------------------------------------------- |
| No breakpoints hit in `carcontroller.py` | Replay is blocking too much or not enough. Confirm `card.py` is running standalone. |
| No CAN output | `sendcan` not blocked in replay; conflict with replay publisher. |
| No data in replay | Incorrect segment path or segment not downloaded properly. |
---
## 📝 Segment Path Format
The path used in `replay` follows this format:
```
<route_prefix>/<segment_name>
```
Example:
```sh
cb6aec3054a67f94/00000273--dae50621b9
```
@@ -22,7 +22,6 @@ Ecu = CarParams.Ecu
NO_DATES_PLATFORMS = {
# CAN FD
CAR.KIA_SPORTAGE_5TH_GEN,
CAR.KIA_SPORTAGE_HEV_2026, # no date on camera
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN,
CAR.HYUNDAI_TUCSON_4TH_GEN,
# CAN
@@ -190,7 +189,7 @@ class TestHyundaiFingerprint(unittest.TestCase):
else:
assert all(date is not None for _, date in codes)
if car_model in (CAR.HYUNDAI_GENESIS, CAR.KIA_SPORTAGE_HEV_2026):
if car_model == CAR.HYUNDAI_GENESIS:
raise unittest.SkipTest("No part numbers for car model")
# Hyundai places the ECU part number in their FW versions, assert all parsable
+1 -100
View File
@@ -3,7 +3,6 @@ from dataclasses import dataclass, field
from enum import IntFlag
from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, uds
from opendbc.car.lateral import AngleSteeringLimitsVM
from opendbc.car.common.conversions import Conversions as CV
from opendbc.car.structs import CarParams
from opendbc.car.docs_definitions import CarHarness, CarDocs, CarParts, SupportType
@@ -18,22 +17,6 @@ class CarControllerParams:
ACCEL_MIN = -3.5 # m/s^2
ACCEL_MAX = 2.0 # m/s^2
ANGLE_LIMITS: AngleSteeringLimitsVM = AngleSteeringLimitsVM(
# Steering angle limits based on observed stock ADAS behavior:
# - LKAS max requested angle is 176.7°, but no fault occurs if higher values are requested.
# - LFA max stock value is 119.9°.
# The ADAS ECU clamps LKAS commands above 176.7° down to 176.7°,
# and clamps LFA commands above 119.9° down to 119.9°.
360, # degrees (safe upper bound for command, allowing some margin)
MAX_ANGLE_RATE=5 # comfort rate limit for angle commands, in degrees per frame.
)
# More torque optimization
# The torque is calculated based on the curvature of the road and the speed of the car and it's a percentage of the maximum torque.
SMOOTHING_ANGLE_VEGO_MATRIX = [0, 8.5, 11, 13.8, 18]
SMOOTHING_ANGLE_ALPHA_MATRIX = [0.05, 0.1, 0.3, 0.6, 1]
SMOOTHING_ANGLE_MAX_VEGO = SMOOTHING_ANGLE_VEGO_MATRIX[-1]
def __init__(self, CP):
self.STEER_DELTA_UP = 3
self.STEER_DELTA_DOWN = 7
@@ -51,9 +34,6 @@ class CarControllerParams:
self.STEER_DELTA_UP = 2
self.STEER_DELTA_DOWN = 3
if CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
self.STEER_THRESHOLD = 175
# To determine the limit for your car, find the maximum value that the stock LKAS will request.
# If the max stock LKAS request is <384, add your car to this list.
elif CP.carFingerprint in (CAR.GENESIS_G80, CAR.HYUNDAI_ELANTRA, CAR.HYUNDAI_ELANTRA_GT_I30, CAR.HYUNDAI_IONIQ,
@@ -88,7 +68,6 @@ class HyundaiSafetyFlags(IntFlag):
CANFD_LKA_STEER_MSG_ALT = 128
FCEV_GAS = 256
ALT_LIMITS_2 = 512
CANFD_ANGLE_STEERING = 1024
# Hyundai/Kia/Genesis SCC (Smart Cruise Control) and steering architecture:
@@ -170,8 +149,6 @@ class HyundaiFlags(IntFlag):
ALT_LIMITS_2 = 2 ** 26
CANFD_ANGLE_STEERING = 2 ** 27
@dataclass
class HyundaiCarDocs(CarDocs):
@@ -230,13 +207,6 @@ class CAR(Platforms):
CarSpecs(mass=1675, wheelbase=2.885, steerRatio=14.5),
flags=HyundaiFlags.HYBRID,
)
HYUNDAI_AZERA_HEV_7TH_GEN = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai AZERA Hybrid (with HDA II & LFA2) 2025", "Highway Driving Assist II & Lane Follow Assist 2", car_parts=CarParts.common([CarHarness.hyundai_s])),
],
CarSpecs(mass=1720, wheelbase=2.895, steerRatio=13.5),
flags=HyundaiFlags.CANFD_ANGLE_STEERING,
)
HYUNDAI_ELANTRA = HyundaiPlatformConfig(
[
# TODO: 2017-18 could be Hyundai G
@@ -363,14 +333,6 @@ class CAR(Platforms):
HYUNDAI_SANTA_FE.specs,
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
)
HYUNDAI_SANTA_FE_HEV_5TH_GEN = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Santa Fe Hybrid (with HDA II & LFA2) 2024-25", "Highway Driving Assist II & Lane Follow Assist 2",
car_parts=CarParts.common([CarHarness.hyundai_p])),
],
CarSpecs(mass=2035, wheelbase=2.81, steerRatio=13.72),
flags=HyundaiFlags.CANFD_ANGLE_STEERING,
)
HYUNDAI_SONATA = HyundaiPlatformConfig(
[HyundaiCarDocs("Hyundai Sonata 2020-23", "All", video="https://www.youtube.com/watch?v=ix63r9kE3Fw",
car_parts=CarParts.common([CarHarness.hyundai_a]))],
@@ -421,14 +383,6 @@ class CAR(Platforms):
CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65),
flags=HyundaiFlags.EV,
)
HYUNDAI_IONIQ_5_PE = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Ioniq 5 PE (with HDA II & LFA2) 2025-26", "Highway Driving Assist II & Lane Follow Assist 2",
car_parts=CarParts.common([CarHarness.hyundai_q]))
],
HYUNDAI_IONIQ_5.specs,
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING,
)
HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Ioniq 6 (without HDA II) 2023-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_l])),
@@ -437,14 +391,6 @@ class CAR(Platforms):
HYUNDAI_IONIQ_5.specs,
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE,
)
HYUNDAI_IONIQ_9 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Ioniq 9 (with HDA II & LFA2) 2025-26", "Highway Driving Assist II & Lane Follow Assist 2",
car_parts=CarParts.common([CarHarness.hyundai_m]))
],
CarSpecs(mass=2700, wheelbase=3.13, steerRatio=16.02),
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING,
)
HYUNDAI_TUCSON_4TH_GEN = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Tucson 2022", car_parts=CarParts.common([CarHarness.hyundai_n])),
@@ -574,13 +520,6 @@ class CAR(Platforms):
# weight from SX and above trims, average of FWD and AWD version, steering ratio according to Kia News https://www.kiamedia.com/us/en/models/sportage/2023/specifications
CarSpecs(mass=1725, wheelbase=2.756, steerRatio=13.6),
)
KIA_SPORTAGE_HEV_2026 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia Sportage Hybrid 2026", car_parts=CarParts.common([CarHarness.hyundai_n])),
],
CarSpecs(mass=1812, wheelbase=2.756, steerRatio=13.7),
flags=HyundaiFlags.CANFD_ANGLE_STEERING,
)
KIA_SORENTO = HyundaiPlatformConfig(
[
HyundaiCarDocs("Kia Sorento 2018", "Advanced Smart Cruise Control & LKAS", video="https://www.youtube.com/watch?v=Fkh3s6WHJz8",
@@ -603,13 +542,6 @@ class CAR(Platforms):
CarSpecs(mass=4395 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
KIA_SORENTO_HEV_4TH_GEN_LFA2 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia Sorento Hybrid 2026", "All", car_parts=CarParts.common([CarHarness.hyundai_q])),
],
CarSpecs(mass=1970, wheelbase=2.814, steerRatio=13.27, tireStiffnessFactor=0.65),
flags=HyundaiFlags.CANFD_ANGLE_STEERING,
)
KIA_STINGER = HyundaiPlatformConfig(
[HyundaiCarDocs("Kia Stinger 2018-20", video="https://www.youtube.com/watch?v=MJ94qoofYw0",
car_parts=CarParts.common([CarHarness.hyundai_c]))],
@@ -633,20 +565,6 @@ class CAR(Platforms):
CarSpecs(mass=2055, wheelbase=2.9, steerRatio=16, tireStiffnessFactor=0.65),
flags=HyundaiFlags.EV,
)
KIA_EV6_2025 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia EV6 (with HDA I) 2025", "Highway Driving Assist I", car_parts=CarParts.common([CarHarness.hyundai_p]))
],
CarSpecs(mass=2055, wheelbase=2.9, steerRatio=16, tireStiffnessFactor=0.65),
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING,
)
KIA_EV9 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia EV9 2025-26", car_parts=CarParts.common([CarHarness.hyundai_r]))
],
CarSpecs(mass=2664, wheelbase=3.1, steerRatio=16),
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING,
)
KIA_CARNIVAL_4TH_GEN = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia Carnival 2022-24", car_parts=CarParts.common([CarHarness.hyundai_a])),
@@ -697,13 +615,6 @@ class CAR(Platforms):
CarSpecs(mass=2260, wheelbase=2.87, steerRatio=17.1),
flags=HyundaiFlags.EV,
)
GENESIS_GV70_ELECTRIFIED_2ND_GEN = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Genesis GV70 Electrified 2026", "All", car_parts=CarParts.common([CarHarness.hyundai_m])),
],
GENESIS_GV70_ELECTRIFIED_1ST_GEN.specs,
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING,
)
GENESIS_G80 = HyundaiPlatformConfig(
[HyundaiCarDocs("Genesis G80 2018-19", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))],
CarSpecs(mass=2060, wheelbase=3.01, steerRatio=16.5),
@@ -722,16 +633,6 @@ class CAR(Platforms):
CarSpecs(mass=2258, wheelbase=2.95, steerRatio=14.14),
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
GENESIS_GV80_2025 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Genesis GV80 (3.5T Prestige Trim, with HDA II & LFA2) 2025", "Highway Driving Assist II & Lane Follow Assist 2",
car_parts=CarParts.common([CarHarness.hyundai_q])),
HyundaiCarDocs("Genesis GV80 Coupe (with HDA II & LFA2) 2025", "Highway Driving Assist II & Lane Follow Assist 2",
car_parts=CarParts.common([CarHarness.hyundai_q])),
],
GENESIS_GV80.specs,
flags=HyundaiFlags.CANFD_ANGLE_STEERING,
)
# port extensions
HYUNDAI_BAYON_1ST_GEN_NON_SCC = HyundaiNonSccPlatformConfig(
@@ -879,7 +780,7 @@ PART_NUMBER_FW_PATTERN = re.compile(b'(?<=[0-9][.,][0-9]{2} )([0-9]{5}[-/]?[A-Z]
CANFD_FUZZY_WHITELIST = {CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_SORENTO_HEV_4TH_GEN, CAR.KIA_K8_HEV_1ST_GEN,
CAR.KIA_SPORTAGE_5TH_GEN,
# TODO: the hybrid variant is not out yet
CAR.KIA_CARNIVAL_4TH_GEN, CAR.KIA_SORENTO_HEV_4TH_GEN_LFA2}
CAR.KIA_CARNIVAL_4TH_GEN}
# List of ECUs expected to have platform codes, camera and radar should exist on all cars
# TODO: use abs, it has the platform code and part number on many platforms
+1 -8
View File
@@ -148,7 +148,7 @@ def get_max_angle_vm(v_ego_raw: float, VM: VehicleModel, limits):
def apply_steer_angle_limits_vm(apply_angle: float, apply_angle_last: float, v_ego_raw: float, steering_angle: float,
lat_active: bool, limits, VM: VehicleModel) -> float | None:
lat_active: bool, limits, VM: VehicleModel) -> float:
"""Apply jerk, accel, and safety limit constraints to steering angle."""
v_ego_raw = max(v_ego_raw, 1)
@@ -163,13 +163,6 @@ def apply_steer_angle_limits_vm(apply_angle: float, apply_angle_last: float, v_e
max_angle = get_max_angle_vm(v_ego_raw, VM, limits)
new_apply_angle = np.clip(new_apply_angle, -max_angle, max_angle)
# Check if lateral acceleration limits comply with max delta limits
safety_violation = lat_active and new_apply_angle != rate_limit(new_apply_angle, apply_angle_last, -max_angle_delta, max_angle_delta)
# Shouldn't give any angle, since there's no good choice. We are vatiolating either way.
if safety_violation:
return None
# angle is current angle when inactive
if not lat_active:
new_apply_angle = steering_angle
@@ -56,10 +56,10 @@ class CarController(CarControllerBase):
CarControllerParams.LKAS_MAX_TORQUE - 0.6 * max(0, abs(CS.out.steeringTorque) - CarControllerParams.STEER_THRESHOLD),
)
if self.CP.carFingerprint in (CAR.NISSAN_ROGUE, CAR.NISSAN_XTRAIL, CAR.NISSAN_ALTIMA) and pcm_cancel_cmd:
if self.CP.carFingerprint == CAR.NISSAN_ALTIMA and pcm_cancel_cmd:
can_sends.append(nissancan.create_acc_cancel_cmd(self.packer, self.car_fingerprint, CS.cruise_throttle_msg))
if self.CP.carFingerprint in (CAR.NISSAN_LEAF, CAR.NISSAN_LEAF_IC) and self.frame % 2 == 0:
if self.CP.carFingerprint != CAR.NISSAN_ALTIMA and self.frame % 2 == 0:
button = "CANCEL_BUTTON" if pcm_cancel_cmd else None
can_sends.append(create_cruise_throttle_msg(self.packer, self.car_fingerprint, CS.cruise_throttle_msg, self.frame, button))
-22
View File
@@ -56,19 +56,6 @@ non_tested_cars = [
GM.CADILLAC_XT5_NON_ACC_1ST_GEN,
]
# HKG Angle Steering (LFA2) (Still WIP, hence why ignored)
non_tested_cars += [
HYUNDAI.GENESIS_GV80_2025,
HYUNDAI.HYUNDAI_IONIQ_5_PE,
HYUNDAI.KIA_EV6_2025,
HYUNDAI.KIA_EV9,
HYUNDAI.GENESIS_GV70_ELECTRIFIED_2ND_GEN,
HYUNDAI.HYUNDAI_SANTA_FE_HEV_5TH_GEN,
HYUNDAI.KIA_SPORTAGE_HEV_2026,
HYUNDAI.KIA_SORENTO_HEV_4TH_GEN_LFA2,
HYUNDAI.HYUNDAI_AZERA_HEV_7TH_GEN,
]
class CarTestRoute(NamedTuple):
route: str
@@ -175,7 +162,6 @@ routes = [
CarTestRoute("ca4de5b12321bd98/2022-10-18--21-15-59", HYUNDAI.GENESIS_GV70_1ST_GEN),
CarTestRoute("afe09b9f5d3f3548/00000011--15fefe1c50", HYUNDAI.GENESIS_GV70_ELECTRIFIED_1ST_GEN),
CarTestRoute("afe09b9f5d3f3548/0000001b--a1129a4a15", HYUNDAI.GENESIS_GV70_ELECTRIFIED_1ST_GEN), # openpilot longitudinal enabled
#CarTestRoute("afe09b9f5d3f3548/0000000b--0ac07f9835", HYUNDAI.GENESIS_GV70_ELECTRIFIED_2ND_GEN), # openpilot longitudinal enabled
CarTestRoute("6b301bf83f10aa90/2020-11-22--16-45-07", HYUNDAI.GENESIS_G80),
CarTestRoute("66eaa6c3b6b2afc6/00000009--3a5199aabe", HYUNDAI.GENESIS_G80_2ND_GEN_FL), # LKA steering
CarTestRoute("0bbe367c98fa1538/2023-09-16--00-16-49", HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN),
@@ -184,7 +170,6 @@ routes = [
CarTestRoute("bf43d9df2b660eb0/2021-09-23--14-16-37", HYUNDAI.HYUNDAI_SANTA_FE_2022),
CarTestRoute("37398f32561a23ad/2021-11-18--00-11-35", HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022),
CarTestRoute("656ac0d830792fcc/2021-12-28--14-45-56", HYUNDAI.HYUNDAI_SANTA_FE_PHEV_2022, segment=1),
#CarTestRoute("51489459ad31cccc/00000001--642891d0af", HYUNDAI.HYUNDAI_SANTA_FE_HEV_5TH_GEN), # 2025 HDA2 Angle Control
CarTestRoute("de59124955b921d8/2023-06-24--00-12-50", HYUNDAI.KIA_CARNIVAL_4TH_GEN),
CarTestRoute("409c9409979a8abc/2023-07-11--09-06-44", HYUNDAI.KIA_CARNIVAL_4TH_GEN), # Chinese model
CarTestRoute("e0e98335f3ebc58f/2021-03-07--16-38-29", HYUNDAI.KIA_CEED),
@@ -205,9 +190,7 @@ routes = [
CarTestRoute("628935d7d3e5f4f7/2022-11-30--01-12-46", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN), # plug-in hybrid
CarTestRoute("9c917ba0d42ffe78/2020-04-17--12-43-19", HYUNDAI.HYUNDAI_PALISADE),
CarTestRoute("05a8f0197fdac372/2022-10-19--14-14-09", HYUNDAI.HYUNDAI_IONIQ_5), # LKA steering
#CarTestRoute("e1107f9d04dfb1e2/00000455--9b2328ec73", HYUNDAI.HYUNDAI_IONIQ_5_PE), # LKA steering HDA2 LFA2
CarTestRoute("eb4eae1476647463/2023-08-26--18-07-04", HYUNDAI.HYUNDAI_IONIQ_6, segment=6), # LKA steering
CarTestRoute("71e4e67d29034771/0000001b--b7b4774ec4", HYUNDAI.HYUNDAI_IONIQ_9), # LKA steering
CarTestRoute("3f29334d6134fcd4/2022-03-30--22-00-50", HYUNDAI.HYUNDAI_IONIQ_PHEV_2019),
CarTestRoute("fa8db5869167f821/2021-06-10--22-50-10", HYUNDAI.HYUNDAI_IONIQ_PHEV),
CarTestRoute("e1107f9d04dfb1e2/2023-09-05--22-32-12", HYUNDAI.HYUNDAI_IONIQ_PHEV), # openpilot longitudinal enabled
@@ -230,9 +213,6 @@ routes = [
CarTestRoute("d624b3d19adce635/2020-08-01--14-59-12", HYUNDAI.HYUNDAI_VELOSTER),
CarTestRoute("d545129f3ca90f28/2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # LKA steering
CarTestRoute("68d6a96e703c00c9/2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # LFA steering
#CarTestRoute("84711a8268bf3b9a|2024-11-27--00-04-53", HYUNDAI.KIA_EV6_2025), # 2025 HDA1 Angle Control
#CarTestRoute("fab807792f63fea6/00000283--e3d8c65d78", HYUNDAI.KIA_EV6_2025), # 2025 Angle Control
#CarTestRoute("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", HYUNDAI.KIA_EV9), # 2025 HDA1 Angle Control
CarTestRoute("9b25e8c1484a1b67/2023-04-13--10-41-45", HYUNDAI.KIA_EV6),
CarTestRoute("007d5e4ad9f86d13/2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021),
CarTestRoute("c58dfc9fc16590e0/2023-01-14--13-51-48", HYUNDAI.KIA_K5_HEV_2020),
@@ -248,7 +228,6 @@ routes = [
CarTestRoute("192283cdbb7a58c2/2022-10-15--01-43-18", HYUNDAI.KIA_SPORTAGE_5TH_GEN),
CarTestRoute("09559f1fcaed4704/2023-11-16--02-24-57", HYUNDAI.KIA_SPORTAGE_5TH_GEN, segment=0), # openpilot longitudinal
CarTestRoute("b3537035ffe6a7d6/2022-10-17--15-23-49", HYUNDAI.KIA_SPORTAGE_5TH_GEN), # hybrid
#CarTestRoute("1635e7fee82dec3b/00000000--aa7efe7199", HYUNDAI.KIA_SPORTAGE_HEV_2026), # 2025 Angle Control
CarTestRoute("c5ac319aa9583f83/2021-06-01--18-18-31", HYUNDAI.HYUNDAI_ELANTRA),
CarTestRoute("734ef96182ddf940/2022-10-02--16-41-44", HYUNDAI.HYUNDAI_ELANTRA_GT_I30),
CarTestRoute("82e9cdd3f43bf83e/2021-05-15--02-42-51", HYUNDAI.HYUNDAI_ELANTRA_2021),
@@ -256,7 +235,6 @@ routes = [
CarTestRoute("7120aa90bbc3add7/2021-08-02--07-12-31", HYUNDAI.HYUNDAI_SONATA_HYBRID),
CarTestRoute("715ac05b594e9c59/2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020),
CarTestRoute("6b0d44d22df18134/2023-05-06--10-36-55", HYUNDAI.GENESIS_GV80),
#CarTestRoute("bf5d5a62cc79a28e/00000002--4d370e2bc2", HYUNDAI.GENESIS_GV80_2025),
CarTestRoute("00c829b1b7613dea/2021-06-24--09-10-10", TOYOTA.TOYOTA_ALPHARD_TSS2),
CarTestRoute("912119ebd02c7a42/2022-03-19--07-24-50", TOYOTA.TOYOTA_ALPHARD_TSS2), # hybrid
@@ -115,15 +115,3 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
# port extensions
"HONDA_CLARITY" = [0.96, 0.4018518740819229, 0.19]
"CHEVROLET_MALIBU_NON_ACC_9TH_GEN" = [1.85, 1.85, 0.075]
# Hyundai/Kia/Genesis angle control
"HYUNDAI_IONIQ_5_PE" = [3.172929, 3.5, 0.096019]
"HYUNDAI_IONIQ_9" = [2.5, 2.0, 0.05]
"GENESIS_GV80_2025" = [2.5, 2.5, 0.1]
"HYUNDAI_SANTA_FE_HEV_5TH_GEN" = [2.5, 2.5, 0.1]
"KIA_EV6_2025" = [3.2, 2.093457, 0.005]
"KIA_EV9" = [3.2, 2.093457, 0.005]
"GENESIS_GV70_ELECTRIFIED_2ND_GEN" = [1.9, 1.9, 0.09]
"KIA_SPORTAGE_HEV_2026" = [nan, 2.5, nan]
"KIA_SORENTO_HEV_4TH_GEN_LFA2" = [nan, 2.5, nan]
"HYUNDAI_AZERA_HEV_7TH_GEN" = [nan, 2.5, nan]
@@ -1,5 +1,6 @@
import math
import numpy as np
from openpilot.common.params import Params
from opendbc.car import Bus, make_tester_present_msg, rate_limit, structs, ACCELERATION_DUE_TO_GRAVITY, DT_CTRL
from opendbc.car.lateral import apply_meas_steer_torque_limits, apply_std_steer_angle_limits, common_fault_avoidance
from opendbc.car.carlog import carlog
@@ -12,7 +13,8 @@ from opendbc.car.toyota.values import CAR, NO_STOP_TIMER_CAR, TSS2_CAR, \
CarControllerParams, ToyotaFlags, \
UNSUPPORTED_DSU_CAR
from opendbc.can import CANPacker
from opendbc.sunnypilot.car.toyota.auto_brake_hold import AutoBrakeHoldCarController
from opendbc.sunnypilot.car.toyota.enhanced_bsm import EnhancedBsmCarController
from opendbc.sunnypilot.car.toyota.gas_interceptor import GasInterceptorCarController
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP
@@ -20,6 +22,7 @@ Ecu = structs.CarParams.Ecu
LongCtrlState = structs.CarControl.Actuators.LongControlState
SteerControlType = structs.CarParams.SteerControlType
VisualAlert = structs.CarControl.HUDControl.VisualAlert
GearShifter = structs.CarState.GearShifter
# The up limit allows the brakes/gas to unwind quickly leaving a stop,
# the down limit roughly matches the rate of ACCEL_NET, reducing PCM compensation windup
@@ -37,11 +40,18 @@ MAX_STEER_RATE_FRAMES = 17 # tx control frames needed before torque can be cut
# EPS allows user torque above threshold for 50 frames before permanently faulting
MAX_USER_TORQUE = 500
def get_long_tune(CP, params):
if CP.carFingerprint in TSS2_CAR:
kiBP = [2., 5.]
kiV = [0.5, 0.25]
if Params().get_bool("ToyotaTSS2Long"):
#kiBP = [0., 2.0, 9.0, 14., 20., 27.]
#kiV = [0.25, 0.25, 0.15, 0.12, 0.12, 0.12]
#kiBP= [0., 1.0, 2.0, 3.0, 4.0, 5.0, 7., 20., 27., 36.]
#kiV = [0.31, 0.32, 0.301, 0.280, 0.259, 0.226, 0.15, 0.15, 0.101, 0.10]
kiBP= [0.3, 0.9, 1.0, 2.0, 5.0, 27., 36.]
kiV = [0.46, 0.46, 0.50, 0.50, 0.244, 0.10, 0.09]
else:
kiBP = [2., 5.]
kiV = [0.5, 0.25]
else:
kiBP = [0., 5., 35.]
kiV = [3.6, 2.4, 1.5]
@@ -82,6 +92,14 @@ class CarController(CarControllerBase, GasInterceptorCarController):
self.secoc_acc_message_counter = 0
self.secoc_prev_reset_counter = 0
self.enhanced_bsm = EnhancedBsmCarController(CP, CP_SP)
self.auto_brake_hold = AutoBrakeHoldCarController(CP, CP_SP)
self._auto_lock_speed = 0.0
self._auto_lock_once = False
self._gear_prev = GearShifter.park
def update(self, CC, CC_SP, CS, now_nanos):
actuators = CC.actuators
stopping = actuators.longControlState == LongCtrlState.stopping
@@ -197,6 +215,9 @@ class CarController(CarControllerBase, GasInterceptorCarController):
self.last_standstill = CS.out.standstill
if self.auto_brake_hold.enabled:
can_sends.extend(self.auto_brake_hold.update(CS, self.frame, self.packer))
# handle UI messages
fcw_alert = hud_control.visualAlert == VisualAlert.fcw
steer_alert = hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw)
@@ -320,6 +341,9 @@ class CarController(CarControllerBase, GasInterceptorCarController):
if self.frame % 20 == 0 and self.CP.flags & ToyotaFlags.DISABLE_RADAR.value:
can_sends.append(make_tester_present_msg(0x750, 0, 0xF))
if self.enhanced_bsm.enabled:
can_sends.extend(self.enhanced_bsm.update(CS, self.frame))
new_actuators = actuators.as_builder()
new_actuators.torque = apply_torque / self.params.STEER_MAX
new_actuators.torqueOutputCan = apply_torque
+63 -3
View File
@@ -1,5 +1,7 @@
import copy
from openpilot.cereal import custom
from openpilot.common.params import Params
from opendbc.can import CANDefine, CANParser
from opendbc.car import Bus, DT_CTRL, create_button_events, structs
from opendbc.car.common.conversions import Conversions as CV
@@ -9,10 +11,12 @@ from opendbc.car.toyota.values import ToyotaFlags, CAR, DBC, STEER_THRESHOLD, NO
TSS2_CAR, RADAR_ACC_CAR, EPS_SCALE, UNSUPPORTED_DSU_CAR, \
SECOC_CAR
from opendbc.sunnypilot.car.toyota.carstate_ext import CarStateExt
from opendbc.sunnypilot.car.toyota.enhanced_bsm import EnhancedBsmCarState
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP
ButtonType = structs.CarState.ButtonEvent.Type
SteerControlType = structs.CarParams.SteerControlType
AccelPersonality = custom.LongitudinalPlanSP.AccelerationPersonality
# These steering fault definitions seem to be common across LKA (torque) and LTA (angle):
# - high steer rate fault: goes to 21 or 25 for 1 frame, then 9 for 2 seconds
@@ -56,6 +60,20 @@ class CarState(CarStateBase, CarStateExt):
self.gvc = 0.0
self.secoc_synchronization = None
self.enhanced_bsm = EnhancedBsmCarState(CP, CP_SP)
if CP_SP.flags & ToyotaFlagsSP.SP_AUTO_BRAKE_HOLD:
self.pre_collision_2 = {}
self.toyota_drive_mode = Params().get_bool('ToyotaDriveMode')
self._drive_mode_signals_checked = False
self._sport_signal_available = False
self._eco_signal_available = False
self._prev_accel_profile = None
self._accel_profile_init = False
self.frame = 0
def update(self, can_parsers) -> tuple[structs.CarState, structs.CarStateSP]:
cp = can_parsers[Bus.pt]
cp_cam = can_parsers[Bus.cam]
@@ -73,18 +91,52 @@ class CarState(CarStateBase, CarStateExt):
ret.parkingBrake = cp.vl["BODY_CONTROL_STATE"]["PARKING_BRAKE"] == 1
ret.brakePressed = cp.vl["BRAKE_MODULE"]["BRAKE_PRESSED"] != 0
ret.brakeHoldActive = cp.vl["ESP_CONTROL"]["BRAKE_HOLD_ACTIVE"] == 1
#ret.brakeHoldActive = cp.vl["ESP_CONTROL"]["BRAKE_HOLD_ACTIVE"] == 1
if self.CP.flags & ToyotaFlags.SECOC.value:
self.secoc_synchronization = copy.copy(cp.vl["SECOC_SYNCHRONIZATION"])
ret.gasPressed = cp.vl["GAS_PEDAL"]["GAS_PEDAL_USER"] > 0
can_gear = int(cp.vl["GEAR_PACKET_HYBRID"]["GEAR"])
else:
ret.gasPressed = cp.vl["PCM_CRUISE"]["GAS_RELEASED"] == 0
ret.gasPressed = cp.vl["PCM_CRUISE"]["GAS_RELEASED"] == 0 # TODO: these also have GAS_PEDAL, come back and unify
can_gear = int(cp.vl["GEAR_PACKET"]["GEAR"])
if not self.CP.flags & ToyotaFlags.DISABLE_RADAR.value:
ret.stockAeb = bool(cp_acc.vl["PRE_COLLISION"]["PRECOLLISION_ACTIVE"] and cp_acc.vl["PRE_COLLISION"]["FORCE"] < -1e-5)
if self.toyota_drive_mode: # and not self.CP.flags & ToyotaFlags.SECOC.value:
sport_signal = 'SPORT_ON_2' if self.CP.carFingerprint in (CAR.TOYOTA_RAV4_TSS2, CAR.LEXUS_ES_TSS2,
CAR.TOYOTA_HIGHLANDER_TSS2) else 'SPORT_ON'
if not self._drive_mode_signals_checked:
self._drive_mode_signals_checked = True
try:
sport_mode = cp.vl["GEAR_PACKET"][sport_signal]
self._sport_signal_available = True
except KeyError:
sport_mode = 0
self._sport_signal_available = False
try:
eco_mode = cp.vl["GEAR_PACKET"]['ECON_ON']
self._eco_signal_available = True
except KeyError:
eco_mode = 0
self._eco_signal_available = False
else:
sport_mode = cp.vl["GEAR_PACKET"][sport_signal] if self._sport_signal_available else 0
eco_mode = cp.vl["GEAR_PACKET"]['ECON_ON'] if self._eco_signal_available else 0
if sport_mode == 1:
accel_profile = AccelPersonality.sport
elif eco_mode == 1:
accel_profile = AccelPersonality.eco
else:
accel_profile = AccelPersonality.normal
if not self._accel_profile_init or accel_profile != self._prev_accel_profile:
Params().put('AccelPersonality', int(accel_profile))
self._accel_profile_init = True
self._prev_accel_profile = accel_profile
self.parse_wheel_speeds(ret,
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"],
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"],
@@ -213,6 +265,14 @@ class CarState(CarStateBase, CarStateExt):
ret.buttonEvents = buttonEvents
if self.enhanced_bsm.enabled and self.frame > 199:
ret.leftBlindspot, ret.rightBlindspot = self.enhanced_bsm.update(cp, self.frame)
if self.CP_SP.flags & ToyotaFlagsSP.SP_AUTO_BRAKE_HOLD:
self.pre_collision_2 = copy.copy(cp_cam.vl["PRE_COLLISION_2"])
self.frame += 1
CarStateExt.update(self, ret, ret_sp, can_parsers)
return ret, ret_sp
@@ -231,4 +291,4 @@ class CarState(CarStateBase, CarStateExt):
return {
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], pt_messages, 0),
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [] + cam_messages, 2),
}
}
+5 -1
View File
@@ -4,7 +4,7 @@ from opendbc.car.toyota.carcontroller import CarController
from opendbc.car.toyota.radar_interface import RadarInterface
from opendbc.car.toyota.values import Ecu, CAR, DBC, ToyotaFlags, CarControllerParams, TSS2_CAR, RADAR_ACC_CAR, NO_DSU_CAR, \
MIN_ACC_SPEED, EPS_SCALE, NO_STOP_TIMER_CAR, ANGLE_CONTROL_CAR, \
ToyotaSafetyFlags, UNSUPPORTED_DSU_CAR
ToyotaSafetyFlags, UNSUPPORTED_DSU_CAR, SECOC_CAR
from opendbc.car.disable_ecu import disable_ecu
from opendbc.car.interfaces import CarInterfaceBase
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP, ToyotaSafetyFlagsSP
@@ -115,6 +115,7 @@ class CarInterface(CarInterfaceBase):
# min speed to enable ACC. if car can do stop and go, then set enabling speed
# to a negative value, so it won't matter.
ret.minEnableSpeed = -1. if stop_and_go else MIN_ACC_SPEED
if candidate in TSS2_CAR:
ret.flags |= ToyotaFlags.RAISED_ACCEL_LIMIT.value
@@ -131,6 +132,9 @@ class CarInterface(CarInterfaceBase):
if candidate in UNSUPPORTED_DSU_CAR:
ret.safetyParam |= ToyotaSafetyFlagsSP.UNSUPPORTED_DSU
if candidate == CAR.TOYOTA_PRIUS_TSS2:
ret.flags |= ToyotaFlagsSP.SP_NEED_DEBUG_BSM.value
# Detect smartDSU, which intercepts ACC_CMD from the DSU (or radar) allowing openpilot to send it
# 0x2AA is sent by a similar device which intercepts the radar instead of DSU on NO_DSU_CARs
if 0x2FF in fingerprint[0] or (0x2AA in fingerprint[0] and candidate in NO_DSU_CAR):
@@ -1,4 +1,5 @@
from opendbc.car.structs import CarParams
from opendbc.car.can_definitions import CanData
SteerControlType = CarParams.SteerControlType
@@ -164,3 +165,47 @@ def toyota_checksum(address: int, sig, d: bytearray) -> int:
for i in range(len(d) - 1):
s += d[i]
return s & 0xFF
def create_set_bsm_debug_mode(lr_blindspot, enabled):
dat = b"\x02\x10\x60\x00\x00\x00\x00" if enabled else b"\x02\x10\x01\x00\x00\x00\x00"
dat = lr_blindspot + dat
return CanData(0x750, dat, 0)
def create_bsm_polling_status(lr_blindspot):
return CanData(0x750, lr_blindspot + b"\x02\x21\x69\x00\x00\x00\x00", 0)
# auto brake hold
def create_brake_hold_command(packer, frame, pre_collision_2, brake_hold_active):
# forward PRE_COLLISION_2 when auto brake hold is not active
values = {s: pre_collision_2[s] for s in [
"DSS1GDRV",
"DS1STAT2",
"DS1STBK2",
"PCSWAR",
"PCSALM",
"PCSOPR",
"PCSABK",
"PBATRGR",
"PPTRGR",
"IBTRGR",
"CLEXTRGR",
"IRLT_REQ",
"BRKHLD",
"AVSTRGR",
"VGRSTRGR",
"PREFILL",
"PBRTRGR",
"PCSDIS",
"PBPREPMP",
]}
if brake_hold_active:
values = {
"DSS1GDRV": 0x3FF,
"PBRTRGR": frame % 730 < 727, # cut actuation for 3 frames
}
return packer.make_can_msg("PRE_COLLISION_2", 0, values)
@@ -1,125 +0,0 @@
BO_ 203 ADAS_CMD_35_10ms: 24 CGW_CCU
SG_ ADAS_CMD_Crc35Val : 0|16@1+ (1,0) [0|0] "0" FCU_C,GW_RGW,MDPS,SFA
SG_ ADAS_CMD_AlvCnt35Val : 16|8@1+ (1,0) [0|0] "0" FCU_C,GW_RGW,MDPS,SFA
SG_ ADAS_ActvACISta : 24|4@1+ (1,0) [0|0] "" GW_RGW,MDPS,SFA
SG_ ADAS_ActvACILvl2Sta : 28|4@1+ (1,0) [0|0] "" ESC,FCU_C,GW_RGW,MDPS,SFA,VPC_C
SG_ ADAS_StrAnglReqVal : 32|14@1- (0.1,0) [0|0] "Deg" GW_RGW,MDPS,SFA
SG_ ADAS_ACIAnglTqRedcGainVal : 48|8@1+ (0.004,0) [0|0] "" GW_RGW,MDPS,SFA
SG_ FCA_ESA_ActvSta : 56|2@1+ (1,0) [0|0] "" GW_RGW,MDPS,SFA
SG_ FCA_ESA_TqBstGainVal : 64|8@1+ (0.004,0) [0|0] "" GW_RGW,MDPS,SFA
BO_ 272 ESC_06_200ms: 32 XXX
SG_ ESC_Crc6Val : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ ESC_AlvCnt6Val : 16|8@1+ (1,0) [0|255] "" XXX
SG_ IEB_BrkMod_Sta : 24|3@1+ (1,0) [0|7] "" XXX
SG_ IEB_BrkMod_Type : 27|2@1+ (1,0) [0|255] "" XXX
SG_ LFA2_USING_LEAD_MAYBE : 30|1@0+ (1,0) [0|1] "" XXX
SG_ LKA_WARNING : 32|1@1+ (1,0) [0|1] "" XXX
SG_ LKA_SysIndReq : 38|3@1+ (1,0) [0|7] "" CLU,RR_C_RDR,CGW
SG_ ADAS_StrTqReqVal : 41|11@1+ (0.0078125,-8) [-8|7.9921875] "Nm" CGW
SG_ ADAS_ActToiSta : 52|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ADAS_ToiFltSta : 54|2@1+ (1,0) [0|3] "" CGW
SG_ LFA_BUTTON : 56|1@1+ (1,0) [0|255] "" XXX
SG_ LKA_ASSIST : 62|1@1+ (1,0) [0|1] "" XXX
SG_ STEER_MODE : 65|3@1+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_2 : 70|2@0+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_3_LDW_UNK : 72|2@1+ (1,0) [0|3] "" XXX
SG_ LKAS_ANGLE_ACTIVE : 77|2@0+ (1,0) [0|3] "" XXX
SG_ HAS_LANE_SAFETY : 80|1@0+ (1,0) [0|1] "" XXX
SG_ LKAS_ANGLE_CMD : 82|14@1- (0.1,0) [0|511] "" XXX
SG_ LKAS_ANGLE_MAX_TORQUE : 96|8@1+ (1,0) [0|255] "" XXX
SG_ LDW_SHAKE_STEERING : 105|2@0+ (1,0) [0|255] "" XXX
SG_ FCA_ESA_CtrlSta : 107|1@0+ (1,0) [0|1] "" XXX
SG_ CAR_IN_DRIVE_MAYBE : 232|1@0+ (1,0) [0|1] "" XXX
BO_ 298 ADAS_CMD_30_10ms: 16 FR_CMR
SG_ ADAS_CMD_Crc30Val : 0|16@1+ (1,0) [0|65535] "" CLU,CGW
SG_ ADAS_CMD_AlvCnt30Val : 16|8@1+ (1,0) [0|255] "" CLU,CGW
SG_ LKA_OptUsmSta : 24|3@1+ (1,0) [0|7] "" CLU,CGW
SG_ LKA_RcgSta : 27|3@1+ (1,0) [0|7] "" CLU,CGW
SG_ LKA_LHLnWrnSta : 30|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ LKA_RHLnWrnSta : 32|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ LKA_HndsoffSnd : 34|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ LKA_StrSnd : 36|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ LKA_SysIndReq : 38|3@1+ (1,0) [0|7] "" CLU,RR_C_RDR,CGW
SG_ ADAS_StrTqReqVal : 41|11@1+ (0.0078125,-8) [-8|7.9921875] "Nm" CGW
SG_ ADAS_ActToiSta : 52|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ADAS_ToiFltSta : 54|2@1+ (1,0) [0|3] "" CGW
SG_ LFA_BUTTON : 56|1@0+ (1,0) [0|1] "" XXX
SG_ BCA_Rear_WrnSta : 57|3@1+ (1,0) [0|255] "" ADRV
SG_ LKA_SysWrn : 60|4@1+ (1,0) [0|15] "" CLU,CGW
SG_ FCA_LO_WrnSta : 64|1@1+ (1,0) [0|1] "" ADRV
SG_ STEER_MODE : 65|3@1+ (1,0) [0|1] "" ADRV
SG_ FCA_LS_WrnSta : 68|2@1+ (1,0) [0|3] "" ADRV
SG_ NEW_SIGNAL_2 : 70|1@0+ (1,0) [0|3] "" ADRV
SG_ SCC_TakeoverReq_CLU_AMP_PE_02_Warn_Sound : 72|2@1+ (1,0) [0|255] "" ADRV
SG_ NEW_SIGNAL_1 : 79|1@0+ (1,0) [0|1] "" XXX
SG_ LKA_UsmMod : 80|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ LDW_SHAKE_STEERING : 82|2@1+ (1,0) [0|3] "" XXX
SG_ ELK_SysFlrSta : 85|5@1+ (1,0) [0|31] "" ADRV
SG_ ELK_SymbDisp : 90|3@1+ (1,0) [0|7] "" ADRV
SG_ FCA_ESA_CtrlSta : 98|1@0+ (1,0) [0|1] "" XXX
SG_ ADAS_Damping_Gain : 104|8@1+ (1,0) [0|255] "" CGW
CM_ BO_ 203 "[P] Periodic";
CM_ SG_ 203 ADAS_CMD_Crc35Val "ADAS_CMD_CyclicRedundancyCheck35Value";
CM_ SG_ 203 ADAS_CMD_AlvCnt35Val "ADAS_CMD_AliveCounter35Value";
CM_ SG_ 203 ADAS_ActvACISta "ADAS Active AngleControlInterface State";
CM_ SG_ 203 ADAS_ActvACILvl2Sta "ADAS Active AngleControlInterface Level 2 State";
CM_ SG_ 203 ADAS_StrAnglReqVal "ADAS Steering Angle Request Value";
CM_ SG_ 203 ADAS_ACIAnglTqRedcGainVal "ADAS AngleControlInterface Angle Torque Reduction Gain Value";
CM_ SG_ 203 FCA_ESA_ActvSta "State for FCA w/ESA";
CM_ SG_ 203 FCA_ESA_TqBstGainVal "FCA w/ESA Torque boost Gain";
CM_ SG_ 272 IEB_BrkMod_Sta "Brake Mode State";
CM_ SG_ 272 IEB_BrkMod_Type "Brake Mode Type";
CM_ SG_ 272 LFA2_USING_LEAD_MAYBE "I don't know about this signal much. But I noticed that it flipped to 1 when the lane was dubious but we had a lead in front";
CM_ SG_ 272 LKA_SysIndReq "LKA_SystemIndicatorRequest ##2G##LDW_LKA - LKA11 - CF_LKA_SymbolState";
CM_ SG_ 272 NEW_SIGNAL_3_LDW_UNK "I don't know what this signal is meant to do or convery. I just know it the 2 bits changed together when I manually disabled LKAS. ";
CM_ SG_ 272 LDW_SHAKE_STEERING "I am not 100% sure on this signal. I believe that when this happens, the steering vibrates. Same as ADAS_CMD_30_10ms";
CM_ SG_ 272 FCA_ESA_CtrlSta "Signal is a best guess. It went \"off\" when I disabled LKAS on a route. Same as ADAS_CMD_30_10ms";
CM_ SG_ 272 CAR_IN_DRIVE_MAYBE "This seems to indicate when the car is on D maybe. I am not sure. I saw it twice on a route on hoth times I do remember stopping completely and in one instance I remember putting park. ";
CM_ BO_ 298 "[P] Periodic";
CM_ SG_ 298 ADAS_CMD_Crc30Val "ADAS_CMD_CyclicRedundancyCheck30Value";
CM_ SG_ 298 ADAS_CMD_AlvCnt30Val "ADAS_CMD_AliveCounter30Value";
CM_ SG_ 298 LKA_OptUsmSta "LKA_OptionUsmStatus ##2G##LDW_LKA - LKA11 - CF_LKA_Opt_USM";
CM_ SG_ 298 LKA_RcgSta "LKA_RecognitionStatus ##2G##LDW_LKA - LKA11 - CF_LKA_LaneRecogState";
CM_ SG_ 298 LKA_LHLnWrnSta "LKA_LHLaneWarningStatus ##2G##LDW_LKA - LKA11 - CF_LKA_LHWarning";
CM_ SG_ 298 LKA_RHLnWrnSta "LKA_RHLaneWarningStatus ##2G##LDW_LKA - LKA11 - CF_LKA_RHWarning";
CM_ SG_ 298 LKA_HndsoffSnd "LKA_HandsoffSound ##2G##LDW_LKA - LKA11 - CF_LKA_HandsOff_Snd";
CM_ SG_ 298 LKA_StrSnd "LKA_SteeringSound ##2G##LDW_LKA - LKA11 - CF_LKA_Steer_Snd";
CM_ SG_ 298 LKA_SysIndReq "LKA_SystemIndicatorRequest ##2G##LDW_LKA - LKA11 - CF_LKA_SymbolState";
CM_ SG_ 298 ADAS_StrTqReqVal "LKA_SteeringTorqueRequestValue ##2G##LDW_LKA - LKA11 - CR_LKA_StrToqReq";
CM_ SG_ 298 ADAS_ActToiSta "ADAS_ActiveTorqueOverlayInterfaceStatus ##2G##LDW_LKA - LKA11 - CF_LKA_ActToi";
CM_ SG_ 298 ADAS_ToiFltSta "ADAS_TorqueOverlayInterfaceFaultStatus ##2G##LDW_LKA - LKA11 - CF_LKA_ToiFlt";
CM_ SG_ 298 BCA_Rear_WrnSta "best-guess";
CM_ SG_ 298 LKA_SysWrn "LKA_Additional_Info";
CM_ SG_ 298 LKA_UsmMod "LKA_USM Mode ##2G##LDW_LKA-LKA11-CF_LKA_USM_Mode";
CM_ SG_ 298 LDW_SHAKE_STEERING "I am not 100% sure on this signal. I believe that when this happens, the steering vibrates. Same as ESC_06_200ms";
CM_ SG_ 298 FCA_ESA_CtrlSta "Signal is a best guess. It went \"off\" when I disabled LKAS on a route. Same as ESC_06_200ms";
CM_ SG_ 298 ADAS_Damping_Gain "ADAS_Damping_Gain";
VAL_ 203 ADAS_CMD_Crc35Val 0 "0x0x0~0xFFFF:CRCValue" 65535 "0x0x0~0xFFFF:CRCValue";
VAL_ 203 ADAS_CMD_AlvCnt35Val 0 "0x0x0~0xFF:AlvCntValue" 255 "0x0x0~0xFF:AlvCntValue";
VAL_ 203 ADAS_ActvACISta 0 "INIT" 1 "INACTIVE" 2 "ACTIVE35(ACTIVE)" 3 "ACTIVE33(Redundancy)" 4 "RESERVED" 5 "RESERVED" 6 "RESERVED" 7 "RESERVED" 8 "RESERVED" 9 "RESERVED" 10 "RESERVED" 11 "RESERVED" 12 "RESERVED" 13 "RESERVED" 14 "RESERVED" 15 "RESERVED";
VAL_ 203 ADAS_ActvACILvl2Sta 0 "INIT" 1 "INACTIVE" 2 "ACTIVE35(ACTIVE)" 3 "RESERVED" 4 "RESERVED" 5 "RESERVED" 6 "RESERVED" 7 "RESERVED" 8 "RESERVED" 9 "RESERVED" 10 "RESERVED" 11 "RESERVED" 12 "RESERVED" 13 "RESERVED" 14 "RESERVED" 15 "RESERVED";
VAL_ 203 ADAS_StrAnglReqVal 0 "0x0x000~0x3FFF:Real Values" 16383 "0x0x000~0x3FFF:Real Values";
VAL_ 203 ADAS_ACIAnglTqRedcGainVal 0 "0x0x00~0xFA:Real Values" 250 "0x0x00~0xFA:Real Values" 251 "RESERVED" 252 "RESERVED" 253 "RESERVED" 254 "RESERVED" 255 "RESERVED";
VAL_ 203 FCA_ESA_ActvSta 0 "Inactive" 1 "Active" 2 "RESERVED" 3 "RESERVED";
VAL_ 203 FCA_ESA_TqBstGainVal 0 "0x0x00~0xFA:Real Values" 250 "0x0x00~0xFA:Real Values" 251 "RESERVED" 252 "RESERVED" 253 "RESERVED" 254 "RESERVED" 255 "RESERVED";
VAL_ 272 IEB_BrkMod_Sta 0 "0x0: Not Applied" 1 "Normal" 2 "Sport" 3 "Chauffeur" 7 "Failure";
VAL_ 272 IEB_BrkMod_Type 0 "type1 (Normal/Sport)" 1 "type2 (Normal/Sport/Chauffeur)";
VAL_ 272 LKA_SysIndReq 0 "Off" 1 "Unavailable_(Grey On)" 2 "Lane Recognized_(Green On)" 3 "Lane Departure_(Green Blink)" 4 "System Fail_(Orange On)" 5 "Not Calibrated_(Orange Blink)" 6 "Regulation_(Orange On)" 7 "Reserved";
VAL_ 272 FCA_ESA_CtrlSta 0 "Off" 1 "On";
VAL_ 298 LKA_OptUsmSta 0 "None LKA/LDW Option (Default)" 1 "LDW" 2 "LKA" 3 "Reserved" 4 "LDW Only (None LKA)" 5 "LDW only OFF (None LKA)" 6 "LDW/LKA OFF" 7 "Invalid";
VAL_ 298 LKA_RcgSta 0 "Not Recognized" 1 "Left Lane Recognition" 2 "Right Lane Recognition" 3 "Full Lane Recognition" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Reserved";
VAL_ 298 LKA_LHLnWrnSta 0 "No Warning" 1 "Lane Departure Warning" 2 "Reserved" 3 "Reserved";
VAL_ 298 LKA_RHLnWrnSta 0 "No Warning" 1 "Lane Departure Warning" 2 "Reserved" 3 "Reserved";
VAL_ 298 LKA_HndsoffSnd 0 "Off" 1 "Hands-off Sound Warning" 2 "Reserved" 3 "Reserved";
VAL_ 298 LKA_StrSnd 0 "Off" 1 "Warning" 2 "Reserved" 3 "Reserved";
VAL_ 298 LKA_SysIndReq 0 "Off" 1 "Unavailable_(Grey On)" 2 "Lane Recognized_(Green On)" 3 "Lane Departure_(Green Blink)" 4 "System Fail_(Orange On)" 5 "Not Calibrated_(Orange Blink)" 6 "Regulation_(Orange On)" 7 "Reserved";
VAL_ 298 ADAS_StrTqReqVal 2046 "Reserved" 2047 "Invalid";
VAL_ 298 ADAS_ActToiSta 0 "De-activate TOI" 1 "Activate TOI" 2 "Reserved" 3 "Error indicator";
VAL_ 298 ADAS_ToiFltSta 0 "No Fault" 1 "Fault" 2 "Reserved" 3 "Error indicatorr";
VAL_ 298 LKA_SysWrn 0 "No Info" 1 "Reserved" 2 "Reserved" 3 "Reserved" 4 "Hands-Off Warning 1" 5 "Hands-Off Warning 2" 6 "Hands-Off Warning 3" 7 "Reserved" 8 "Reserved" 9 "System Automatic off" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Reserved" 15 "System Fail";
VAL_ 298 LKA_UsmMod 0 "NONE" 1 "LKA 1 mode" 2 "Reserved" 3 "LDW";
VAL_ 298 FCA_ESA_CtrlSta 0 "Off";
VAL_ 298 ADAS_Damping_Gain 0 "Reserved" 1 "Reserved" 2 "Reserved" 0 "Reserved" 202 "Reserved" 203 "Reserved" 204 "Reserved" 205 "Reserved" 206 "Reserved" 207 "Reserved" 208 "Reserved" 209 "Reserved" 210 "Reserved" 211 "Reserved" 212 "Reserved" 213 "Reserved" 214 "Reserved" 215 "Reserved" 216 "Reserved" 217 "Reserved" 218 "Reserved" 219 "Reserved" 220 "Reserved" 221 "Reserved" 222 "Reserved" 223 "Reserved" 224 "Reserved" 225 "Reserved" 226 "Reserved" 227 "Reserved" 228 "Reserved" 229 "Reserved" 230 "Reserved" 231 "Reserved" 232 "Reserved" 233 "Reserved" 234 "Reserved" 235 "Reserved" 236 "Reserved" 237 "Reserved" 238 "Reserved" 239 "Reserved" 240 "Reserved" 241 "Reserved" 242 "Reserved" 243 "Reserved" 244 "Reserved" 245 "Reserved" 246 "Reserved" 247 "Reserved" 248 "Reserved" 249 "Reserved" 250 "Reserved" 251 "Reserved" 252 "Reserved" 253 "Reserved" 254 "Reserved" 255 "Reserved";
@@ -1,271 +0,0 @@
BO_ 560 NEW_MSG_230: 16 FR_CMR_OR_CAR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 565 NEW_MSG_235: 32 FR_CMR_OR_CAR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 566 NEW_MSG_236: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 567 NEW_MSG_237: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 568 NEW_MSG_238: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 569 NEW_MSG_239: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 570 NEW_MSG_23A: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 571 NEW_MSG_23B: 32 FR_CMR_OR_CAR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 572 NEW_MSG_23C: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 573 NEW_MSG_23D: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 574 NEW_MSG_23E: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 575 NEW_MSG_23F: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 577 NEW_MSG_241: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 578 NEW_MSG_242: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 579 NEW_MSG_243: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 580 NEW_MSG_244: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 581 NEW_MSG_245: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 582 NEW_MSG_246: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 583 NEW_MSG_247: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 584 NEW_MSG_248: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 864 NEW_MSG_360: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 865 NEW_MSG_361: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 867 NEW_MSG_363: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 868 NEW_MSG_364: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 869 NEW_MSG_365: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 870 NEW_MSG_366: 32 FR_CMR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 896 NEW_MSG_380: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 917 NEW_MSG_395: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|255] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|65535] "" FR_CMR
BO_ 928 NEW_MSG_3A0: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|255] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 933 NEW_MSG_3A5: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 934 NEW_MSG_3A6: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 935 NEW_MSG_3A7: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 936 NEW_MSG_3A8: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 937 NEW_MSG_3A9: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 938 NEW_MSG_3AA: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 939 NEW_MSG_3AB: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 940 NEW_MSG_3AC: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 941 NEW_MSG_3AD: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 942 NEW_MSG_3AE: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 943 NEW_MSG_3AF: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 944 NEW_MSG_3B0: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 945 NEW_MSG_3B1: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 946 NEW_MSG_3B2: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 947 NEW_MSG_3B3: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 948 NEW_MSG_3B4: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 949 NEW_MSG_3B5: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 950 NEW_MSG_3B6: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 951 NEW_MSG_3B7: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 952 NEW_MSG_3B8: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 953 NEW_MSG_3B9: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 954 NEW_MSG_3BA: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 955 NEW_MSG_3BB: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 956 NEW_MSG_3BC: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 957 NEW_MSG_3BD: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 958 NEW_MSG_3BE: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 959 NEW_MSG_3BF: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 960 NEW_MSG_3C0: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 962 NEW_MSG_3C2: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 963 NEW_MSG_3C3: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 964 NEW_MSG_3C4: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 976 NEW_MSG_3D0: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 977 NEW_MSG_3D1: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|127] "" FR_CMR
BO_ 978 NEW_MSG_3D2: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 979 NEW_MSG_3D3: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|32767] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 980 NEW_MSG_3D4: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ NEW_SIGNAL_1 : 16|8@1+ (1,0) [0|255] "" FR_CMR
BO_ 1280 NEW_MSG_500: 16 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" FR_CMR
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" FR_CMR
SG_ NEW_SIGNAL_3_SPEED_DEPENDANT : 24|8@1+ (1,0) [0|255] "" FR_CMR
CM_ BO_ 976 "(all 0)";
CM_ BO_ 977 "(all 0)";
CM_ BO_ 978 "(all 0)";
CM_ BO_ 979 "(all 0)";
CM_ BO_ 980 "(all 0)";
CM_ SG_ 1280 NEW_SIGNAL_3_SPEED_DEPENDANT "I dont know what this is but it IS speed dependant";
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,4 @@
CM_ "IMPORT _hyundai_canfd_common.dbc";
CM_ "IMPORT _hyundai_canfd_hda2_cam_unknown.dbc";
BO_ 53 ACCELERATOR: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
@@ -210,9 +209,6 @@ BO_ 298 LFA: 16 ADRV
SG_ ELK_SymbDisp : 90|3@1+ (1,0) [0|7] "" ADRV
SG_ FCA_ESA_WrnSta : 93|1@1+ (1,0) [0|7] "" ADRV
SG_ FCA_ESA_CtrlSta : 101|1@1+ (1,0) [0|7] "" ADRV
SG_ LKAS_ANGLE_ACTIVE : 77|2@0+ (1,0) [0|3] "" XXX
SG_ ADAS_StrAnglReqVal : 82|14@1- (0.1,0) [0|176.7] "Deg" GW_RGW,MDPS,SFA
SG_ ADAS_ACIAnglTqRedcGainVal : 96|8@1+ (0.004,0) [0|1] "" GW_RGW,MDPS,SFA
SG_ Damping_Gain : 104|8@1+ (1,0) [0|255] "" CGW
BO_ 304 GEAR_SHIFTER: 16 XXX
@@ -838,9 +834,7 @@ CM_ SG_ 282 FR_CMR_SCCEquipSta "This signal indicates equipment for SCC";
CM_ SG_ 282 FR_CMR_ReqADASMapMsgVal "This signal indicates an ADAS map message request from FR_CMR to H_U. Each bit indicates the request messages as follows. - Bit 0 : H_U_NAVI_V2_STUB_E - Bit 1 : HU_NAVI_V2_PROSHORT_E_00 (곡률) - Bit 2 : HU_NAVI_V2_PROSHORT_E_00 (곡률 외 정보)";
CM_ SG_ 282 FR_CMR_SwVer1Val "This signal indicates a major version of FR_CMR software. If FR_CMR software version is A.00, 'A' and '00' mean major and minor version respectively.";
CM_ SG_ 282 FR_CMR_SwVer2Val "This signal indicates a minor version of FR_CMR software. If FR_CMR software version is A.00, 'A' and '00' mean major and minor version respectively.";
CM_ BO_ 298 "This message controls steering and alerts regarding lateral control. Formerly known as LFA.
Node is flagged as ADRV, but in reality this signal can be seen from either the FR_CMR (front camera) or the ADRV (adas ecu) for some trims.";
CM_ BO_ 298 "This message controls steering and alerts regarding lateral control. Formerly known as LFA. Node is flagged as ADRV, but in reality this signal can be seen from either the FR_CMR (front camera) or the ADRV (adas ecu) for some trims.";
CM_ SG_ 298 LKA_OptUsmSta "LKA_OptionUsmStatus ##2G##LDW_LKA - LKA11 - CF_LKA_Opt_USM";
CM_ SG_ 298 LKA_RcgSta "LKA_RecognitionStatus ##2G##LDW_LKA - LKA11 - CF_LKA_LaneRecogState";
CM_ SG_ 298 LKA_LHLnWrnSta "LKA_LHLaneWarningStatus ##2G##LDW_LKA - LKA11 - CF_LKA_LHWarning";
@@ -1,855 +0,0 @@
CM_ "IMPORT _hyundai_canfd_common.dbc";
CM_ "IMPORT _hyundai_canfd_ccnc_og.dbc";
BO_ 74 IMU_01_10ms: 32 CGW_CCU
SG_ IMU_Crc1Val : 0|16@1+ (1,0) [0|0] "" ECS,ESC,FCU_C,GW_RGW,ICSC,MDPS,RCU,RWS,SFA,VPC_C
SG_ IMU_AlvCnt1Val : 16|8@1+ (1,0) [0|0] "" ECS,ESC,FCU_C,GW_RGW,ICSC,MDPS,RCU,RWS,SFA,VPC_C
SG_ IMU_YawSigSta : 24|4@1+ (1,0) [0|15] "" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ IMU_LatAccelSigSta : 28|4@1+ (1,0) [0|15] "" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ IMU_LongAccelSigSta : 32|4@1+ (1,0) [0|15] "" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ IMU_VerAccelSigSta : 36|4@1+ (1,0) [0|15] "" XXX
SG_ IMU_McuVoltSta : 40|4@1+ (1,0) [0|15] "" XXX
SG_ IMU_AcuRstSta : 44|4@1+ (1,0) [0|15] "" XXX
SG_ IMU_SnsrTyp : 48|8@1+ (1,0) [0|255] "" XXX
SG_ IMU_RollSigSta : 56|8@1+ (1,0) [0|255] "" XXX
SG_ IMU_YawRtVal : 64|16@1+ (0.005,-163.84) [-163.84|163.835] "Deg/s" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ IMU_LatAccelVal : 80|16@1+ (0.000127465,-4.17677312) [-4.17677312|4.176645655] "g" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ IMU_LongAccelVal : 96|16@1+ (0.000127465,-4.17677312) [-4.17677312|4.176645655] "g" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ IMU_SnsrTempVal : 112|16@1+ (1,0) [0|65535] "" XXX
SG_ IMU_SeralNumVal : 128|64@1+ (1,0) [0|1.84467440737096e+19] "" XXX
SG_ IMU_RollRtVal : 192|16@1+ (0.005,-163.84) [0|0] "º/s" XXX
SG_ IMU_VerAccelVal : 208|8@1+ (1,0) [0|255] "" XXX
BO_ 229 ESC_02_10ms: 32 CGW
SG_ ESC_YawSigSta : 24|4@1+ (1,0) [0|15] "" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ ESC_LatAccelSigSta : 28|4@1+ (1,0) [0|15] "" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ ESC_LongAccelSigSta : 32|4@1+ (1,0) [0|15] "" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ ESC_YawRtVal : 64|16@1+ (0.005,-163.84) [-163.84|163.835] "Deg/s" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ ESC_LatAccelVal : 80|16@1+ (0.000127465,-4.17677312) [-4.17677312|4.176645655] "g" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
SG_ ESC_LongAccelVal : 96|16@1+ (0.000127465,-4.17677312) [-4.17677312|4.176645655] "g" CLU,ADAS_PRK,FR_CMR,RR_C_RDR
BO_ 53 ACCELERATOR: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ ACCELERATOR_PEDAL : 40|8@1+ (1,0) [0|255] "" XXX
SG_ GEAR : 192|3@1+ (1,0) [0|7] "" XXX
BO_ 64 GEAR_ALT: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ GEAR : 32|3@1+ (1,0) [0|7] "" XXX
BO_ 69 GEAR: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ GEAR : 44|3@1+ (1,0) [0|7] "" XXX
BO_ 96 ESP_STATUS: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ TRACTION_AND_STABILITY_CONTROL : 42|3@1+ (1,0) [0|63] "" XXX
SG_ BRAKE_PRESSURE : 128|10@1+ (1,0) [0|65535] "" XXX
SG_ BRAKE_PRESSED : 148|1@1+ (1,0) [0|3] "" XXX
BO_ 101 BRAKE: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ BRAKE_POSITION : 40|16@1- (1,0) [0|65535] "" XXX
SG_ BRAKE_PRESSED : 57|1@1+ (1,0) [0|3] "" XXX
BO_ 112 GEAR_ALT_2: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ GEAR : 60|3@1+ (1,0) [0|7] "" XXX
BO_ 160 WHEEL_SPEEDS: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ MOVING_FORWARD : 56|1@0+ (1,0) [0|1] "" XXX
SG_ MOVING_BACKWARD : 57|1@0+ (1,0) [0|1] "" XXX
SG_ MOVING_FORWARD2 : 58|1@0+ (1,0) [0|1] "" XXX
SG_ MOVING_BACKWARD2 : 59|1@0+ (1,0) [0|1] "" XXX
SG_ WHL_SpdFLVal : 64|14@1+ (0.03125,0) [0|0] "km^h" XXX
SG_ WHL_SpdFRVal : 80|14@1+ (0.03125,0) [0|0] "km^h" XXX
SG_ WHL_SpdRLVal : 96|14@1+ (0.03125,0) [0|0] "km^h" XXX
SG_ WHL_SpdRRVal : 112|14@1+ (0.03125,0) [0|0] "km^h" XXX
BO_ 234 MDPS: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ LKA_ACTIVE : 48|1@0+ (1,0) [0|16777215] "" XXX
SG_ LKA_FAULT : 54|1@0+ (1,0) [0|1] "" XXX
SG_ STEERING_OUT_TORQUE : 64|12@1+ (0.1,-204.8) [0|65535] "" XXX
SG_ STEERING_COL_TORQUE : 80|13@1+ (1,-4095) [0|4095] "" XXX
SG_ STEERING_ANGLE : 96|16@1- (0.1,0) [0|255] "deg" XXX
SG_ STEERING_ANGLE_2 : 128|16@1- (0.1,0) [0|65535] "deg" XXX
SG_ LKA_ANGLE_ACTIVE : 145|2@0+ (1,0) [0|3] "" XXX
SG_ LKA_ANGLE_FAULT : 149|1@0+ (1,0) [0|1] "" XXX
BO_ 256 ACCELERATOR_BRAKE_ALT: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ BRAKE_PRESSED : 32|1@1+ (1,0) [0|1] "" XXX
SG_ ACCELERATOR_PEDAL_PRESSED : 176|1@1+ (1,0) [0|1] "" XXX
BO_ 261 ACCELERATOR_ALT: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ ACCELERATOR_PEDAL : 103|10@1+ (0.25,0) [0|1022] "" XXX
BO_ 282 FR_CMR_01_10ms: 16 FR_CMR
SG_ FR_CMR_Crc1Val : 0|16@1+ (1,0) [0|0] "" Dummy,IBU_HS,vBDM
SG_ FR_CMR_AlvCnt1Val : 16|8@1+ (1,0) [0|0] "" CLU,IBU_HS,vBDM
SG_ HBA_SysOptSta : 24|2@1+ (1,0) [0|3] "" CLU,IBU_HS,vBDM
SG_ HBA_SysSta : 26|3@1+ (1,0) [0|7] "" CLU,IBU_HS,vBDM
SG_ HBA_IndLmpReq : 29|2@1+ (1,0) [0|3] "" CLU,vBDM
SG_ iHBAref_VehLftSta : 31|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM
SG_ iHBAref_VehCtrSta : 33|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM
SG_ iHBAref_VehRtSta : 35|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM
SG_ iHBAref_ILLAmbtSta : 37|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM
SG_ FCA_Equip_MFC : 39|3@1+ (1,0) [0|0] "" ADAS_DRV,RR_C_RDR,vBDM
SG_ HBA_OptUsmSta : 42|2@1+ (1,0) [0|3] "" CLU,H_U_MM
SG_ FCAref_FusSta : 45|3@1+ (1,0) [0|0] "" vBDM
SG_ DAW_LVDA_PUDis : 48|2@1+ (1,0) [0|0] "" CLU,vBDM
SG_ DAW_LVDA_OptUsmSta : 50|2@1+ (1,0) [0|3] "" CLU,H_U_MM,vBDM
SG_ DAW_OptUsmSta : 52|3@1+ (1,0) [0|0] "" CLU,H_U_MM
SG_ DAW_SysSta : 55|4@1+ (1,0) [0|0] "" CLU
SG_ DAW_WrnMsgSta : 59|3@1+ (1,0) [0|0] "" CLU
SG_ DAW_TimeRstReq : 62|2@1+ (1,0) [0|0] "" CLU
SG_ DAW_SnstvtyModRetVal : 64|3@1+ (1,0) [0|0] "" CLU,H_U_MMz
BO_ 293 STEERING_SENSORS: 16 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ STEERING_ANGLE : 24|16@1- (0.1,0) [0|255] "deg" XXX
SG_ STEERING_RATE : 40|8@1+ (4,0) [0|1016] "deg/s" XXX
BO_ 304 GEAR_SHIFTER: 16 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ PARK_BUTTON : 32|2@1+ (1,0) [0|3] "" XXX
SG_ KNOB_POSITION : 40|3@1+ (1,0) [0|3] "" XXX
SG_ GEAR : 64|3@1+ (1,0) [0|7] "" XXX
BO_ 352 ADRV_0x160: 16 ADRV
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ AEB_SETTING : 24|2@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_2 : 56|8@1+ (1,0) [0|1] "" XXX
SG_ SET_ME_FF : 64|8@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_FC : 72|8@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_9 : 80|8@1+ (1,0) [0|255] "" XXX
BO_ 353 CCNC_0x161: 32 CCNC
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ FCA_ICON : 24|3@1+ (1,0) [0|7] "" XXX
SG_ FCA_ALT_ICON : 27|3@1+ (1,0) [0|7] "" XXX
SG_ LKA_ICON : 30|3@1+ (1,0) [0|3] "" XXX
SG_ HBA_ICON : 33|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_1 : 36|4@1+ (1,0) [0|15] "" XXX
SG_ ZEROS_2 : 40|2@1+ (1,0) [0|3] "" XXX
SG_ FCA_IMAGE : 42|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_3 : 45|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_4 : 48|3@1+ (1,0) [0|7] "" XXX
SG_ BCA_LEFT : 51|3@1+ (1,0) [0|7] "" XXX
SG_ BCA_RIGHT : 54|3@1+ (1,0) [0|7] "" XXX
SG_ LCA_LEFT_ARROW : 57|3@1+ (1,0) [0|7] "" XXX
SG_ LCA_RIGHT_ARROW : 60|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_5 : 63|1@0+ (1,0) [0|1] "" XXX
SG_ CENTERLINE : 64|2@1+ (1,0) [0|3] "" XXX
SG_ TARGET : 66|3@1+ (1,0) [0|7] "" XXX
SG_ TARGET_DISTANCE : 69|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ LANELINE_LEFT : 80|4@1+ (1,0) [0|15] "" XXX
SG_ LANELINE_LEFT_POSITION : 84|6@1+ (1,0) [0|15] "" XXX
SG_ LANELINE_RIGHT : 90|4@1+ (1,0) [0|15] "" XXX
SG_ LANELINE_RIGHT_POSITION : 94|6@1+ (1,0) [0|3] "" XXX
SG_ LANELINE_CURVATURE : 100|5@1- (1,15) [0|31] "" XXX
SG_ LANE_HIGHLIGHT : 105|4@1+ (1,0) [0|15] "" XXX
SG_ LANE_HIGHLIGHT_DISTANCE : 109|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ LANE_LEFT : 120|3@1+ (1,0) [0|7] "" XXX
SG_ LANE_RIGHT : 123|3@1+ (1,0) [0|7] "" XXX
SG_ LANE_ZOOM : 126|2@1+ (1,0) [0|3] "" XXX
SG_ ALERTS_1 : 128|6@1+ (1,0) [0|63] "" XXX
SG_ ALERTS_2 : 134|5@1+ (1,0) [0|3] "" XXX
SG_ ALERTS_3 : 139|5@1+ (1,0) [0|15] "" XXX
SG_ ALERTS_4 : 144|8@1+ (1,0) [0|511] "" XXX
SG_ ALERTS_5 : 152|5@1+ (1,0) [0|7] "" XXX
SG_ MUTE : 157|3@1+ (1,0) [0|7] "" XXX
SG_ SOUNDS_1 : 160|4@1+ (1,0) [0|3] "" XXX
SG_ SOUNDS_2 : 164|4@1+ (1,0) [0|3] "" XXX
SG_ SOUNDS_3 : 168|4@1+ (1,0) [0|15] "" XXX
SG_ SOUNDS_4 : 172|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_6 : 175|1@0+ (1,0) [0|1] "" XXX
SG_ ZEROS_7 : 176|5@1+ (1,0) [0|31] "" XXX
SG_ SETSPEED_HUD : 181|3@1+ (1,0) [0|3] "" XXX
SG_ DISTANCE_LEAD : 184|5@1+ (1,0) [0|31] "" XXX
SG_ DISTANCE_CAR : 189|3@1+ (1,0) [0|7] "" XXX
SG_ DISTANCE_SPACING : 192|4@1+ (1,0) [0|15] "" XXX
SG_ DISTANCE : 196|4@1+ (1,0) [0|7] "" XXX
SG_ SETSPEED_SPEED : 200|8@1+ (1,0) [0|255] "" XXX
SG_ SETSPEED : 208|4@1+ (1,0) [0|3] "" XXX
SG_ HDA_ICON : 212|4@1+ (1,0) [0|3] "" XXX
SG_ SLA_ICON : 216|4@1+ (1,0) [0|15] "" XXX
SG_ NAV_ICON : 220|4@1+ (1,0) [0|3] "" XXX
SG_ LFA_ICON : 224|4@1+ (1,0) [0|3] "" XXX
SG_ LCA_LEFT_ICON : 228|4@1+ (1,0) [0|15] "" XXX
SG_ LCA_RIGHT_ICON : 232|4@1+ (1,0) [0|15] "" XXX
SG_ BACKGROUND : 236|4@1+ (1,0) [0|15] "" XXX
SG_ DAW_ICON : 240|3@1+ (1,0) [0|7] "" XXX
SG_ CAR_CIRCLE : 243|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_8 : 246|2@1+ (1,0) [0|3] "" XXX
SG_ ZEROS_9 : 248|8@1+ (1,0) [0|255] "" XXX
BO_ 354 CCNC_0x162: 32 CCNC
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ COUNTRY : 24|4@1+ (1,0) [0|7] "" XXX
SG_ SPEEDLIMIT_FLASH : 28|4@1+ (1,0) [0|15] "" XXX
SG_ SPEEDLIMIT : 32|8@1+ (1,0) [0|255] "" XXX
SG_ SIGNS : 40|8@1+ (1,0) [0|15] "" XXX
SG_ SPEEDLIMIT_WEATHER : 48|4@1+ (1,0) [0|15] "" XXX
SG_ VIBRATE : 52|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_1 : 55|1@0+ (1,0) [0|1] "" XXX
SG_ ZEROS_2 : 56|8@1+ (1,0) [0|255] "" XXX
SG_ LEAD : 64|5@1+ (1,0) [0|31] "" XXX
SG_ LEAD_DISTANCE : 69|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ LEAD_LATERAL : 80|7@1+ (0.1,0) [0|127] "m" XXX
SG_ ZEROS_3 : 87|1@0+ (1,0) [0|1] "" XXX
SG_ LEAD_ALT : 88|5@1+ (1,0) [0|31] "" XXX
SG_ LEAD_ALT_DISTANCE : 93|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ LEAD_ALT_LATERAL : 104|7@1+ (0.1,0) [0|127] "m" XXX
SG_ ZEROS_4 : 111|1@0+ (1,0) [0|1] "" XXX
SG_ LEAD_LEFT : 112|5@1+ (1,0) [0|31] "" XXX
SG_ LEAD_LEFT_DISTANCE : 117|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ LEAD_LEFT_LATERAL : 128|7@1+ (0.1,0) [0|127] "m" XXX
SG_ ZEROS_5 : 135|1@0+ (1,0) [0|1] "" XXX
SG_ LEAD_RIGHT : 136|5@1+ (1,0) [0|31] "" XXX
SG_ LEAD_RIGHT_DISTANCE : 141|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ LEAD_RIGHT_LATERAL : 152|7@1+ (0.1,0) [0|127] "m" XXX
SG_ ZEROS_6 : 159|1@0+ (1,0) [0|1] "" XXX
SG_ ZEROS_7 : 162|3@0+ (1,0) [0|7] "" XXX
SG_ LEAD_LEFT_REAR_STATUS : 167|5@0+ (1,0) [0|31] "" XXX
SG_ LEAD_LEFT_REAR_DISTANCE : 175|8@0+ (0.1,0) [0|255] "m" XXX
SG_ LEAD_LEFT_REAR_LATERAL : 182|7@0+ (0.1,0) [0|127] "m" XXX
SG_ ZEROS_8 : 183|1@0+ (1,0) [0|1] "" XXX
SG_ ZEROS_9 : 191|8@0+ (1,0) [0|255] "" XXX
SG_ LEAD_RIGHT_REAR_STATUS : 196|5@0+ (1,0) [0|31] "" XXX
SG_ LEAD_RIGHT_REAR_DISTANCE : 197|8@1+ (0.1,0) [0|255] "m" XXX
SG_ LEAD_RIGHT_REAR_LATERAL : 205|7@1+ (0.1,0) [0|127] "m" XXX
SG_ ZEROS_10 : 212|1@0+ (1,0) [0|1] "" XXX
SG_ FAULT_FSS : 213|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_FCA : 216|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_LSS : 219|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_SLA : 222|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_DAW : 225|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_HBA : 228|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_SCC : 231|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_LFA : 234|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_HDA : 237|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_LCA : 240|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_HDP : 243|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_DAS : 246|3@1+ (1,0) [0|7] "" XXX
SG_ FAULT_ESS : 249|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_11 : 252|4@1+ (1,0) [0|15] "" XXX
BO_ 357 SPAS1: 24 APRK
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|0] "" XXX
SG_ NEW_SIGNAL_2 : 90|3@1+ (1,0) [0|0] "" XXX
SG_ NEW_SIGNAL_1 : 96|16@1- (0.1,0) [0|0] "" XXX
BO_ 362 SPAS2: 32 APRK
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|0] "" XXX
SG_ BLINKER_CONTROL : 133|3@1+ (1,0) [0|0] "" XXX
BO_ 373 TCS: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_4 : 24|7@1+ (1,0) [0|127] "" XXX
SG_ aBasis : 32|11@1+ (0.01,-10.23) [0|7] "m/s^2" XXX
SG_ ACCEL_REF_ACC : 48|11@1- (1,0) [0|1023] "" XXX
SG_ EQUIP_MAYBE : 64|1@0+ (1,0) [0|1] "" XXX
SG_ ACCEnable : 67|2@0+ (1,0) [0|3] "" XXX
SG_ ACC_REQ : 68|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_5 : 72|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_2 : 74|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_3 : 76|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_1 : 80|1@0+ (1,0) [0|1] "" XXX
SG_ DriverBraking : 81|1@0+ (1,0) [0|1] "" XXX
SG_ DriverBrakingLowSens : 84|1@1+ (1,0) [0|1] "" XXX
SG_ AEB_EQUIP_MAYBE : 96|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_6 : 128|4@1+ (1,0) [0|15] "" XXX
SG_ NEW_SIGNAL_7 : 135|2@0+ (1,0) [0|3] "" XXX
SG_ PROBABLY_EQUIP : 136|2@1+ (1,0) [0|3] "" XXX
BO_ 416 SCC_CONTROL: 32 ADRV
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ ACC_ObjDist : 24|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ ACC_ObjRelSpd : 35|9@1+ (0.1,-16.4) [-16.4|34.7] "m/s" XXX
SG_ SET_ME_3 : 45|2@0+ (1,0) [0|3] "" XXX
SG_ ObjValid : 46|1@0+ (1,0) [0|3] "" XXX
SG_ SET_ME_TMP_64 : 55|8@0+ (1,0) [0|63] "" XXX
SG_ ZEROS_7 : 63|8@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_1 : 64|2@1+ (1,0) [0|3] "" XXX
SG_ MainMode_ACC : 66|1@1+ (1,0) [0|1] "" XXX
SG_ ACCMode : 68|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_9 : 71|5@1+ (1,0) [0|15] "" XXX
SG_ CRUISE_STANDSTILL : 76|1@1+ (1,0) [0|1] "" XXX
SG_ ZEROS_5 : 77|11@1+ (1,0) [0|2047] "" XXX
SG_ DISTANCE_SETTING : 88|3@1+ (1,0) [0|3] "" XXX
SG_ ZEROS_8 : 95|5@0+ (1,0) [0|31] "" XXX
SG_ VSetDis : 103|8@0+ (1,0) [0|255] "km/h or mph" XXX
SG_ NEW_SIGNAL_6 : 104|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_2 : 105|3@1+ (1,0) [0|7] "" XXX
SG_ NEW_SIGNAL_3 : 109|2@0+ (1,0) [0|1] "" XXX
SG_ ZEROS_10 : 111|2@0+ (1,0) [0|3] "" XXX
SG_ ZEROS_6 : 119|16@0+ (1,0) [0|65535] "" XXX
SG_ aReqValue : 128|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX
SG_ aReqRaw : 140|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX
SG_ JerkUpperLimit : 158|7@0+ (0.1,0) [0|0] "" XXX
SG_ JerkLowerLimit : 166|7@0+ (0.1,0) [0|12.7] "m/s^3" XXX
SG_ NEW_SIGNAL_2 : 168|2@1+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_8 : 170|4@1+ (1,0) [0|15] "" XXX
SG_ OBJ_STATUS : 176|3@1+ (1,0) [0|7] "" XXX
SG_ ZEROS_4 : 183|4@0+ (1,0) [0|63] "" XXX
SG_ StopReq : 184|1@0+ (1,0) [0|1] "" XXX
SG_ ZEROS_3 : 191|7@0+ (1,0) [0|127] "" XXX
SG_ NEW_SIGNAL_15 : 192|11@1+ (0.1,0) [0|204.7] "m" XXX
SG_ ZEROS_2 : 207|5@0+ (1,0) [0|63] "" XXX
SG_ ZEROS : 215|48@0+ (1,0) [0|281474976710655] "" XXX
BO_ 426 CRUISE_BUTTONS_ALT: 16 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_1 : 24|4@1+ (1,0) [0|15] "" XXX
SG_ SET_ME_1 : 28|2@1+ (1,0) [0|3] "" XXX
SG_ DISTANCE_UNIT : 30|1@1+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_2 : 31|3@1+ (1,0) [0|7] "" XXX
SG_ ADAPTIVE_CRUISE_MAIN_BTN : 34|1@1+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_3 : 35|1@1+ (1,0) [0|1] "" XXX
SG_ CRUISE_BUTTONS : 36|3@1+ (1,0) [0|4] "" XXX
SG_ LDA_BTN : 39|1@1+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_4 : 40|1@1+ (1,0) [0|1] "" XXX
SG_ NORMAL_CRUISE_MAIN_BTN : 41|1@1+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_5 : 42|2@1+ (1,0) [0|3] "" XXX
SG_ SET_ME_2 : 44|3@1+ (1,0) [0|7] "" XXX
SG_ NEW_SIGNAL_6 : 47|1@1+ (1,0) [0|1] "" XXX
SG_ BYTE6 : 48|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE7 : 56|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE8 : 64|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE9 : 72|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE10 : 80|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE11 : 88|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE12 : 96|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE13 : 104|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE14 : 112|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE15 : 120|8@1+ (1,0) [0|255] "" XXX
BO_ 437 FR_CMR_03_50ms: 32 FR_CMR
SG_ FR_CMR_Crc3Val : 0|16@1+ (1,0) [0|65535] "" RR_C_RDR,CGW
SG_ FR_CMR_AlvCnt3Val : 16|8@1+ (1,0) [0|255] "" RR_C_RDR,CGW
SG_ Info_LftLnQualSta : 24|3@1+ (1,0) [0|7] "" RR_C_RDR,CGW
SG_ Info_LftLnDptSta : 27|2@1+ (1,0) [0|3] "" RR_C_RDR,CGW
SG_ Info_LftLnPosVal : 29|14@1- (0.0039625,0) [-32.4608|32.4568375] "m" RR_C_RDR,CGW
SG_ Info_LftLnHdingAnglVal : 43|10@1- (0.000976563,0) [-0.500000256|0.499023693] "rad" RR_C_RDR,CGW
SG_ Info_LftLnCvtrVal : 64|16@1- (1e-06,0) [-0.032768|0.032767] "1/m" CGW
SG_ Info_LftLnCrvtrDrvtvVal : 80|16@1- (4e-09,0) [-0.000131072|0.000131068] "1/m2" CGW
SG_ Info_RtLnQualSta : 96|3@1+ (1,0) [0|7] "" RR_C_RDR,CGW
SG_ Info_RtLnDptSta : 99|2@1+ (1,0) [0|3] "" RR_C_RDR,CGW
SG_ Info_RtLnPosVal : 101|14@1- (0.0039625,0) [-32.4608|32.4568375] "m" RR_C_RDR,CGW
SG_ Info_RtLnHdingAnglVal : 115|10@1- (0.000976563,0) [-0.500000256|0.499023693] "rad" RR_C_RDR,CGW
SG_ Info_RtLnCvtrVal : 128|16@1- (1,0) [0|65535] "" CGW
SG_ Info_RtLnCrvtrDrvtvVal : 144|16@1- (1,0) [0|65535] "" CGW
SG_ ID_CIPV : 192|8@1+ (1,0) [0|255] "" XXX
SG_ Relative_Velocity : 200|12@1+ (0.05,-100) [-100|104.75] "m/s" Dummy
SG_ Longitudinal_Distance : 212|12@1+ (0.05,0) [0|204.75] "m" Dummy
BO_ 442 BLINDSPOTS_REAR_CORNERS: 24 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ LEFT_BLOCKED : 24|1@0+ (1,0) [0|1] "" XXX
SG_ LEFT_MB : 30|1@0+ (1,0) [0|3] "" XXX
SG_ MORE_LEFT_PROB : 32|1@1+ (1,0) [0|3] "" XXX
SG_ FL_INDICATOR : 46|6@0+ (1,0) [0|1] "" XXX
SG_ FR_INDICATOR : 54|6@0+ (1,0) [0|63] "" XXX
SG_ RIGHT_BLOCKED : 64|1@0+ (1,0) [0|1] "" XXX
SG_ COLLISION_AVOIDANCE_ACTIVE : 68|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_2 : 96|1@0+ (1,0) [0|1] "" XXX
SG_ FL_INDICATOR_ALT : 138|1@0+ (1,0) [0|1] "" XXX
SG_ FR_INDICATOR_ALT : 141|1@0+ (1,0) [0|1] "" XXX
BO_ 463 CRUISE_BUTTONS: 8 XXX
SG_ _CHECKSUM : 0|8@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 12|4@1+ (1,0) [0|255] "" XXX
SG_ CRUISE_BUTTONS : 16|3@1+ (1,0) [0|3] "" XXX
SG_ ADAPTIVE_CRUISE_MAIN_BTN : 19|1@1+ (1,0) [0|1] "" XXX
SG_ NORMAL_CRUISE_MAIN_BTN : 21|1@1+ (1,0) [0|1] "" XXX
SG_ LDA_BTN : 23|1@1+ (1,0) [0|1] "" XXX
SG_ RIGHT_PADDLE : 25|1@1+ (1,0) [0|1] "" XXX
SG_ LEFT_PADDLE : 27|1@1+ (1,0) [0|1] "" XXX
SG_ SET_ME_1 : 29|1@1+ (1,0) [0|1] "" XXX
BO_ 474 ADRV_0x1da: 32 ADRV
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_22 : 31|8@0+ (1,0) [0|255] "" XXX
SG_ SET_ME_41 : 47|8@0+ (1,0) [0|255] "" XXX
BO_ 480 LFAHDA_CLUSTER: 16 ADRV
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_4 : 24|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_5 : 25|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_2 : 30|1@0+ (1,0) [0|1] "" XXX
SG_ HDA_ICON : 31|1@1+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_1 : 32|3@1+ (1,0) [0|7] "" XXX
SG_ LFA_ICON : 47|2@1+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_3 : 49|1@0+ (1,0) [0|1] "" XXX
BO_ 485 BLINDSPOTS_FRONT_CORNER_1: 16 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ REVERSING : 24|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_5 : 31|2@0+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_7 : 32|2@1+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_8 : 47|8@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_9 : 55|8@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_4 : 80|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_3 : 88|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_2 : 96|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_1 : 108|2@0+ (1,0) [0|3] "" XXX
BO_ 490 ADRV_0x1ea: 32 ADRV
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_1C : 31|8@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_1 : 32|2@1+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_2 : 47|2@0+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_3 : 55|8@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_4 : 64|6@1+ (1,0) [0|31] "" XXX
SG_ NEW_SIGNAL_5 : 72|2@1+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_6 : 75|5@1+ (1,0) [0|31] "" XXX
SG_ NEW_SIGNAL_7 : 80|5@1+ (1,0) [0|31] "" XXX
SG_ NEW_SIGNAL_8 : 88|7@1+ (1,0) [0|127] "" XXX
SG_ NEW_SIGNAL_9 : 96|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_FF : 120|8@1+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_10 : 143|5@0+ (1,0) [0|31] "" XXX
SG_ NEW_SIGNAL_11 : 144|3@1+ (1,0) [0|7] "" XXX
SG_ NEW_SIGNAL_12 : 152|6@1+ (1,0) [0|63] "" XXX
SG_ NEW_SIGNAL_13 : 160|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_14 : 163|5@1+ (1,0) [0|31] "" XXX
SG_ NEW_SIGNAL_16 : 168|3@1+ (1,0) [0|7] "" XXX
SG_ NEW_SIGNAL_15 : 175|4@0+ (1,0) [0|63] "" XXX
SG_ NEW_SIGNAL_17 : 176|2@1+ (1,0) [0|3] "" XXX
SG_ NEW_SIGNAL_18 : 184|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_19 : 208|3@1+ (1,0) [0|7] "" XXX
SG_ NEW_SIGNAL_20 : 212|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_TMP_F : 232|5@1+ (1,0) [0|31] "" XXX
SG_ SET_ME_TMP_F_2 : 240|5@1+ (1,0) [0|31] "" XXX
BO_ 506 FR_CMR_02_100ms: 32 FR_CMR
SG_ FR_CMR_Crc2Val : 0|16@1+ (1,0) [0|65535] "" CGW
SG_ FR_CMR_AlvCnt2Val : 16|8@1+ (1,0) [0|255] "" CGW
SG_ ISLW_OptUsmSta : 24|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ISLW_SysSta : 26|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ISLW_NoPassingInfoDis : 28|3@1+ (1,0) [0|7] "" CLU,CGW
SG_ ISLW_OvrlpSignDis : 31|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ISLW_SpdCluMainDis : 33|8@1+ (1,0) [0|255] "" CLU,CGW
SG_ ISLW_SpdNaviMainDis : 41|8@1+ (1,0) [0|255] "" CGW
SG_ ISLW_SubCondinfoSta1 : 49|4@1+ (1,0) [0|15] "" CLU,CGW
SG_ ISLW_SubCondinfoSta2 : 53|4@1+ (1,0) [0|15] "" CLU,CGW
SG_ ISLW_SpdCluSubMainDis : 64|8@1+ (1,0) [0|255] "" CLU
SG_ ISLW_SpdCluDisSubCond1 : 72|8@1+ (1,0) [0|255] "" CLU,CGW
SG_ ISLW_SpdCluDisSubCond2 : 80|8@1+ (1,0) [0|255] "" CLU,CGW
SG_ ISLW_SpdNaviSubMainDis : 88|8@1+ (1,0) [0|255] "" CLU
SG_ ISLW_SpdNaviDisSubCond1 : 96|8@1+ (1,0) [0|255] "" CLU,CGW
SG_ ISLW_SpdNaviDisSubCond2 : 104|8@1+ (1,0) [0|255] "" CLU,CGW
SG_ ISLA_SpdwOffst : 112|8@1+ (1,0) [0|255] "" CLU,CGW
SG_ ISLA_SwIgnoreReq : 120|2@1+ (1,0) [0|3] "" CGW
SG_ ISLA_SpdChgReq : 122|2@1+ (1,0) [0|3] "" CGW
SG_ ISLA_SpdWrn : 124|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ISLA_IcyWrn : 126|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ISLA_SymFlashMod : 128|3@1+ (1,0) [0|7] "" CLU,CGW
SG_ ISLA_Popup : 131|3@1+ (1,0) [0|7] "" CLU
SG_ ISLA_OptUsmSta : 136|3@1+ (1,0) [0|7] "" CLU,CGW
SG_ ISLA_OffstUsmSta : 139|3@1+ (1,0) [0|7] "" CLU,CGW
SG_ ISLA_AutoUsmSta : 142|2@1+ (1,0) [0|3] "" CLU,CGW
SG_ ISLA_Cntry : 144|4@1+ (1,0) [0|15] "" CLU,CGW
SG_ ISLA_AddtnlSign : 149|5@1+ (1,0) [0|31] "" CLU,CGW
SG_ ISLA_SchoolZone : 154|2@1+ (1,0) [0|3] "" CLU,CGW
BO_ 507 CAM_0x1fb: 32 CAMERA
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 512 ADRV_0x200: 8 ADRV
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_E1 : 24|8@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_3A : 32|8@1+ (1,0) [0|255] "" XXX
BO_ 593 RADAR_0x251: 16 FRONT_RADAR
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 687 HOD_FD_01_100ms: 8 XXX
SG_ HOD_Dir_Status : 18|3@0+ (1,0) [0|7] "" XXX
SG_ NEW_SIGNAL_2 : 32|8@1+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_3 : 40|8@1+ (1,0) [0|255] "" XXX
SG_ HOD_Option : 48|2@1+ (1,0) [0|255] "" XXX
BO_ 698 FR_CMR_04_40ms: 32 FR_CMR
SG_ FR_CMR_Crc4Val : 0|16@1+ (1,0) [0|65535] "" Dummy
SG_ FR_CMR_AlvCnt4Val : 16|8@1+ (1,0) [0|255] "" Dummy
SG_ IFSref_FR_CMR_Sta : 24|2@1+ (1,0) [0|3] "" CGW
SG_ IFSref_VehNumVal : 26|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_ILLAmbtSta : 30|2@1+ (0.1,0) [0|0.3] "" CGW
SG_ IFSref_VehLftAngl1Val : 32|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl1Val : 41|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl2Val : 50|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehDst1Val : 59|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehRtAngl2Val : 64|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl3Val : 73|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl3Val : 82|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl4Val : 91|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl4Val : 100|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl5Val : 109|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl5Val : 118|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl6Val : 128|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl6Val : 137|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl7Val : 146|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl7Val : 155|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl8Val : 164|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl8Val : 173|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl9Val : 182|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl9Val : 192|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehLftAngl10Val : 201|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehRtAngl10Val : 210|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW
SG_ IFSref_VehDst2Val : 219|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst3Val : 223|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst4Val : 227|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst5Val : 231|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst6Val : 235|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst7Val : 239|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst8Val : 243|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst9Val : 247|4@1+ (1,0) [0|15] "" CGW
SG_ IFSref_VehDst10Val : 251|4@1+ (1,0) [0|15] "" CGW
BO_ 736 MANUAL_SPEED_LIMIT_ASSIST: 32 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ MSLA_STATUS : 26|2@1+ (1,0) [0|3] "" XXX
SG_ MSLA_ENABLED : 38|1@1+ (1,0) [0|1] "" XXX
SG_ MAX_SPEED : 55|8@0+ (1,0) [0|255] "" XXX
SG_ MAX_SPEED_COPY : 144|8@1+ (1,0) [0|255] "" XXX
BO_ 837 ADRV_0x345: 8 ADRV
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ SET_ME_15 : 24|8@1+ (1,0) [0|255] "" XXX
BO_ 866 CAM_0x362: 32 CAMERA
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE3 : 24|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE4 : 32|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE5 : 40|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE6 : 48|8@1+ (1,0) [0|255] "" XXX
SG_ LEFT_LANE_LINE : 56|2@1+ (1,0) [0|3] "" XXX
SG_ SET_ME_0 : 58|2@1+ (1,0) [0|3] "" XXX
SG_ RIGHT_LANE_LINE : 60|2@1+ (1,0) [0|3] "" XXX
SG_ SET_ME_0_2 : 62|2@1+ (1,0) [0|3] "" XXX
SG_ BYTE8 : 64|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE9 : 72|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE10 : 80|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE11 : 88|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE12 : 96|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE13 : 104|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE14 : 112|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE15 : 120|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE16 : 128|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE17 : 136|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE18 : 144|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE19 : 152|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE20 : 160|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE21 : 168|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE22 : 176|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE23 : 184|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE24 : 192|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE25 : 200|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE26 : 208|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE27 : 216|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE28 : 224|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE29 : 232|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE30 : 240|8@1+ (1,0) [0|255] "" XXX
SG_ BYTE31 : 248|8@1+ (1,0) [0|255] "" XXX
BO_ 874 BLINDSPOTS_FRONT_CORNER_2: 16 XXX
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
BO_ 961 BLINKER_STALKS: 8 XXX
SG_ CHECKSUM_MAYBE : 7|8@0+ (1,0) [0|255] "" XXX
SG_ COUNTER_ALT : 15|4@0+ (1,0) [0|15] "" XXX
SG_ HIGHBEAM_FORWARD : 18|1@0+ (1,0) [0|1] "" XXX
SG_ LIGHT_KNOB_POSITION : 21|2@0+ (1,0) [0|3] "" XXX
SG_ HIGHBEAM_BACKWARD : 26|1@0+ (1,0) [0|1] "" XXX
SG_ LEFT_BLINKER : 30|1@0+ (1,0) [0|1] "" XXX
SG_ RIGHT_BLINKER : 32|1@0+ (1,0) [0|1] "" XXX
BO_ 1041 DOORS_SEATBELTS: 8 XXX
SG_ CHECKSUM_MAYBE : 7|8@0+ (1,0) [0|65535] "" XXX
SG_ COUNTER_ALT : 15|4@0+ (1,0) [0|15] "" XXX
SG_ DRIVER_DOOR : 24|1@1+ (1,0) [0|1] "" XXX
SG_ PASSENGER_DOOR : 34|1@0+ (1,0) [0|1] "" XXX
SG_ PASSENGER_SEATBELT : 36|1@0+ (1,0) [0|1] "" XXX
SG_ DRIVER_SEATBELT : 42|1@0+ (1,0) [0|1] "" XXX
SG_ DRIVER_REAR_DOOR : 52|1@0+ (1,0) [0|1] "" XXX
SG_ PASSENGER_REAR_DOOR : 56|1@0+ (1,0) [0|1] "" XXX
BO_ 1043 BLINKERS: 8 XXX
SG_ LEFT_STALK : 8|1@0+ (1,0) [0|1] "" XXX
SG_ RIGHT_STALK : 10|1@0+ (1,0) [0|1] "" XXX
SG_ COUNTER_ALT : 15|4@0+ (1,0) [0|15] "" XXX
SG_ LEFT_LAMP : 20|1@0+ (1,0) [0|1] "" XXX
SG_ RIGHT_LAMP : 22|1@0+ (1,0) [0|1] "" XXX
SG_ LEFT_LAMP_ALT : 59|1@0+ (1,0) [0|1] "" XXX
SG_ RIGHT_LAMP_ALT : 61|1@0+ (1,0) [0|1] "" XXX
SG_ USE_ALT_LAMP : 62|1@0+ (1,0) [0|1] "" XXX
BO_ 1144 DRIVE_MODE: 8 XXX
SG_ DRIVE_MODE : 0|16@1+ (1,-61611) [0|61611] "" XXX
SG_ DRIVE_MODE2 : 28|3@1+ (1,0) [1|3] "" XXX
BO_ 1151 HVAC_TOUCH_BUTTONS: 8 XXX
SG_ AUTO_BUTTON : 8|1@0+ (1,0) [0|1] "" XXX
SG_ SYNC_BUTTON : 12|1@0+ (1,0) [0|1] "" XXX
SG_ FR_DEFROST_BUTTON : 20|1@0+ (1,0) [0|1] "" XXX
SG_ RR_DEFROST_BUTTON : 22|1@0+ (1,0) [0|1] "" XXX
SG_ FAN_SPEED_UP_BUTTON : 24|1@0+ (1,0) [0|1] "" XXX
SG_ FAN_SPEED_DOWN_BUTTON : 26|1@0+ (1,0) [0|1] "" XXX
SG_ AIR_DIRECTION_BUTTON : 28|1@0+ (1,0) [0|1] "" XXX
SG_ AC_BUTTON : 40|1@0+ (1,0) [0|1] "" XXX
SG_ DRIVER_ONLY_BUTTON : 44|1@0+ (1,0) [0|1] "" XXX
SG_ RECIRC_BUTTON : 48|1@0+ (1,0) [0|1] "" XXX
SG_ HEAT_BUTTON : 52|1@0+ (1,0) [0|1] "" XXX
BO_ 1240 CLUSTER_INFO: 8 XXX
SG_ DISTANCE_UNIT : 0|1@1+ (1,0) [0|1] "" XXX
BO_ 1259 LOCAL_TIME2: 8 XXX
SG_ HOURS : 15|5@0+ (1,0) [0|31] "" XXX
SG_ MINUTES : 21|6@0+ (1,0) [0|63] "" XXX
SG_ SECONDS : 24|6@1+ (1,0) [0|63] "" XXX
SG_ NEW_SIGNAL_3 : 39|1@0+ (1,0) [0|1] "" XXX
BO_ 1264 LOCAL_TIME: 8 XXX
SG_ HOURS : 12|5@0+ (1,0) [0|31] "" XXX
SG_ MINUTES : 21|6@0+ (1,0) [0|63] "" XXX
SG_ SECONDS : 31|8@0+ (1,0) [0|59] "" XXX
CM_ SG_ 96 BRAKE_PRESSURE "User applied brake pedal pressure. Ramps from computer applied pressure on falling edge of cruise. Cruise cancels if !=0";
CM_ SG_ 101 BRAKE_POSITION "User applied brake pedal position, max is ~700. Signed on some vehicles";
CM_ SG_ 352 SET_ME_9 "has something to do with AEB settings";
CM_ SG_ 373 ACCEnable "Likely a copy of CAN's TCS13->ACCEnable";
CM_ SG_ 373 DriverBraking "Likely derived from BRAKE->BRAKE_POSITION";
CM_ SG_ 373 DriverBrakingLowSens "Higher threshold version of DriverBraking";
CM_ SG_ 373 PROBABLY_EQUIP "aeb equip?";
CM_ SG_ 416 VSetDis "set speed in display units";
CM_ SG_ 480 NEW_SIGNAL_5 "todo: figure out why always set to 1";
CM_ SG_ 687 HOD_Dir_Status "This signal indicates the status of hands on/off";
CM_ SG_ 736 MAX_SPEED "Display units. Restricts car from driving above this speed unless accelerator pedal is depressed beyond pressure point";
CM_ BO_ 866 "Contains signals with detailed lane line information. Used by ADAS ECU on HDA 2 vehicles to operate LFA. Used on cars that use message 272.";
CM_ SG_ 866 LEFT_LANE_LINE "Left lane line confidence";
CM_ SG_ 866 RIGHT_LANE_LINE "Right lane line confidence";
CM_ SG_ 961 COUNTER_ALT "only increments on change";
CM_ SG_ 1041 COUNTER_ALT "only increments on change";
CM_ BO_ 1043 "Lamp signals do not seem universal on cars that use LKAS_ALT, but stalk signals do.";
CM_ SG_ 1043 COUNTER_ALT "only increments on change";
CM_ SG_ 1043 USE_ALT_LAMP "likely 1 on cars that use alt lamp signals";
VAL_ 53 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
VAL_ 64 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
VAL_ 69 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
VAL_ 96 TRACTION_AND_STABILITY_CONTROL 0 "On" 5 "Limited" 1 "Off";
VAL_ 112 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
VAL_ 234 LKA_FAULT 0 "ok" 1 "lka fault";
VAL_ 282 HBA_SysOptSta 0 "None HBA Option (Default)" 1 "HBA Option" 2 "Reserved" 3 "Error indicator";
VAL_ 282 HBA_SysSta 0 "HBA Disable" 1 "HBA Enable & High Beam Off" 2 "HBA Enable & High Beam On" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "System Fail";
VAL_ 282 HBA_IndLmpReq 0 "HBA Indicator Lamp Off" 1 "HBA Indicator Lamp On" 2 "Reserved" 3 "Error indicator";
VAL_ 282 FCA_Equip_MFC 0 "No Coding" 1 "Sensor Fusion FCA" 2 "Camera only FCA" 3 "No FCA Option" 4 "ADAS_DRV Option" 5 "Reserved" 6 "Not used" 7 "Error indicator";
VAL_ 282 HBA_OptUsmSta 0 "None HBA Option (Default)" 1 "HBA Function Off" 2 "HBA Function On" 3 "Invalid (Fail)";
VAL_ 282 DAW_LVDA_PUDis 0 "Default" 1 "Display “Leading vehicle departure alert”" 2 "Reserved" 3 "Error indicator";
VAL_ 282 DAW_LVDA_OptUsmSta 0 "No Option (default)" 1 "Off" 2 "On" 3 "Error Indicator";
VAL_ 282 DAW_OptUsmSta 0 "None DAW Option (Default)" 1 "System Off" 2 "System On" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid (Gray)";
VAL_ 282 DAW_SysSta 0 "System Off" 1 "Attention Level 1" 2 "Attention Level 2" 3 "Attention Level 3" 4 "Attention Level 4" 5 "Attention Level 5" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "System Standby" 15 "System Fail";
VAL_ 282 DAW_WrnMsgSta 0 "No Warning" 1 "Rest Recommend Warning" 2 "Hands-Off TMS call request" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Error indicator";
VAL_ 282 DAW_TimeRstReq 0 "No signal" 1 "Time reset" 2 "Reserved" 3 "Error indicator";
VAL_ 282 DAW_SnstvtyModRetVal 0 "Default" 1 "Late" 2 "Normal" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid";
VAL_ 304 PARK_BUTTON 1 "Pressed" 2 "Not Pressed";
VAL_ 304 KNOB_POSITION 1 "R" 2 "N (on R side)" 3 "Centered" 4 "N (on D side)" 5 "D";
VAL_ 304 GEAR 1 "P" 2 "R" 3 "N" 4 "D";
VAL_ 352 AEB_SETTING 1 "off" 2 "warning only" 3 "active assist";
VAL_ 353 FCA_ICON 0 "HIDDEN" 1 "ORANGE" 2 "RED";
VAL_ 353 FCA_ALT_ICON 0 "HIDDEN" 1 "ORANGE" 3 "RED";
VAL_ 353 LKA_ICON 0 "HIDDEN" 1 "ORANGE" 3 "GRAY" 4 "GREEN";
VAL_ 353 HBA_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN";
VAL_ 353 FCA_IMAGE 0 "HIDDEN" 2 "VISIBLE";
VAL_ 353 BCA_LEFT 0 "HIDDEN" 1 "VISIBLE" 2 "VISIBLE+ICON";
VAL_ 353 BCA_RIGHT 0 "HIDDEN" 1 "VISIBLE" 2 "VISIBLE+ICON";
VAL_ 353 LCA_LEFT_ARROW 0 "HIDDEN" 1 "VISIBLE";
VAL_ 353 LCA_RIGHT_ARROW 0 "HIDDEN" 1 "VISIBLE";
VAL_ 353 CENTERLINE 0 "HIDDEN" 1 "GREEN";
VAL_ 353 TARGET 0 "HIDDEN" 1 "BLUE" 3 "WHITE";
VAL_ 353 LANELINE_LEFT 0 "GRAY" 1 "HIDDEN" 2 "WHITE" 4 "ORANGE" 6 "GREEN";
VAL_ 353 LANELINE_RIGHT 0 "GRAY" 1 "HIDDEN" 2 "WHITE" 4 "ORANGE" 6 "GREEN";
VAL_ 353 LANE_HIGHLIGHT 0 "HIDDEN" 1 "GREEN" 2 "WHITE" 3 "BLUE" 4 "ORANGE" 5 "RED";
VAL_ 353 LANE_LEFT 0 "HIDDEN" 1 "GREEN";
VAL_ 353 LANE_RIGHT 0 "HIDDEN" 1 "GREEN";
VAL_ 353 LANE_ZOOM 0 "ZOOM" 1 "HIDDEN";
VAL_ 353 ALERTS_1 0 "HIDDEN" 1 "WARNING_ONLY_CAR_CENTER" 2 "WARNING_ONLY_CAR_LEFT" 3 "WARNING_ONLY_CAR_RIGHT" 4 "WARNING_ONLY_LEFT" 5 "WARNING_ONLY_RIGHT" 11 "EMERGENCY_BRAKING_CAR_CENTER" 12 "EMERGENCY_BRAKING_CAR_LEFT" 13 "EMERGENCY_BRAKING_CAR_RIGHT" 14 "EMERGENCY_BRAKING_LEFT" 15 "EMERGENCY_BRAKING_RIGHT" 21 "EMERGENCY_STEERING_CAR_LEFT" 22 "EMERGENCY_STEERING_CAR_RIGHT" 23 "EMERGENCY_STEERING_CAR_LEFT_AWAY" 24 "EMERGENCY_STEERING_CAR_RIGHT_AWAY" 25 "EMERGENCY_STEERING_REAR_LEFT" 26 "EMERGENCY_STEERING_REAR_RIGHT" 33 "DRIVE_CAREFULLY";
VAL_ 353 ALERTS_2 0 "HIDDEN" 1 "KEEP_HANDS_ON_STEERING_WHEEL" 2 "KEEP_HANDS_ON_STEERING_WHEEL_RED" 3 "LANE_FOLLOWING_ASSIST_DEACTIVATED" 4 "HIGHWAY_DRIVING_ASSIST_DEACTIVATED" 5 "CONSIDER_TAKING_A_BREAK" 6 "PRESS_OK_BUTTON_TO_ENABLE_LANE_CHANGE_ASSIST" 7 "COLLISION_RISK_VEHICLE_TAKING_EMERGENCY_CONTROL" 8 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY_VEHICLE_IS_STOPPING" 9 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY" 11 "HIGHWAY_DRIVING_PILOT_SYSTEM_DEACTIVATED_AUDIBLE" 12 "KEEP_YOUR_EYES_ON_THE_ROAD" 13 "HIGHWAY_DRIVING_PILOT_CONDITIONS_NOT_MET_AUDIBLE" 14 "COLLISION_RISK_VEHICLE_TAKING_EMERGENCY_CONTROL" 15 "SET_THE_WIPER_AND_LIGHT_CONTROLS_TO_AUTO" 16 "BE_PREPARED_TO_TAKE_CONTROL_OF_THE_VEHICLE_AT_ANY_TIME" 21 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY_VEHICLE_IS_STOPPING" 10 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY";
VAL_ 353 ALERTS_3 1 "AUTOMATICALLY_ADJUSTING_TO_THE_POSTED_SPEED_LIMIT" 2 "SET_SPEED_CHANGED" 3 "AUTOMATICALLY_ADJUSTING_TO_THE_POSTED_SPEED_LIMIT" 4 "SET_SPEED_CHANGED" 7 "DISTANCE_1" 8 "DISTANCE_2" 9 "DISTANCE_3" 10 "DISTANCE_4" 17 "DRIVE_CAREFULLY" 18 "CHECK_SURROUNDINGS" 19 "CONDITIONS_NOT_MET" 20 "LANES_NOT_DETECTED" 21 "CURVE_TOO_SHARP" 22 "LANE_TOO_NARROW" 23 "ROAD_TYPE_NOT_SUPPORTED" 24 "UNAVAILABLE_WITH_HAZARD_LIGHTS_ON" 25 "VEHICLE_SPEED_IS_TOO_LOW" 26 "KEEP_HANDS_ON_STEERING_WHEEL" 27 "LANE_TYPE_NOT_SUPPORTED" 28 "LANE_ASSIST_CANCELED_STEERING_INPUT_DETECTED" 0 "HIDDEN";
VAL_ 353 ALERTS_4 0 "HIDDEN" 1 "TAKE_FOOT_OFF_THE_ACCELERATOR_PEDAL" 2 "TAKE_FOOT_OFF_THE_BRAKE_PEDAL" 3 "UNAVAILABLE_WHILE_HIGHWAY_DRIVING_PILOT_SYSTEM_IS_ACTIVE" 4 "TO_EXIT_HDP_GRASP_THE_STEERING_WHEEL_THEN_PRESS_AND_HOLD_THE_HDP_BUTTON" 5 "ACCELERATOR_PEDAL_OPERATION_LIMITED_FOR_SAFETY" 6 "TURN_OFF_HAZARD_WARNING_LIGHTS_AND_TURN_SIGNAL" 7 "KEEP_THE_DRIVERS_SEAT_IN_A_SAFE_DRIVING_POSITION" 16 "SET_SPEED_CHANGED" 17 "ACTIVATING_WINDSHIELD_DEFOG_TO_MAINTAIN_THE_DRIVERS_VIEW" 18 "SET_THE_WIPER_AND_LIGHT_CONTROLS_TO_AUTO" 19 "VEHICLE_SPEED_REDUCED_FOR_SAFETY_MERGING_LANES_AHEAD" 20 "SPEED_REDUCED_FOR_SAFETY_CONSTRUCTION_ZONE_DETECTED" 21 "VEHICLE_SPEED_LIMITED_SENSOR_DETECTION_RANGE_LIMITED" 22 "PREPARE_TO_TAKE_CONTROL_UNSUPPORTED_ROAD_TYPE_AHEAD" 23 "PREPARE_TO_TAKE_CONTROL_ENTRANCE_AND_EXIT_RAMPS_AHEAD" 24 "PREPARE_TO_TAKE_CONTROL_TOLLGATE_AHEAD" 25 "PREPARE_TO_TAKE_CONTROL_ROAD_EVENT_AHEAD" 26 "CLEARING_PATH_FOR_EMERGENCY_VEHICLE" 27 "VEHICLE_IS_TOO_SLOW_COMPARED_TO_TRAFFIC_FLOW" 28 "AFTER_SUNSET_HDP_IS_AVAILABLE_IN_AN_INSIDE_LANE_BEHIND_A_LEADING_VEHICLE" 29 "VEHICLE_SPEED_LIMITED_MERGING_LANES_AHEAD" 30 "VEHICLE_SPEED_LIMITED_CONSTRUCTION_ZONE_DETECTED" 31 "VEHICLE_SPEED_TEMPORARILY_LIMITED_FOR_SAFETY" 32 "PRESS_AND_HOLD_THE_BUTTON_TO_ACTIVATE_HIGHWAY_DRIVING_PILOT" 40 "HIGHWAY_DRIVING_PILOT_SYSTEM_IS_AVAILABLE" 64 "RESTART_VEHICLE_AFTER_EMERGENCY_STOP" 65 "CONNECTED_SERVICES_UNAVAILABLE" 66 "AVAILABLE_AFTER_VEHICLE_SOFTWARE_IS_UPDATED" 67 "ROAD_TYPE_NOT_SUPPORTED" 68 "ONLY_AVAILABLE_WHILE_DRIVING_ON_HIGHWAY_LANES" 69 "UNAVAILABLE_WHILE_OTHER_WARNINGS_ARE_ACTIVE" 70 "CANNOT_ACTIVATE_AT_ENTRANCE_EXIT_RAMPS" 71 "LANE_UNSUPPORTED" 72 "NOT_AVAILABLE_IN_THIS_COUNTRY" 79 "CHECKING_THE_DETECTION_RANGE_OF_THE_SENSOR" 80 "SHIFT_TO_D" 81 "ENGINE_STOPPED_BY_AUTO_STOP" 82 "INCREASE_DISTANCE_FROM_VEHICLE_AHEAD" 83 "VEHICLE_SPEED_IS_TOO_HIGH" 84 "CENTER_VEHICLE_IN_THE_LANE" 85 "PARKING_ASSIST_IS_ACTIVE" 86 "ESC_ACTIVIATION_REQUIRED" 87 "UNFOLD_SIDE_VIEW_MIRRORS" 88 "UNAVAILABLE_IN_THE_OUTER_LANE_AFTER_SUNSET" 89 "VEHICLE_SPEED_LIMITED_AFTER_SUNSET_FOR_SAFETY" 90 "LEADING_VEHICLE_NOT_DETECTED" 104 "AGGRESSIVE_BRAKING_OR_STEERING_DETECTED" 110 "SENSOR_AUTO_CALIBRATION_IN_PROGRESS_THIS_MAY_TAKE_SEVERAL_MINUTES" 111 "HIGHWAY_DRIVING_PILOT_WILL_BE_AVAILABLE_SHORTLY" 112 "IF_STEERING_WHEEL_IS_USED_HDP_WILL_BE_DEACTIVATED" 120 "IMPACT_DETECTED" 128 "UNSUITABLE_USE_OF_ACCELERATOR_PEDAL_DETECTED" 129 "GEAR_SHIFTER_USE_DETECTED" 130 "UNSUITABLE_BRAKE_PEDAL_USE_DETECTED" 131 "VEHICLE_START_BUTTON_PRESSED" 132 "VEHICLE_HAS_BEEN_STOPPED_FOR_TOO_LONG" 141 "TRAFFIC_CONGESTION_HAS_CLEARED" 142 "ENTRANCE_AND_EXIT_RAMPS_AHEAD" 143 "UNSUPPORTED_LANE_AHEAD" 144 "UNSUPPORTED_ROAD_TYPE_AHEAD" 145 "LANE_DEPARTURE_DETECTED" 146 "MAXIMUM_SPEED_EXCEEDED" 147 "HIGHWAY_DRIVING_PILOT_LIMITED_ABNORMAL_VEHICLE_CONTROLLER_STATUS" 148 "WIPER_LIGHT_CONTROL_SETTINGS_ARE_UNSUITABLE_FOR_USE_WITH_HDP" 149 "WINDSHIELD_DEFOG_SYSTEM_STATUS_IS_UNSUITABLE_FOR_USE_WITH_HDP" 150 "HAZARD_WARNING_LIGHTS_OR_TURN_SIGNAL_OPERATION_DETECTED" 151 "PERFORMING_EVASIVE_STEERING_OBSTACLES_DETECTED_AHEAD" 152 "HIGHWAY_DRIVING_PILOT_LIMITED_SENSOR_DETECTION_RANGE_LIMITED" 160 "CHECK_HIGHWAY_DRIVING_PILOT_SYSTEM" 161 "SAFETY_FUNCTION_ACTIVATED" 176 "CAMERA_OBSCURED" 177 "RADAR_BLOCKED" 178 "LIDAR_BLOCKED" 179 "AIRBAG_WARNING_LIGHT_IS_ON" 180 "ATTACHED_TRAILED_DETECTED" 181 "HIGH_OUTSIDE_TEMPERATURE" 182 "LOW_OUTSIDE_TEMPERATURE" 190 "UNAVAILABLE_DUE_TO_THE_ROAD_EVENT_INFORMATION_RECEIVED" 191 "UNAVAILABLE_NEAR_TOLLGATES" 192 "DRIVERS_SEAT_IS_NOT_IN_A_SAFE_DRIVING_POSITION" 193 "VEHICLE_DRIVING_THE_WRONG_WAY_DETECTED_AHEAD" 194 "EMERGENCY_VEHICLE_DETECTED" 195 "OBSTACLE_DETECTED_AHEAD" 196 "SENSOR_BLOCKED_DUE_TO_RAIN_SNOW_OR_ROAD_DEBRIS" 197 "SLIPPERY_ROAD_SURFACE_DETECTED" 198 "CONSTRUCTION_ZONE_DETECTED_AHEAD" 199 "PEDESTRIAN_DETECTED_AHEAD" 200 "UNSUITABLE_DRIVERS_SEAT_POSITION_DETECTED" 201 "FOLDED_SIDE_VIEW_MIRRORS_DETECTED" 208 "VEHICLE_POSITION_NOT_DETECTED" 209 "LANE_NOT_DETECTED" 210 "DRIVER_NOT_DETECTED" 211 "KEEP_YOUR_EYES_ON_THE_ROAD" 212 "LEADING_VEHICLE_REQUIRED_AFTER_SUNSET" 213 "TBD" 240 "LOW_FUEL" 241 "LOW_TIRE_PRESSURE" 242 "DOOR_OPEN" 243 "TRUNK_OPEN" 244 "HOOD_OPEN" 245 "SEAT_BELT_NOT_FASTENED" 246 "PARKING_BRAKE_ACTIVATED" 247 "LOW_EV_BATTERY" 248 "HDP_DEACTIVATION_DELAYED_RISK_OF_COLLISION_DETECTED" 249 "LIFTGATE_OPENED";
VAL_ 353 ALERTS_5 0 "HIDDEN" 1 "DRIVERS_GRASP_NOT_DETECTED_DRIVING_SPEED_WILL_BE_LIMITED" 2 "WATCH_FOR_SURROUNDING_VEHICLES" 3 "SMART_CRUISE_CONTROL_DEACTIVATED" 4 "SMART_CRUISE_CONTROL_CONDITIONS_NOT_MET" 5 "USE_SWITCH_OR_PEDAL_TO_ACCELERATE" 6 "DRIVER_ASSISTNCE_SYSTEM_LIMITED_TRAILER_ATTACHED" 7 "DRIVER_ASSISTNCE_SYSTEM_LIMITED_DRIVER_FULL_FACE_NOT_VISIBLE" 11 "LEADING_VEHICLE_IS_DRIVING_AWAY" 12 "STOP_VEHICLE_THEN_TRY_AGAIN" 19 "ACTIVATING_HIGHWAY_DRIVING_PILOT_SYSTEM" 20 "CONTINUING_USE_OF_HIGHWAY_DRIVING_PILOT_WILL_RESULT_IN_DEVIATION_FROM_THE_NAVIGATION_ROUTE" 21 "HIGHWAY_DRIVING_PILOT_SYSTEM_DEACTIVATED_SILENT" 22 "HIGHWAY_DRIVING_PILOT_SYSTEM_NOT_APPLIED" 23 "HIGHWAY_DRIVING_PILOT_CONDITIONS_NOT_MET_SILENT";
VAL_ 353 MUTE 0 "NONE" 1 "MUTED";
VAL_ 353 SOUNDS_1 0 "NONE" 3 "FAST BEEP" 6 "CONSTANT BEEP";
VAL_ 353 SOUNDS_2 0 "NONE" 2 "SINGLE CHIME" 3 "CONSTANT CHIME" 6 "FAST BEEP";
VAL_ 353 SOUNDS_3 0 "NONE" 3 "SOFT CHIME" 5 "SINGLE CHIME";
VAL_ 353 SOUNDS_4 0 "NONE" 2 "DOUBLE CHIME";
VAL_ 353 SETSPEED_HUD 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 5 "CYAN";
VAL_ 353 DISTANCE_LEAD 0 "HIDDEN" 1 "GRAY" 2 "WHITE";
VAL_ 353 DISTANCE_CAR 0 "HIDDEN" 1 "GRAY" 2 "WHITE" 3 "CYAN A";
VAL_ 353 DISTANCE_SPACING 0 "HIDDEN" 1 "BLUE" 3 "WHITE" 5 "CYAN";
VAL_ 353 SETSPEED 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 6 "CYAN";
VAL_ 353 HDA_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 5 "CYAN HDP";
VAL_ 353 SLA_ICON 0 "HIDDEN" 1 "WHITE UP" 2 "WHITE DOWN" 3 "GREEN UP" 4 "GREEN DOWN";
VAL_ 353 NAV_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 4 "WHITE";
VAL_ 353 LFA_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 5 "CYAN";
VAL_ 353 LCA_LEFT_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 4 "WHITE";
VAL_ 353 LCA_RIGHT_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 4 "WHITE";
VAL_ 353 BACKGROUND 0 "HIDDEN" 1 "BLUE" 3 "ORANGE" 4 "FLASHING ORANGE" 6 "FLASHING RED" 7 "GRAY";
VAL_ 353 DAW_ICON 0 "HIDDEN" 1 "ORANGE";
VAL_ 353 CAR_CIRCLE 0 "HIDDEN" 1 "GRAY" 2 "CYAN";
VAL_ 354 COUNTRY 0 "HIDDEN" 1 "SOUTH_KOREA" 4 "INTL" 5 "JAPAN" 6 "CANADA" 7 "USA" 8 "CHINA" 9 "INTL";
VAL_ 354 SPEEDLIMIT_FLASH 0 "HIDDEN" 1 "ERROR" 2 "NORMAL" 4 "RED";
VAL_ 354 SIGNS 0 "HIDDEN" 1 "PEDESTRIAN_CROSSING" 2 "SCHOOL_CROSSWALK" 8 "STOP" 9 "YIELD" 16 "DO_NOT_PASS" 19 "DO_NOT_ENTER" 24 "ROUNDABOUT" 26 "RIGHT_CURVE_AHEAD" 27 "LEFT_CURVE_AHEAD" 28 "SLIGHT_RIGHT_CURVE_AHEAD" 29 "SLIGHT_LEFT_CURVE_AHEAD";
VAL_ 354 SPEEDLIMIT_WEATHER 0 "HIDDEN" 1 "RAIN" 2 "SNOW" 3 "RAIN+SNOW" 4 "TRAILER";
VAL_ 354 VIBRATE 0 "NONE" 1 "VIBRATE";
VAL_ 354 LEAD 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "GRAY CAR" 4 "WHITE CAR" 5 "GRAY TRUCK" 6 "WHITE TRUCK" 7 "GRAY PERSON" 8 "WHITE PERSON" 9 "GRAY BICYCLE" 10 "WHITE BICYCLE" 11 "GRAY MOTORCYCLE" 12 "WHITE MOTORCYCLE" 13 "DARK CONE" 14 "ORANGE CONE";
VAL_ 354 LEAD_ALT 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "DIM CONE" 4 "ORANGE CONE";
VAL_ 354 LEAD_LEFT 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "GRAY CAR" 4 "WHITE CAR" 5 "GRAY TRUCK" 6 "WHITE TRUCK" 7 "GRAY PERSON" 8 "WHITE PERSON" 9 "GRAY BICYCLE" 10 "WHITE BICYCLE" 11 "GRAY MOTORCYCLE" 12 "WHITE MOTORCYCLE" 13 "DARK CONE" 14 "ORANGE CONE";
VAL_ 354 LEAD_RIGHT 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "GRAY CAR" 4 "WHITE CAR" 5 "GRAY TRUCK" 6 "WHITE TRUCK" 7 "GRAY PERSON" 8 "WHITE PERSON" 9 "GRAY BICYCLE" 10 "WHITE BICYCLE" 11 "GRAY MOTORCYCLE" 12 "WHITE MOTORCYCLE" 13 "DARK CONE" 14 "ORANGE CONE";
VAL_ 354 FAULT_FSS 0 "HIDDEN" 1 "CHECK_FORWARD_SAFETY_SYSTEM" 2 "FORWARD_SAFETY_SYSTEM_LIMITED_CAMERA_OBSCURED" 3 "FORWARD_SAFETY_SYSTEM_LIMITED_RADAR_BLOCKED";
VAL_ 354 FAULT_FCA 0 "HIDDEN" 1 "CHECK_FORWARD_SIDE_SAFETY_SYSTEM" 2 "FORWARD_SIDE_SAFETY_SYSTEM_LIMITED_CAMERA_OBSCURED" 3 "FORWARD_SIDE_SAFETY_SYSTEM_LIMITED_RADAR_BLOCKED";
VAL_ 354 FAULT_LSS 0 "HIDDEN" 1 "CHECK_LANE_SAFETY_SYSTEM" 2 "LANE_SAFETY_SYSTEM_DISABLED_CAMERA_OBSCURED";
VAL_ 354 FAULT_SLA 0 "HIDDEN" 1 "CHECK_SPEED_LIMIT_SYSTEM" 2 "SPEED_LIMIT_SYSTEM_DISABLED_CAMERA_OBSCURED";
VAL_ 354 FAULT_DAW 0 "HIDDEN" 1 "CHECK_INATTENTIVE_DRIVING_WARNING_SYSTEM" 2 "INATTENTIVE_DRIVING_WARNING_SYSTEM_DISABLED_CAMERA_OBSCURED";
VAL_ 354 FAULT_HBA 0 "HIDDEN" 1 "CHECK_HIGH_BEAM_ASSIST_SYSTEM";
VAL_ 354 FAULT_SCC 0 "HIDDEN" 1 "CHECK_SMART_CRUISE_CONTROL_SYSTEM" 2 "SMART_CRUISE_CONTROL_DISABLED_RADAR_BLOCKED";
VAL_ 354 FAULT_LFA 0 "HIDDEN" 1 "CHECK_LANE_FOLLOWING_SYSTEM_ASSIST_SYSTEM";
VAL_ 354 FAULT_HDA 0 "HIDDEN" 1 "CHECK_HIGHWAY_DRIVING_ASSIST_SYSTEM";
VAL_ 354 FAULT_LCA 0 "HIDDEN" 1 "CHECK_LANE_CHANGE_ASSIST_FUNCTION" 2 "LANE_CHANGE_ASSIST_FUNCTION_DISABLED_CAMERA_OBSCURED" 3 "LANE_CHANGE_ASSIST_FUNCTION_DISABLED_RADAR_BLOCKED";
VAL_ 354 FAULT_HDP 0 "HIDDEN" 1 "CHECK_HIGHWAY_DRIVING_PILOT_SYSTEM" 2 "HIGHWAY_DRIVING_PILOT_DISABLED_CAMERA_OBSCURED" 3 "HIGHWAY_DRIVING_PILOT_DISABLED_RADAR_BLOCKED" 4 "HIGHWAY_DRIVING_PILOT_DISABLED_LIDAR_BLOCKED";
VAL_ 354 FAULT_DAS 0 "HIDDEN" 1 "CHECK_DRIVER_ASSISTANCE_SYSTEM" 2 "DRIVER_ASSISTANCE_SYSTEM_LIMITED_CAMERA_OBSCURED" 3 "DRIVER_ASSISTANCE_SYSTEM_LIMITED_RADAR_BLOCKED" 4 "DRIVER_ASSISTANCE_SYSTEM_LIMITED_CAMERA_OBSCURED_AND_RADAR_BLOCKED";
VAL_ 354 FAULT_ESS 0 "HIDDEN" 1 "CHECK_EMERGENCY_STOPPING_FUNCTION" 2 "EMERGENCY_STOPPING_FUNCTION_DISABLED_CAMERA_OBSCURED" 3 "EMERGENCY_STOPPING_FUNCTION_DISABLED_RADAR_BLOCKED";
VAL_ 362 BLINKER_CONTROL 1 "hazards" 2 "hazards button backlight" 3 "left blinkers" 4 "right blinkers";
VAL_ 373 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue";
VAL_ 416 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled";
VAL_ 426 CRUISE_BUTTONS 0 "none" 1 "res_accel" 2 "set_decel" 3 "gap_distance" 4 "pause_resume";
VAL_ 437 Info_RtLnCvtrVal 65534 "Reserved" 65535 "Error indicator";
VAL_ 463 CRUISE_BUTTONS 0 "none" 1 "res_accel" 2 "set_decel" 3 "gap_distance" 4 "pause_resume";
VAL_ 463 RIGHT_PADDLE 0 "Not Pulled" 1 "Pulled";
VAL_ 463 LEFT_PADDLE 0 "Not Pulled" 1 "Pulled";
VAL_ 506 ISLW_OptUsmSta 0 "None ISLW Option (Default)" 1 "System Disabled by USM" 2 "System Enable by USM" 3 "Invalid";
VAL_ 506 ISLW_SysSta 0 "Normal (Default)" 1 "System Fail" 2 "ISLW Temporary Unavailable" 3 "Reserved";
VAL_ 506 ISLW_NoPassingInfoDis 0 "None Display (Default)" 1 "LHD No Passing Zone Display" 2 "RHD No Passing Zone Display" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid";
VAL_ 506 ISLW_OvrlpSignDis 0 "None (Default)" 1 "Overlap Sign" 2 "Reserved" 3 "Error indicator";
VAL_ 506 ISLW_SpdCluMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid";
VAL_ 506 ISLW_SpdNaviMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid";
VAL_ 506 ISLW_SubCondinfoSta1 0 "None (Default)" 1 "Rain" 2 "Snow" 3 "Snow&Rain" 4 "Trailer" 5 "Reserved" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Generic" 15 "Invalid";
VAL_ 506 ISLW_SubCondinfoSta2 0 "None (Default)" 1 "Rain" 2 "Snow" 3 "Snow&Rain" 4 "Trailer" 5 "Reserved" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Generic" 15 "Invalid";
VAL_ 506 ISLW_SpdCluSubMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid";
VAL_ 506 ISLW_SpdCluDisSubCond1 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid";
VAL_ 506 ISLW_SpdCluDisSubCond2 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid";
VAL_ 506 ISLW_SpdNaviSubMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid";
VAL_ 506 ISLW_SpdNaviDisSubCond1 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid";
VAL_ 506 ISLW_SpdNaviDisSubCond2 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid";
VAL_ 506 ISLA_SpdwOffst 0 "No Recognition" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid";
VAL_ 506 ISLA_SwIgnoreReq 0 "Allow All Switch Inputs (default)" 1 "-(SET) Switch Input Ignore" 2 "+(SET) Switch Input Ignore" 3 "-(SET) & +(SET) Switch Inputs Ignore";
VAL_ 506 ISLA_SpdChgReq 0 "Default" 1 "Speed Change Request" 2 "Reserved" 3 "Reserved";
VAL_ 506 ISLA_SpdWrn 0 "No Warning" 1 "Warning" 2 "Reserved" 3 "Reserved";
VAL_ 506 ISLA_IcyWrn 0 "No Warning" 1 "Warning" 2 "Reserved" 3 "Reserved";
VAL_ 506 ISLA_SymFlashMod 0 "No Flasing" 1 "Flashing Sign" 2 "Flashing - Arrow Symbol" 3 "Flashing + Arrow Symbol" 4 "Flashing Auto Symbol" 5 "Reserved" 6 "Reserved" 7 "Reserved";
VAL_ 506 ISLA_Popup 0 "No Popup" 1 "MSLA Speed will Change" 2 "MSLA Speed has Changed" 3 "CC_SCC Speed will Change" 4 "CC_SCC Speed has Changed" 5 "Reserved" 6 "Reserved" 7 "Reserved";
VAL_ 506 ISLA_OptUsmSta 0 "None ISLA Option (속도 제한 메뉴 삭제)" 1 "Off" 2 "Warning" 3 "Assist" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid (GRAY)";
VAL_ 506 ISLA_OffstUsmSta 0 "None Offset Function" 1 "-10kph or -5mph" 2 "-5kph or -3mph" 3 "0kph or 0mph" 4 "+5kph or +3mph" 5 "+10kph or +5mph" 6 "Reserved" 7 "Invalid (GRAY)";
VAL_ 506 ISLA_AutoUsmSta 0 "None Auto Function (Delete Menu)" 1 "Auto Off" 2 "Auto On" 3 "Invalid (GRAY)";
VAL_ 506 ISLA_Cntry 0 "Europe/Russia/Australia" 1 "Domestic" 2 "China" 3 "USA" 4 "Canada" 5 "Australia" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Reserved" 15 "Initial Value (default)";
VAL_ 506 ISLA_AddtnlSign 0 "No Recognition (default)" 1 "School Crossing" 16 "Do Not Pass" 17 "Reserved" 18 "Reserved" 19 "Reserved" 20 "Reserved" 21 "Reserved" 22 "Reserved" 23 "Reserved" 24 "Exit" 25 "Roundabout" 26 "Right Curve" 27 "Left Curve" 28 "Winding Road" 29 "Reserved" 30 "Reserved" 31 "Reserved" 2 "Pedestrian Crossing" 3 "Bicycle Crossing" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Reserved" 8 "Stop" 9 "Yield" 10 "Stop Ahead" 11 "Yield Ahead" 12 "Road Construction Ahead" 13 "Lane Reduction" 14 "Reserved" 15 "Reserved";
VAL_ 506 ISLA_SchoolZone 0 "No School Zone" 1 "School Zone" 2 "Reserved" 3 "Reserved";
VAL_ 687 HOD_Dir_Status 0 "HANDS OFF" 1 "HAND TOUCH (SOFT)" 2 "HAND TOUCH (STRONG)" 3 "HAND GRIP (SOFT)" 4 "HAND GRIP (STRONG)" 5 "RESERVED" 6 "RESERVED";
VAL_ 698 IFSref_FR_CMR_Sta 0 "None Option (Default)" 1 "Normal" 2 "Blockage Status" 3 "Error Indicator";
VAL_ 698 IFSref_VehNumVal 0 "No vehicle" 1 "Number of vehicles" 2 "Number of vehicles" 3 "Number of vehicles" 4 "Number of vehicles" 5 "Number of vehicles" 6 "Number of vehicles" 7 "Number of vehicles" 8 "Number of vehicles" 9 "Number of vehicles" 10 "Number of vehicles" 11 "Over than 10 vehicles" 12 "Reserved" 13 "Reserved" 14 "Default" 15 "Error indicator";
VAL_ 698 IFSref_ILLAmbtSta 0 "Bright" 1 "Dark" 2 "Not used" 3 "Error indicator";
VAL_ 698 IFSref_VehLftAngl1Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl1Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl2Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehDst1Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehRtAngl2Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl3Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl3Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl4Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl4Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl5Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl5Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl6Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl6Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl7Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl7Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl8Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl8Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl9Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl9Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehLftAngl10Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehRtAngl10Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator";
VAL_ 698 IFSref_VehDst2Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst3Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst4Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst5Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst6Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst7Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst8Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst9Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 698 IFSref_VehDst10Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator";
VAL_ 736 MSLA_STATUS 0 "disabled" 1 "active" 2 "paused";
VAL_ 866 LEFT_LANE_LINE 0 "Not Detected" 1 "Low Confidence" 2 "Medium Confidence" 3 "High Confidence";
VAL_ 866 RIGHT_LANE_LINE 0 "Not Detected" 1 "Low Confidence" 2 "Medium Confidence" 3 "High Confidence";
VAL_ 1041 DRIVER_DOOR 0 "Closed" 1 "Opened";
VAL_ 1041 PASSENGER_DOOR 0 "Closed" 1 "Opened";
VAL_ 1041 PASSENGER_SEATBELT 0 "Unlatched" 1 "Latched";
VAL_ 1041 DRIVER_SEATBELT 0 "Unlatched" 1 "Latched";
VAL_ 1041 DRIVER_REAR_DOOR 0 "Closed" 1 "Opened";
VAL_ 1041 PASSENGER_REAR_DOOR 0 "Closed" 1 "Opened";
VAL_ 1144 DRIVE_MODE2 3 "Set Sport" 1 "Set Normal" 2 "Set Eco";
VAL_ 1240 DISTANCE_UNIT 1 "Miles" 0 "Kilometers";
CM_ BO_ 74 "[P] Periodic";
CM_ SG_ 74 IMU_Crc1Val "The data area for CRC calculation is based on the data length (DLC) of the message DB.The CRC shall be calculated over the entire data block (excluding the CRC bytes) including the user data, alive counter and Data ID- CRC Polynomial (0x1021) , Ini";
CM_ SG_ 74 IMU_AlvCnt1Val "For the first transmission request for a data element the counter shall be initialized with 0 and shall be incremented by 1 for every subsequent send request. When the counter reaches the maximum value(0xFF), then it shall restart with 0 for the next s";
CM_ SG_ 74 IMU_YawSigSta "This signal indicates failure status of yaw rate signal and yaw rate sensing element.0000B : No failure xxx1B : IMU_Yawrate_failurexx1xB : Initialization is runningx1xxB : Reserved1xxxB : ReservedThis signal represents the physica";
CM_ SG_ 74 IMU_LatAccelSigSta "This signal indicates failure status of lateral acceleration signal and sensing element.0000B : No failurexxx1B : IMU_Lateral acceleration failurexx1xB : Initialization is runningx1xxB : Reserved1xxxB : ReservedThis signal represe";
CM_ SG_ 74 IMU_AcuRstSta "This signal indicates the status of IMU.0000B : Normal mode xxx1B : IMU Reset modexx1xB : Reservedx1xxB : Reserved1xxxB : ReservedIf ACU reset is required, ACU will send IMU RESET bit(XXX1B) up to 30 times and perform a reset. If ";
CM_ SG_ 74 IMU_YawRtVal "This signal indicates Information regarding yaw rate.physical range : -163.84..163.83 ˚/s = 0000H..FFFEhConversion : (PH) = ((HEX)-8000H)*0.005[˚/s/digit] = (HEX)*0.005[˚/s/digit] - 163.84[˚/s] ";
CM_ SG_ 74 IMU_LatAccelVal "This signal indicates Information regarding lateral acceleration.physical range : -4.1768g..4.1765g = 0000H..FFFEhConversion : (PH) = ((HEX)-8000H)*0.000127465[g/digit] = (HEX)*0.000127465[g/digit] - 4.17677312[g]";
CM_ BO_ 229 "[P] Periodic";
CM_ SG_ 229 ESC_YawSigSta "ESC_YawSigSta";
CM_ SG_ 229 ESC_LatAccelSigSta "ESC_LatAccelSigSta";
CM_ SG_ 229 ESC_LongAccelSigSta "ESC_LongAccelSigSta";
CM_ SG_ 229 ESC_YawRtVal "ESC_YawRtVal";
CM_ SG_ 229 ESC_LatAccelVal "ESC_LatAccelVal";
CM_ SG_ 229 ESC_LongAccelVal "ESC_LongAccelVal";
@@ -0,0 +1,79 @@
BO_ 1880 DEBUG: 8 XXX
SG_ BLINDSPOTSIDE : 7|8@0+ (1,0) [0|255] "" XXX
SG_ BLINDSPOT : 38|1@0+ (1,0) [0|15] "" XXX
SG_ BLINDSPOTD1 : 47|8@0+ (1,0) [0|255] "" XXX
SG_ BLINDSPOTD2 : 55|8@0+ (1,0) [0|255] "" XXX
BO_ 836 PRE_COLLISION_2: 8 DSU
SG_ DSS1GDRV : 7|10@0- (0.1,0) [0|0] "m/s^2" Vector__XXX
SG_ DS1STAT2 : 13|3@0+ (1,0) [0|0] "" Vector__XXX
SG_ DS1STBK2 : 10|3@0+ (1,0) [0|0] "" Vector__XXX
SG_ PCSWAR : 18|1@0+ (1,0) [0|0] "" FCM
SG_ PCSALM : 17|1@0+ (1,0) [0|0] "" FCM
SG_ PCSOPR : 16|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ PCSABK : 31|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ PBATRGR : 30|2@0+ (1,0) [0|0] "" Vector__XXX
SG_ PPTRGR : 28|1@0+ (1,0) [0|0] "" FCM
SG_ IBTRGR : 27|1@0+ (1,0) [0|0] "" FCM
SG_ CLEXTRGR : 26|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ IRLT_REQ : 25|2@0+ (1,0) [0|0] "" Vector__XXX
SG_ BRKHLD : 37|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ AVSTRGR : 36|1@0+ (1,0) [0|0] "" SCS
SG_ VGRSTRGR : 35|2@0+ (1,0) [0|0] "" Vector__XXX
SG_ PREFILL : 33|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ PBRTRGR : 32|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ PCSDIS : 43|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ PBPREPMP : 40|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|0] "" XXX
BO_ 713 HYBRID_POWERTRAIN: 8 XXX
SG_ COAST_FUEL_CUT : 5|1@0+ (1,0) [0|1] "" XXX
SG_ HYBRID_DRIVE_STATE : 11|4@0+ (1,0) [0|15] "" XXX
BO_ 814 BRAKE_HYDRAULIC: 8 XXX
SG_ BRAKE_PRESSURE : 15|8@0+ (1,0) [0|255] "" XXX
SG_ BRAKE_PRESSURE_COPY1 : 31|8@0+ (1,0) [0|255] "" XXX
SG_ BRAKE_PRESSURE_COPY2 : 47|8@0+ (1,0) [0|255] "" XXX
BO_ 971 MOTOR_SPEED_CLUSTER: 7 XXX
SG_ CLUSTER_SPEED : 55|8@0+ (1,-21) [0|255] "km/h" XXX
BO_ 896 HYBRID_BATTERY: 8 XXX
SG_ HV_SOC_PCT : 55|8@0+ (1,0) [0|100] "%" XXX
BO_ 1654 HV_POWER_INTEGRATOR: 8 XXX
SG_ HV_POWER_ACCUM : 39|8@0+ (1,0) [0|255] "" XXX
BO_ 975 HV_INVERTER: 5 XXX
SG_ HV_VOLTAGE_LO : 23|8@0+ (1,0) [0|255] "" XXX
SG_ HV_CURRENT_LO : 39|8@0+ (1,0) [0|255] "" XXX
BO_ 955 BRAKE_REDUNDANT: 8 XXX
SG_ BRAKE_PRESSED_REDUNDANT : 0|1@0+ (1,0) [0|1] "" XXX
BO_ 918 VEHICLE_DRIVE_MODE: 8 XXX
SG_ DRIVE_MODE_STATE : 7|8@0+ (1,0) [0|255] "" XXX
CM_ "Sunnypilot Prius TSS2 reverse-engineered signals — route 550a71ee4c7a7fbe/0000038f--6b48497966, 2026-05-19. Confidence: high unless noted.";
CM_ BO_ 713 "Hybrid powertrain status. 100Hz on bus 0.";
CM_ SG_ 713 COAST_FUEL_CUT "byte0 bit5. 1 when accelerator lifted at speed -> ICE fuel cut / decel-fuel-cut active. P(=1|coast)=0.95, P(=1|accel)=0.008, P(=1|brake)=0.0. Use: lift detection for accel feedforward, EV-only mode hint.";
CM_ SG_ 713 HYBRID_DRIVE_STATE "byte1 lower-nibble (bits 8-11). Enum (validated): 4=brake/regen-active, 5-8=coast/cruise levels, 10/12=ICE running active, 11=idle-stop. Not a scalar magnitude. Use: distinguish ICE-on vs EV for accel command shaping.";
CM_ BO_ 814 "Brake hydraulic. 5Hz on bus 0. Bytes 0,2,4,6 are status/flag bytes (not yet decoded). Saturates 255 under hard brake.";
CM_ SG_ 814 BRAKE_PRESSURE "byte1. Master cylinder pressure proxy. 0 during coast, 33-45 mean during brake, 254-255 max. NOT same as BRAKE_MODULE.BRAKE_PRESSURE.";
CM_ SG_ 814 BRAKE_PRESSURE_COPY1 "byte3. Identical to BRAKE_PRESSURE 90% of brake samples. Redundant copy (CRC/safety).";
CM_ SG_ 814 BRAKE_PRESSURE_COPY2 "byte5. Identical to BRAKE_PRESSURE 90% of brake samples. Redundant copy.";
CM_ BO_ 971 "Cluster speedometer feed. 10Hz on bus 0.";
CM_ SG_ 971 CLUSTER_SPEED "byte6. Encoded as raw_byte = v_kph + 21. After (1,-21) factor/offset: km/h matching dashboard speedometer. Corr 0.998 w/ WHEEL_SPEEDS. ~5km/h higher than wheel mean = cluster display bias.";
CM_ BO_ 896 "HV battery status. 5Hz on bus 0.";
CM_ SG_ 896 HV_SOC_PCT "byte6. HV battery state-of-charge percent. Validated range 53-62% on route 0000038f (Prius hybrid SoC normal band 40-80%). Use: energy-aware planner — reduce regen demand at high SoC (>70%), lift accel demand at low SoC (<50%).";
CM_ BO_ 1654 "HV power integrator. 1Hz on bus 0. Slow drift signal, semantic not fully confirmed.";
CM_ SG_ 1654 HV_POWER_ACCUM "byte4. Slow-drifting integer 0-59, independent of HV_SOC_PCT. Hypothesis: HV power flow accumulator or charging-cycle counter. Needs more routes.";
CM_ BO_ 975 "HV inverter telemetry. 10Hz on bus 0. 5-byte message.";
CM_ SG_ 975 HV_VOLTAGE_LO "byte2. Sequential integer 40-53 range. Hypothesis: HV bus voltage low-byte scaled. Moderate corr w/ brake (regen-loaded voltage).";
CM_ SG_ 975 HV_CURRENT_LO "byte4. Sequential integer 17-36 range. JUMPS -16 at brake-release (regen current cutoff signature). Use: real-time regen current readback for brake-blend tuning.";
CM_ BO_ 955 "Brake redundant signal. 10Hz on bus 0.";
CM_ SG_ 955 BRAKE_PRESSED_REDUNDANT "byte0 bit0. 99.9% agreement with BRAKE_MODULE.BRAKE_PRESSED. Safety-redundant copy. Use: cross-check brake state for fault detection.";
CM_ BO_ 918 "Vehicle drive mode state. 5Hz on bus 0.";
CM_ SG_ 918 DRIVE_MODE_STATE "byte0. 3 states observed: 185=parked-with-brake, 189=ready-to-drive, 191=ready-no-brake. Transitions on GEAR shifts + brake. Use: more reliable drive-state machine than gear+brake combo.";
VAL_ 713 HYBRID_DRIVE_STATE 4 "brake_regen_active" 5 "coast_5" 6 "coast_6" 7 "coast_7" 8 "coast_cruise" 10 "ice_active_10" 11 "idle_stop" 12 "ice_active_12";
VAL_ 918 DRIVE_MODE_STATE 185 "parked_brake" 189 "ready" 191 "ready_no_brake";
@@ -234,6 +234,7 @@ BO_ 956 GEAR_PACKET: 8 XXX
SG_ SPORT_GEAR_ON : 33|1@0+ (1,0) [0|1] "" XXX
SG_ SPORT_GEAR : 38|3@0+ (1,0) [0|7] "" XXX
SG_ ECON_ON : 40|1@0+ (1,0) [0|1] "" XXX
SG_ SPORT_ON_2 : 55|1@0+ (1,0) [0|1] "" XXX
SG_ B_GEAR_ENGAGED : 41|1@0+ (1,0) [0|1] "" XXX
SG_ DRIVE_ENGAGED : 47|1@0+ (1,0) [0|1] "" XXX
@@ -545,6 +546,7 @@ VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P";
VAL_ 956 SPORT_GEAR_ON 0 "off" 1 "on";
VAL_ 956 SPORT_GEAR 1 "S1" 2 "S2" 3 "S3" 4 "S4" 5 "S5" 6 "S6";
VAL_ 956 ECON_ON 0 "off" 1 "on";
VAL_ 956 SPORT_ON_2 0 "off" 1 "on";
VAL_ 956 B_GEAR_ENGAGED 0 "off" 1 "on";
VAL_ 956 DRIVE_ENGAGED 0 "off" 1 "on";
VAL_ 1005 REVERSE_CAMERA_GUIDELINES 3 "No guidelines" 2 "Static guidelines" 1 "Active guidelines";
@@ -35,14 +35,6 @@ BO_ 740 STEERING_LKA: 5 XXX
SG_ STEER_TORQUE_CMD : 15|16@0- (1,0) [0|65535] "" XXX
SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX
BO_ 836 PRE_COLLISION_2: 8 DSU
SG_ DSS1GDRV : 7|10@0- (0.1,0) [0|0] "m/s^2" Vector__XXX
SG_ PCSALM : 17|1@0+ (1,0) [0|0] "" FCM
SG_ IBTRGR : 27|1@0+ (1,0) [0|0] "" FCM
SG_ PBATRGR : 30|2@0+ (1,0) [0|0] "" Vector__XXX
SG_ PREFILL : 33|1@0+ (1,0) [0|0] "" Vector__XXX
SG_ AVSTRGR : 36|1@0+ (1,0) [0|0] "" SCS
SG_ CHECKSUM : 63|8@0+ (1,0) [0|0] "" XXX
CM_ SG_ 466 NEUTRAL_FORCE "force in newtons the engine/electric motors are applying without any acceleration commands or user input";
CM_ SG_ 466 ACC_BRAKING "whether brakes are being actuated from ACC command";
@@ -1,6 +1,7 @@
CM_ "IMPORT _community.dbc";
CM_ "IMPORT _toyota_2017.dbc";
CM_ "IMPORT _toyota_adas_standard.dbc";
CM_ "IMPORT _sp_debug_toyota.dbc";
BO_ 548 BRAKE_MODULE: 8 XXX
SG_ BRAKE_PRESSURE : 43|12@0+ (1,0) [0|4047] "" XXX
@@ -1,6 +1,7 @@
CM_ "IMPORT _community.dbc";
CM_ "IMPORT _toyota_2017.dbc";
CM_ "IMPORT _toyota_adas_standard.dbc";
CM_ "IMPORT _sp_debug_toyota.dbc";
BO_ 401 STEERING_LTA: 8 XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
@@ -1,6 +1,7 @@
CM_ "IMPORT _community.dbc";
CM_ "IMPORT _toyota_2017.dbc";
CM_ "IMPORT _toyota_adas_standard.dbc";
CM_ "IMPORT _sp_debug_toyota.dbc";
BO_ 550 BRAKE_MODULE: 8 XXX
SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|511] "" XXX
@@ -46,7 +46,6 @@
{.msg = {{0x1a0, (scc_bus), 32, 50U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
static bool hyundai_canfd_alt_buttons = false;
static bool hyundai_canfd_angle_steering = false;
static bool hyundai_canfd_lka_steer_msg_alt = false;
static unsigned int hyundai_canfd_get_lka_addr(void) {
@@ -79,10 +78,6 @@ static void hyundai_canfd_rx_hook(const CANPacket_t *msg) {
int torque_driver_new = ((msg->data[11] & 0x1fU) << 8U) | msg->data[10];
torque_driver_new -= 4095;
update_sample(&torque_driver, torque_driver_new);
int angle_meas_new = (msg->data[17] << 8) | msg->data[16];
angle_meas_new = to_signed(angle_meas_new, 16);
update_sample(&angle_meas, angle_meas_new);
}
// cruise buttons
@@ -146,7 +141,7 @@ static void hyundai_canfd_rx_hook(const CANPacket_t *msg) {
}
static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
const TorqueSteeringLimits HYUNDAI_CANFD_TORQUE_STEERING_LIMITS = {
const TorqueSteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = {
.max_torque = 270,
.max_rt_delta = 112,
.max_rate_up = 2,
@@ -163,77 +158,16 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
.has_steer_req_tolerance = true,
};
const AngleSteeringLimits HYUNDAI_CANFD_ANGLE_STEERING_LIMITS = {
.max_angle = 3600,
.angle_deg_to_can = 10,
.frequency = 100U,
};
// We need to find a middle ground between all the possible params or find a way to properly fingerprint.
// HYUNDAI_IONIQ_5_PE: -0.0008688329819908074
// KIA_EV6_2025: -0.000889804937754786
// KIA_EV9: -0.0005410588125765342
// GENESIS_GV80_2025: -0.0005685702046115589
// HYUNDAI_SANTA_FE_HEV_5TH_GEN: -0.00059689759884299
// IONIQ 5 PE values.
// const AngleSteeringParams HYUNDAI_STEERING_PARAMS = {
// .slip_factor = -0.0008688329819908074, // calc_slip_factor(VM)
// .steer_ratio = 14.26,
// .wheelbase = 2.97,
// };
// // GENESIS_GV80_2025 values. (values can be found on values.py)
// const AngleSteeringParams HYUNDAI_STEERING_PARAMS = {
// .slip_factor = -0.0005685702046115589, // calc_slip_factor(VM)
// .steer_ratio = 14.14,
// .wheelbase = 2.95,
// };
// HYUNDAI_SANTA_FE_HEV_5TH_GEN values. (values can be found on values.py)
// const AngleSteeringParams HYUNDAI_STEERING_PARAMS = {
// .slip_factor = -0.00059689759884299, // calc_slip_factor(VM)
// .steer_ratio = 13.72,
// .wheelbase = 2.81,
// };
// KIA_SPORTAGE_HEV_2026 values. (most conservative for now) (values can be found on values.py)
const AngleSteeringParams HYUNDAI_STEERING_PARAMS = {
.slip_factor = -0.0006085930193026732, // calc_slip_factor(VM)
.steer_ratio = 13.7,
.wheelbase = 2.756,
};
bool tx = true;
// steering
const unsigned int steer_addr = (hyundai_canfd_lka_steer_msg && !hyundai_longitudinal) ? hyundai_canfd_get_lka_addr() : 0x12aU;
if (msg->addr == steer_addr) {
if (hyundai_canfd_angle_steering) {
const int lkas_angle_active = (msg->data[9] >> 4U) & 0x3U;
const bool steer_angle_req = lkas_angle_active != 1;
int desired_torque = (((msg->data[6] & 0xFU) << 7U) | (msg->data[5] >> 1U)) - 1024U;
bool steer_req = GET_BIT(msg, 52U);
int desired_angle = (msg->data[11] << 6U) | (msg->data[10] >> 2U);
desired_angle = to_signed(desired_angle, 14);
// ADAS_ACIAnglTqRedcGainVal: bit 96, 8 bits, unsigned. Raw 0-250 valid, 251-255 reserved.
const uint8_t gain_raw = msg->data[12];
bool gain_violation = gain_raw > 250U;
if (!steer_angle_req && (gain_raw != 0U)) {
gain_violation = true;
}
if (steer_angle_cmd_checks_vm(desired_angle, steer_angle_req, HYUNDAI_CANFD_ANGLE_STEERING_LIMITS, HYUNDAI_STEERING_PARAMS) || gain_violation) {
tx = false;
}
} else {
int desired_torque = (((msg->data[6] & 0xFU) << 7U) | (msg->data[5] >> 1U)) - 1024U;
bool steer_req = GET_BIT(msg, 52U);
if (steer_torque_cmd_checks(desired_torque, steer_req, HYUNDAI_CANFD_TORQUE_STEERING_LIMITS)) {
tx = false;
}
if (steer_torque_cmd_checks(desired_torque, steer_req, HYUNDAI_CANFD_STEERING_LIMITS)) {
tx = false;
}
}
@@ -293,7 +227,6 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
static safety_config hyundai_canfd_init(uint16_t param) {
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT = 128;
const uint16_t HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32;
const uint16_t HYUNDAI_PARAM_CANFD_ANGLE_STEERING = 1024;
static const CanMsg HYUNDAI_CANFD_LKA_STEER_MSG_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEER_MSG_COMMON_TX_MSGS(0, 1)
@@ -342,8 +275,6 @@ static safety_config hyundai_canfd_init(uint16_t param) {
gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut);
hyundai_canfd_alt_buttons = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ALT_BUTTONS);
hyundai_canfd_angle_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ANGLE_STEERING);
// TODO: test this restriction
hyundai_canfd_lka_steer_msg_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT);
safety_config ret;
+1 -7
View File
@@ -109,12 +109,6 @@ static bool nissan_tx_hook(const CANPacket_t *msg) {
}
}
// acc button check, only allow cancel button to be sent
if (msg->addr == 0x20bU) {
// Violation of any button other than cancel is pressed
violation |= ((msg->data[1] & 0x3dU) > 0U);
}
if (violation) {
tx = false;
}
@@ -135,7 +129,7 @@ static safety_config nissan_init(uint16_t param) {
{0x169, 0, 8, .check_relay = true}, // LKAS
{0x2b1, 0, 8, .check_relay = true}, // PROPILOT_HUD
{0x4cc, 0, 8, .check_relay = true}, // PROPILOT_HUD_INFO_MSG
{0x20b, 2, 6, .check_relay = false} // CRUISE_THROTTLE (X-Trail)
{0x20b, 2, 6, .check_relay = true} // CRUISE_THROTTLE (X-Trail)
};
static const CanMsg NISSAN_TX_MSGS_ALTIMA[] = {
+20 -1
View File
@@ -33,6 +33,10 @@ static bool tesla_autopark_prev = false;
extern bool tesla_has_vehicle_bus;
bool tesla_has_vehicle_bus = false;
// Configured MADS screen button finger count (0 = disabled, 3-5 = expected touch-point count)
extern uint8_t tesla_mads_screen_button_fingers;
uint8_t tesla_mads_screen_button_fingers = 0U;
static uint8_t tesla_get_counter(const CANPacket_t *msg) {
uint8_t cnt = 0;
@@ -201,7 +205,9 @@ static void tesla_rx_hook(const CANPacket_t *msg) {
if (msg->bus == 1U) {
if (msg->addr == 0x3DFU) {
mads_button_press = (msg->data[3] == 3U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED;
if (tesla_mads_screen_button_fingers != 0U) {
mads_button_press = (msg->data[3] == tesla_mads_screen_button_fingers) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED;
}
}
}
@@ -380,9 +386,22 @@ static safety_config tesla_init(uint16_t param) {
#endif
const uint16_t TESLA_PARAM_SP_VEHICLE_BUS = 1;
const uint16_t TESLA_PARAM_SP_MADS_SCREEN_BUTTON_3_FINGER = 2;
const uint16_t TESLA_PARAM_SP_MADS_SCREEN_BUTTON_4_FINGER = 4;
const uint16_t TESLA_PARAM_SP_MADS_SCREEN_BUTTON_5_FINGER = 8;
tesla_has_vehicle_bus = GET_FLAG(current_safety_param_sp, TESLA_PARAM_SP_VEHICLE_BUS);
if (GET_FLAG(current_safety_param_sp, TESLA_PARAM_SP_MADS_SCREEN_BUTTON_3_FINGER)) {
tesla_mads_screen_button_fingers = 3U;
} else if (GET_FLAG(current_safety_param_sp, TESLA_PARAM_SP_MADS_SCREEN_BUTTON_4_FINGER)) {
tesla_mads_screen_button_fingers = 4U;
} else if (GET_FLAG(current_safety_param_sp, TESLA_PARAM_SP_MADS_SCREEN_BUTTON_5_FINGER)) {
tesla_mads_screen_button_fingers = 5U;
} else {
tesla_mads_screen_button_fingers = 0U;
}
tesla_stock_aeb = false;
tesla_stock_lkas = false;
tesla_stock_lkas_prev = false;
+44 -2
View File
@@ -4,7 +4,7 @@
// Stock longitudinal
#define TOYOTA_BASE_TX_MSGS \
{0x191, 0, 8, .check_relay = true}, {0x412, 0, 8, .check_relay = true}, {0x1D2, 0, 8, .check_relay = false}, /* LKAS + LTA + PCM cancel cmd */ \
{0x191, 0, 8, .check_relay = true}, {0x412, 0, 8, .check_relay = true}, {0x1D2, 0, 8, .check_relay = false}, {0x750, 0, 8, .check_relay = false}, /* LKAS + LTA + PCM cancel cmd */ \
#define TOYOTA_COMMON_TX_MSGS \
TOYOTA_BASE_TX_MSGS \
@@ -69,6 +69,7 @@ static bool toyota_secoc = false;
static bool toyota_alt_brake = false;
static bool toyota_stock_longitudinal = false;
static bool toyota_lta = false;
static bool toyota_cruise_engaged = false; // SP: PCM_CRUISE.CRUISE_ACTIVE, narrows the auto brake hold AEB window below
static int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
static uint32_t toyota_compute_checksum(const CANPacket_t *msg) {
@@ -151,6 +152,7 @@ static void toyota_rx_hook(const CANPacket_t *msg) {
if (msg->addr == 0x176U) {
bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE
pcm_cruise_check(cruise_engaged);
toyota_cruise_engaged = cruise_engaged;
}
if (msg->addr == 0x116U) {
gas_pressed = msg->data[1] != 0U; // GAS_PEDAL.GAS_PEDAL_USER
@@ -162,6 +164,7 @@ static void toyota_rx_hook(const CANPacket_t *msg) {
if (msg->addr == 0x1D2U) {
bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE
pcm_cruise_check(cruise_engaged);
toyota_cruise_engaged = cruise_engaged;
if (!enable_gas_interceptor) {
gas_pressed = !GET_BIT(msg, 4U); // PCM_CRUISE.GAS_RELEASED
@@ -386,13 +389,35 @@ static bool toyota_tx_hook(const CANPacket_t *msg) {
tx = false;
}
}
// SP: auto brake hold https://github.com/AlexandreSato
if ((msg->addr == 0x344U) && (alternative_experience & ALT_EXP_ALLOW_AEB)) {
if (vehicle_moving || gas_pressed || !acc_main_on || toyota_cruise_engaged) {
tx = false;
}
}
}
// UDS: Only tester present ("\x0F\x02\x3E\x00\x00\x00\x00\x00") allowed on diagnostics address
if (msg->addr == 0x750U) {
// this address is sub-addressed. only allow tester present to radar (0xF)
bool invalid_uds_msg = (GET_BYTES(msg, 0, 4) != 0x003E020FU) || (GET_BYTES(msg, 4, 4) != 0x0U);
if (invalid_uds_msg) {
// SP: Secret sauce from dp. (ask @rav4kumar prior to modifing)
// Enhanced BSM
bool sp_valid_uds_msgs = ((GET_BYTES(msg, 0, 4) == 0x01100241U) || // disable left BSM debug
(GET_BYTES(msg, 0, 4) == 0x60100241U) || // enable left BSM debug
(GET_BYTES(msg, 0, 4) == 0x69210241U) || // poll left BSM status
(GET_BYTES(msg, 0, 4) == 0x01100242U) || // disable right BSM debug
(GET_BYTES(msg, 0, 4) == 0x60100242U) || // enable right BSM debug
(GET_BYTES(msg, 0, 4) == 0x69210242U)) // poll right BSM status
&& (GET_BYTES(msg, 4, 4) == 0x0U);
sp_valid_uds_msgs |= (GET_BYTES(msg, 0, 4) == 0x11300540U) && // automatic door locking and unlocking
((GET_BYTES(msg, 4, 4) == 0x00004000U) || // unlock
(GET_BYTES(msg, 4, 4) == 0x00008000U)); // lock
bool valid_tester_present = !invalid_uds_msg && !toyota_stock_longitudinal && !toyota_secoc;
if (!valid_tester_present && !sp_valid_uds_msgs) {
tx = false;
}
}
@@ -566,10 +591,27 @@ static safety_config toyota_init(uint16_t param) {
return ret;
}
static bool toyota_fwd_hook(int bus_num, int addr) {
bool block_msg = false;
if (bus_num == 2) {
// SP: block AEB when auto brake hold is active, unblock AEB when auto brake hold is not active.
// Narrowed to match auto brake hold's own precondition (cruise must be off) - previously this
// blocked native AEB forwarding, forcing a slower software relay, any time the car was simply
// stopped with the gas released and ACC main on, even while cruise was actively engaged and
// auto brake hold couldn't be active at all.
bool is_aeb_msg = (addr == 0x344);
block_msg = (is_aeb_msg && (alternative_experience & ALT_EXP_ALLOW_AEB) && !vehicle_moving && !gas_pressed && acc_main_on &&
!toyota_cruise_engaged);
}
return block_msg;
}
const safety_hooks toyota_hooks = {
.init = toyota_init,
.rx = toyota_rx_hook,
.tx = toyota_tx_hook,
.fwd = toyota_fwd_hook,
.get_checksum = toyota_get_checksum,
.compute_checksum = toyota_compute_checksum,
.get_quality_flag_valid = toyota_get_quality_flag_valid,
File diff suppressed because one or more lines are too long
@@ -60,11 +60,7 @@ def get_steer_value(mode, param, msg):
elif mode in (CarParams.SafetyModel.hyundai, CarParams.SafetyModel.hyundaiLegacy):
torque = (((msg.data[3] & 0x7) << 8) | msg.data[2]) - 1024
elif mode == CarParams.SafetyModel.hyundaiCanfd:
if param & HyundaiSafetyFlags.CANFD_ANGLE_STEERING:
angle = (msg.data[11] << 6) | (msg.data[10] >> 2)
angle = to_signed(angle, 14)
else:
torque = ((msg.data[5] >> 1) | (msg.data[6] & 0xF) << 7) - 1024
torque = ((msg.data[5] >> 1) | (msg.data[6] & 0xF) << 7) - 1024
elif mode == CarParams.SafetyModel.chrysler:
torque = (((msg.data[0] & 0x7) << 8) | msg.data[1]) - 1024
elif mode == CarParams.SafetyModel.subaru:
@@ -18,9 +18,6 @@ DEBUG_VARS = {
'current_disengage_reason': lambda safety: safety.mads_get_current_disengage_reason(),
'stock_acc_main': lambda safety: safety.get_acc_main_on(),
'mads_acc_main': lambda safety: safety.get_mads_acc_main(),
'desired_angle_last': lambda safety: safety.get_desired_angle_last(),
'angle_meas_min': lambda safety: safety.get_angle_meas_min(),
'angle_meas_max': lambda safety: safety.get_angle_meas_max(),
}
@@ -92,27 +89,17 @@ def replay_drive(msgs, safety_mode, param, alternative_experience, param_sp):
last_good = last_good_states[canmsg.address]
print(f"\nBlocked message at {(msg.logMonoTime - start_t) / 1e9:.3f}s:")
print(f"Address: {hex(canmsg.address)} (bus {canmsg.src})")
# Header with tab-separated columns
print("\nVariable\t\tLast Good State\t\tCurrent State")
print("-" * 80)
print("Current state:")
for var, getter in DEBUG_VARS.items():
current_val = getter(safety)
last_val = last_good[var] if last_good['timestamp'] is not None else "N/A"
# Align columns based on variable name length
tab_count = 1 if len(var) >= 16 else 2 # crude spacing control
tabs = '\t' * tab_count
print(f"{var}{tabs}\t{last_val}\t\t{current_val}")
print(f" {var}: {getter(safety)}")
if last_good['timestamp'] is not None:
print(f"\nLast good timestamp: {last_good['timestamp']:.3f}s")
print(f"\nLast good state ({last_good['timestamp']:.3f}s):")
for var in DEBUG_VARS:
print(f" {var}: {last_good[var]}")
else:
print("\nNo previous good state found for this address")
print("-" * 80)
else: # Update last good state if message is allowed
last_good_states[canmsg.address].update({
'timestamp': (msg.logMonoTime - start_t) / 1e9,
@@ -1,18 +1,13 @@
#!/usr/bin/env python3
from opendbc.testing import parameterized_class, parameterized
from opendbc.testing import parameterized_class
import unittest
import numpy as np
from opendbc.car.hyundai.carcontroller import ANGLE_SAFETY_BASELINE_MODEL
from opendbc.car.hyundai.values import HyundaiSafetyFlags, CAR, HyundaiFlags, CarControllerParams
from opendbc.car.hyundai.values import HyundaiSafetyFlags
from opendbc.car.structs import CarParams
from opendbc.car.vehicle_model import VehicleModel, calc_slip_factor
from opendbc.safety.tests.libsafety import libsafety_py
import opendbc.safety.tests.common as common
from opendbc.safety.tests.common import CANPackerSafety, away_round, round_speed
from opendbc.safety.tests.common import CANPackerSafety
from opendbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase
from opendbc.car.lateral import get_max_angle_delta_vm, get_max_angle_vm, AngleSteeringLimitsVM
from opendbc.car.hyundai.interface import CarInterface
# All combinations of radar/camera-SCC and gas/hybrid/EV cars
ALL_GAS_EV_HYBRID_COMBOS = [
@@ -27,16 +22,10 @@ ALL_GAS_EV_HYBRID_COMBOS = [
]
def round_angle(angle_deg: float, can_offset=0):
scaled = angle_deg / 0.1
scaled += can_offset
return int(scaled) * 0.1
class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
STANDSTILL_THRESHOLD = 0.375 * 0.03125 # 0.375 kph
STANDSTILL_THRESHOLD = 12 # 0.375 kph
FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]}
MAX_RATE_UP = 2
@@ -68,7 +57,7 @@ class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.Drive
return self.packer.make_can_msg_safety(self.STEER_MSG, self.STEER_BUS, values)
def _speed_msg(self, speed):
values = {f"WHL_Spd{pos}Val": speed * 3.6 for pos in ["FL", "FR", "RL", "RR"]}
values = {f"WHL_Spd{pos}Val": speed * 0.03125 for pos in ["FL", "FR", "RL", "RR"]}
return self.packer.make_can_msg_safety("WHEEL_SPEEDS", self.PT_BUS, values)
def _user_brake_msg(self, brake):
@@ -104,285 +93,7 @@ class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.Drive
return self._button_msg(0, enabled)
class TestHyundaiCanfdTorqueSteering(TestHyundaiCanfdBase, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
MAX_RATE_UP = 2
MAX_RATE_DOWN = 3
MAX_TORQUE = 270
MAX_RT_DELTA = 112
RT_INTERVAL = 250000
DRIVER_TORQUE_ALLOWANCE = 250
DRIVER_TORQUE_FACTOR = 2
# Safety around steering req bit
MIN_VALID_STEERING_FRAMES = 89
MAX_INVALID_STEERING_FRAMES = 2
MIN_VALID_STEERING_RT_INTERVAL = 810000 # a ~10% buffer, can send steer up to 110Hz
@classmethod
def setUpClass(cls):
super().setUpClass()
if cls.__name__ == "TestHyundaiCanfdTorqueSteering":
cls.packer = None
cls.safety = None
raise unittest.SkipTest
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, 0)
self.safety.init_tests()
class TestHyundaiCanfdAngleSteering(TestHyundaiCanfdBase, common.AngleSteeringSafetyTest):
PLATFORMS = {str(platform): platform for platform in CAR if
platform.config.flags & HyundaiFlags.CANFD_ANGLE_STEERING and not CarInterface.get_non_essential_params(str(platform)).dashcamOnly}
# Angle control limits
BASELINE_PANDA_ANGLE_LIMITS: AngleSteeringLimitsVM = AngleSteeringLimitsVM(
360, # degrees (safe upper bound for command, allowing some margin)
MAX_ANGLE_RATE=5 # comfort rate limit for angle commands, in degrees per frame.
)
STEER_ANGLE_MAX = 360 # deg
DEG_TO_CAN = 10
ANGLE_SAFETY_THRESHOLD_PCT = -2.0 # Fail if difference is less than -2%
# Hyundai uses get_max_angle_delta and get_max_angle for real lateral accel and jerk limits
# TODO: integrate this into AngleSteeringSafetyTest
ANGLE_RATE_BP = None
ANGLE_RATE_UP = None
ANGLE_RATE_DOWN = None
# Real time limits
LATERAL_FREQUENCY = 100 # Hz
cnt_angle_cmd = 0
def get_baseline_limits(self):
limits = CarControllerParams(CarInterface.get_non_essential_params(ANGLE_SAFETY_BASELINE_MODEL))
limits.ANGLE_LIMITS = self.BASELINE_PANDA_ANGLE_LIMITS
return limits
def _angle_cmd_msg(self, angle: float, enabled: bool, increment_timer: bool = True, gain: float = 0.0):
if increment_timer:
self.safety.set_timer(self.cnt_angle_cmd * int(1e6 / self.LATERAL_FREQUENCY))
self.__class__.cnt_angle_cmd += 1
values = {"ADAS_StrAnglReqVal": angle, "LKAS_ANGLE_ACTIVE": 2 if enabled else 1,
"ADAS_ACIAnglTqRedcGainVal": gain}
return self.packer.make_can_msg_safety(self.STEER_MSG, self.STEER_BUS, values)
def _angle_meas_msg(self, angle: float):
values = {"MDPS_EstStrAnglVal": angle}
return self.packer.make_can_msg_safety("MDPS", self.PT_BUS, values)
def _get_steer_cmd_angle_max(self, speed):
baseline_vm = self.get_vm(ANGLE_SAFETY_BASELINE_MODEL)
return get_max_angle_vm(max(speed, 1), baseline_vm, self.get_baseline_limits())
@classmethod
def setUpClass(cls):
super().setUpClass()
if cls.__name__ == "TestHyundaiCanfdAngleSteering":
cls.packer = None
cls.safety = None
raise unittest.SkipTest
def get_vm(self, car_name):
return VehicleModel(CarInterface.get_non_essential_params(car_name))
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_ANGLE_STEERING)
self.safety.init_tests()
def test_angle_cmd_when_enabled(self):
# We properly test lateral acceleration and jerk below
pass
def test_lateral_accel_limit(self):
car_name = ANGLE_SAFETY_BASELINE_MODEL
for speed in np.linspace(0, 40, 100):
speed = round_speed(away_round(speed / 0.03125 * 3.6) * 0.03125 / 3.6)
speed = max(speed, 1)
for sign in (-1, 1):
self.safety.set_controls_allowed(True)
self._reset_speed_measurement(speed + 1) # safety fudges the speed
# at limit (safety tolerance adds 1)
angl = get_max_angle_vm(speed, self.get_vm(car_name), self.get_baseline_limits())
max_angle = round_angle(get_max_angle_vm(speed, self.get_vm(car_name), self.get_baseline_limits()), 1) * sign
max_angle = np.clip(max_angle, -self.STEER_ANGLE_MAX, self.STEER_ANGLE_MAX)
self.safety.set_desired_angle_last(round(max_angle * self.DEG_TO_CAN))
self.assertTrue(self._tx(self._angle_cmd_msg(max_angle, True)), f"{angl} -- {max_angle}")
# above limit (offset 6 to reliably exceed C float tolerance)
max_angle_raw = round_angle(get_max_angle_vm(speed, self.get_vm(car_name), self.get_baseline_limits()), 6) * sign
max_angle = np.clip(max_angle_raw, -self.STEER_ANGLE_MAX, self.STEER_ANGLE_MAX)
self._tx(self._angle_cmd_msg(max_angle, True))
# at low speeds max angle is above 360, so adding 1 has no effect
should_tx = abs(max_angle_raw) >= self.STEER_ANGLE_MAX
self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(max_angle, True)), f"should_tx: {should_tx}, max_angle: {max_angle}, speed: {speed}")
def test_lateral_jerk_limit(self):
car_name = ANGLE_SAFETY_BASELINE_MODEL
for speed in np.linspace(0, 40, 100):
speed = round_speed(away_round(speed / 0.03125 * 3.6) * 0.03125 / 3.6)
speed = max(speed, 1)
for sign in (-1, 1): # (-1, 1):
self.safety.set_controls_allowed(True)
self._reset_speed_measurement(speed + 1) # safety fudges the speed
self._tx(self._angle_cmd_msg(0, True))
# Stay within limits
# Up
max_angle_delta = round_angle(get_max_angle_delta_vm(speed, self.get_vm(car_name), self.get_baseline_limits())) * sign
self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True)))
# Don't change
self.safety.set_desired_angle_last(round(max_angle_delta * self.DEG_TO_CAN))
self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True)))
# Down
self.assertTrue(self._tx(self._angle_cmd_msg(0, True)))
# Inject too high rates
# Up
# TODO-SP: Why do I need to set a can_offset so high to pass the tests and why tesla only does +1? and why does it seem to differ based on the baseline?
max_angle_delta = round_angle(get_max_angle_delta_vm(speed, self.get_vm(car_name), self.get_baseline_limits()), 6) * sign
self.assertFalse(self._tx(self._angle_cmd_msg(max_angle_delta, True)), vars(self.get_baseline_limits()))
# Don't change
self.safety.set_desired_angle_last(round(max_angle_delta * self.DEG_TO_CAN))
self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True)))
# Down
self.assertFalse(self._tx(self._angle_cmd_msg(0, True)))
# Recover
self.assertTrue(self._tx(self._angle_cmd_msg(0, True)))
def test_rt_limits(self):
# TODO: remove and check all safety modes
if self.LATERAL_FREQUENCY == -1:
raise unittest.SkipTest("No real time limits")
# Angle safety enforces real time limits by checking the message send frequency in a 250ms time window
self.safety.set_timer(0)
self.safety.set_controls_allowed(True)
max_rt_msgs = int(self.LATERAL_FREQUENCY * common.RT_INTERVAL / 1e6 * 1.2 + 1) # 1.2x buffer
for i in range(max_rt_msgs * 2):
should_tx = i <= max_rt_msgs
self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(0, True, increment_timer=False)))
# One under RT interval should do nothing
self.safety.set_timer(common.RT_INTERVAL - 1)
for _ in range(5):
self.assertFalse(self._tx(self._angle_cmd_msg(0, True, increment_timer=False)))
# Increment timer and send 1 message to reset RT window
self.safety.set_timer(common.RT_INTERVAL)
self.assertFalse(self._tx(self._angle_cmd_msg(0, True, increment_timer=False)))
for _ in range(5):
self.assertTrue(self._tx(self._angle_cmd_msg(0, True, increment_timer=False)))
def test_torque_reduction_gain(self):
# Valid gains when enabled
for gain in [0.0, 0.5, 1.0]:
self.safety.set_controls_allowed(True)
self.assertTrue(self._tx(self._angle_cmd_msg(0, True, gain=gain)),
f"gain={gain} should be allowed when enabled")
# Reserved values (raw 251+) must fail even when enabled
for gain in [1.004, 1.008, 1.02]:
self.safety.set_controls_allowed(True)
self.assertFalse(self._tx(self._angle_cmd_msg(0, True, gain=gain)),
f"gain={gain} (reserved) should be blocked")
# Non-zero gain when disabled must fail
for gain in [0.004, 0.5, 1.0]:
self.safety.set_controls_allowed(True)
self.assertFalse(self._tx(self._angle_cmd_msg(0, False, gain=gain)),
f"gain={gain} should be blocked when disabled")
# Zero gain when disabled must pass
self.safety.set_controls_allowed(True)
self.assertTrue(self._tx(self._angle_cmd_msg(0, False, gain=0.0)))
@parameterized("car_name", sorted(PLATFORMS))
def test_max_steering_angle_safety(self, car_name):
"""
Test that ensures the current car's max steering angles are never more than 2%
lower than the baseline car across all test speeds.
"""
baseline_car = ANGLE_SAFETY_BASELINE_MODEL
baseline_vm = self.get_vm(baseline_car)
current_vm = self.get_vm(car_name)
for speed in np.linspace(1, 40, 10):
baseline_max_angle = get_max_angle_vm(speed, baseline_vm, self.get_baseline_limits())
current_max_angle = get_max_angle_vm(speed, current_vm, self.get_baseline_limits())
# Skip if both exceed STEER_ANGLE_MAX (only_relevant_angles logic)
if current_max_angle > self.STEER_ANGLE_MAX and baseline_max_angle > self.STEER_ANGLE_MAX:
continue
# Calculate percentage difference
if baseline_max_angle != 0:
angle_diff_pct = ((current_max_angle - baseline_max_angle) / baseline_max_angle) * 100
else:
angle_diff_pct = 0
# Assert that difference is not dangerously low
self.assertTrue(
angle_diff_pct >= self.ANGLE_SAFETY_THRESHOLD_PCT,
f"{car_name} max steering angle at {speed:.1f} m/s [{current_max_angle:.2f}°] is {angle_diff_pct:.2f}% " +
f"lower than baseline {baseline_car} ({current_max_angle:.2f}° vs {baseline_max_angle:.2f}°). " +
f"Must be >= {self.ANGLE_SAFETY_THRESHOLD_PCT}% to ensure safety." +
f"Consider updating the baseline model to be {car_name} (which will lower the threshold for ALL models). " +
f"Slip Factor: {repr(calc_slip_factor(current_vm))}"
)
@parameterized("car_name", sorted(PLATFORMS))
def test_max_steering_angle_delta_safety(self, car_name):
"""
Test that ensures the current car's max steering angle deltas are never more than 2%
lower than the baseline car across all test speeds.
"""
baseline_car = ANGLE_SAFETY_BASELINE_MODEL
baseline_vm = self.get_vm(baseline_car)
baseline_limits = CarControllerParams(CarInterface.get_non_essential_params(baseline_car))
current_vm = self.get_vm(car_name)
current_limits = CarControllerParams(CarInterface.get_non_essential_params(car_name))
for speed in np.linspace(1, 40, 10):
baseline_max_delta = get_max_angle_delta_vm(speed, baseline_vm, baseline_limits)
current_max_delta = get_max_angle_delta_vm(speed, current_vm, current_limits)
# Calculate percentage difference
if baseline_max_delta != 0:
delta_diff_pct = ((current_max_delta - baseline_max_delta) / baseline_max_delta) * 100
else:
delta_diff_pct = 0
# Assert that difference is not dangerously low
self.assertTrue(
delta_diff_pct >= self.ANGLE_SAFETY_THRESHOLD_PCT,
f"{car_name} max steering angle delta at {speed:.1f} m/s is {delta_diff_pct:.2f}% " +
f"lower than {baseline_car} ({current_max_delta:.4f} vs {baseline_max_delta:.4f} deg/frame). " +
f"Must be >= {self.ANGLE_SAFETY_THRESHOLD_PCT}% to ensure safety." +
f"Consider updating the baseline model to be {car_name} (which will lower the threshold for ALL models)." +
f"Slip Factor: {repr(calc_slip_factor(current_vm))}"
)
class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdTorqueSteering):
class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdBase):
TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0)} # LFA, LFAHDA_CLUSTER
@@ -460,7 +171,7 @@ class TestHyundaiCanfdLFASteeringAltButtons(TestHyundaiCanfdLFASteeringAltButton
pass
class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdTorqueSteering):
class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase):
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4)} # LKAS, CAM_0x2A4
@@ -479,7 +190,7 @@ class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdTorqueSteering):
# TODO: Handle ICE and HEV configurations once we see cars that use the new messages
class TestHyundaiCanfdLKASteeringAltEVBase(TestHyundaiCanfdBase):
class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase):
TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)} # LKAS_ALT, CAM_0x362
@@ -498,60 +209,6 @@ class TestHyundaiCanfdLKASteeringAltEVBase(TestHyundaiCanfdBase):
self.safety.init_tests()
class TestHyundaiCanfdLKASteeringAltEVTorque(TestHyundaiCanfdLKASteeringAltEVBase, TestHyundaiCanfdTorqueSteering):
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.EV_GAS |
HyundaiSafetyFlags.CANFD_LKA_STEER_MSG_ALT)
self.safety.init_tests()
class TestHyundaiCanfdLKASteeringAltAngle(TestHyundaiCanfdAngleSteering):
TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)}
FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]}
PT_BUS = 1
SCC_BUS = 1
STEER_MSG = "LKAS_ALT"
GAS_MSG = ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED")
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG |
HyundaiSafetyFlags.CANFD_LKA_STEER_MSG_ALT | HyundaiSafetyFlags.CANFD_ANGLE_STEERING)
self.safety.init_tests()
# Angle steering does not use torque — override inherited torque tests
def test_steer_safety_check(self):
pass
def test_non_realtime_limit_up(self):
pass
def test_steer_req_bit(self):
pass
def test_steer_req_bit_frames(self):
pass
def test_steer_req_bit_multi_invalid(self):
pass
def test_steer_req_bit_realtime(self):
pass
def test_against_torque_driver(self):
pass
def test_realtime_limits(self):
pass
class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdLKASteeringEV):
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1],
@@ -13,8 +13,8 @@ class TestNissanSafety(common.CarSafetyTest, common.AngleSteeringSafetyTest):
TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2]]
GAS_PRESSED_THRESHOLD = 3
RELAY_MALFUNCTION_ADDRS = {0: (0x169, 0x2b1, 0x4cc)}
FWD_BLACKLISTED_ADDRS = {2: [0x169, 0x2b1, 0x4cc]}
RELAY_MALFUNCTION_ADDRS = {0: (0x169, 0x2b1, 0x4cc), 2: (0x20b,)}
FWD_BLACKLISTED_ADDRS = {0: [0x20b], 2: [0x169, 0x2b1, 0x4cc]}
EPS_BUS = 0
CRUISE_BUS = 2
@@ -72,11 +72,11 @@ class TestNissanSafety(common.CarSafetyTest, common.AngleSteeringSafetyTest):
def test_acc_buttons(self):
btns = [
("cancel", True),
("propilot", False),
("flw_dist", False),
("_set", False),
("res", False),
(None, False),
("propilot", True),
("flw_dist", True),
("_set", True),
("res", True),
(None, True),
]
for controls_allowed in (True, False):
for btn, should_tx in btns:
@@ -498,7 +498,7 @@ class TestTeslaVehicleBusSafety(TestTeslaSafetyBase):
super().setUp()
self.safety = libsafety_py.libsafety
self.packer_adas = CANPackerSafety("tesla_model3_vehicle")
self.safety.set_current_safety_param_sp(TeslaSafetyFlagsSP.HAS_VEHICLE_BUS)
self.safety.set_current_safety_param_sp(TeslaSafetyFlagsSP.HAS_VEHICLE_BUS | TeslaSafetyFlagsSP.MADS_SCREEN_BUTTON_3_FINGER)
self.safety.set_safety_hooks(CarParams.SafetyModel.tesla, 0)
self.safety.init_tests()
@@ -506,6 +506,40 @@ class TestTeslaVehicleBusSafety(TestTeslaSafetyBase):
values = {"UI_activeTouchPoints": 3 if enabled else 0}
return self.packer_adas.make_can_msg_safety("UI_status2", CANBUS.vehicle, values)
def _set_mads_screen_button_config(self, finger_flag):
param_sp = TeslaSafetyFlagsSP.HAS_VEHICLE_BUS
if finger_flag is not None:
param_sp |= finger_flag
self.safety.set_current_safety_param_sp(param_sp)
self.safety.set_safety_hooks(CarParams.SafetyModel.tesla, 0)
self.safety.init_tests()
def _touch_points_msg(self, touch_points):
return self.packer_adas.make_can_msg_safety("UI_status2", CANBUS.vehicle, {"UI_activeTouchPoints": touch_points})
def test_mads_screen_button_finger_count_match(self):
"""Configured finger count must match received touch-point count to register a MADS button press."""
configs = [
(TeslaSafetyFlagsSP.MADS_SCREEN_BUTTON_3_FINGER, 3),
(TeslaSafetyFlagsSP.MADS_SCREEN_BUTTON_4_FINGER, 4),
(TeslaSafetyFlagsSP.MADS_SCREEN_BUTTON_5_FINGER, 5),
]
for config_flag, config_count in configs:
for actual in (0, 3, 4, 5):
with self.subTest(configured=config_count, actual=actual):
self._set_mads_screen_button_config(config_flag)
self._rx(self._touch_points_msg(actual))
expected = 1 if actual == config_count else 0 # PRESSED vs NOT_PRESSED
self.assertEqual(expected, self.safety.get_mads_button_press())
def test_mads_screen_button_disabled(self):
"""With no finger-count flag set, touch messages must not change the MADS button state from UNAVAILABLE."""
self._set_mads_screen_button_config(None)
for actual in (0, 3, 4, 5):
with self.subTest(actual=actual):
self._rx(self._touch_points_msg(actual))
self.assertEqual(-1, self.safety.get_mads_button_press()) # UNAVAILABLE
if __name__ == "__main__":
unittest.main()
@@ -101,6 +101,29 @@ class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyT
tester_present = libsafety_py.make_CANPacket(0x750, 0, msg)
self.assertEqual(should_tx and ecu_disabled and not stock_longitudinal, self._tx(tester_present))
def test_enhanced_bsm(self):
# SP: enable/disable/poll left+right blind spot debug mode, sent to the radar diagnostic address
valid_msgs = [
b"\x41\x02\x10\x60\x00\x00\x00\x00", # enable left
b"\x41\x02\x10\x01\x00\x00\x00\x00", # disable left
b"\x41\x02\x21\x69\x00\x00\x00\x00", # poll left
b"\x42\x02\x10\x60\x00\x00\x00\x00", # enable right
b"\x42\x02\x10\x01\x00\x00\x00\x00", # disable right
b"\x42\x02\x21\x69\x00\x00\x00\x00", # poll right
]
for msg in valid_msgs:
pkt = libsafety_py.make_CANPacket(0x750, 0, msg)
self.assertTrue(self._tx(pkt), msg.hex())
invalid_msgs = [
b"\x41\x02\x10\x61\x00\x00\x00\x00", # wrong subfunction
b"\x43\x02\x10\x60\x00\x00\x00\x00", # wrong sub-address (not left/right)
b"\x41\x02\x10\x60\x01\x00\x00\x00", # non-zero trailing bytes
]
for msg in invalid_msgs:
pkt = libsafety_py.make_CANPacket(0x750, 0, msg)
self.assertFalse(self._tx(pkt), msg.hex())
def test_block_aeb(self, stock_longitudinal: bool = False):
for controls_allowed in (True, False):
for bad in (True, False):
@@ -929,16 +929,6 @@
],
"package": "All"
},
"Genesis GV70 Electrified 2026": {
"platform": "GENESIS_GV70_ELECTRIFIED_2ND_GEN",
"make": "Genesis",
"brand": "hyundai",
"model": "GV70 Electrified",
"year": [
"2026"
],
"package": "All"
},
"Genesis GV70 Electrified (Australia Only) 2022": {
"platform": "GENESIS_GV70_ELECTRIFIED_1ST_GEN",
"make": "Genesis",
@@ -970,26 +960,6 @@
],
"package": "All"
},
"Genesis GV80 (3.5T Prestige Trim, with HDA II & LFA2) 2025": {
"platform": "GENESIS_GV80_2025",
"make": "Genesis",
"brand": "hyundai",
"model": "GV80 (3.5T Prestige Trim, with HDA II & LFA2)",
"year": [
"2025"
],
"package": "Highway Driving Assist II & Lane Follow Assist 2"
},
"Genesis GV80 Coupe (with HDA II & LFA2) 2025": {
"platform": "GENESIS_GV80_2025",
"make": "Genesis",
"brand": "hyundai",
"model": "GV80 Coupe (with HDA II & LFA2)",
"year": [
"2025"
],
"package": "Highway Driving Assist II & Lane Follow Assist 2"
},
"GMC Acadia 2018": {
"platform": "GMC_ACADIA",
"make": "GMC",
@@ -1497,16 +1467,6 @@
],
"package": "All"
},
"Hyundai AZERA Hybrid (with HDA II & LFA2) 2025": {
"platform": "HYUNDAI_AZERA_HEV_7TH_GEN",
"make": "Hyundai",
"brand": "hyundai",
"model": "AZERA Hybrid (with HDA II & LFA2)",
"year": [
"2025"
],
"package": "Highway Driving Assist II & Lane Follow Assist 2"
},
"Hyundai Custin 2023": {
"platform": "HYUNDAI_CUSTIN_1ST_GEN",
"make": "Hyundai",
@@ -1644,17 +1604,6 @@
],
"package": "Highway Driving Assist"
},
"Hyundai Ioniq 5 PE (with HDA II & LFA2) 2025-26": {
"platform": "HYUNDAI_IONIQ_5_PE",
"make": "Hyundai",
"brand": "hyundai",
"model": "Ioniq 5 PE (with HDA II & LFA2)",
"year": [
"2025",
"2026"
],
"package": "Highway Driving Assist II & Lane Follow Assist 2"
},
"Hyundai Ioniq 6 (with HDA II) 2023-24": {
"platform": "HYUNDAI_IONIQ_6",
"make": "Hyundai",
@@ -1677,17 +1626,6 @@
],
"package": "Highway Driving Assist"
},
"Hyundai Ioniq 9 (with HDA II & LFA2) 2025-26": {
"platform": "HYUNDAI_IONIQ_9",
"make": "Hyundai",
"brand": "hyundai",
"model": "Ioniq 9 (with HDA II & LFA2)",
"year": [
"2025",
"2026"
],
"package": "Highway Driving Assist II & Lane Follow Assist 2"
},
"Hyundai Ioniq Electric 2019": {
"platform": "HYUNDAI_IONIQ_EV_LTD",
"make": "Hyundai",
@@ -1907,17 +1845,6 @@
],
"package": "All"
},
"Hyundai Santa Fe Hybrid (with HDA II & LFA2) 2024-25": {
"platform": "HYUNDAI_SANTA_FE_HEV_5TH_GEN",
"make": "Hyundai",
"brand": "hyundai",
"model": "Santa Fe Hybrid (with HDA II & LFA2)",
"year": [
"2024",
"2025"
],
"package": "Highway Driving Assist II & Lane Follow Assist 2"
},
"Hyundai Santa Fe Plug-in Hybrid 2022-23": {
"platform": "HYUNDAI_SANTA_FE_PHEV_2022",
"make": "Hyundai",
@@ -2130,16 +2057,6 @@
],
"package": "All"
},
"Kia EV6 (with HDA I) 2025": {
"platform": "KIA_EV6_2025",
"make": "Kia",
"brand": "hyundai",
"model": "EV6 (with HDA I)",
"year": [
"2025"
],
"package": "Highway Driving Assist I"
},
"Kia EV6 (with HDA II) 2022-24": {
"platform": "KIA_EV6",
"make": "Kia",
@@ -2164,17 +2081,6 @@
],
"package": "Highway Driving Assist"
},
"Kia EV9 2025-26": {
"platform": "KIA_EV9",
"make": "Kia",
"brand": "hyundai",
"model": "EV9",
"year": [
"2025",
"2026"
],
"package": "Smart Cruise Control (SCC)"
},
"Kia Forte 2019-21": {
"platform": "KIA_FORTE",
"make": "Kia",
@@ -2483,16 +2389,6 @@
],
"package": "All"
},
"Kia Sorento Hybrid 2026": {
"platform": "KIA_SORENTO_HEV_4TH_GEN_LFA2",
"make": "Kia",
"brand": "hyundai",
"model": "Sorento Hybrid",
"year": [
"2026"
],
"package": "All"
},
"Kia Sorento Plug-in Hybrid 2022-23": {
"platform": "KIA_SORENTO_HEV_4TH_GEN",
"make": "Kia",
@@ -2525,16 +2421,6 @@
],
"package": "Smart Cruise Control (SCC)"
},
"Kia Sportage Hybrid 2026": {
"platform": "KIA_SPORTAGE_HEV_2026",
"make": "Kia",
"brand": "hyundai",
"model": "Sportage Hybrid",
"year": [
"2026"
],
"package": "Smart Cruise Control (SCC)"
},
"Kia Stinger 2018-20": {
"platform": "KIA_STINGER",
"make": "Kia",
@@ -13,12 +13,12 @@ from opendbc.car import structs
from opendbc.car.can_definitions import CanRecvCallable, CanSendCallable
from opendbc.car.hyundai.values import HyundaiFlags
from opendbc.car.subaru.values import SubaruFlags
from opendbc.car.toyota.values import ToyotaSafetyFlags
from opendbc.car.toyota.values import RADAR_ACC_CAR, SECOC_CAR, TSS2_CAR, ToyotaSafetyFlags
from opendbc.sunnypilot.car.hyundai.enable_radar_tracks import enable_radar_tracks as hyundai_enable_radar_tracks
from opendbc.sunnypilot.car.hyundai.longitudinal.helpers import LongitudinalTuningType
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP
from opendbc.sunnypilot.car.subaru.values_ext import SubaruFlagsSP, SubaruSafetyFlagsSP
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP, TeslaSafetyFlagsSP
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP
@@ -85,6 +85,7 @@ def setup_interfaces(CI, CP: structs.CarParams, CP_SP: structs.CarParamsSP,
_initialize_custom_longitudinal_tuning(CI, CP, CP_SP, params_dict)
_initialize_coop_steering(CP, CP_SP, params_dict)
_initialize_tesla_mads_screen_button(CP, CP_SP, params_dict)
_initialize_radar_tracks(CP, CP_SP, can_recv, can_send)
_initialize_stop_and_go(CP, CP_SP, params_dict)
_initialize_toyota(CP, CP_SP, params_dict)
@@ -112,6 +113,21 @@ def _initialize_coop_steering(CP: structs.CarParams, CP_SP: structs.CarParamsSP,
CP_SP.flags |= TeslaFlagsSP.COOP_STEERING.value
def _initialize_tesla_mads_screen_button(CP: structs.CarParams, CP_SP: structs.CarParamsSP,
params_dict: dict[str, str]) -> None:
if CP.brand == 'tesla' and CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
selection = int(params_dict.get("TeslaMadsScreenButton", MadsScreenButtonType.OFF))
if selection == MadsScreenButtonType.THREE_FINGER:
CP_SP.flags |= TeslaFlagsSP.MADS_SCREEN_BUTTON_3_FINGER.value
CP_SP.safetyParam |= TeslaSafetyFlagsSP.MADS_SCREEN_BUTTON_3_FINGER
elif selection == MadsScreenButtonType.FOUR_FINGER:
CP_SP.flags |= TeslaFlagsSP.MADS_SCREEN_BUTTON_4_FINGER.value
CP_SP.safetyParam |= TeslaSafetyFlagsSP.MADS_SCREEN_BUTTON_4_FINGER
elif selection == MadsScreenButtonType.FIVE_FINGER:
CP_SP.flags |= TeslaFlagsSP.MADS_SCREEN_BUTTON_5_FINGER.value
CP_SP.safetyParam |= TeslaSafetyFlagsSP.MADS_SCREEN_BUTTON_5_FINGER
def _initialize_radar_tracks(CP: structs.CarParams, CP_SP: structs.CarParamsSP,
can_recv: CanRecvCallable | None = None, can_send: CanSendCallable | None = None) -> None:
if CP.brand == 'hyundai':
@@ -137,6 +153,8 @@ def _initialize_toyota(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params
if CP.brand == 'toyota':
toyota_stock_long = int(params_dict.get("ToyotaEnforceStockLongitudinal", 0)) == 1
toyota_stop_and_go_hack = int(params_dict.get("ToyotaStopAndGoHack", 0)) == 1
toyota_enhanced_bsm = int(params_dict.get("ToyotaEnhancedBsm", 0)) == 1
toyota_auto_brake_hold = int(params_dict.get("ToyotaAutoHold", 0)) == 1
if toyota_stock_long:
CP_SP.flags |= ToyotaFlagsSP.STOCK_LONGITUDINAL.value
@@ -146,3 +164,9 @@ def _initialize_toyota(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params
if toyota_stop_and_go_hack and CP.openpilotLongitudinalControl:
CP_SP.flags |= ToyotaFlagsSP.STOP_AND_GO_HACK.value
if toyota_enhanced_bsm and CP.carFingerprint in (TSS2_CAR - SECOC_CAR):
CP_SP.flags |= ToyotaFlagsSP.SP_ENHANCED_BSM.value
if toyota_auto_brake_hold and CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR - SECOC_CAR):
CP_SP.flags |= ToyotaFlagsSP.SP_AUTO_BRAKE_HOLD.value
@@ -20,19 +20,28 @@ class CarStateExt:
self.CP = CP
self.CP_SP = CP_SP
self.infotainment_3_finger_press = 0
self.active_touch_points = 0
def update(self, ret: structs.CarState, ret_sp: structs.CarStateSP, can_parsers: dict[StrEnum, CANParser]) -> None:
if self.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
cp_adas = can_parsers[Bus.adas]
prev_infotainment_3_finger_press = self.infotainment_3_finger_press
self.infotainment_3_finger_press = int(cp_adas.vl["UI_status2"]["UI_activeTouchPoints"])
prev_active_touch_points = self.active_touch_points
self.active_touch_points = int(cp_adas.vl["UI_status2"]["UI_activeTouchPoints"])
ret.buttonEvents = [*create_button_events(self.infotainment_3_finger_press, prev_infotainment_3_finger_press,
{3: ButtonType.lkas})]
finger_count = None
if self.CP_SP.flags & TeslaFlagsSP.MADS_SCREEN_BUTTON_3_FINGER:
finger_count = 3
elif self.CP_SP.flags & TeslaFlagsSP.MADS_SCREEN_BUTTON_4_FINGER:
finger_count = 4
elif self.CP_SP.flags & TeslaFlagsSP.MADS_SCREEN_BUTTON_5_FINGER:
finger_count = 5
if finger_count is not None:
ret.buttonEvents = [*create_button_events(self.active_touch_points, prev_active_touch_points,
{finger_count: ButtonType.lkas})]
cp_party = can_parsers[Bus.party]
cp_ap_party = can_parsers[Bus.ap_party]
speed_units = self.can_define.dv["DI_state"]["DI_speedUnits"].get(int(cp_party.vl["DI_state"]["DI_speedUnits"]), None)
@@ -8,9 +8,22 @@ from enum import IntFlag
class TeslaFlagsSP(IntFlag):
HAS_VEHICLE_BUS = 1 # 3-finger infotainment press signal is present on the VEHICLE bus with the deprecated Tesla harness installed
HAS_VEHICLE_BUS = 1 # Multi-finger infotainment press signal is present on the VEHICLE bus with the deprecated Tesla harness installed
COOP_STEERING = 2 # Coop steering
MADS_SCREEN_BUTTON_3_FINGER = 4
MADS_SCREEN_BUTTON_4_FINGER = 8
MADS_SCREEN_BUTTON_5_FINGER = 16
class MadsScreenButtonType:
OFF = 0
THREE_FINGER = 1
FOUR_FINGER = 2
FIVE_FINGER = 3
class TeslaSafetyFlagsSP:
HAS_VEHICLE_BUS = 1
MADS_SCREEN_BUTTON_3_FINGER = 2
MADS_SCREEN_BUTTON_4_FINGER = 4
MADS_SCREEN_BUTTON_5_FINGER = 8
@@ -0,0 +1,79 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from opendbc.car import structs
from opendbc.car.toyota import toyotacan
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP
GearShifter = structs.CarState.GearShifter
# frames of confirmed hold-eligible standstill required before engaging
BRAKE_HOLD_ALLOWED_TIMER = 100
DISALLOWED_GEARS = (GearShifter.park, GearShifter.reverse)
# PRE_COLLISION_2 fields that go high when the camera's own PCS/AEB is genuinely intervening this
# frame (PCSALM mirrors PRECOLLISION_ACTIVE; IBTRGR/PBATRGR/PREFILL/AVSTRGR/PBRTRGR/PPTRGR are its
# actuation triggers - see create_pcs_commands for the same field set on the stock-DSU PCS path).
# Deliberately over-inclusive: a false positive here just means we pass a quiescent frame through
# instead of holding it, never the other way around, so err toward checking more fields, not fewer.
PCS_TRIGGER_FIELDS = ("PCSALM", "IBTRGR", "PBATRGR", "PREFILL", "AVSTRGR", "PBRTRGR", "PPTRGR")
def pcs_is_active(pre_collision_2: dict) -> bool:
return any(pre_collision_2.get(field, 0) for field in PCS_TRIGGER_FIELDS) or pre_collision_2.get("DSS1GDRV", 0) != 0
class AutoBrakeHold:
def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP):
self.CP = CP
self.CP_SP = CP_SP
@property
def enabled(self):
return bool(self.CP_SP.flags & ToyotaFlagsSP.SP_AUTO_BRAKE_HOLD)
# Auto Brake Hold (@AlexandreSato, @rav4kumar): holds the car at a stop with cruise off by
# overriding PRE_COLLISION_2 - the only channel on this platform that can command the brake
# independent of ACC engagement, since PCS/AEB is an always-on active safety system by design.
# Yields to any genuine PCS activation this frame - the real message is only ever overridden while
# it's quiescent - and releases for the rest of the current standstill episode on a brake press,
# rather than for a single frame.
class AutoBrakeHoldCarController(AutoBrakeHold):
def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP):
super().__init__(CP, CP_SP)
self.active = False
self._counter = 0
self._released = False
self._prev_brake_pressed = False
def update(self, CS: structs.CarState, frame: int, packer) -> list:
hold_allowed = (CS.out.standstill and CS.out.cruiseState.available and not CS.out.cruiseState.enabled and
not CS.out.gasPressed and CS.out.gearShifter not in DISALLOWED_GEARS)
if hold_allowed:
# only a fresh press releases hold - the press that caused the stop is already reflected in
# _prev_brake_pressed by the time standstill is reached, so it doesn't count as a release
if CS.out.brakePressed and not self._prev_brake_pressed:
self._released = True
self._counter += 1
self.active = self._counter > BRAKE_HOLD_ALLOWED_TIMER and not self._released
else:
self._counter = 0
self.active = False
self._released = False
self._prev_brake_pressed = CS.out.brakePressed
can_sends = []
if frame % 2 == 0:
override = self.active and not pcs_is_active(CS.pre_collision_2)
can_sends.append(toyotacan.create_brake_hold_command(packer, frame, CS.pre_collision_2, override))
return can_sends
@@ -0,0 +1,126 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from opendbc.car import structs
from opendbc.car.can_definitions import CanData
from opendbc.car.toyota import toyotacan
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP
LEFT_BLINDSPOT = b"\x41"
RIGHT_BLINDSPOT = b"\x42"
LEFT_SIDE = LEFT_BLINDSPOT[0]
RIGHT_SIDE = RIGHT_BLINDSPOT[0]
# BLINDSPOTD1/D2 aren't real distances despite the DBC name: verified against 3 real routes, values
# fall into 3 clean bands - idle (0), a small transitional-noise band (seen 1-31, rare: single-digit
# occurrence counts, present during side/state transitions), and two real zone codes (~46-47 and
# ~50-53, consistent across routes and cars - likely mirroring stock BSM's own ADJACENT/APPROACHING
# split). A plain nonzero check lets the noise band through as false "occupied" hits; gate on the
# real-zone floor instead - comfortably above every noise value seen, comfortably below neither zone code.
BLINDSPOT_NOISE_FLOOR = 35
# DEBUG also carries a 1-bit BLINDSPOT flag (byte 4) that isn't read here. Checked against the same
# route: stayed 0 across all frames, including every confirmed real detection - not a usable signal.
class EnhancedBsm:
def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP):
self.CP = CP
self.CP_SP = CP_SP
@property
def enabled(self):
return bool(self.CP_SP.flags & ToyotaFlagsSP.SP_ENHANCED_BSM)
class _BsmSideState:
def __init__(self):
self.blindspot = False
self.counter = 0
def update(self, distance_1, distance_2):
# every fresh matching-side reading directly reflects the current occupancy check - this is not
# a latch. A drop to an idle/noise reading on this exact side clears it immediately, same as the
# original. The counter is purely a silence timeout for when this side stops responding entirely,
# not a "hold the last detection for a while" mechanism.
self.blindspot = distance_1 > BLINDSPOT_NOISE_FLOOR or distance_2 > BLINDSPOT_NOISE_FLOOR
self.counter = 100
def decay(self):
self.counter = max(0, self.counter - 1)
if self.counter == 0:
self.blindspot = False
# Enhanced BSM (@arne182, @rav4kumar)
class EnhancedBsmCarState(EnhancedBsm):
def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP):
super().__init__(CP, CP_SP)
self._sides = {LEFT_SIDE: _BsmSideState(), RIGHT_SIDE: _BsmSideState()}
def update(self, cp, frame: int) -> tuple[bool, bool]:
# Let's keep all the commented out code for easy debug purposes in the future.
distance_1 = cp.vl["DEBUG"].get('BLINDSPOTD1')
distance_2 = cp.vl["DEBUG"].get('BLINDSPOTD2')
side = cp.vl["DEBUG"].get('BLINDSPOTSIDE')
if all(val is not None for val in [distance_1, distance_2, side]) and side in self._sides:
self._sides[side].update(distance_1, distance_2)
for side_state in self._sides.values():
side_state.decay()
return self._sides[LEFT_SIDE].blindspot, self._sides[RIGHT_SIDE].blindspot
class _BsmSideController:
def __init__(self, addr_byte: bytes):
self.addr_byte = addr_byte
self.debug_enabled = False
self.last_poll_frame = 0
def update(self, frame: int, poll_phase: int, e_bsm_rate: int, always_on: bool, vego_ok: bool) -> list[CanData]:
can_sends = []
if not self.debug_enabled:
if always_on or vego_ok: # eagle eye camera will stop working if bsm is switched on under 6m/s
can_sends.append(toyotacan.create_set_bsm_debug_mode(self.addr_byte, True))
self.debug_enabled = True
self.last_poll_frame = frame # give the poll loop a fresh baseline so the stale-poll disable check below can't fire before the first real poll
else:
# no periodic re-assert: re-sending DiagnosticSessionControl(extendedSession) while already in that
# session appears to make the ECU intermittently drop its own detection state (confirmed against a
# real route - two reasserts landed inside an 8s window where the ECU went silent on that side).
# send it once and leave it alone, matching the original, proven-stable behavior.
if not always_on and frame - self.last_poll_frame > 50:
can_sends.append(toyotacan.create_set_bsm_debug_mode(self.addr_byte, False))
self.debug_enabled = False
if frame % e_bsm_rate == poll_phase:
can_sends.append(toyotacan.create_bsm_polling_status(self.addr_byte))
self.last_poll_frame = frame
return can_sends
# Enhanced BSM (@arne182, @rav4kumar)
class EnhancedBsmCarController(EnhancedBsm):
def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP):
super().__init__(CP, CP_SP)
self._left = _BsmSideController(LEFT_BLINDSPOT)
self._right = _BsmSideController(RIGHT_BLINDSPOT)
def update(self, CS: structs.CarState, frame: int, e_bsm_rate: int = 20, always_on: bool = True) -> list[CanData]:
if frame <= 200:
return []
vego_ok = CS.out.vEgo > 6
can_sends = self._left.update(frame, 0, e_bsm_rate, always_on, vego_ok)
can_sends += self._right.update(frame, e_bsm_rate // 2, e_bsm_rate, always_on, vego_ok)
return can_sends
@@ -0,0 +1,199 @@
import unittest
from unittest.mock import patch
from opendbc.car import structs
from opendbc.sunnypilot.car.toyota.auto_brake_hold import AutoBrakeHoldCarController, BRAKE_HOLD_ALLOWED_TIMER, pcs_is_active
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP
GearShifter = structs.CarState.GearShifter
def make_car_params_sp(enabled: bool = True) -> structs.CarParamsSP:
cp_sp = structs.CarParamsSP()
cp_sp.flags = ToyotaFlagsSP.SP_AUTO_BRAKE_HOLD if enabled else 0
return cp_sp
class FakeCarState:
def __init__(self, standstill=True, cruise_enabled=False, cruise_available=True, gas_pressed=False,
gear=GearShifter.drive, brake_pressed=False, pre_collision_2=None):
self.out = structs.CarState()
self.out.standstill = standstill
self.out.cruiseState.enabled = cruise_enabled
self.out.cruiseState.available = cruise_available
self.out.gasPressed = gas_pressed
self.out.gearShifter = gear
self.out.brakePressed = brake_pressed
self.pre_collision_2 = pre_collision_2 if pre_collision_2 is not None else {}
@patch("opendbc.sunnypilot.car.toyota.auto_brake_hold.toyotacan.create_brake_hold_command")
class TestAutoBrakeHoldCarController(unittest.TestCase):
def _make(self):
return AutoBrakeHoldCarController(structs.CarParams(), make_car_params_sp())
def test_enabled_reflects_flag(self, mock_create):
for value in range(256):
with self.subTest(flags=value):
cp_sp = structs.CarParamsSP()
cp_sp.flags = value
ctrl = AutoBrakeHoldCarController(structs.CarParams(), cp_sp)
self.assertEqual(ctrl.enabled, bool(value & ToyotaFlagsSP.SP_AUTO_BRAKE_HOLD))
def test_does_not_engage_before_timer(self, mock_create):
ctrl = self._make()
cs = FakeCarState(brake_pressed=False)
for i in range(BRAKE_HOLD_ALLOWED_TIMER):
ctrl.update(cs, i, None)
self.assertFalse(ctrl.active)
def test_engages_after_timer_once_brake_released(self, mock_create):
ctrl = self._make()
cs = FakeCarState(brake_pressed=False)
for i in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, i, None)
self.assertTrue(ctrl.active)
def test_brake_still_down_from_the_stop_does_not_block_engagement(self, mock_create):
# the driver's foot is normally still on the brake on the very frame standstill is reached -
# that must not count as a "fresh press" release, or the feature could never engage
ctrl = self._make()
# decelerating into the stop with the brake held continuously
cs = FakeCarState(standstill=False, brake_pressed=True)
for i in range(30):
ctrl.update(cs, i, None)
# reaches standstill, foot stays down for a while, then lifts
cs.out.standstill = True
for i in range(30, 50):
ctrl.update(cs, i, None)
self.assertFalse(ctrl.active, "must not engage while the original stopping press is still held")
cs.out.brakePressed = False
for i in range(50, 50 + BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, i, None)
self.assertTrue(ctrl.active, "should engage once the stopping press is released and the timer elapses")
def test_fresh_brake_press_mid_hold_releases_and_stays_released(self, mock_create):
ctrl = self._make()
cs = FakeCarState(brake_pressed=False)
frame = 0
for _ in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, frame, None)
frame += 1
self.assertTrue(ctrl.active)
cs.out.brakePressed = True
ctrl.update(cs, frame, None)
frame += 1
self.assertFalse(ctrl.active, "a fresh press should release immediately")
for _ in range(20):
ctrl.update(cs, frame, None)
frame += 1
self.assertFalse(ctrl.active, "must stay released for the rest of the episode while continuously held")
cs.out.brakePressed = False
for _ in range(20):
ctrl.update(cs, frame, None)
frame += 1
self.assertFalse(ctrl.active, "must stay released for the rest of the episode even after lifting off again")
def test_drive_off_and_restop_rearms(self, mock_create):
ctrl = self._make()
cs = FakeCarState(brake_pressed=False)
frame = 0
for _ in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, frame, None)
frame += 1
cs.out.brakePressed = True
ctrl.update(cs, frame, None)
frame += 1
self.assertFalse(ctrl.active)
# drives off - leaves the standstill episode entirely
cs.out.standstill = False
ctrl.update(cs, frame, None)
frame += 1
# stops again
cs.out.standstill = True
cs.out.brakePressed = False
for _ in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, frame, None)
frame += 1
self.assertTrue(ctrl.active, "should re-arm and engage again at the next stop")
def test_cruise_engaged_blocks_hold(self, mock_create):
ctrl = self._make()
cs = FakeCarState(cruise_enabled=True, brake_pressed=False)
for i in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, i, None)
self.assertFalse(ctrl.active, "must not hold while ACC is engaged - that's the point of the constraint")
def test_gas_pressed_blocks_hold(self, mock_create):
ctrl = self._make()
cs = FakeCarState(gas_pressed=True, brake_pressed=False)
for i in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, i, None)
self.assertFalse(ctrl.active)
def test_park_and_reverse_block_hold(self, mock_create):
for gear in (GearShifter.park, GearShifter.reverse):
with self.subTest(gear=gear):
ctrl = self._make()
cs = FakeCarState(gear=gear, brake_pressed=False)
for i in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, i, None)
self.assertFalse(ctrl.active)
def test_yields_to_live_pcs_without_dropping_active_state(self, mock_create):
ctrl = self._make()
cs = FakeCarState(brake_pressed=False)
frame = 0
for _ in range(BRAKE_HOLD_ALLOWED_TIMER + 1):
ctrl.update(cs, frame, None)
frame += 1
self.assertTrue(ctrl.active)
mock_create.reset_mock()
# a real PCS event shows up on the live signal
cs.pre_collision_2 = {"PCSALM": 1}
# advance to the next even frame the message is actually built on
while frame % 2 != 0:
frame += 1
ctrl.update(cs, frame, None)
override_arg = mock_create.call_args.args[-1]
self.assertTrue(ctrl.active, "internal hold state should not be cleared by a live PCS event")
self.assertFalse(override_arg, "must not override PRE_COLLISION_2 while PCS is genuinely active")
# once PCS goes quiet again, override resumes on our own signal, not stale PCS state
frame += 2
cs.pre_collision_2 = {}
ctrl.update(cs, frame, None)
override_arg = mock_create.call_args.args[-1]
self.assertTrue(override_arg)
def test_message_only_built_every_other_frame(self, mock_create):
ctrl = self._make()
cs = FakeCarState(brake_pressed=False)
for i in range(10):
ctrl.update(cs, i, None)
self.assertEqual(mock_create.call_count, 5)
class TestPcsIsActive(unittest.TestCase):
def test_all_zero_is_not_active(self):
self.assertFalse(pcs_is_active({}))
self.assertFalse(pcs_is_active({"PCSALM": 0, "DSS1GDRV": 0}))
def test_any_trigger_field_is_active(self):
for field in ("PCSALM", "IBTRGR", "PBATRGR", "PREFILL", "AVSTRGR", "PBRTRGR", "PPTRGR"):
with self.subTest(field=field):
self.assertTrue(pcs_is_active({field: 1}))
def test_nonzero_force_signal_is_active(self):
self.assertTrue(pcs_is_active({"DSS1GDRV": -5}))
self.assertFalse(pcs_is_active({"DSS1GDRV": 0}))
if __name__ == "__main__":
unittest.main()
@@ -14,6 +14,9 @@ class ToyotaFlagsSP(IntFlag):
ZSS = 4
STOCK_LONGITUDINAL = 8
STOP_AND_GO_HACK = 16
SP_ENHANCED_BSM = 32
SP_NEED_DEBUG_BSM = 64
SP_AUTO_BRAKE_HOLD = 128
class ToyotaSafetyFlagsSP:
-1
View File
@@ -64,7 +64,6 @@ check-hidden = true
line-length = 160
indent-width = 2
target-version="py311"
exclude = ["**/*.ipynb"]
[tool.ruff.lint]
preview = true
+42
View File
@@ -69,6 +69,8 @@ struct LeadData {
struct SelfdriveStateSP @0x81c2f05a394cf4af {
mads @0 :ModularAssistiveDrivingSystem;
intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
buttonsPressed @2 :UInt16;
buttonsReleaseToggle @3 :UInt16;
enum AudibleAlert {
none @0;
@@ -137,10 +139,16 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
eta @2 :UInt32;
}
struct Chunk {
fileName @0 :Text;
sha256 @1 :Text;
}
struct Artifact {
fileName @0 :Text;
downloadUri @1 :DownloadUri;
downloadProgress @2 :DownloadProgress;
chunks @3 :List(Chunk);
}
struct Model {
@@ -155,6 +163,7 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
policy @3;
offPolicy @4;
onPolicy @5;
chunked @6;
}
}
@@ -194,6 +203,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 {
aTarget @5 :Float32;
events @6 :List(OnroadEventSP.Event);
e2eAlerts @7 :E2eAlerts;
accelController @8 :AccelController;
struct DynamicExperimentalControl {
state @0 :DynamicExperimentalControlState;
@@ -296,6 +306,35 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 {
greenLightAlert @0 :Bool;
leadDepartAlert @1 :Bool;
}
struct AccelController {
enabled @0 :Bool;
active @1 :Bool;
shadowOnlyDEPRECATED @2 :Bool;
profile @3 :Profile;
state @4 :State;
enum Profile {
eco @0;
normal @1;
sport @2;
}
enum State {
inactive @0;
free @1;
restrict @2;
hold @3;
release @4;
stopHold @5;
}
}
enum AccelerationPersonality {
eco @0;
normal @1;
sport @2;
}
}
struct OnroadEventSP @0xda96579883444c35 {
@@ -342,6 +381,7 @@ struct OnroadEventSP @0xda96579883444c35 {
speedLimitChanged @21;
speedLimitPending @22;
e2eChime @23;
laneChangeRoadEdge @24;
}
}
@@ -448,6 +488,8 @@ struct LiveMapDataSP @0xf416ec09499d9d19 {
struct ModelDataV2SP @0xa1680744031fdb2d {
laneTurnDirection @0 :TurnDirection;
leftLaneChangeEdgeBlock @1 :Bool;
rightLaneChangeEdgeBlock @2 :Bool;
enum TurnDirection {
none @0;
File diff suppressed because it is too large Load Diff
+564 -3
View File
@@ -96,6 +96,7 @@ enum class DownloadStatus_da834d53e62048b9: uint16_t {
};
CAPNP_DECLARE_ENUM(DownloadStatus, da834d53e62048b9);
CAPNP_DECLARE_SCHEMA(a677b25114d64c73);
CAPNP_DECLARE_SCHEMA(8d6e2aaaa9978a41);
CAPNP_DECLARE_SCHEMA(e441ce74a64693d1);
CAPNP_DECLARE_SCHEMA(e7c36e65fea112b1);
CAPNP_DECLARE_SCHEMA(af23faeb2c26a5b2);
@@ -106,6 +107,7 @@ enum class Type_af23faeb2c26a5b2: uint16_t {
POLICY,
OFF_POLICY,
ON_POLICY,
CHUNKED,
};
CAPNP_DECLARE_ENUM(Type, af23faeb2c26a5b2);
CAPNP_DECLARE_SCHEMA(c99c128a7e247b05);
@@ -175,6 +177,31 @@ enum class LongitudinalPlanSource_ad47440556d96ec4: uint16_t {
};
CAPNP_DECLARE_ENUM(LongitudinalPlanSource, ad47440556d96ec4);
CAPNP_DECLARE_SCHEMA(a567bce822ae28fe);
CAPNP_DECLARE_SCHEMA(88dcd6d006f3c4a1);
CAPNP_DECLARE_SCHEMA(8c9f9544b04650a6);
enum class Profile_8c9f9544b04650a6: uint16_t {
ECO,
NORMAL,
SPORT,
};
CAPNP_DECLARE_ENUM(Profile, 8c9f9544b04650a6);
CAPNP_DECLARE_SCHEMA(f3ef31c99115f2a3);
enum class State_f3ef31c99115f2a3: uint16_t {
INACTIVE,
FREE,
RESTRICT,
HOLD,
RELEASE,
STOP_HOLD,
};
CAPNP_DECLARE_ENUM(State, f3ef31c99115f2a3);
CAPNP_DECLARE_SCHEMA(d02d61eb7efff99e);
enum class AccelerationPersonality_d02d61eb7efff99e: uint16_t {
ECO,
NORMAL,
SPORT,
};
CAPNP_DECLARE_ENUM(AccelerationPersonality, d02d61eb7efff99e);
CAPNP_DECLARE_SCHEMA(da96579883444c35);
CAPNP_DECLARE_SCHEMA(f6e831752fcdf793);
CAPNP_DECLARE_SCHEMA(b8007ed8a646b5e6);
@@ -203,6 +230,7 @@ enum class EventName_b8007ed8a646b5e6: uint16_t {
SPEED_LIMIT_CHANGED,
SPEED_LIMIT_PENDING,
E2E_CHIME,
LANE_CHANGE_ROAD_EDGE,
};
CAPNP_DECLARE_ENUM(EventName, b8007ed8a646b5e6);
CAPNP_DECLARE_SCHEMA(80ae746ee2596b11);
@@ -320,7 +348,7 @@ struct SelfdriveStateSP {
struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 0, 2)
CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 1, 2)
#if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE
@@ -337,6 +365,7 @@ struct ModelManagerSP {
typedef ::capnp::schemas::DownloadStatus_da834d53e62048b9 DownloadStatus;
struct DownloadProgress;
struct Chunk;
struct Artifact;
struct Model;
typedef ::capnp::schemas::Runner_c99c128a7e247b05 Runner;
@@ -382,6 +411,21 @@ struct ModelManagerSP::DownloadProgress {
};
};
struct ModelManagerSP::Chunk {
Chunk() = delete;
class Reader;
class Builder;
class Pipeline;
struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(8d6e2aaaa9978a41, 0, 2)
#if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE
};
};
struct ModelManagerSP::Artifact {
Artifact() = delete;
@@ -390,7 +434,7 @@ struct ModelManagerSP::Artifact {
class Pipeline;
struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(e441ce74a64693d1, 0, 3)
CAPNP_DECLARE_STRUCT_HEADER(e441ce74a64693d1, 0, 4)
#if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE
@@ -456,9 +500,12 @@ struct LongitudinalPlanSP {
typedef ::capnp::schemas::LongitudinalPlanSource_ad47440556d96ec4 LongitudinalPlanSource;
struct E2eAlerts;
struct AccelController;
typedef ::capnp::schemas::AccelerationPersonality_d02d61eb7efff99e AccelerationPersonality;
struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(f35cc4560bbf6ec2, 2, 5)
CAPNP_DECLARE_STRUCT_HEADER(f35cc4560bbf6ec2, 2, 6)
#if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE
@@ -599,6 +646,25 @@ struct LongitudinalPlanSP::E2eAlerts {
};
};
struct LongitudinalPlanSP::AccelController {
AccelController() = delete;
class Reader;
class Builder;
class Pipeline;
typedef ::capnp::schemas::Profile_8c9f9544b04650a6 Profile;
typedef ::capnp::schemas::State_f3ef31c99115f2a3 State;
struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(88dcd6d006f3c4a1, 1, 0)
#if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE
};
};
struct OnroadEventSP {
OnroadEventSP() = delete;
@@ -1327,6 +1393,10 @@ public:
inline bool hasIntelligentCruiseButtonManagement() const;
inline ::cereal::IntelligentCruiseButtonManagement::Reader getIntelligentCruiseButtonManagement() const;
inline ::uint16_t getButtonsPressed() const;
inline ::uint16_t getButtonsReleaseToggle() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
@@ -1369,6 +1439,12 @@ public:
inline void adoptIntelligentCruiseButtonManagement(::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement>&& value);
inline ::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement> disownIntelligentCruiseButtonManagement();
inline ::uint16_t getButtonsPressed();
inline void setButtonsPressed( ::uint16_t value);
inline ::uint16_t getButtonsReleaseToggle();
inline void setButtonsReleaseToggle( ::uint16_t value);
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
@@ -1677,6 +1753,97 @@ private:
};
#endif // !CAPNP_LITE
class ModelManagerSP::Chunk::Reader {
public:
typedef Chunk Reads;
Reader() = default;
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
inline ::capnp::MessageSize totalSize() const {
return _reader.totalSize().asPublic();
}
#if !CAPNP_LITE
inline ::kj::StringTree toString() const {
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
}
#endif // !CAPNP_LITE
inline bool hasFileName() const;
inline ::capnp::Text::Reader getFileName() const;
inline bool hasSha256() const;
inline ::capnp::Text::Reader getSha256() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
};
class ModelManagerSP::Chunk::Builder {
public:
typedef Chunk Builds;
Builder() = delete; // Deleted to discourage incorrect usage.
// You can explicitly initialize to nullptr instead.
inline Builder(decltype(nullptr)) {}
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
inline operator Reader() const { return Reader(_builder.asReader()); }
inline Reader asReader() const { return *this; }
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
#if !CAPNP_LITE
inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE
inline bool hasFileName();
inline ::capnp::Text::Builder getFileName();
inline void setFileName( ::capnp::Text::Reader value);
inline ::capnp::Text::Builder initFileName(unsigned int size);
inline void adoptFileName(::capnp::Orphan< ::capnp::Text>&& value);
inline ::capnp::Orphan< ::capnp::Text> disownFileName();
inline bool hasSha256();
inline ::capnp::Text::Builder getSha256();
inline void setSha256( ::capnp::Text::Reader value);
inline ::capnp::Text::Builder initSha256(unsigned int size);
inline void adoptSha256(::capnp::Orphan< ::capnp::Text>&& value);
inline ::capnp::Orphan< ::capnp::Text> disownSha256();
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
};
#if !CAPNP_LITE
class ModelManagerSP::Chunk::Pipeline {
public:
typedef Chunk Pipelines;
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
: _typeless(kj::mv(typeless)) {}
private:
::capnp::AnyPointer::Pipeline _typeless;
friend class ::capnp::PipelineHook;
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
#endif // !CAPNP_LITE
class ModelManagerSP::Artifact::Reader {
public:
typedef Artifact Reads;
@@ -1703,6 +1870,9 @@ public:
inline bool hasDownloadProgress() const;
inline ::cereal::ModelManagerSP::DownloadProgress::Reader getDownloadProgress() const;
inline bool hasChunks() const;
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader getChunks() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
@@ -1752,6 +1922,13 @@ public:
inline void adoptDownloadProgress(::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress>&& value);
inline ::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress> disownDownloadProgress();
inline bool hasChunks();
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder getChunks();
inline void setChunks( ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader value);
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder initChunks(unsigned int size);
inline void adoptChunks(::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>&& value);
inline ::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>> disownChunks();
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
@@ -2168,6 +2345,9 @@ public:
inline bool hasE2eAlerts() const;
inline ::cereal::LongitudinalPlanSP::E2eAlerts::Reader getE2eAlerts() const;
inline bool hasAccelController() const;
inline ::cereal::LongitudinalPlanSP::AccelController::Reader getAccelController() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
@@ -2240,6 +2420,13 @@ public:
inline void adoptE2eAlerts(::capnp::Orphan< ::cereal::LongitudinalPlanSP::E2eAlerts>&& value);
inline ::capnp::Orphan< ::cereal::LongitudinalPlanSP::E2eAlerts> disownE2eAlerts();
inline bool hasAccelController();
inline ::cereal::LongitudinalPlanSP::AccelController::Builder getAccelController();
inline void setAccelController( ::cereal::LongitudinalPlanSP::AccelController::Reader value);
inline ::cereal::LongitudinalPlanSP::AccelController::Builder initAccelController();
inline void adoptAccelController(::capnp::Orphan< ::cereal::LongitudinalPlanSP::AccelController>&& value);
inline ::capnp::Orphan< ::cereal::LongitudinalPlanSP::AccelController> disownAccelController();
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
@@ -2262,6 +2449,7 @@ public:
inline ::cereal::LongitudinalPlanSP::SmartCruiseControl::Pipeline getSmartCruiseControl();
inline ::cereal::LongitudinalPlanSP::SpeedLimit::Pipeline getSpeedLimit();
inline ::cereal::LongitudinalPlanSP::E2eAlerts::Pipeline getE2eAlerts();
inline ::cereal::LongitudinalPlanSP::AccelController::Pipeline getAccelController();
private:
::capnp::AnyPointer::Pipeline _typeless;
friend class ::capnp::PipelineHook;
@@ -3037,6 +3225,102 @@ private:
};
#endif // !CAPNP_LITE
class LongitudinalPlanSP::AccelController::Reader {
public:
typedef AccelController Reads;
Reader() = default;
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
inline ::capnp::MessageSize totalSize() const {
return _reader.totalSize().asPublic();
}
#if !CAPNP_LITE
inline ::kj::StringTree toString() const {
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
}
#endif // !CAPNP_LITE
inline bool getEnabled() const;
inline bool getActive() const;
inline bool getShadowOnlyDEPRECATED() const;
inline ::cereal::LongitudinalPlanSP::AccelController::Profile getProfile() const;
inline ::cereal::LongitudinalPlanSP::AccelController::State getState() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
};
class LongitudinalPlanSP::AccelController::Builder {
public:
typedef AccelController Builds;
Builder() = delete; // Deleted to discourage incorrect usage.
// You can explicitly initialize to nullptr instead.
inline Builder(decltype(nullptr)) {}
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
inline operator Reader() const { return Reader(_builder.asReader()); }
inline Reader asReader() const { return *this; }
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
#if !CAPNP_LITE
inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE
inline bool getEnabled();
inline void setEnabled(bool value);
inline bool getActive();
inline void setActive(bool value);
inline bool getShadowOnlyDEPRECATED();
inline void setShadowOnlyDEPRECATED(bool value);
inline ::cereal::LongitudinalPlanSP::AccelController::Profile getProfile();
inline void setProfile( ::cereal::LongitudinalPlanSP::AccelController::Profile value);
inline ::cereal::LongitudinalPlanSP::AccelController::State getState();
inline void setState( ::cereal::LongitudinalPlanSP::AccelController::State value);
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
};
#if !CAPNP_LITE
class LongitudinalPlanSP::AccelController::Pipeline {
public:
typedef AccelController Pipelines;
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
: _typeless(kj::mv(typeless)) {}
private:
::capnp::AnyPointer::Pipeline _typeless;
friend class ::capnp::PipelineHook;
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
#endif // !CAPNP_LITE
class OnroadEventSP::Reader {
public:
typedef OnroadEventSP Reads;
@@ -4428,6 +4712,10 @@ public:
inline ::cereal::ModelDataV2SP::TurnDirection getLaneTurnDirection() const;
inline bool getLeftLaneChangeEdgeBlock() const;
inline bool getRightLaneChangeEdgeBlock() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
@@ -4459,6 +4747,12 @@ public:
inline ::cereal::ModelDataV2SP::TurnDirection getLaneTurnDirection();
inline void setLaneTurnDirection( ::cereal::ModelDataV2SP::TurnDirection value);
inline bool getLeftLaneChangeEdgeBlock();
inline void setLeftLaneChangeEdgeBlock(bool value);
inline bool getRightLaneChangeEdgeBlock();
inline void setRightLaneChangeEdgeBlock(bool value);
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
@@ -5597,6 +5891,34 @@ inline ::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement> SelfdriveSt
::capnp::bounded<1>() * ::capnp::POINTERS));
}
inline ::uint16_t SelfdriveStateSP::Reader::getButtonsPressed() const {
return _reader.getDataField< ::uint16_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
}
inline ::uint16_t SelfdriveStateSP::Builder::getButtonsPressed() {
return _builder.getDataField< ::uint16_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
}
inline void SelfdriveStateSP::Builder::setButtonsPressed( ::uint16_t value) {
_builder.setDataField< ::uint16_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
}
inline ::uint16_t SelfdriveStateSP::Reader::getButtonsReleaseToggle() const {
return _reader.getDataField< ::uint16_t>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline ::uint16_t SelfdriveStateSP::Builder::getButtonsReleaseToggle() {
return _builder.getDataField< ::uint16_t>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline void SelfdriveStateSP::Builder::setButtonsReleaseToggle( ::uint16_t value) {
_builder.setDataField< ::uint16_t>(
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
}
inline bool ModelManagerSP::Reader::hasActiveBundle() const {
return !_reader.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
@@ -5819,6 +6141,74 @@ inline void ModelManagerSP::DownloadProgress::Builder::setEta( ::uint32_t value)
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
}
inline bool ModelManagerSP::Chunk::Reader::hasFileName() const {
return !_reader.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
}
inline bool ModelManagerSP::Chunk::Builder::hasFileName() {
return !_builder.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
}
inline ::capnp::Text::Reader ModelManagerSP::Chunk::Reader::getFileName() const {
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS));
}
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::getFileName() {
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS));
}
inline void ModelManagerSP::Chunk::Builder::setFileName( ::capnp::Text::Reader value) {
::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS), value);
}
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::initFileName(unsigned int size) {
return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS), size);
}
inline void ModelManagerSP::Chunk::Builder::adoptFileName(
::capnp::Orphan< ::capnp::Text>&& value) {
::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
}
inline ::capnp::Orphan< ::capnp::Text> ModelManagerSP::Chunk::Builder::disownFileName() {
return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS));
}
inline bool ModelManagerSP::Chunk::Reader::hasSha256() const {
return !_reader.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
}
inline bool ModelManagerSP::Chunk::Builder::hasSha256() {
return !_builder.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
}
inline ::capnp::Text::Reader ModelManagerSP::Chunk::Reader::getSha256() const {
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS));
}
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::getSha256() {
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS));
}
inline void ModelManagerSP::Chunk::Builder::setSha256( ::capnp::Text::Reader value) {
::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS), value);
}
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::initSha256(unsigned int size) {
return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS), size);
}
inline void ModelManagerSP::Chunk::Builder::adoptSha256(
::capnp::Orphan< ::capnp::Text>&& value) {
::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value));
}
inline ::capnp::Orphan< ::capnp::Text> ModelManagerSP::Chunk::Builder::disownSha256() {
return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField(
::capnp::bounded<1>() * ::capnp::POINTERS));
}
inline bool ModelManagerSP::Artifact::Reader::hasFileName() const {
return !_reader.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
@@ -5931,6 +6321,40 @@ inline ::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress> ModelManager
::capnp::bounded<2>() * ::capnp::POINTERS));
}
inline bool ModelManagerSP::Artifact::Reader::hasChunks() const {
return !_reader.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS).isNull();
}
inline bool ModelManagerSP::Artifact::Builder::hasChunks() {
return !_builder.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS).isNull();
}
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader ModelManagerSP::Artifact::Reader::getChunks() const {
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS));
}
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder ModelManagerSP::Artifact::Builder::getChunks() {
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS));
}
inline void ModelManagerSP::Artifact::Builder::setChunks( ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader value) {
::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS), value);
}
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder ModelManagerSP::Artifact::Builder::initChunks(unsigned int size) {
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS), size);
}
inline void ModelManagerSP::Artifact::Builder::adoptChunks(
::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>&& value) {
::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value));
}
inline ::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>> ModelManagerSP::Artifact::Builder::disownChunks() {
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField(
::capnp::bounded<3>() * ::capnp::POINTERS));
}
inline ::cereal::ModelManagerSP::Model::Type ModelManagerSP::Model::Reader::getType() const {
return _reader.getDataField< ::cereal::ModelManagerSP::Model::Type>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
@@ -6611,6 +7035,45 @@ inline ::capnp::Orphan< ::cereal::LongitudinalPlanSP::E2eAlerts> LongitudinalPla
::capnp::bounded<4>() * ::capnp::POINTERS));
}
inline bool LongitudinalPlanSP::Reader::hasAccelController() const {
return !_reader.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS).isNull();
}
inline bool LongitudinalPlanSP::Builder::hasAccelController() {
return !_builder.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS).isNull();
}
inline ::cereal::LongitudinalPlanSP::AccelController::Reader LongitudinalPlanSP::Reader::getAccelController() const {
return ::capnp::_::PointerHelpers< ::cereal::LongitudinalPlanSP::AccelController>::get(_reader.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS));
}
inline ::cereal::LongitudinalPlanSP::AccelController::Builder LongitudinalPlanSP::Builder::getAccelController() {
return ::capnp::_::PointerHelpers< ::cereal::LongitudinalPlanSP::AccelController>::get(_builder.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS));
}
#if !CAPNP_LITE
inline ::cereal::LongitudinalPlanSP::AccelController::Pipeline LongitudinalPlanSP::Pipeline::getAccelController() {
return ::cereal::LongitudinalPlanSP::AccelController::Pipeline(_typeless.getPointerField(5));
}
#endif // !CAPNP_LITE
inline void LongitudinalPlanSP::Builder::setAccelController( ::cereal::LongitudinalPlanSP::AccelController::Reader value) {
::capnp::_::PointerHelpers< ::cereal::LongitudinalPlanSP::AccelController>::set(_builder.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS), value);
}
inline ::cereal::LongitudinalPlanSP::AccelController::Builder LongitudinalPlanSP::Builder::initAccelController() {
return ::capnp::_::PointerHelpers< ::cereal::LongitudinalPlanSP::AccelController>::init(_builder.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS));
}
inline void LongitudinalPlanSP::Builder::adoptAccelController(
::capnp::Orphan< ::cereal::LongitudinalPlanSP::AccelController>&& value) {
::capnp::_::PointerHelpers< ::cereal::LongitudinalPlanSP::AccelController>::adopt(_builder.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value));
}
inline ::capnp::Orphan< ::cereal::LongitudinalPlanSP::AccelController> LongitudinalPlanSP::Builder::disownAccelController() {
return ::capnp::_::PointerHelpers< ::cereal::LongitudinalPlanSP::AccelController>::disown(_builder.getPointerField(
::capnp::bounded<5>() * ::capnp::POINTERS));
}
inline ::cereal::LongitudinalPlanSP::DynamicExperimentalControl::DynamicExperimentalControlState LongitudinalPlanSP::DynamicExperimentalControl::Reader::getState() const {
return _reader.getDataField< ::cereal::LongitudinalPlanSP::DynamicExperimentalControl::DynamicExperimentalControlState>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
@@ -7201,6 +7664,76 @@ inline void LongitudinalPlanSP::E2eAlerts::Builder::setLeadDepartAlert(bool valu
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
}
inline bool LongitudinalPlanSP::AccelController::Reader::getEnabled() const {
return _reader.getDataField<bool>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
}
inline bool LongitudinalPlanSP::AccelController::Builder::getEnabled() {
return _builder.getDataField<bool>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
}
inline void LongitudinalPlanSP::AccelController::Builder::setEnabled(bool value) {
_builder.setDataField<bool>(
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
}
inline bool LongitudinalPlanSP::AccelController::Reader::getActive() const {
return _reader.getDataField<bool>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline bool LongitudinalPlanSP::AccelController::Builder::getActive() {
return _builder.getDataField<bool>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline void LongitudinalPlanSP::AccelController::Builder::setActive(bool value) {
_builder.setDataField<bool>(
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
}
inline bool LongitudinalPlanSP::AccelController::Reader::getShadowOnlyDEPRECATED() const {
return _reader.getDataField<bool>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline bool LongitudinalPlanSP::AccelController::Builder::getShadowOnlyDEPRECATED() {
return _builder.getDataField<bool>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline void LongitudinalPlanSP::AccelController::Builder::setShadowOnlyDEPRECATED(bool value) {
_builder.setDataField<bool>(
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
}
inline ::cereal::LongitudinalPlanSP::AccelController::Profile LongitudinalPlanSP::AccelController::Reader::getProfile() const {
return _reader.getDataField< ::cereal::LongitudinalPlanSP::AccelController::Profile>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline ::cereal::LongitudinalPlanSP::AccelController::Profile LongitudinalPlanSP::AccelController::Builder::getProfile() {
return _builder.getDataField< ::cereal::LongitudinalPlanSP::AccelController::Profile>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline void LongitudinalPlanSP::AccelController::Builder::setProfile( ::cereal::LongitudinalPlanSP::AccelController::Profile value) {
_builder.setDataField< ::cereal::LongitudinalPlanSP::AccelController::Profile>(
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
}
inline ::cereal::LongitudinalPlanSP::AccelController::State LongitudinalPlanSP::AccelController::Reader::getState() const {
return _reader.getDataField< ::cereal::LongitudinalPlanSP::AccelController::State>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline ::cereal::LongitudinalPlanSP::AccelController::State LongitudinalPlanSP::AccelController::Builder::getState() {
return _builder.getDataField< ::cereal::LongitudinalPlanSP::AccelController::State>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline void LongitudinalPlanSP::AccelController::Builder::setState( ::cereal::LongitudinalPlanSP::AccelController::State value) {
_builder.setDataField< ::cereal::LongitudinalPlanSP::AccelController::State>(
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
}
inline bool OnroadEventSP::Reader::hasEvents() const {
return !_reader.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
@@ -8653,6 +9186,34 @@ inline void ModelDataV2SP::Builder::setLaneTurnDirection( ::cereal::ModelDataV2S
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
}
inline bool ModelDataV2SP::Reader::getLeftLaneChangeEdgeBlock() const {
return _reader.getDataField<bool>(
::capnp::bounded<16>() * ::capnp::ELEMENTS);
}
inline bool ModelDataV2SP::Builder::getLeftLaneChangeEdgeBlock() {
return _builder.getDataField<bool>(
::capnp::bounded<16>() * ::capnp::ELEMENTS);
}
inline void ModelDataV2SP::Builder::setLeftLaneChangeEdgeBlock(bool value) {
_builder.setDataField<bool>(
::capnp::bounded<16>() * ::capnp::ELEMENTS, value);
}
inline bool ModelDataV2SP::Reader::getRightLaneChangeEdgeBlock() const {
return _reader.getDataField<bool>(
::capnp::bounded<17>() * ::capnp::ELEMENTS);
}
inline bool ModelDataV2SP::Builder::getRightLaneChangeEdgeBlock() {
return _builder.getDataField<bool>(
::capnp::bounded<17>() * ::capnp::ELEMENTS);
}
inline void ModelDataV2SP::Builder::setRightLaneChangeEdgeBlock(bool value) {
_builder.setDataField<bool>(
::capnp::bounded<17>() * ::capnp::ELEMENTS, value);
}
} // namespace
CAPNP_END_HEADER
+13
View File
@@ -179,12 +179,20 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
{"RoadEdgeLaneChangeEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
{"RocketFuel", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
// toyota specific params
{"ToyotaAutoHold", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaEnhancedBsm", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaTSS2Long", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaDriveMode", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaPriusTss2Pid", {PERSISTENT | BACKUP, BOOL, "0"}},
// MADS params
{"Mads", {PERSISTENT | BACKUP, BOOL, "1"}},
{"MadsMainCruiseAllowed", {PERSISTENT | BACKUP, BOOL, "1"}},
@@ -222,12 +230,17 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TeslaMadsScreenButton", {PERSISTENT | BACKUP, INT, "0"}},
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
{"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
// Accel Controller profiles (Eco / Normal / Sport)
{"AccelPersonalityEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
{"AccelPersonality", {PERSISTENT | BACKUP, INT, "1"}},
// sunnypilot model params
{"CameraOffset", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
{"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
Binary file not shown.
+4
View File
@@ -112,12 +112,16 @@ class TestParams:
def test_params_default_value(self):
self.params.remove("LanguageSetting")
self.params.remove("LongitudinalPersonality")
self.params.remove("AccelPersonalityEnabled")
self.params.remove("AccelPersonality")
self.params.remove("LiveParametersV2")
assert self.params.get("LanguageSetting") is None
assert self.params.get("LanguageSetting", return_default=False) is None
assert isinstance(self.params.get("LanguageSetting", return_default=True), str)
assert isinstance(self.params.get("LongitudinalPersonality", return_default=True), int)
assert self.params.get("AccelPersonalityEnabled", return_default=True) is False
assert self.params.get("AccelPersonality", return_default=True) == 1
assert self.params.get("LiveParametersV2") is None
assert self.params.get("LiveParametersV2", return_default=True) is None
-2
View File
@@ -28,8 +28,6 @@ SP_BRANCH_MIGRATIONS = {
("tizi", "release3-staging"): "release-tizi-staging",
("mici", "release3"): "release-mici",
("mici", "release3-staging"): "release-mici-staging",
("tici", "hkg-angle-steering-2025"): "hkg-angle-steering-2025-tici",
("tici", "hkg-angle-steering-2025-prebuilt"): "hkg-angle-steering-2025-tici-prebuilt"
}
BUILD_METADATA_FILENAME = "build.json"
+7 -1
View File
@@ -11,7 +11,7 @@ from opendbc.car.structs import car
from openpilot.common.params import Params
from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper
from openpilot.common.swaglog import cloudlog, ForwardingHandler
from opendbc.safety import ALTERNATIVE_EXPERIENCE
from opendbc.car import DT_CTRL, structs
from opendbc.car.can_definitions import CanData, CanRecvCallable, CanSendCallable
from opendbc.car.carlog import carlog
@@ -122,7 +122,13 @@ class Car:
self.CI, self.CP, self.CP_SP = CI, CI.CP, CI.CP_SP
self.RI = RI
# set alternative experiences from parameters
sp_toyota_auto_brake_hold = self.params.get_bool("ToyotaAutoHold")
self.CP.alternativeExperience = 0
if sp_toyota_auto_brake_hold:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.ALLOW_AEB
# mads
set_alternative_experience(self.CP, self.CP_SP, self.params)
set_car_specific_params(self.CP, self.CP_SP, self.params)
@@ -33,7 +33,7 @@ class DesireHelper:
def get_lane_change_direction(CS):
return LaneChangeDirection.left if CS.leftBlinker else LaneChangeDirection.right
def update(self, carstate, lateral_active, lane_change_prob):
def update(self, carstate, lateral_active, lane_change_prob, left_edge_detected=False, right_edge_detected=False):
self.alc.update_params()
self.lane_turn_controller.update_params()
v_ego = carstate.vEgo
@@ -64,8 +64,8 @@ class DesireHelper:
((carstate.steeringTorque > 0 and self.lane_change_direction == LaneChangeDirection.left) or
(carstate.steeringTorque < 0 and self.lane_change_direction == LaneChangeDirection.right))
blindspot_detected = ((carstate.leftBlindspot and self.lane_change_direction == LaneChangeDirection.left) or
(carstate.rightBlindspot and self.lane_change_direction == LaneChangeDirection.right))
blindspot_detected = (((carstate.leftBlindspot or left_edge_detected) and self.lane_change_direction == LaneChangeDirection.left) or
((carstate.rightBlindspot or right_edge_detected) and self.lane_change_direction == LaneChangeDirection.right))
self.alc.update_lane_change(blindspot_detected, carstate.brakePressed)
@@ -4,6 +4,7 @@ from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N
from openpilot.common.pid import PIDController
from openpilot.selfdrive.modeld.constants import ModelConstants
from openpilot.sunnypilot.selfdrive.controls.lib.longcontrol import LongControlSP
CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N]
@@ -39,7 +40,7 @@ def long_control_state_trans(CP_SP, active, long_control_state,
return long_control_state
class LongControl:
class LongControl(LongControlSP):
def __init__(self, CP, CP_SP):
self.CP = CP
self.CP_SP = CP_SP
@@ -66,7 +67,7 @@ class LongControl:
elif self.long_control_state == LongCtrlState.stopping:
output_accel = self.last_output_accel
if output_accel > self.CP.stopAccel:
if output_accel > self.CP.stopAccel and not LongControlSP.should_hold_stopping(self, CS, a_target):
output_accel = min(output_accel, 0.0)
# TODO: can we just go straight to stopAccel?
output_accel -= 1.0 * DT_CTRL # m/s^2/s while trying to stop
@@ -0,0 +1,524 @@
{
"acados_include_path": "/usr/local/venv/lib/python3.12/site-packages/acados/install/include",
"acados_lib_path": "/usr/local/venv/lib/python3.12/site-packages/acados/install/lib",
"code_export_directory": "/data/openpilot/openpilot/selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code",
"constraints": {
"C": [],
"C_e": [],
"D": [],
"constr_type": "BGH",
"constr_type_e": "BGH",
"idxbu": [],
"idxbx": [],
"idxbx_0": [
0,
1,
2
],
"idxbx_e": [],
"idxbxe_0": [
0,
1,
2
],
"idxsbu": [],
"idxsbx": [],
"idxsbx_e": [],
"idxsg": [],
"idxsg_e": [],
"idxsh": [
0,
1,
2,
3
],
"idxsh_e": [],
"idxsphi": [],
"idxsphi_e": [],
"lbu": [],
"lbx": [],
"lbx_0": [
0.0,
0.0,
0.0
],
"lbx_e": [],
"lg": [],
"lg_e": [],
"lh": [
0.0,
0.0,
0.0,
0.0
],
"lh_e": [],
"lphi": [],
"lphi_e": [],
"lsbu": [],
"lsbx": [],
"lsbx_e": [],
"lsg": [],
"lsg_e": [],
"lsh": [
0.0,
0.0,
0.0,
0.0
],
"lsh_e": [],
"lsphi": [],
"lsphi_e": [],
"ubu": [],
"ubx": [],
"ubx_0": [
0.0,
0.0,
0.0
],
"ubx_e": [],
"ug": [],
"ug_e": [],
"uh": [
10000.0,
10000.0,
10000.0,
10000.0
],
"uh_e": [],
"uphi": [],
"uphi_e": [],
"usbu": [],
"usbx": [],
"usbx_e": [],
"usg": [],
"usg_e": [],
"ush": [
0.0,
0.0,
0.0,
0.0
],
"ush_e": [],
"usphi": [],
"usphi_e": []
},
"cost": {
"Vu": [],
"Vu_0": [],
"Vx": [],
"Vx_0": [],
"Vx_e": [],
"Vz": [],
"Vz_0": [],
"W": [
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
]
],
"W_0": [
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
]
],
"W_e": [
[
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0
],
[
0.0,
0.0,
0.0,
0.0,
0.0
]
],
"Zl": [
0.0,
0.0,
0.0,
0.0
],
"Zl_e": [],
"Zu": [
0.0,
0.0,
0.0,
0.0
],
"Zu_e": [],
"cost_ext_fun_type": "casadi",
"cost_ext_fun_type_0": "casadi",
"cost_ext_fun_type_e": "casadi",
"cost_type": "NONLINEAR_LS",
"cost_type_0": "NONLINEAR_LS",
"cost_type_e": "NONLINEAR_LS",
"yref": [
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
"yref_0": [
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
"yref_e": [
0.0,
0.0,
0.0,
0.0,
0.0
],
"zl": [
0.0,
0.0,
0.0,
0.0
],
"zl_e": [],
"zu": [
0.0,
0.0,
0.0,
0.0
],
"zu_e": []
},
"cython_include_dirs": [
"/usr/local/venv/lib/python3.12/site-packages/numpy/_core/include",
"/usr/include/python3.12"
],
"dims": {
"N": 12,
"nbu": 0,
"nbx": 0,
"nbx_0": 3,
"nbx_e": 0,
"nbxe_0": 3,
"ng": 0,
"ng_e": 0,
"nh": 4,
"nh_e": 0,
"np": 6,
"nphi": 0,
"nphi_e": 0,
"nr": 0,
"nr_e": 0,
"ns": 4,
"ns_e": 0,
"nsbu": 0,
"nsbx": 0,
"nsbx_e": 0,
"nsg": 0,
"nsg_e": 0,
"nsh": 4,
"nsh_e": 0,
"nsphi": 0,
"nsphi_e": 0,
"nu": 1,
"nx": 3,
"ny": 6,
"ny_0": 6,
"ny_e": 5,
"nz": 0
},
"json_file": "/data/openpilot/openpilot/selfdrive/controls/lib/longitudinal_mpc_lib/acados_ocp_long.json",
"model": {
"con_h_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegiaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegpcaaaaaaaaaaaaaafaaaaaaabgpfngjgogegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpfngbgihchcaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaacbaaaaaamgfgbgegpfegbgoghgfgchpfggbgdgehpgchegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaachbaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhchbaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaachbaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaa",
"con_h_expr_e": null,
"con_phi_expr": null,
"con_phi_expr_e": null,
"con_r_expr": null,
"con_r_expr_e": null,
"con_r_in_phi": null,
"con_r_in_phi_e": null,
"cost_conl_custom_outer_hess": null,
"cost_conl_custom_outer_hess_0": null,
"cost_conl_custom_outer_hess_e": null,
"cost_expr_ext_cost": null,
"cost_expr_ext_cost_0": null,
"cost_expr_ext_cost_custom_hess": null,
"cost_expr_ext_cost_custom_hess_0": null,
"cost_expr_ext_cost_custom_hess_e": null,
"cost_expr_ext_cost_e": null,
"cost_psi_expr": null,
"cost_psi_expr_0": null,
"cost_psi_expr_e": null,
"cost_r_in_psi_expr": null,
"cost_r_in_psi_expr_0": null,
"cost_r_in_psi_expr_e": null,
"cost_y_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegkaaaaaaaaaaaaaaagaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhcheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaachcaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaachbbaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfgghegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
"cost_y_expr_0": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegkaaaaaaaaaaaaaaagaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhcheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaachcaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaachbbaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfgghegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
"cost_y_expr_e": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegjaaaaaaaaaaaaaaafaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhcheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaachcaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaachbbaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfggh",
"disc_dyn_expr": null,
"dyn_disc_fun": null,
"dyn_disc_fun_jac": null,
"dyn_disc_fun_jac_hess": null,
"dyn_ext_fun_type": "casadi",
"dyn_generic_source": null,
"f_expl_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
"f_impl_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaaihpffghgpgpfegpgehegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaaghpffghgpgpfegpgehegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaabgpffghgpgpfegpgehegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
"gnsf": {
"nontrivial_f_LO": 1,
"purely_linear": 0
},
"name": "long",
"p": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegkaaaaaaaaaaaaaaagaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpfngjgogegpcaaaaaaaaaaaaaafaaaaaaabgpfngbgihegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfgghegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhegpcaaaaaaaaaaaaaacbaaaaaamgfgbgegpfegbgoghgfgchpfggbgdgehpgch",
"u": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegfaaaaaaaaaaaaaaabaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
"x": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpg",
"xdot": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaaihpffghgpgpfegpgehegpcaaaaaaaaaaaaaajaaaaaaaghpffghgpgpfegpgehegpcaaaaaaaaaaaaaajaaaaaaabgpffghgpgpfegpgeh",
"z": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"parameter_values": [
-1.2,
1.2,
0.0,
0.0,
1.45,
0.75
],
"problem_class": "OCP",
"shared_lib_ext": ".so",
"solver_options": {
"Tsim": 0.06944444444444445,
"alpha_min": 0.05,
"alpha_reduction": 0.7,
"collocation_type": "GAUSS_LEGENDRE",
"custom_templates": [],
"custom_update_copy": true,
"custom_update_filename": "",
"custom_update_header_filename": "",
"eps_sufficient_descent": 0.0001,
"exact_hess_constr": 1,
"exact_hess_cost": 1,
"exact_hess_dyn": 1,
"ext_cost_num_hess": 0,
"ext_fun_compile_flags": "-O2",
"full_step_dual": 0,
"globalization": "FIXED_STEP",
"globalization_use_SOC": 0,
"hessian_approx": "GAUSS_NEWTON",
"hpipm_mode": "BALANCE",
"initialize_t_slacks": 0,
"integrator_type": "ERK",
"levenberg_marquardt": 0.0,
"line_search_use_sufficient_descent": 0,
"model_external_shared_lib_dir": null,
"model_external_shared_lib_name": null,
"nlp_solver_ext_qp_res": 0,
"nlp_solver_max_iter": 100,
"nlp_solver_step_length": 1.0,
"nlp_solver_tol_comp": 1e-06,
"nlp_solver_tol_eq": 1e-06,
"nlp_solver_tol_ineq": 1e-06,
"nlp_solver_tol_stat": 1e-06,
"nlp_solver_type": "SQP_RTI",
"print_level": 0,
"qp_solver": "PARTIAL_CONDENSING_HPIPM",
"qp_solver_cond_N": 1,
"qp_solver_cond_ric_alg": 1,
"qp_solver_iter_max": 10,
"qp_solver_ric_alg": 1,
"qp_solver_tol_comp": 0.001,
"qp_solver_tol_eq": 0.001,
"qp_solver_tol_ineq": 0.001,
"qp_solver_tol_stat": 0.001,
"qp_solver_warm_start": 0,
"regularize_method": null,
"shooting_nodes": [
0.0,
0.06944444444444445,
0.2777777777777778,
0.625,
1.1111111111111112,
1.7361111111111114,
2.5,
3.4027777777777786,
4.444444444444445,
5.625,
6.9444444444444455,
8.402777777777777,
10.0
],
"sim_method_jac_reuse": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"sim_method_newton_iter": 3,
"sim_method_newton_tol": 0.0,
"sim_method_num_stages": [
4,
4,
4,
4,
4,
4,
4,
4,
4,
4,
4,
4
],
"sim_method_num_steps": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
],
"tf": 10.0,
"time_steps": [
0.06944444444444445,
0.20833333333333334,
0.3472222222222222,
0.48611111111111116,
0.6250000000000002,
0.7638888888888886,
0.9027777777777786,
1.041666666666666,
1.1805555555555554,
1.3194444444444455,
1.4583333333333313,
1.5972222222222232
]
}
}
@@ -9,6 +9,7 @@ from openpilot.common.swaglog import cloudlog
# WARNING: imports outside of constants will not trigger a rebuild
from openpilot.selfdrive.modeld.constants import index_function
from openpilot.selfdrive.controls.radard import _LEAD_ACCEL_TAU
from openpilot.sunnypilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import LongitudinalMpcSP
if __name__ == '__main__': # generating code
from acados.acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver
@@ -213,8 +214,9 @@ def gen_long_ocp():
return ocp
class LongitudinalMpc:
class LongitudinalMpc(LongitudinalMpcSP):
def __init__(self, dt=DT_MDL):
LongitudinalMpcSP.__init__(self)
self.dt = dt
self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N)
self.reset()
@@ -266,7 +268,8 @@ class LongitudinalMpc:
def set_weights(self, prev_accel_constraint=True, personality=log.LongitudinalPersonality.standard):
jerk_factor = get_jerk_factor(personality)
a_change_cost = A_CHANGE_COST if prev_accel_constraint else 0
cost_weights = [X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, jerk_factor * a_change_cost, jerk_factor * J_EGO_COST]
cost_weights = [X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, jerk_factor * a_change_cost,
LongitudinalMpcSP.scale_jerk_cost(self, jerk_factor * J_EGO_COST)]
constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, DANGER_ZONE_COST]
self.set_cost_weights(cost_weights, constraint_cost_weights)
@@ -326,7 +329,7 @@ class LongitudinalMpc:
# when the leads are no factor.
v_lower = v_ego + (T_IDXS * CRUISE_MIN_ACCEL * 1.05)
# TODO does this make sense when max_a is negative?
v_upper = v_ego + (T_IDXS * CRUISE_MAX_ACCEL * 1.05)
v_upper = v_ego + (T_IDXS * self.cruise_accel_max(CRUISE_MAX_ACCEL) * 1.05)
v_cruise_clipped = np.clip(v_cruise * np.ones(N+1), v_lower, v_upper)
cruise_obstacle = np.cumsum(T_DIFFS * v_cruise_clipped) + get_safe_obstacle_distance(v_cruise_clipped, t_follow)
@@ -340,6 +343,7 @@ class LongitudinalMpc:
self.params[:,0] = ACCEL_MIN
self.params[:,1] = ACCEL_MAX
LongitudinalMpcSP.apply_accel_limits(self)
self.params[:,2] = np.min(x_obstacles, axis=1)
self.params[:,3] = np.copy(self.a_prev)
self.params[:,4] = t_follow
@@ -359,6 +363,7 @@ class LongitudinalMpc:
self.solver.constraints_set(0, "ubx", self.x0)
self.solution_status = self.solver.solve()
LongitudinalMpcSP.save_solution_status(self)
self.solve_time = float(self.solver.get_stats('time_tot')[0])
for i in range(N+1):
@@ -51,7 +51,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
def __init__(self, CP, CP_SP, init_v=0.0, init_a=0.0, dt=DT_MDL):
self.CP = CP
self.mpc = LongitudinalMpc(dt=dt)
LongitudinalPlannerSP.__init__(self, self.CP, CP_SP, self.mpc)
LongitudinalPlannerSP.__init__(self, self.CP, CP_SP, self.mpc, dt=dt)
self.fcw = False
self.dt = dt
self.allow_throttle = True
@@ -110,13 +110,13 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
clipped_accel_coast = max(accel_coast, accel_clip[0])
clipped_accel_coast_interp = np.interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_clip[1], clipped_accel_coast])
accel_clip[1] = min(accel_clip[1], clipped_accel_coast_interp)
# Get new v_cruise and a_desired from Smart Cruise Control and Speed Limit Assist
v_cruise, self.a_desired = LongitudinalPlannerSP.update_targets(self, sm, self.v_desired_filter.x, self.a_desired, v_cruise)
if force_slow_decel:
v_cruise = 0.0
is_e2e, v_cruise = LongitudinalPlannerSP.update_accel_controller(self, sm, v_cruise, prev_accel_constraint, accel_clip[1], reset_state)
self.mpc.set_weights(prev_accel_constraint, personality=sm['selfdriveState'].personality)
self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired)
self.mpc.update(sm['radarState'], v_cruise, personality=sm['selfdriveState'].personality)
@@ -135,13 +135,13 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
self.a_desired = float(np.interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory))
self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0
action_t = self.CP.longitudinalActuatorDelay + DT_MDL
action_t = self.CP.longitudinalActuatorDelay + DT_MDL
output_a_target_mpc, output_should_stop_mpc = get_accel_from_plan(self.v_desired_trajectory, self.a_desired_trajectory, CONTROL_N_T_IDX,
action_t=action_t)
output_a_target_e2e = sm['modelV2'].action.desiredAcceleration
output_should_stop_e2e = sm['modelV2'].action.shouldStop
if self.is_e2e(sm):
if is_e2e:
output_a_target = min(output_a_target_e2e, output_a_target_mpc)
self.output_should_stop = output_should_stop_e2e or output_should_stop_mpc
if output_a_target < output_a_target_mpc:
@@ -149,6 +149,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
else:
output_a_target = output_a_target_mpc
self.output_should_stop = output_should_stop_mpc
self.output_should_stop = LongitudinalPlannerSP.update_should_stop(self, self.output_should_stop)
for idx in range(2):
accel_clip[idx] = np.clip(accel_clip[idx], self.prev_accel_clip[idx] - 0.05, self.prev_accel_clip[idx] + 0.05)
@@ -158,7 +159,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
def publish(self, sm, pm):
plan_send = messaging.new_message('longitudinalPlan')
plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'selfdriveState', 'radarState'])
plan_send.valid = sm.all_checks()
longitudinalPlan = plan_send.longitudinalPlan
longitudinalPlan.modelMonoTime = sm.logMonoTime['modelV2']
+4 -4
View File
@@ -29,19 +29,19 @@ def main():
longitudinal_planner = LongitudinalPlanner(CP, CP_SP)
pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance', 'longitudinalPlanSP'])
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState',
'liveMapDataSP', 'carStateSP', gps_location_service],
poll='carState', ignore_alive=ignore_services, ignore_avg_freq=ignore_services, ignore_valid=ignore_services)
'liveMapDataSP', 'carStateSP', 'selfdriveStateSP', gps_location_service],
poll='modelV2', ignore_alive=ignore_services, ignore_avg_freq=ignore_services, ignore_valid=ignore_services)
while True:
sm.update()
longitudinal_planner.sla.update_car_state(sm['carState'])
longitudinal_planner.sla.update_buttons(sm['selfdriveStateSP'].buttonsReleaseToggle)
if sm.updated['modelV2']:
longitudinal_planner.update(sm)
longitudinal_planner.publish(sm, pm)
ldw.update(sm.frame, sm['modelV2'], sm['carState'], sm['carControl'])
msg = messaging.new_message('driverAssistance')
msg.valid = sm.all_checks(['carState', 'carControl', 'modelV2', 'liveParameters'])
msg.valid = sm.all_checks()
msg.driverAssistance.leftLaneDeparture = ldw.left
msg.driverAssistance.rightLaneDeparture = ldw.right
pm.send('driverAssistance', msg)
Binary file not shown.
+13 -1
View File
@@ -30,6 +30,7 @@ from openpilot.sunnypilot import get_sanitize_int_param
from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP
from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper
from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
REPLAY = "REPLAY" in os.environ
@@ -177,6 +178,7 @@ class SelfdriveD(CruiseHelper):
self.car_events_sp = CarSpecificEventsSP(self.CP, self.CP_SP)
CruiseHelper.__init__(self, self.CP)
self.button_state_tracker = ButtonStateTracker()
def update_events(self, CS):
"""Compute onroadEvents from carState"""
@@ -325,9 +327,16 @@ class SelfdriveD(CruiseHelper):
# Handle lane change
if self.sm['modelV2'].meta.laneChangeState == LaneChangeState.preLaneChange:
direction = self.sm['modelV2'].meta.laneChangeDirection
mdv2sp = self.sm['modelDataV2SP']
if (CS.leftBlindspot and direction == LaneChangeDirection.left) or \
(CS.rightBlindspot and direction == LaneChangeDirection.right):
(CS.rightBlindspot and direction == LaneChangeDirection.right):
self.events.add(EventName.laneChangeBlocked)
elif (mdv2sp.leftLaneChangeEdgeBlock and direction == LaneChangeDirection.left) or \
(mdv2sp.rightLaneChangeEdgeBlock and direction == LaneChangeDirection.right):
self.events_sp.add(custom.OnroadEventSP.EventName.laneChangeRoadEdge)
else:
if direction == LaneChangeDirection.left:
self.events.add(EventName.preLaneChangeLeft)
@@ -597,6 +606,8 @@ class SelfdriveD(CruiseHelper):
icbm.sendButton = self.icbm.cruise_button
icbm.vTarget = self.icbm.v_target
self.button_state_tracker.publish(ss_sp)
self.pm.send('selfdriveStateSP', ss_sp_msg)
# onroadEventsSP - logged every second or on change
@@ -616,6 +627,7 @@ class SelfdriveD(CruiseHelper):
self.mads.update(CS)
self.update_alerts(CS)
self.button_state_tracker.update(CS)
self.publish_selfdriveState(CS)
self.CS_prev = CS
@@ -11,6 +11,14 @@ from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPl
from openpilot.selfdrive.controls.radard import _LEAD_ACCEL_TAU
class PlannerSM(dict):
def __init__(self, radar_frame: int, services: dict):
super().__init__(services)
self.logMonoTime = {"radarState": radar_frame}
self.valid = {"radarState": True}
self.alive = {"radarState": True}
class Plant:
messaging_initialized = False
@@ -132,7 +140,7 @@ class Plant:
car_control.carControl.orientationNED = [0., float(pitch), 0.]
# ******** get controlsState messages for plotting ***
sm = {'radarState': radar.radarState,
sm = PlannerSM(self.rk.frame, {'radarState': radar.radarState,
'carState': car_state.carState,
'carControl': car_control.carControl,
'controlsState': control.controlsState,
@@ -141,7 +149,7 @@ class Plant:
'modelV2': model.modelV2,
'carStateSP': car_state_sp.carStateSP,
'liveMapDataSP': live_map_data_sp.liveMapDataSP,
'gpsLocation': gps_data.gpsLocation}
'gpsLocation': gps_data.gpsLocation})
self.planner.update(sm)
self.acceleration = self.planner.output_a_target
if self.planner.output_should_stop:
@@ -27,6 +27,12 @@ DESCRIPTIONS = {
"In relaxed mode sunnypilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with " +
"your steering wheel distance button."
),
"AccelPersonalityEnabled": tr_noop(
"Begin slowing early and smoothly behind lead vehicles. Stock longitudinal control retains braking and stopping authority."
),
"AccelPersonality": tr_noop(
"Eco slows earliest and recovers gently, Normal balances comfort and response, and Sport reacts and recovers more quickly."
),
"IsLdwEnabled": tr_noop(
"Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line " +
"without a turn signal activated while driving over 31 mph (50 km/h)."
@@ -106,6 +112,24 @@ class TogglesLayout(Widget):
icon="speed_limit.png"
)
self._accel_personality_enabled = toggle_item(
lambda: tr("Enable Accel Controller"),
lambda: tr(DESCRIPTIONS["AccelPersonalityEnabled"]),
self._params.get_bool("AccelPersonalityEnabled"),
callback=self._set_accel_personality_enabled,
icon="speed_limit.png",
)
self._accel_personality_setting = multiple_button_item(
lambda: tr("Acceleration Profile"),
lambda: tr(DESCRIPTIONS["AccelPersonality"]),
buttons=[lambda: tr("Eco"), lambda: tr("Normal"), lambda: tr("Sport")],
button_width=300,
callback=self._set_accel_personality,
selected_index=self._params.get("AccelPersonality", return_default=True),
icon="speed_limit.png"
)
self._toggles = {}
self._locked_toggles = set()
for param, (title, desc, icon, needs_restart) in self._toggle_defs.items():
@@ -135,9 +159,11 @@ class TogglesLayout(Widget):
self._toggles[param] = toggle
# insert longitudinal personality after NDOG toggle
# insert longitudinal personality and Accel Controller settings after NDOG toggle
if param == "DisengageOnAccelerator":
self._toggles["LongitudinalPersonality"] = self._long_personality_setting
self._toggles["AccelPersonalityEnabled"] = self._accel_personality_enabled
self._toggles["AccelPersonality"] = self._accel_personality_setting
self._update_experimental_mode_icon()
self._scroller = Scroller(list(self._toggles.values()), line_separator=True, spacing=0)
@@ -158,6 +184,7 @@ class TogglesLayout(Widget):
def _update_toggles(self):
ui_state.update_params()
accel_personality_enabled = self._params.get_bool("AccelPersonalityEnabled")
e2e_description = tr(
"sunnypilot defaults to driving in chill mode. Experimental mode enables alpha-level features that aren't ready for chill mode. " +
@@ -176,11 +203,15 @@ class TogglesLayout(Widget):
self._toggles["ExperimentalMode"].action_item.set_enabled(True)
self._toggles["ExperimentalMode"].set_description(e2e_description)
self._long_personality_setting.action_item.set_enabled(True)
self._accel_personality_enabled.action_item.set_enabled(True)
self._accel_personality_setting.action_item.set_enabled(accel_personality_enabled)
else:
# no long for now
self._toggles["ExperimentalMode"].action_item.set_enabled(False)
self._toggles["ExperimentalMode"].action_item.set_state(False)
self._long_personality_setting.action_item.set_enabled(False)
self._accel_personality_enabled.action_item.set_enabled(False)
self._accel_personality_setting.action_item.set_enabled(False)
self._params.remove("ExperimentalMode")
unavailable = tr("Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control.")
@@ -203,6 +234,10 @@ class TogglesLayout(Widget):
# refresh toggles from params to mirror external changes
for param in self._toggle_defs:
self._toggles[param].action_item.set_state(self._params.get_bool(param))
self._accel_personality_enabled.action_item.set_state(accel_personality_enabled)
self._accel_personality_setting.action_item.set_selected_button(
self._params.get("AccelPersonality", return_default=True)
)
# these toggles need restart, block while engaged
for toggle_def in self._toggle_defs:
@@ -247,3 +282,10 @@ class TogglesLayout(Widget):
def _set_longitudinal_personality(self, button_index: int):
self._params.put("LongitudinalPersonality", button_index, block=True)
def _set_accel_personality(self, button_index: int):
self._params.put("AccelPersonality", button_index, block=True)
def _set_accel_personality_enabled(self, state: bool):
self._params.put_bool("AccelPersonalityEnabled", state, block=True)
self._accel_personality_setting.action_item.set_enabled(state and ui_state.has_longitudinal_control)
+5 -2
View File
@@ -13,6 +13,7 @@ from openpilot.system.ui.lib.application import gui_app
if gui_app.sunnypilot_ui():
from openpilot.selfdrive.ui.sunnypilot.mici.layouts.settings import SettingsLayoutSP as SettingsLayout
from openpilot.selfdrive.ui.sunnypilot.mici.layouts.onroad import OnroadViewContainerSP as AugmentedRoadView
ONROAD_DELAY = 2.5 # seconds
@@ -118,13 +119,15 @@ class MiciMainLayout(Scroller):
# FIXME: these two pops can interrupt user interacting in the settings
if self._onroad_time_delay is not None and rl.get_time() - self._onroad_time_delay >= ONROAD_DELAY:
gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout))
if not gui_app.sunnypilot_ui() or self._should_auto_scroll_to_onroad():
gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout))
self._onroad_time_delay = None
# When car leaves standstill, pop nav stack and scroll to onroad
CS = ui_state.sm["carState"]
if not CS.standstill and self._prev_standstill:
gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout))
if not gui_app.sunnypilot_ui() or self._should_auto_scroll_to_onroad():
gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout))
self._prev_standstill = CS.standstill
def _on_interactive_timeout(self):
@@ -14,6 +14,8 @@ class TogglesLayoutMici(NavScroller):
super().__init__()
self._personality_toggle = BigMultiParamToggle("driving personality", "LongitudinalPersonality", ["aggressive", "standard", "relaxed"])
self._accel_personality_enabled = BigParamControl("enable accel controller", "AccelPersonalityEnabled")
self._accel_personality_toggle = BigMultiParamToggle("acceleration profile", "AccelPersonality", ["eco", "normal", "sport"])
self._experimental_btn = BigParamControl("experimental mode", "ExperimentalMode")
is_metric_toggle = BigParamControl("use metric units", "IsMetric")
ldw_toggle = BigParamControl("lane departure warnings", "IsLdwEnabled")
@@ -24,6 +26,8 @@ class TogglesLayoutMici(NavScroller):
self._scroller.add_widgets([
self._personality_toggle,
self._accel_personality_enabled,
self._accel_personality_toggle,
self._experimental_btn,
is_metric_toggle,
ldw_toggle,
@@ -36,6 +40,7 @@ class TogglesLayoutMici(NavScroller):
# Toggle lists
self._refresh_toggles = (
("ExperimentalMode", self._experimental_btn),
("AccelPersonalityEnabled", self._accel_personality_enabled),
("IsMetric", is_metric_toggle),
("IsLdwEnabled", ldw_toggle),
("AlwaysOnDM", always_on_dm_toggle),
@@ -45,6 +50,9 @@ class TogglesLayoutMici(NavScroller):
)
enable_openpilot.set_enabled(lambda: not ui_state.engaged)
self._accel_personality_toggle.set_enabled(
lambda: ui_state.has_longitudinal_control and ui_state.params.get_bool("AccelPersonalityEnabled")
)
record_front.set_enabled(False if ui_state.params.get_bool("RecordFrontLock") else (lambda: not ui_state.engaged))
record_mic.set_enabled(lambda: not ui_state.engaged)
@@ -75,13 +83,18 @@ class TogglesLayoutMici(NavScroller):
if ui_state.has_longitudinal_control:
self._experimental_btn.set_visible(True)
self._personality_toggle.set_visible(True)
self._accel_personality_enabled.set_visible(True)
self._accel_personality_toggle.set_visible(True)
else:
# no long for now
self._experimental_btn.set_visible(False)
self._experimental_btn.set_checked(False)
self._personality_toggle.set_visible(False)
self._accel_personality_enabled.set_visible(False)
self._accel_personality_toggle.set_visible(False)
ui_state.params.remove("ExperimentalMode")
# Refresh toggles from params to mirror external changes
for key, item in self._refresh_toggles:
item.set_checked(ui_state.params.get_bool(key))
self._accel_personality_toggle.refresh()
@@ -383,13 +383,18 @@ class BigMultiParamToggle(BigMultiToggle):
self._load_value()
def _load_value(self):
self.set_value(self._options[self._params.get(self._param) or 0])
value = self._params.get(self._param, return_default=True)
index = value if isinstance(value, int) else 0
self.set_value(self._options[max(0, min(index, len(self._options) - 1))])
def _handle_mouse_release(self, mouse_pos: MousePos):
super()._handle_mouse_release(mouse_pos)
new_idx = self._options.index(self.value)
self._params.put(self._param, new_idx)
def refresh(self):
self._load_value()
class BigParamControl(BigToggle):
def __init__(self, text: str, param: str, toggle_callback: Callable | None = None):
@@ -43,7 +43,7 @@ class ModelsLayout(Widget):
self._initialize_items()
self.clear_cache_item.action_item.set_value(f"{self.calculate_cache_size():.2f} MB")
for ctrl, key in [(self.lane_turn_value_control, "LaneTurnValue"), (self.delay_control, "LagdToggleDelay")]:
for ctrl, key in [(self.lane_turn_value_control, "LaneTurnValue"), (self.delay_control, "LagdToggleDelay"), (self.camera_offset, "CameraOffset")]:
ctrl.action_item.set_value(int(float(ui_state.params.get(key, return_default=True)) * 100))
self._scroller = Scroller(self.items, line_separator=True, spacing=0)
@@ -93,9 +93,14 @@ class ModelsLayout(Widget):
self.lagd_toggle = toggle_item_sp(tr("Live Learning Steer Delay"), "", param="LagdToggle")
self.camera_offset = option_item_sp(tr("Adjust Camera Offset"), "CameraOffset", -35, 35,
tr("Virtually shift camera's perspective to move model's center to Left(+ values) or Right (- values)"),
1, None, True, "", style.BUTTON_ACTION_WIDTH, None, True,
lambda v: f"{v / 100:.2f} m")
self.items = [self.current_model_item, self.cancel_download_item, self.supercombo_label, self.vision_label,
self.policy_label, self.off_policy_label, self.on_policy_label, self.refresh_item, self.clear_cache_item, self.lane_turn_desire_toggle,
self.lane_turn_value_control, self.lagd_toggle, self.delay_control]
self.policy_label, self.off_policy_label, self.on_policy_label, self.refresh_item, self.clear_cache_item,
self.lane_turn_desire_toggle, self.lane_turn_value_control, self.lagd_toggle, self.delay_control, self.camera_offset]
def _update_lagd_description(self, lagd_toggle: bool):
desc = tr("Enable this for the car to learn and adapt its steering response time. Disable to use a fixed steering response time. " +
@@ -232,6 +237,7 @@ class ModelsLayout(Widget):
advanced_controls: bool = ui_state.params.get_bool("ShowAdvancedControls")
turn_desire: bool = ui_state.params.get_bool("LaneTurnDesire")
live_delay: bool = ui_state.params.get_bool("LagdToggle")
camera_offset: bool = ui_state.params.get("ModelManager_ActiveBundle") is not None
self.lane_turn_desire_toggle.action_item.set_state(turn_desire)
self.lane_turn_value_control.set_visible(turn_desire and advanced_controls)
@@ -240,6 +246,7 @@ class ModelsLayout(Widget):
new_step = int(round(100 / CV.MPH_TO_KPH)) if ui_state.is_metric else 100
if self.lane_turn_value_control.action_item is not None and self.lane_turn_value_control.action_item.value_change_step != new_step:
self.lane_turn_value_control.action_item.value_change_step = new_step
self.camera_offset.set_visible(camera_offset)
self._update_lagd_description(live_delay)
self.model_manager = ui_state.sm["modelManagerSP"]
@@ -51,11 +51,17 @@ class LaneChangeSettingsLayout(Widget):
description=lambda: tr("Toggle to enable a delay timer for seamless lane changes when blind spot monitoring " +
"(BSM) detects a obstructing vehicle, ensuring safe maneuvering."),
)
self._road_edge_block = toggle_item_sp(
param="RoadEdgeLaneChangeEnabled",
title=lambda: tr("Block Lane Change: Road Edge Detection"),
description=lambda: tr("Blocks the lane change if the model sees a road edge on your signaled side."),
)
items = [
self._lane_change_timer,
LineSeparatorSP(40),
self._bsm_delay,
self._road_edge_block,
]
return items
@@ -7,7 +7,7 @@ See the LICENSE.md file in the root directory for more details.
from collections.abc import Callable
import pyray as rl
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake
from openpilot.system.ui.lib.multilang import tr, tr_noop
@@ -96,7 +96,10 @@ class MadsSettingsLayout(Widget):
if brand == "rivian":
return True
elif brand == "tesla":
return not (ui_state.CP_SP is not None and ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS)
if ui_state.CP_SP is None or not ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
return True
screen_button = int(ui_state.params.get("TeslaMadsScreenButton", return_default=True))
return screen_button == MadsScreenButtonType.OFF
return False
def _update_steering_mode_description(self, button_index: int):
@@ -4,10 +4,11 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.vehicle.brands.base import BrandSettings
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp
from openpilot.system.ui.sunnypilot.widgets.list_view import multiple_button_item_sp, toggle_item_sp
COOP_STEERING_MIN_KMH = 23
OEM_STEERING_MIN_KMH = 48
@@ -18,7 +19,14 @@ class TeslaSettings(BrandSettings):
def __init__(self):
super().__init__()
self.coop_steering_toggle = toggle_item_sp(tr("Cooperative Steering (Beta)"), "", param="TeslaCoopSteering")
self.items = [self.coop_steering_toggle]
self.mads_screen_button = multiple_button_item_sp(
title=lambda: tr("MADS Screen Activation"),
description="",
buttons=[lambda: tr("Off"), lambda: tr("3-Finger"), lambda: tr("4-Finger"), lambda: tr("5-Finger")],
param="TeslaMadsScreenButton",
inline=False,
)
self.items = [self.coop_steering_toggle, self.mads_screen_button]
def update_settings(self):
is_metric = ui_state.is_metric
@@ -41,3 +49,18 @@ class TeslaSettings(BrandSettings):
self.coop_steering_toggle.set_description(coop_steering_desc)
self.coop_steering_toggle.action_item.set_enabled(ui_state.is_offroad())
has_vehicle_bus = ui_state.CP_SP is not None and bool(ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS)
self.mads_screen_button.set_visible(has_vehicle_bus)
mads_screen_button_desc = (
f"{tr('Use a multi-finger press on the infotainment screen to toggle MADS.')} " +
f"{tr('This allows the use of full MADS functionality when enabled.')}<br><br>" +
f"{tr('Selecting a higher finger count may reduce accidental activations.')}<br><br>" +
f"<b>{tr('Note: Setting this to Off will reset your MADS settings to default.')}</b>"
)
if not ui_state.is_offroad():
mads_screen_button_disabled_msg = tr("Enable \"Always Offroad\" in Device panel, or turn vehicle off to change.")
mads_screen_button_desc = f"<b>{mads_screen_button_disabled_msg}</b><br><br>{mads_screen_button_desc}"
self.mads_screen_button.set_description(mads_screen_button_desc)
self.mads_screen_button.action_item.set_enabled(ui_state.is_offroad())
@@ -0,0 +1,13 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from openpilot.selfdrive.ui.mici.layouts.main import MiciMainLayout
class MiciMainLayoutSP(MiciMainLayout):
def _should_auto_scroll_to_onroad(self) -> bool:
return not self._onroad_layout.is_on_info_panel()
@@ -0,0 +1,63 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import pyray as rl
from openpilot.system.ui.lib.application import gui_app
from openpilot.selfdrive.ui.sunnypilot.mici.widgets.scroller_sp import ScrollerSP
from openpilot.selfdrive.ui.sunnypilot.mici.onroad.augmented_road_view import AugmentedRoadViewSP
from openpilot.selfdrive.ui.sunnypilot.mici.layouts.onroad_info_panel import OnroadInfoPanel
CONFIDENCE_BALL_VISIBLE_RATIO = 0.4
HORIZONTAL_SETTLE_PX = 5
HORIZONTAL_RESET_RATIO = 0.5
class OnroadViewContainerSP(ScrollerSP):
def __init__(self, bookmark_callback=None):
super().__init__(horizontal=False, snap_items=True, spacing=0, pad=0, scroll_indicator=False, edge_shadows=False)
self.road_view = AugmentedRoadViewSP(bookmark_callback=bookmark_callback)
self.onroad_info_panel = OnroadInfoPanel(bookmark_callback=bookmark_callback)
self._scroller.add_widgets([
self.road_view,
self.onroad_info_panel,
])
self._scroller.set_reset_scroll_at_show(False)
self._scroller.set_scrolling_enabled(lambda: abs(self.rect.x) < HORIZONTAL_SETTLE_PX)
for child in (self.road_view, self.onroad_info_panel):
inner_touch_valid = child._touch_valid_callback
child.set_touch_valid_callback(
lambda inner=inner_touch_valid: self._touch_valid() and (inner() if inner else True)
)
def set_rect(self, rect: rl.Rectangle):
super().set_rect(rect)
self.road_view.set_rect(rect)
self.onroad_info_panel.set_rect(rect)
return self
def is_swiping_left(self) -> bool:
return self.road_view.is_swiping_left() or self.onroad_info_panel.is_swiping_left()
def set_click_callback(self, callback) -> None:
self.road_view.set_click_callback(callback)
self.onroad_info_panel.set_click_callback(callback)
def is_on_info_panel(self) -> bool:
"""True when scrolled past halfway toward onroad_info_panel (used by main layout
to skip auto-pop-back-to-camera while user is reading the info panel)."""
return abs(self._scroller.scroll_panel.get_offset()) > self._rect.height / 2
def _render(self, rect: rl.Rectangle):
if abs(self.rect.x) > gui_app.width * HORIZONTAL_RESET_RATIO:
self._scroller.scroll_panel.set_offset(0)
vertical_offset = self._scroller.scroll_panel.get_offset()
show_ball = abs(vertical_offset) < rect.height * CONFIDENCE_BALL_VISIBLE_RATIO
self.road_view.set_show_confidence_ball(show_ball)
super()._render(rect)
@@ -0,0 +1,324 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import pyray as rl
from dataclasses import dataclass
from openpilot.common.constants import CV
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.lib.application import MousePos
from openpilot.system.ui.widgets import Widget
from openpilot.selfdrive.ui.mici.onroad.alert_renderer import AlertRenderer
from openpilot.selfdrive.ui.mici.onroad.augmented_road_view import BookmarkIcon
METER_TO_KM = 0.001
METER_TO_MILE = 0.000621371
@dataclass(frozen=True)
class OnroadInfoPanelColors:
white: rl.Color = rl.WHITE
black: rl.Color = rl.BLACK
red: rl.Color = rl.Color(255, 0, 0, 255)
green: rl.Color = rl.Color(0, 255, 0, 255)
grey: rl.Color = rl.Color(190, 195, 190, 255)
light_grey: rl.Color = rl.Color(200, 200, 200, 255)
dark_grey: rl.Color = rl.Color(100, 100, 100, 255)
bg_dark: rl.Color = rl.Color(0, 0, 0, 255)
card_bg: rl.Color = rl.Color(50, 50, 50, 200)
badge_bg: rl.Color = rl.Color(60, 60, 60, 255)
COLORS = OnroadInfoPanelColors()
class OnroadInfoPanel(Widget):
def __init__(self, bookmark_callback=None):
super().__init__()
self.speed_limit: float = 0.0
self.speed_limit_valid: bool = False
self.speed_limit_offset: float = 0.0
self.next_speed_limit: float = 0.0
self.next_speed_limit_distance: float = 0.0
self.road_name: str = ""
self.current_speed: float = 0.0
self.set_speed: float = 0.0
self.cruise_enabled: bool = False
self._sign_slide: float = 0.0
self._font_bold: rl.Font = gui_app.font(FontWeight.BOLD)
self._font_semi_bold: rl.Font = gui_app.font(FontWeight.SEMI_BOLD)
self._font_medium: rl.Font = gui_app.font(FontWeight.MEDIUM)
self._marquee_offset: float = 0.0
self._marquee_direction: int = 1
self._marquee_pause_timer: float = 0.0
self._marquee_speed: float = 40.0
self._marquee_pause_duration: float = 1.5
self._alert_renderer = AlertRenderer()
self._alert_alpha_filter = FirstOrderFilter(0, 0.05, 1 / gui_app.target_fps)
self._bookmark_icon = BookmarkIcon(bookmark_callback)
def is_swiping_left(self) -> bool:
return self._bookmark_icon.is_swiping_left()
def _handle_mouse_release(self, mouse_pos: MousePos) -> None:
# Mirror stock AugmentedRoadView: suppress click while bookmark gesture active
if not self._bookmark_icon.interacting():
super()._handle_mouse_release(mouse_pos)
def _update_state(self) -> None:
sm = ui_state.sm
speed_conv = CV.MS_TO_KPH if ui_state.is_metric else CV.MS_TO_MPH
if sm.valid["longitudinalPlanSP"]:
lp_sp = sm["longitudinalPlanSP"]
resolver = lp_sp.speedLimit.resolver
self.speed_limit = resolver.speedLimit * speed_conv
self.speed_limit_valid = resolver.speedLimitValid
self.speed_limit_offset = resolver.speedLimitOffset * speed_conv
if sm.valid["liveMapDataSP"]:
lmd = sm["liveMapDataSP"]
self.next_speed_limit = lmd.speedLimitAhead * speed_conv
self.next_speed_limit_distance = lmd.speedLimitAheadDistance
self.road_name = lmd.roadName
if sm.updated["carState"]:
self.current_speed = sm["carState"].vEgo * speed_conv
if sm.valid["carState"] and sm.valid["controlsState"]:
self.cruise_enabled = sm["carState"].cruiseState.enabled
v_cruise_cluster = sm["carState"].vCruiseCluster
set_speed_kph = sm["controlsState"].vCruiseDEPRECATED if v_cruise_cluster == 0.0 else v_cruise_cluster
self.set_speed = set_speed_kph * (METER_TO_MILE / METER_TO_KM) if not ui_state.is_metric else set_speed_kph
def _render(self, rect: rl.Rectangle) -> None:
self._update_state()
rl.draw_rectangle(int(rect.x), int(rect.y), int(rect.width), int(rect.height), COLORS.bg_dark)
margin = 20
mid_y = rect.y + rect.height / 2
left_x = rect.x + margin
if self.cruise_enabled:
unit = tr("MAX")
display_speed = self.set_speed
else:
unit = tr("km/h") if ui_state.is_metric else tr("MPH")
display_speed = self.current_speed
speed_val = str(round(display_speed))
if self.speed_limit_valid and display_speed > self.speed_limit:
speed_color = COLORS.red
else:
speed_color = COLORS.white
rl.draw_text_ex(self._font_semi_bold, unit, rl.Vector2(left_x, mid_y - 95), 38, 0, COLORS.grey)
rl.draw_text_ex(self._font_bold, speed_val, rl.Vector2(left_x, mid_y - 60), 110, 0, speed_color)
sign_width = 135
sign_height = 135 if ui_state.is_metric else 175
has_next = self.next_speed_limit > 0 and self.next_speed_limit != self.speed_limit
target_slide = 1.0 if has_next else 0.0
slide_speed = 3.0 * rl.get_frame_time()
if self._sign_slide < target_slide:
self._sign_slide = min(self._sign_slide + slide_speed, target_slide)
elif self._sign_slide > target_slide:
self._sign_slide = max(self._sign_slide - slide_speed, target_slide)
next_w = int(sign_width * 0.7)
next_h = int(sign_height * 0.7)
next_peek = int(next_w * 0.85) + 5
centered_x = rect.x + rect.width - sign_width - margin
shifted_x = rect.x + rect.width - sign_width - margin - next_peek
sign_x = centered_x + (shifted_x - centered_x) * self._sign_slide
sign_y = rect.y + (rect.height - sign_height) / 2
road_y = mid_y + 55
road_width = sign_x - left_x - margin
self._draw_road_name(left_x, road_y, road_width)
if has_next and self._sign_slide > 0.01:
next_val = str(round(self.next_speed_limit))
dist_str = self._format_distance(self.next_speed_limit_distance)
next_x = sign_x + sign_width - int(next_w * 0.15)
next_y = sign_y + (sign_height - next_h) / 2
next_speed_color = COLORS.black
if ui_state.is_metric:
self._draw_vienna_sign(next_x, next_y, next_w, next_h, next_val, next_speed_color, is_upcoming=True)
else:
self._draw_mutcd_sign(next_x, next_y, next_w, next_h, next_val, next_speed_color, is_upcoming=True)
dist_size = measure_text_cached(self._font_medium, dist_str, 24)
rl.draw_text_ex(self._font_medium, dist_str, rl.Vector2(next_x + next_w / 2 - dist_size.x / 2, next_y + next_h + 4), 24, 0, COLORS.grey)
self._draw_speed_limit_sign(sign_x, sign_y, sign_width, sign_height)
if self.speed_limit_offset != 0 and self.speed_limit_valid:
offset_val = str(abs(round(self.speed_limit_offset)))
badge_sz = 42
badge_x = sign_x + sign_width - badge_sz * 0.85
badge_y = sign_y - badge_sz * 0.25
if ui_state.is_metric:
badge_r = badge_sz / 2
badge_cx = badge_x + badge_r
badge_cy = badge_y + badge_r
rl.draw_circle(int(badge_cx), int(badge_cy), badge_r + 2, COLORS.dark_grey)
rl.draw_circle(int(badge_cx), int(badge_cy), badge_r, COLORS.badge_bg)
self._draw_text_centered(self._font_bold, offset_val, 24, rl.Vector2(badge_cx, badge_cy), COLORS.white)
else:
mutcd_badge_x = sign_x + sign_width - badge_sz * 0.65
mutcd_badge_y = sign_y - badge_sz * 0.50
badge_rect = rl.Rectangle(mutcd_badge_x, mutcd_badge_y, badge_sz, badge_sz)
rl.draw_rectangle_rounded(badge_rect, 0.25, 10, COLORS.badge_bg)
rl.draw_rectangle_rounded_lines_ex(badge_rect, 0.25, 10, 2, COLORS.dark_grey)
self._draw_text_centered(self._font_bold, offset_val, 24, rl.Vector2(mutcd_badge_x + badge_sz / 2, mutcd_badge_y + badge_sz / 2), COLORS.white)
# SCC
speed_size = measure_text_cached(self._font_bold, speed_val, 110)
scc_x = left_x + speed_size.x + 30
scc_y = mid_y - 50
self._draw_scc_icons(scc_x, scc_y)
self._bookmark_icon.render(rect)
if ui_state.started:
alert_obj, no_alert = self._alert_renderer.will_render()
self._alert_alpha_filter.update(0 if no_alert else 1)
alpha = self._alert_alpha_filter.x
if alpha > 0.01:
rl.draw_rectangle(int(rect.x), int(rect.y), int(rect.width), int(rect.height), rl.Color(0, 0, 0, int(150 * alpha)))
self._alert_renderer.render(rect)
def _draw_scc_icons(self, x: float, y: float) -> None:
sm = ui_state.sm
if not sm.valid["longitudinalPlanSP"]:
return
scc = sm["longitudinalPlanSP"].smartCruiseControl
box_w, box_h = 100, 36
gap = 6
drawn = 0
for label, active in [("SCC-V", scc.vision.active), ("SCC-M", scc.map.active)]:
if not active:
continue
bx = x
by = y + drawn * (box_h + gap)
rl.draw_rectangle_rounded(rl.Rectangle(bx, by, box_w, box_h), 0.3, 10, COLORS.green)
self._draw_text_centered(self._font_bold, label, 20, rl.Vector2(bx + box_w / 2, by + box_h / 2), COLORS.black)
drawn += 1
def _draw_speed_limit_sign(self, x: float, y: float, sign_width: float, sign_height: float) -> None:
speed_str = str(round(self.speed_limit)) if self.speed_limit_valid and self.speed_limit > 0 else "--"
speed_color = COLORS.black if not self.speed_limit_valid or self.current_speed <= self.speed_limit else COLORS.red
if ui_state.is_metric:
self._draw_vienna_sign(x, y, sign_width, sign_height, speed_str, speed_color, is_upcoming=False)
else:
self._draw_mutcd_sign(x, y, sign_width, sign_height, speed_str, speed_color, is_upcoming=False)
def _draw_road_name(self, x: float, y: float, width: float) -> None:
road_display = self.road_name if self.road_name else "--"
font_size = 30
road_size = measure_text_cached(self._font_semi_bold, road_display, font_size)
text_width = road_size.x
if text_width <= width:
self._marquee_offset = 0.0
self._marquee_direction = 1
self._marquee_pause_timer = 0.0
rl.draw_text_ex(self._font_semi_bold, road_display, rl.Vector2(x, y), font_size, 0, COLORS.white)
else:
overflow = text_width - width
dt = rl.get_frame_time()
if self._marquee_pause_timer > 0:
self._marquee_pause_timer -= dt
else:
self._marquee_offset += self._marquee_direction * self._marquee_speed * dt
if self._marquee_offset >= overflow:
self._marquee_offset = overflow
self._marquee_direction = -1
self._marquee_pause_timer = self._marquee_pause_duration
elif self._marquee_offset <= 0:
self._marquee_offset = 0
self._marquee_direction = 1
self._marquee_pause_timer = self._marquee_pause_duration
rl.begin_scissor_mode(int(x), int(y), int(width), int(road_size.y + 4))
text_pos = rl.Vector2(x - self._marquee_offset, y)
rl.draw_text_ex(self._font_semi_bold, road_display, text_pos, font_size, 0, COLORS.white)
rl.end_scissor_mode()
def _draw_vienna_sign(self, x: float, y: float, width: float, height: float, speed_str: str, speed_color: rl.Color, is_upcoming: bool = False) -> None:
center = rl.Vector2(x + width / 2, y + height / 2)
outer_radius = min(width, height) / 2
rl.draw_circle_v(center, outer_radius, COLORS.white)
ring_width = outer_radius * 0.18
rl.draw_ring(center, outer_radius - ring_width, outer_radius, 0, 360, 36, COLORS.red)
font_size = outer_radius * (0.7 if len(speed_str) >= 3 else 0.9)
text_size = measure_text_cached(self._font_bold, speed_str, int(font_size))
text_pos = rl.Vector2(center.x - text_size.x / 2, center.y - text_size.y / 2)
rl.draw_text_ex(self._font_bold, speed_str, text_pos, font_size, 0, speed_color)
def _draw_mutcd_sign(self, x: float, y: float, width: float, height: float, speed_str: str, speed_color: rl.Color, is_upcoming: bool = False) -> None:
sign_rect = rl.Rectangle(x, y, width, height)
rl.draw_rectangle_rounded(sign_rect, 0.35, 10, COLORS.white)
inset = max(4, width * 0.05)
inner_rect = rl.Rectangle(x + inset, y + inset, width - inset * 2, height - inset * 2)
outer_radius = 0.35 * width / 2.0
inner_radius = outer_radius - inset
inner_roundness = inner_radius / (inner_rect.width / 2.0)
rl.draw_rectangle_rounded_lines_ex(inner_rect, inner_roundness, 10, 3, COLORS.black)
mid_x = x + width / 2
label_size = max(18, int(width * 0.26))
if is_upcoming:
self._draw_text_centered(self._font_bold, tr("AHEAD"), label_size, rl.Vector2(mid_x, y + height * 0.27), COLORS.black)
else:
self._draw_text_centered(self._font_bold, tr("SPEED"), label_size, rl.Vector2(mid_x, y + height * 0.20), COLORS.black)
self._draw_text_centered(self._font_bold, tr("LIMIT"), label_size, rl.Vector2(mid_x, y + height * 0.40), COLORS.black)
speed_font_size = int(width * 0.52) if len(speed_str) >= 3 else int(width * 0.62)
self._draw_text_centered(self._font_bold, speed_str, speed_font_size, rl.Vector2(mid_x, y + height * 0.72), speed_color)
def _draw_text_centered(self, font, text, size, pos_center, color):
sz = measure_text_cached(font, text, size)
rl.draw_text_ex(font, text, rl.Vector2(pos_center.x - sz.x / 2, pos_center.y - sz.y / 2), size, 0, color)
def _format_distance(self, distance: float) -> str:
if ui_state.is_metric:
if distance < 50:
return tr("Near")
if distance >= 1000:
return f"{distance * METER_TO_KM:.1f}" + tr("km")
if distance < 200:
rounded = max(10, int(distance / 10) * 10)
else:
rounded = int(distance / 100) * 100
return str(rounded) + tr("m")
else:
distance_mi = distance * METER_TO_MILE
if distance_mi < 0.1:
return tr("Near")
return f"{distance_mi:.1f}" + tr("mi")
@@ -0,0 +1,30 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import pyray as rl
from openpilot.selfdrive.ui.mici.onroad.augmented_road_view import AugmentedRoadView
class _SuppressedConfidenceBall:
def render(self, *_):
pass
class AugmentedRoadViewSP(AugmentedRoadView):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._show_confidence_ball: bool = True
self._real_confidence_ball = self._confidence_ball
self._confidence_ball = _SuppressedConfidenceBall()
def set_show_confidence_ball(self, show: bool) -> None:
self._show_confidence_ball = show
def _render(self, rect: rl.Rectangle) -> None:
super()._render(rect)
if self._show_confidence_ball:
self._real_confidence_ball.render(self.rect)
@@ -0,0 +1,34 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import pyray as rl
from openpilot.system.ui.lib.application import MouseEvent
from openpilot.system.ui.lib.scroll_panel2 import GuiScrollPanel2, ScrollState
class GuiScrollPanel2SP(GuiScrollPanel2):
"""Reject orthogonal-dominant drags so nested scrollers (outer horizontal +
inner vertical) don't both engage on a slightly diagonal swipe.
Implemented as a post-super state rollback rather than reimplementing the
PRESSED state machine keeps stock behaviour authoritative."""
def _handle_mouse_event(self, mouse_event: MouseEvent, bounds: rl.Rectangle, bounds_size: float,
content_size: float) -> None:
pre_state = self._state
super()._handle_mouse_event(mouse_event, bounds, bounds_size, content_size)
if self._state == ScrollState.MANUAL_SCROLL and pre_state == ScrollState.PRESSED and \
self._initial_click_event is not None:
diff_x = abs(mouse_event.pos.x - self._initial_click_event.pos.x)
diff_y = abs(mouse_event.pos.y - self._initial_click_event.pos.y)
along = diff_x if self._horizontal else diff_y
anti = diff_y if self._horizontal else diff_x
if anti > along:
self._state = ScrollState.STEADY
self._velocity = 0.0
self._velocity_buffer.clear()
@@ -0,0 +1,16 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from openpilot.system.ui.widgets.scroller import Scroller
from openpilot.selfdrive.ui.sunnypilot.mici.widgets.scroll_panel_sp import GuiScrollPanel2SP
class ScrollerSP(Scroller):
def __init__(self, **kwargs):
super().__init__(**kwargs)
inner = self._scroller
inner.scroll_panel = GuiScrollPanel2SP(inner._horizontal, handle_out_of_bounds=not inner._snap_items)
+3
View File
@@ -10,6 +10,9 @@ from openpilot.selfdrive.ui.layouts.main import MainLayout
from openpilot.selfdrive.ui.mici.layouts.main import MiciMainLayout
from openpilot.selfdrive.ui.ui_state import ui_state
if gui_app.sunnypilot_ui():
from openpilot.selfdrive.ui.sunnypilot.mici.layouts.main import MiciMainLayoutSP as MiciMainLayout
BIG_UI = gui_app.big_ui()
+1 -1
View File
@@ -1 +1 @@
#define SUNNYPILOT_VERSION "2026.07.25-4591"
#define SUNNYPILOT_VERSION "2026.08.07-4624"
+8 -5
View File
@@ -9,7 +9,7 @@ from openpilot.common.params import Params
from opendbc.car import structs
from opendbc.safety import ALTERNATIVE_EXPERIENCE
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP, HyundaiSafetyFlagsSP
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
MADS_NO_ACC_MAIN_BUTTON = ("rivian", "tesla")
@@ -21,17 +21,20 @@ class MadsSteeringModeOnBrake:
DISENGAGE = 2
def get_mads_limited_brands(CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> bool:
def get_mads_limited_brands(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params) -> bool:
if CP.brand == 'rivian':
return True
if CP.brand == 'tesla':
return not CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS
if not CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
return True
screen_button = int(params.get("TeslaMadsScreenButton", return_default=True))
return screen_button == MadsScreenButtonType.OFF
return False
def read_steering_mode_param(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params):
if get_mads_limited_brands(CP, CP_SP):
if get_mads_limited_brands(CP, CP_SP, params):
return MadsSteeringModeOnBrake.DISENGAGE
return params.get("MadsSteeringMode", return_default=True)
@@ -63,7 +66,7 @@ def set_car_specific_params(CP: structs.CarParams, CP_SP: structs.CarParamsSP, p
# MADS is currently partially supported for these platforms due to lack of consistent states to engage controls
# Only MadsSteeringModeOnBrake.DISENGAGE is supported for these platforms
# TODO-SP: To enable MADS full support for Rivian and most Tesla, identify consistent signals for MADS toggling
mads_partial_support = get_mads_limited_brands(CP, CP_SP)
mads_partial_support = get_mads_limited_brands(CP, CP_SP, params)
if mads_partial_support:
params.put("MadsSteeringMode", 2, block=True)
params.put_bool("MadsUnifiedEngagementMode", True, block=True)
@@ -13,7 +13,7 @@ from openpilot.selfdrive.selfdrived.events import Events
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake, read_steering_mode_param
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
State = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState
EventName = log.OnroadEvent.EventName
@@ -38,6 +38,12 @@ def make_panda_state(mocker, controls_allowed_lateral=True):
return ps
def make_params_mock(mocker, values):
params = mocker.MagicMock()
params.get = mocker.MagicMock(side_effect=lambda k, **kwargs: values[k])
return params
def make_mads(mocker, steering_mode):
sd = mocker.MagicMock()
sd.CP = structs.CarParams()
@@ -223,15 +229,27 @@ class TestBrandSteeringModeRestrictions:
params = mocker.MagicMock()
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
def test_tesla_with_vehicle_bus_uses_param(self, mocker):
@pytest.mark.parametrize("screen_button", [MadsScreenButtonType.THREE_FINGER,
MadsScreenButtonType.FOUR_FINGER,
MadsScreenButtonType.FIVE_FINGER])
def test_tesla_with_vehicle_bus_uses_param(self, mocker, screen_button):
CP = structs.CarParams()
CP.brand = "tesla"
CP_SP = structs.CarParamsSP()
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
params = mocker.MagicMock()
params.get = mocker.MagicMock(return_value=MadsSteeringModeOnBrake.REMAIN_ACTIVE)
params = make_params_mock(mocker, {"TeslaMadsScreenButton": screen_button,
"MadsSteeringMode": MadsSteeringModeOnBrake.REMAIN_ACTIVE})
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.REMAIN_ACTIVE
def test_tesla_with_vehicle_bus_screen_button_off_forced_to_disengage(self, mocker):
CP = structs.CarParams()
CP.brand = "tesla"
CP_SP = structs.CarParamsSP()
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
params = make_params_mock(mocker, {"TeslaMadsScreenButton": MadsScreenButtonType.OFF,
"MadsSteeringMode": MadsSteeringModeOnBrake.REMAIN_ACTIVE})
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
@pytest.mark.parametrize("brand", ["hyundai", "toyota", "honda", "gm"])
def test_other_brands_use_param(self, mocker, brand):
CP = structs.CarParams()
+268 -384
View File
@@ -10,471 +10,355 @@ import argparse
import os
import pickle
import time
from functools import partial
from collections import defaultdict
from functools import partial
import numpy as np
from tinygrad.tensor import Tensor
os.environ['GMMU'] = '0'
def _patch_tinygrad_fetch_fw():
import hashlib
import pathlib
import zstandard
from tinygrad import helpers
_orig_fetch_fw = helpers.fetch_fw
def fetch_fw(path, name, sha256):
p = pathlib.Path(f"/lib/firmware/{path}/{name}.zst")
if p.is_file():
blob = zstandard.ZstdDecompressor().stream_reader(p.read_bytes()).read()
if hashlib.sha256(blob).hexdigest() == sha256:
return blob
return _orig_fetch_fw(path, name, sha256)
helpers.fetch_fw = fetch_fw
_patch_tinygrad_fetch_fw()
from openpilot.selfdrive.modeld.compile_modeld import NV12Frame, make_frame_prepare, sample_desire, sample_skip, shift_and_sample
from tinygrad import dtypes
from tinygrad.device import Device
from tinygrad.engine.jit import TinyJit
from openpilot.selfdrive.modeld.compile_modeld import (
NV12Frame, make_frame_prepare,
shift_and_sample, sample_skip, sample_desire,
)
from tinygrad.tensor import Tensor
MODEL_TYPES = ('vision_policy', 'supercombo', 'vision_multi_policy')
def _detect_desire_key(policy_input_shapes):
for k in policy_input_shapes:
if k.startswith('desire'):
return k
return None
def _detect_desire_key(shapes: dict) -> str | None:
return next((key for key in shapes if key.startswith('desire')), None)
def _detect_vision_keys(vision_input_shapes):
img_keys = sorted([k for k in vision_input_shapes if 'img' in k])
road_key = next((k for k in img_keys if 'big' not in k), None)
wide_key = next((k for k in img_keys if 'big' in k), None)
if road_key is None or wide_key is None:
raise ValueError(f"Cannot determine road/wide image keys from {list(vision_input_shapes.keys())}")
return road_key, wide_key
def _detect_vision_keys(shapes: dict) -> tuple[str | None, str | None]:
img_keys = sorted(key for key in shapes if 'img' in key)
return (
next((key for key in img_keys if 'big' not in key), None),
next((key for key in img_keys if 'big' in key), None)
)
def make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, device):
road_key, _ = _detect_vision_keys(vision_input_shapes)
img = vision_input_shapes[road_key]
n_frames = img[1] // 6
img_buf_shape = (frame_skip * (n_frames - 1) + 1, 6, img[2], img[3])
fb = policy_input_shapes['features_buffer']
desire_key = _detect_desire_key(policy_input_shapes)
dp = policy_input_shapes[desire_key]
tc = policy_input_shapes.get('traffic_convention', (1, 2))
npy = {
'desire': np.zeros(dp[2], dtype=np.float32),
'traffic_convention': np.zeros(tc, dtype=np.float32),
'tfm': np.zeros((3, 3), dtype=np.float32),
'big_tfm': np.zeros((3, 3), dtype=np.float32),
}
handled = {'features_buffer', desire_key, 'traffic_convention'}
for key, shape in policy_input_shapes.items():
if key in handled:
continue
npy[key] = np.zeros(shape, dtype=np.float32)
input_queues = {
'img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
'big_img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
'feat_q': Tensor(np.zeros((frame_skip * (fb[1] - 1) + 1, fb[0], fb[2]), dtype=np.float32), device=device).contiguous().realize(),
'desire_q': Tensor(np.zeros((frame_skip * dp[1], dp[0], dp[2]), dtype=np.float32), device=device).contiguous().realize(),
**{k: Tensor(v, device='NPY').realize() for k, v in npy.items()},
}
return input_queues, npy
def derive_frame_skip(vision_input_shapes: dict, policy_input_shapes: dict) -> int:
features_buffer = policy_input_shapes.get('features_buffer')
return 1 if not features_buffer or features_buffer[1] >= 99 else 4
def make_run_split_policy(vision_runner, policy_runner, nv12: NV12Frame, model_w, model_h,
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
vision_road_key, vision_wide_key, prepare_only=False):
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
def get_policy_npy_shapes(input_shapes: dict, is_supercombo: bool = False) -> tuple[dict, list[int]]:
desire_key = _detect_desire_key(input_shapes)
shapes = {}
if desire_key:
shapes['desire'] = (input_shapes[desire_key][2],)
def run_policy(img_q, big_img_q, feat_q, desire_q, desire, traffic_convention, tfm, big_tfm, frame, big_frame, **extra):
npy_tensors = [tfm.to(Device.DEFAULT), big_tfm.to(Device.DEFAULT),
desire.to(Device.DEFAULT), traffic_convention.to(Device.DEFAULT)]
extra_device = {k: extra[k].to(Device.DEFAULT) for k in extra_policy_keys}
Tensor.realize(*npy_tensors, *extra_device.values())
tfm, big_tfm, desire, traffic_convention = npy_tensors
if is_supercombo and 'features_buffer' in input_shapes:
fb = input_shapes['features_buffer']
shapes['prev_feat'] = (fb[0], fb[2])
img = shift_and_sample(img_q, frame_prepare(frame, tfm).unsqueeze(0), sample_skip_fn)
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm).unsqueeze(0), sample_skip_fn)
for key, shape in input_shapes.items():
if key not in (desire_key, 'features_buffer') and 'img' not in key:
shapes[key] = tuple(shape)
if prepare_only:
return img, big_img
vision_out = next(iter(vision_runner({vision_road_key: img, vision_wide_key: big_img}).values())).cast('float32')
new_feat = vision_out[:, vision_features_slice].reshape(1, -1).unsqueeze(0)
feat_buf = shift_and_sample(feat_q, new_feat, sample_skip_fn)
desire_buf = shift_and_sample(desire_q, desire.reshape(1, 1, -1), sample_desire_fn)
inputs = {'features_buffer': feat_buf, desire_key: desire_buf, 'traffic_convention': traffic_convention, **extra_device}
policy_out = next(iter(policy_runner(inputs).values())).cast('float32')
return vision_out, policy_out
return run_policy
sizes = [int(np.prod(size)) for size in shapes.values()]
return shapes, sizes
def compile_split_policy(nv12: NV12Frame, model_w, model_h, prepare_only, frame_skip,
vision_runner, policy_runner, vision_metadata, policy_metadata):
print(f"Compiling combined policy JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
vision_features_slice = vision_metadata['output_slices']['hidden_state']
vision_input_shapes = vision_metadata['input_shapes']
policy_input_shapes = policy_metadata['input_shapes']
desire_key = _detect_desire_key(policy_input_shapes)
extra_policy_keys = [k for k in policy_input_shapes if k not in ('features_buffer', desire_key, 'traffic_convention')]
vision_road_key, vision_wide_key = _detect_vision_keys(vision_input_shapes)
_run = make_run_split_policy(vision_runner, policy_runner, nv12, model_w, model_h,
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
vision_road_key, vision_wide_key, prepare_only)
run_policy_jit = TinyJit(_run, prune=True)
SEED = 42
def random_inputs_run_fn(fn, seed, test_val=None, test_buffers=None, expect_match=True):
input_queues, npy = make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, Device.DEFAULT)
rng = np.random.default_rng(seed)
Tensor.manual_seed(seed)
testing = test_val is not None or test_buffers is not None
n_runs = 1 if testing else 3
for i in range(n_runs):
frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
big_frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
for v in npy.values():
v[:] = rng.standard_normal(v.shape).astype(v.dtype)
Device.default.synchronize()
st = time.perf_counter()
outs = fn(**input_queues, frame=frame, big_frame=big_frame)
mt = time.perf_counter()
Device.default.synchronize()
et = time.perf_counter()
print(f" [{i+1}/{n_runs}] enqueue {(mt-st)*1e3:6.2f} ms -- total {(et-st)*1e3:6.2f} ms")
if i == 0:
val = [np.copy(v.numpy()) for v in outs]
buffers = [np.copy(v.numpy().copy()) for v in input_queues.values()]
if test_val is not None:
match = all(np.array_equal(a, b) for a, b in zip(val, test_val, strict=True))
assert match == expect_match, f"outputs {'differ from' if expect_match else 'match'} baseline (seed={seed})"
if test_buffers is not None:
match = all(np.array_equal(a, b) for a, b in zip(buffers, test_buffers, strict=True))
assert match == expect_match, f"buffers {'differ from' if expect_match else 'match'} baseline (seed={seed})"
return fn, val, buffers
print('capture + replay')
run_policy_jit, test_val, test_buffers = random_inputs_run_fn(run_policy_jit, SEED)
print('pickle round trip')
run_policy_jit = pickle.loads(pickle.dumps(run_policy_jit))
random_inputs_run_fn(run_policy_jit, SEED, test_val, test_buffers, expect_match=True)
random_inputs_run_fn(run_policy_jit, SEED+1, test_val, test_buffers, expect_match=False)
return run_policy_jit
def derive_frame_skip(vision_input_shapes, policy_input_shapes):
fb = policy_input_shapes.get('features_buffer')
if fb is None:
return 1
fb_history = fb[1]
if fb_history >= 99:
return 1
return 4
def make_supercombo_input_queues(input_shapes, frame_skip, device):
img_shape = input_shapes.get('img', input_shapes.get('input_imgs'))
if img_shape is None:
raise ValueError("No img input found in model shapes")
def generate_queues_and_npy(input_shapes: dict, frame_skip: int, device: str = Device.DEFAULT,
is_supercombo: bool = False, use_packed: bool = True) -> tuple[dict, dict]:
road_key, _ = _detect_vision_keys(input_shapes)
if not road_key:
raise ValueError("Vision road key missing from input shapes.")
img_shape = input_shapes[road_key]
n_frames = img_shape[1] // 6
img_buf_shape = (frame_skip * (n_frames - 1) + 1, 6, img_shape[2], img_shape[3])
numpy_keys = {}
queue_keys = {}
desire_key = _detect_desire_key(input_shapes)
if not desire_key:
raise ValueError("Desire key missing from input shapes.")
for key, shape in input_shapes.items():
if 'img' in key:
continue
if len(shape) == 3 and shape[1] > 1:
if key.startswith('desire'):
numpy_keys[key] = np.zeros(shape[2], dtype=np.float32)
queue_keys[f'{key}_q'] = Tensor(
np.zeros((frame_skip * shape[1], shape[0], shape[2]), dtype=np.float32),
device=device).contiguous().realize()
elif key == 'features_buffer':
queue_keys['feat_q'] = Tensor(
np.zeros((frame_skip * (shape[1] - 1) + 1, shape[0], shape[2]), dtype=np.float32),
device=device).contiguous().realize()
else:
numpy_keys[key] = np.zeros(shape, dtype=np.float32)
elif len(shape) == 2:
numpy_keys[key] = np.zeros(shape, dtype=np.float32)
desire_shape = input_shapes[desire_key]
features_buffer = input_shapes.get('features_buffer')
if 'traffic_convention' not in numpy_keys:
tc_shape = input_shapes.get('traffic_convention', (1, 2))
numpy_keys['traffic_convention'] = np.zeros(tc_shape, dtype=np.float32)
if use_packed: # remove packed detection block after all models are recompiled
npy_arrays = {
'tfm': np.zeros((3, 3), dtype=np.float32),
'big_tfm': np.zeros((3, 3), dtype=np.float32)
}
numpy_keys['tfm'] = np.zeros((3, 3), dtype=np.float32)
numpy_keys['big_tfm'] = np.zeros((3, 3), dtype=np.float32)
shapes, sizes = get_policy_npy_shapes(input_shapes, is_supercombo=is_supercombo)
packed_npy_inputs = np.zeros(sum(sizes), dtype=np.float32)
input_queues = {
'img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
'big_img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
**queue_keys,
**{k: Tensor(v, device='NPY').realize() for k, v in numpy_keys.items()},
}
return input_queues, numpy_keys
split_indices = np.cumsum(sizes[:-1]) if len(sizes) > 1 else []
split_views = np.split(packed_npy_inputs, split_indices) if len(sizes) > 0 else []
for (k, s), v in zip(shapes.items(), split_views, strict=True):
npy_arrays[k] = v.reshape(s)
queues = {
'img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
'big_img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
'desire_q': Tensor(np.zeros((frame_skip * desire_shape[1], desire_shape[0], desire_shape[2]),
dtype=np.float32), device=device).contiguous().realize(),
'packed_npy_inputs': Tensor(packed_npy_inputs, device='NPY').realize(),
}
if features_buffer:
queues['feat_q'] = Tensor(np.zeros((frame_skip * (features_buffer[1] - 1) + 1, features_buffer[0], features_buffer[2]),
dtype=np.float32), device=device).contiguous().realize()
queues.update({key: Tensor(value, device='NPY').realize() for key, value in npy_arrays.items() if key in ('tfm', 'big_tfm')})
else:
# TODO-SP: Remove legacy queuing fallback else block after all models are recompiled
npy_arrays = {
'desire': np.zeros(desire_shape[2], dtype=np.float32),
'tfm': np.zeros((3, 3), dtype=np.float32),
'big_tfm': np.zeros((3, 3), dtype=np.float32)
}
for key, shape in input_shapes.items():
if key not in npy_arrays and 'img' not in key and key not in ('features_buffer', desire_key):
npy_arrays[key] = np.zeros(shape, dtype=np.float32)
queues = {
'img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
'big_img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
'desire_q': Tensor(np.zeros((frame_skip * desire_shape[1], desire_shape[0], desire_shape[2]),
dtype=np.float32), device=device).contiguous().realize()
}
if features_buffer:
queues['feat_q'] = Tensor(np.zeros((frame_skip * (features_buffer[1] - 1) + 1, features_buffer[0], features_buffer[2]),
dtype=np.float32), device=device).contiguous().realize()
queues.update({key: Tensor(value, device='NPY').realize() for key, value in npy_arrays.items()})
return queues, npy_arrays
def make_run_supercombo(model_runner, nv12: NV12Frame, model_w, model_h,
features_slice, frame_skip, input_shapes, prepare_only=False):
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
def make_split_input_queues(vision_input_shapes: dict, policy_input_shapes: dict,
frame_skip: int, device: str = Device.DEFAULT, use_packed: bool = True) -> tuple[dict, dict]:
return generate_queues_and_npy({**vision_input_shapes, **policy_input_shapes}, frame_skip, device, is_supercombo=False, use_packed=use_packed)
def make_supercombo_input_queues(input_shapes: dict, frame_skip: int,
device: str = Device.DEFAULT, use_packed: bool = True) -> tuple[dict, dict]:
return generate_queues_and_npy(input_shapes, frame_skip, device, is_supercombo=True, use_packed=use_packed)
def create_jit_runner(vision_runner, policy_runners: list, nv12: NV12Frame, model_size: tuple[int, int],
features_slice: slice, frame_skip: int, input_shapes: dict, prepare_only: bool):
frame_prepare = make_frame_prepare(nv12, *model_size)
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
desire_key = _detect_desire_key(input_shapes)
if desire_key is None:
raise ValueError(f"No desire* key found in input_shapes: {list(input_shapes.keys())}")
road_img_key, wide_img_key = _detect_vision_keys(input_shapes)
extra_policy_keys = [k for k in input_shapes
if k not in (desire_key, 'features_buffer', 'traffic_convention')
and 'img' not in k]
road_key, wide_key = _detect_vision_keys(input_shapes)
def run_supercombo(img_q, big_img_q, feat_q, desire_q,
frame, big_frame, **kwargs):
desire = kwargs.get(desire_key)
traffic_convention = kwargs.get('traffic_convention')
tfm = kwargs['tfm']
big_tfm = kwargs['big_tfm']
if not desire_key or not road_key or not wide_key:
raise ValueError("Missing required vision or desire keys in input shapes.")
tfm = tfm.to(Device.DEFAULT)
big_tfm = big_tfm.to(Device.DEFAULT)
desire = desire.to(Device.DEFAULT)
traffic_convention = traffic_convention.to(Device.DEFAULT)
Tensor.realize(tfm, big_tfm, desire, traffic_convention)
is_supercombo = vision_runner is None
npy_shapes, npy_sizes = get_policy_npy_shapes(input_shapes, is_supercombo=is_supercombo)
img = shift_and_sample(img_q, frame_prepare(frame, tfm).unsqueeze(0), sample_skip_fn)
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm).unsqueeze(0), sample_skip_fn)
def runner(img_q, big_img_q, feat_q, packed_npy_inputs, frame, big_frame, tfm, big_tfm, **kwargs):
desire_q = kwargs['desire_q']
packed_npy_inputs_dev = packed_npy_inputs.to(Device.DEFAULT)
tfm_dev = tfm.to(Device.DEFAULT)
big_tfm_dev = big_tfm.to(Device.DEFAULT)
Tensor.realize(packed_npy_inputs_dev, tfm_dev, big_tfm_dev)
img = shift_and_sample(img_q, frame_prepare(frame, tfm_dev).unsqueeze(0), sample_skip_fn).realize()
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm_dev).unsqueeze(0), sample_skip_fn).realize()
if prepare_only:
return img, big_img
desire_buf = shift_and_sample(desire_q, desire.reshape(1, 1, -1), sample_desire_fn)
feat_buf = sample_skip_fn(feat_q)
unpacked_tensors = [tensor.reshape(shape) for tensor, shape in zip(packed_npy_inputs_dev.split(npy_sizes), npy_shapes.values(), strict=True)]
unpacked_dict = dict(zip(npy_shapes.keys(), unpacked_tensors, strict=True))
inputs = {road_img_key: img, wide_img_key: big_img,
desire_key: desire_buf, 'features_buffer': feat_buf,
'traffic_convention': traffic_convention}
for k in extra_policy_keys:
if k in kwargs:
inputs[k] = kwargs[k].to(Device.DEFAULT)
desire_dev = unpacked_dict['desire']
desire_buf = shift_and_sample(desire_q, desire_dev.reshape(1, 1, -1), sample_desire_fn).realize()
model_out = next(iter(model_runner(inputs).values())).cast('float32')
inputs = {desire_key: desire_buf}
for key, tensor_val in unpacked_dict.items():
if key not in ('desire', 'prev_feat'):
inputs[key] = tensor_val
new_feat = model_out[:, features_slice].reshape(1, -1).unsqueeze(0)
shift_and_sample(feat_q, new_feat, sample_skip_fn)
if 'prev_feat' in unpacked_dict:
prev_feat_dev = unpacked_dict['prev_feat']
inputs['features_buffer'] = shift_and_sample(feat_q, prev_feat_dev.reshape(1, 1, -1), sample_skip_fn).realize()
return model_out
if vision_runner:
vision_out_cast = next(iter(vision_runner({road_key: img, wide_key: big_img}).values())).cast('float32').realize()
if 'features_buffer' not in inputs:
new_feat = vision_out_cast[:, features_slice].reshape(1, -1).unsqueeze(0)
inputs['features_buffer'] = shift_and_sample(feat_q, new_feat, sample_skip_fn).realize()
policy_outs = [next(iter(pol_runner(inputs).values())).cast('float32').realize() for pol_runner in policy_runners]
return (vision_out_cast, *policy_outs) if len(policy_outs) > 1 else (vision_out_cast, policy_outs[0])
return run_supercombo
inputs.update({road_key: img, wide_key: big_img})
if 'features_buffer' not in inputs:
inputs['features_buffer'] = sample_skip_fn(feat_q)
policy_out = next(iter(policy_runners[0](inputs).values())).cast('float32').realize()
if 'features_buffer' not in inputs and features_slice is not None:
new_feat = policy_out[:, features_slice].reshape(1, -1).unsqueeze(0)
shift_and_sample(feat_q, new_feat, sample_skip_fn).realize()
return policy_out
return runner
def make_run_vision_multi_policy(vision_runner, policy_runners, nv12: NV12Frame, model_w, model_h,
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
vision_road_key, vision_wide_key, prepare_only=False):
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
def compile_and_warmup(nv12: NV12Frame, model_size: tuple[int, int], prepare_only: bool, frame_skip: int, vision_runner, policy_runners: list, metadata: dict):
print(f"Compiling combined JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
def run_multi_policy(img_q, big_img_q, feat_q, desire_q, desire,
traffic_convention, tfm, big_tfm, frame, big_frame, **extra):
npy_tensors = [tfm.to(Device.DEFAULT), big_tfm.to(Device.DEFAULT),
desire.to(Device.DEFAULT), traffic_convention.to(Device.DEFAULT)]
extra_device = {k: extra[k].to(Device.DEFAULT) for k in extra_policy_keys}
Tensor.realize(*npy_tensors, *extra_device.values())
tfm, big_tfm, desire, traffic_convention = npy_tensors
all_shapes = {key: value for meta in metadata.values() for key, value in meta['input_shapes'].items()}
img = shift_and_sample(img_q, frame_prepare(frame, tfm).unsqueeze(0), sample_skip_fn)
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm).unsqueeze(0), sample_skip_fn)
feat_meta = metadata.get('vision') or metadata.get('model') or metadata.get('policy')
if not feat_meta:
raise ValueError("Could not find vision, model, or policy metadata.")
if prepare_only:
return img, big_img
features_slice = feat_meta['output_slices']['hidden_state']
WARP_DEV = 'CPU' if "USBGPU" in os.environ else Device.DEFAULT
vision_out = next(iter(vision_runner({vision_road_key: img, vision_wide_key: big_img}).values())).cast('float32')
is_supercombo = vision_runner is None
run_func = create_jit_runner(vision_runner, policy_runners, nv12, model_size, features_slice, frame_skip, all_shapes, prepare_only)
run_jit = TinyJit(run_func, prune=True)
queues, npy_arrays = generate_queues_and_npy(all_shapes, frame_skip, Device.DEFAULT, is_supercombo=is_supercombo)
new_feat = vision_out[:, vision_features_slice].reshape(1, -1).unsqueeze(0)
feat_buf = shift_and_sample(feat_q, new_feat, sample_skip_fn)
desire_buf = shift_and_sample(desire_q, desire.reshape(1, 1, -1), sample_desire_fn)
inputs = {'features_buffer': feat_buf, desire_key: desire_buf, 'traffic_convention': traffic_convention, **extra_device}
policy_outputs = []
for runner in policy_runners:
policy_out = next(iter(runner(inputs).values())).cast('float32')
policy_outputs.append(policy_out)
return (vision_out, *policy_outputs)
return run_multi_policy
def _warmup_and_serialize(run_jit, input_queues, npy, nv12):
for i in range(3):
rng = np.random.default_rng(42 + i)
frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
big_frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
for v in npy.values():
v[:] = rng.standard_normal(v.shape).astype(v.dtype)
frame = Tensor.randint(nv12.size, low=0, high=256, dtype=dtypes.uint8, device=WARP_DEV).realize()
big_frame = Tensor.randint(nv12.size, low=0, high=256, dtype=dtypes.uint8, device=WARP_DEV).realize()
for arr in npy_arrays.values():
arr[:] = rng.standard_normal(arr.shape).astype(arr.dtype)
Device.default.synchronize()
st = time.perf_counter()
run_jit(**input_queues, frame=frame, big_frame=big_frame)
mt = time.perf_counter()
start_time = time.perf_counter()
run_jit(**queues, frame=frame, big_frame=big_frame)
mid_time = time.perf_counter()
Device.default.synchronize()
et = time.perf_counter()
print(f" [{i + 1}/3] enqueue {(mt - st) * 1e3:6.2f} ms -- total {(et - st) * 1e3:6.2f} ms")
return pickle.loads(pickle.dumps(run_jit))
print(f" [{i + 1}/3] enqueue {(mid_time - start_time) * 1e3:6.2f} ms -- total {(time.perf_counter() - start_time) * 1e3:6.2f} ms")
# TODO-SP: switch to dump_oob/load_oob on next full recompile of all models
return pickle.loads(pickle.dumps(run_jit)) if not prepare_only else run_jit
def compile_supercombo(nv12: NV12Frame, model_w, model_h, prepare_only, frame_skip,
model_runner, metadata):
print(f"Compiling combined supercombo JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
features_slice = metadata['output_slices']['hidden_state']
input_shapes = metadata['input_shapes']
_run = make_run_supercombo(model_runner, nv12, model_w, model_h,
features_slice, frame_skip, input_shapes, prepare_only)
run_jit = TinyJit(_run, prune=True)
input_queues, npy = make_supercombo_input_queues(input_shapes, frame_skip, Device.DEFAULT)
run_jit = _warmup_and_serialize(run_jit, input_queues, npy, nv12)
return run_jit
def _parse_size(size_str: str) -> tuple[int, int]:
width, height = size_str.lower().split('x')
return int(width), int(height)
def compile_multi_policy(nv12: NV12Frame, model_w, model_h, prepare_only, frame_skip,
vision_runner, policy_runners, vision_metadata, policy_metadata):
print(f"Compiling combined multi-policy JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
vision_features_slice = vision_metadata['output_slices']['hidden_state']
vision_input_shapes = vision_metadata['input_shapes']
policy_input_shapes = policy_metadata['input_shapes']
desire_key = _detect_desire_key(policy_input_shapes)
extra_policy_keys = [k for k in policy_input_shapes if k not in ('features_buffer', desire_key, 'traffic_convention')]
vision_road_key, vision_wide_key = _detect_vision_keys(vision_input_shapes)
_run = make_run_vision_multi_policy(vision_runner, policy_runners, nv12, model_w, model_h,
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
vision_road_key, vision_wide_key, prepare_only)
run_jit = TinyJit(_run, prune=True)
input_queues, npy = make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, Device.DEFAULT)
run_jit = _warmup_and_serialize(run_jit, input_queues, npy, nv12)
return run_jit
def read_file_chunked_to_shm(path):
if not path:
return None
import atexit
import shutil
from openpilot.common.file_chunker import open_file_chunked
from openpilot.common.hardware.hw import Paths
shm_path = os.path.join(Paths.shm_path(), os.path.basename(path))
atexit.register(lambda: os.path.exists(shm_path) and os.remove(shm_path))
with open(shm_path, 'wb') as dst, open_file_chunked(path) as src:
shutil.copyfileobj(src, dst)
return shm_path
def _parse_size(s):
w, h = s.lower().split('x')
return int(w), int(h)
def _compile_for_resolutions(camera_resolutions: list, model_size: tuple[int, int], frame_skip: int,
vision_runner, policy_runners: list, metadata: dict) -> dict:
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
return {
(cam_w, cam_h): {
name: compile_and_warmup(NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h)), model_size, prepare_only,
frame_skip, vision_runner, policy_runners, metadata)
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
}
for cam_w, cam_h in camera_resolutions
}
def _load_policy_runners(args: argparse.Namespace) -> tuple[list, list]:
runners, keys = [], []
for name, onnx_arg in [('policy', args.policy_onnx), ('off_policy', args.off_policy_onnx), ('on_policy', args.on_policy_onnx)]:
if onnx_arg:
runners.append(OnnxRunner(onnx_arg))
keys.append(name)
return runners, keys
if __name__ == "__main__":
from tinygrad.nn.onnx import OnnxRunner
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
from openpilot.selfdrive.modeld.get_model_metadata import make_metadata_dict
from tinygrad.nn.onnx import OnnxRunner
p = argparse.ArgumentParser(description="Compile combined JIT pkl for sunnypilot modeld_v2")
p.add_argument('--model-type', choices=MODEL_TYPES, required=True)
p.add_argument('--model-size', type=_parse_size, required=True, help='model input WxH')
p.add_argument('--camera-resolutions', type=_parse_size, nargs='+', required=True)
p.add_argument('--frame-skip', type=int, default=None, help='frame skip value (auto-derived if not provided)')
p.add_argument('--output', required=True)
parser = argparse.ArgumentParser(description="Compile combined JIT pkl for sunnypilot modeld_v2")
parser.add_argument('--model-type', choices=MODEL_TYPES, required=True)
parser.add_argument('--model-size', type=_parse_size, required=True, help='model input WxH')
parser.add_argument('--camera-resolutions', type=_parse_size, nargs='+', required=True)
parser.add_argument('--frame-skip', type=int, default=None, help='frame skip value (auto-derived if not provided)')
parser.add_argument('--output', required=True)
p.add_argument('--vision-onnx', help='vision ONNX (for split models)')
p.add_argument('--policy-onnx', help='policy ONNX (for vision_policy)')
p.add_argument('--off-policy-onnx', help='off-policy ONNX (for vision_multi_policy)')
p.add_argument('--on-policy-onnx', help='on-policy ONNX (for vision_multi_policy)')
p.add_argument('--supercombo-onnx', help='supercombo ONNX (for supercombo)')
parser.add_argument('--vision-onnx', help='vision ONNX (for split models)')
parser.add_argument('--policy-onnx', help='policy ONNX (for vision_policy)')
parser.add_argument('--off-policy-onnx', help='off-policy ONNX (for vision_multi_policy)')
parser.add_argument('--on-policy-onnx', help='on-policy ONNX (for vision_multi_policy)')
parser.add_argument('--supercombo-onnx', help='supercombo ONNX (for supercombo)')
args = p.parse_args()
out = defaultdict(dict)
args = parser.parse_args()
output_data = defaultdict(dict)
args.vision_onnx = read_file_chunked_to_shm(args.vision_onnx)
args.policy_onnx = read_file_chunked_to_shm(args.policy_onnx)
args.off_policy_onnx = read_file_chunked_to_shm(args.off_policy_onnx)
args.on_policy_onnx = read_file_chunked_to_shm(args.on_policy_onnx)
args.supercombo_onnx = read_file_chunked_to_shm(args.supercombo_onnx)
vision_runner = OnnxRunner(args.vision_onnx) if args.vision_onnx else None
if args.model_type == 'vision_policy':
assert args.vision_onnx and args.policy_onnx
vision_runner = OnnxRunner(args.vision_onnx)
policy_runner = OnnxRunner(args.policy_onnx)
out['metadata']['vision'] = make_metadata_dict(args.vision_onnx)
out['metadata']['policy'] = make_metadata_dict(args.policy_onnx)
frame_skip = args.frame_skip if args.frame_skip is not None else derive_frame_skip(out['metadata']['vision']['input_shapes'],
out['metadata']['policy']['input_shapes'])
for cam_w, cam_h in args.camera_resolutions:
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
model_w, model_h = args.model_size
out[(cam_w, cam_h)] = {
name: compile_split_policy(nv12, model_w, model_h, prepare_only, frame_skip,
vision_runner, policy_runner,
out['metadata']['vision'], out['metadata']['policy'])
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
}
assert vision_runner and args.policy_onnx
policy_runners = [OnnxRunner(args.policy_onnx)]
output_data['metadata'] = {'vision': make_metadata_dict(args.vision_onnx), 'policy': make_metadata_dict(args.policy_onnx)}
elif args.model_type == 'supercombo':
assert args.supercombo_onnx
model_runner = OnnxRunner(args.supercombo_onnx)
out['metadata']['model'] = make_metadata_dict(args.supercombo_onnx)
frame_skip = args.frame_skip if args.frame_skip is not None else derive_frame_skip({}, out['metadata']['model']['input_shapes'])
for cam_w, cam_h in args.camera_resolutions:
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
model_w, model_h = args.model_size
out[(cam_w, cam_h)] = {
name: compile_supercombo(nv12, model_w, model_h, prepare_only, frame_skip,
model_runner, out['metadata']['model'])
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
}
policy_runners = [OnnxRunner(args.supercombo_onnx)]
output_data['metadata'] = {'model': make_metadata_dict(args.supercombo_onnx)}
elif args.model_type == 'vision_multi_policy':
assert args.vision_onnx
vision_runner = OnnxRunner(args.vision_onnx)
out['metadata']['vision'] = make_metadata_dict(args.vision_onnx)
assert vision_runner
policy_runners, policy_names = _load_policy_runners(args)
output_data['metadata'] = {'vision': make_metadata_dict(args.vision_onnx)}
for name in policy_names:
runner_arg = getattr(args, f"{name}_onnx")
output_data['metadata'][name] = make_metadata_dict(runner_arg)
policy_runners = []
policy_onnxes = []
if args.policy_onnx:
policy_onnxes.append(('policy', args.policy_onnx))
if args.off_policy_onnx:
policy_onnxes.append(('off_policy', args.off_policy_onnx))
if args.on_policy_onnx:
policy_onnxes.append(('on_policy', args.on_policy_onnx))
policy_keys = [key for key in output_data['metadata'].keys() if key != 'vision']
first_policy_meta = output_data['metadata'][policy_keys[0]] if policy_keys else {}
vision_meta = output_data['metadata'].get('vision', {})
for name, onnx_path in policy_onnxes:
runner = OnnxRunner(onnx_path)
policy_runners.append(runner)
out['metadata'][name] = make_metadata_dict(onnx_path)
derived_frame_skip = args.frame_skip or derive_frame_skip(vision_meta.get('input_shapes', {}), first_policy_meta.get('input_shapes', {}))
output_data.update(_compile_for_resolutions(args.camera_resolutions, args.model_size, derived_frame_skip,
vision_runner, policy_runners, output_data['metadata']))
first_policy_key = policy_onnxes[0][0]
frame_skip = args.frame_skip if args.frame_skip is not None else derive_frame_skip(out['metadata']['vision']['input_shapes'],
out['metadata'][first_policy_key]['input_shapes'])
with open(args.output, "wb") as file:
# TODO-SP: switch to dump_oob from openpilot/selfdrive/helpers on next full recompile of all models
pickle.dump(output_data, file)
for cam_w, cam_h in args.camera_resolutions:
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
model_w, model_h = args.model_size
out[(cam_w, cam_h)] = {
name: compile_multi_policy(nv12, model_w, model_h, prepare_only, frame_skip,
vision_runner, policy_runners,
out['metadata']['vision'], out['metadata'][first_policy_key])
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
}
with open(args.output, "wb") as f:
pickle.dump(out, f)
pkl_size = os.path.getsize(args.output)
print(f"Saved combined JIT to {args.output} ({pkl_size / 1e6:.2f} MB)")
from openpilot.common.file_chunker import chunk_file, get_chunk_targets
chunk_targets = get_chunk_targets(args.output, pkl_size)
chunk_file(args.output, chunk_targets)
num_chunks = len(chunk_targets) - 1
print(f"Chunked into {num_chunks} file(s)")
print(f"Chunked into {len(chunk_targets) - 1} file(s)")
@@ -1,75 +0,0 @@
#!/usr/bin/env python3
import sys
import shutil
import pickle
import codecs
from pathlib import Path
from openpilot.common.hardware.hw import Paths
from openpilot.sunnypilot.modeld_v2.get_model_metadata import MetadataOnnxPBParser, get_name_and_shape, get_metadata_value_by_name
def generate_metadata_pkl(model_path, output_path):
try:
model = MetadataOnnxPBParser(model_path).parse()
output_slices = get_metadata_value_by_name(model, 'output_slices')
if not output_slices:
return False
metadata = {
'model_checkpoint': get_metadata_value_by_name(model, 'model_checkpoint'),
'output_slices': pickle.loads(codecs.decode(output_slices.encode(), "base64")),
'input_shapes': dict(get_name_and_shape(x) for x in model["graph"]["input"]),
'output_shapes': dict(get_name_and_shape(x) for x in model["graph"]["output"]),
}
with open(output_path, 'wb') as f:
pickle.dump(metadata, f)
return True
except Exception:
return False
def install_models(model_dir):
model_dir = Path(model_dir)
models = ["driving_off_policy", "driving_on_policy", "driving_vision"]
found_models = []
for model in models:
if (model_dir / f"{model}.onnx").exists():
found_models.append(model)
if not found_models:
return
try:
custom_name = input(f"Found models ({', '.join(found_models)}). Enter model short name (e.g. wmiv4): ").strip()
except EOFError:
return
if not custom_name:
print("No name provided, skipping installation.")
return
dest_dir = Path(Paths.model_root())
dest_dir.mkdir(parents=True, exist_ok=True)
for model in found_models:
onnx_path = model_dir / f"{model}.onnx"
tinygrad_pkl = model_dir / f"{model}_tinygrad.pkl"
metadata_pkl = model_dir / f"{model}_metadata.pkl"
if not metadata_pkl.exists():
generate_metadata_pkl(onnx_path, metadata_pkl)
dest_tinygrad = dest_dir / f"{model}_{custom_name}_tinygrad.pkl"
dest_metadata = dest_dir / f"{model}_{custom_name}_metadata.pkl"
if tinygrad_pkl.exists():
shutil.move(str(tinygrad_pkl), str(dest_tinygrad))
if metadata_pkl.exists():
shutil.move(str(metadata_pkl), str(dest_metadata))
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: install_models_pc.py <model_dir>")
sys.exit(1)
install_models(sys.argv[1])
+89 -34
View File
@@ -7,6 +7,7 @@ See the LICENSE.md file in the root directory for more details.
"""
import os
os.environ['GMMU'] = '0'
from openpilot.common.hardware import TICI
os.environ['DEV'] = 'QCOM' if TICI else 'CPU'
USBGPU = "USBGPU" in os.environ
@@ -23,6 +24,11 @@ from setproctitle import setproctitle
from openpilot.cereal.messaging import PubMaster, SubMaster
from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
from opendbc.car.car_helpers import get_demo_car_params
from tinygrad.tensor import Tensor
from tinygrad.device import Device
from openpilot.common.file_chunker import open_file_chunked
from openpilot.common.swaglog import cloudlog
from openpilot.common.params import Params
from openpilot.common.filter_simple import FirstOrderFilter
@@ -30,6 +36,7 @@ from openpilot.common.realtime import config_realtime_process, DT_MDL
from openpilot.common.transformations.camera import DEVICE_CAMERAS
from openpilot.common.transformations.model import get_warp_matrix
from openpilot.system import sentry
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value
@@ -37,10 +44,12 @@ from openpilot.sunnypilot.modeld_v2.fill_model_msg import fill_model_msg, fill_p
from openpilot.sunnypilot.modeld_v2.constants import Plan
from openpilot.sunnypilot.modeld_v2.meta_helper import load_meta_constants
from openpilot.sunnypilot.modeld_v2.camera_offset_helper import CameraOffsetHelper
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
from openpilot.sunnypilot.modeld_v2.modeld_base import ModelStateBase
from openpilot.sunnypilot.models.helpers import get_active_bundle
from openpilot.sunnypilot.selfdrive.controls.lib.relc import RoadEdgeLaneChangeController
PROCESS_NAME = "openpilot.selfdrive.modeld.modeld_tinygrad"
@@ -99,29 +108,37 @@ class ModelState(ModelStateBase):
self._init_combined(pkl_path, cam_w, cam_h, model_bundle)
def _init_combined(self, pkl_path, cam_w, cam_h, bundle):
from tinygrad.tensor import Tensor
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues
from tinygrad.device import Device
from openpilot.common.file_chunker import open_file_chunked
cloudlog.warning(f"loading combined pkl: {pkl_path}")
# TODO-SP: switch to load_oob from openpilot/selfdrive/helpers on next full recompile of all models
jits = pickle.load(open_file_chunked(pkl_path))
self.DEV = Device.DEFAULT
self.WARP_DEV = 'CPU' if USBGPU else self.DEV
self.QUEUE_DEV = self.DEV
metadata = jits['metadata']
self._run_policy = jits[(cam_w, cam_h)]['run_policy']
self._warp_enqueue = jits[(cam_w, cam_h)]['warp_enqueue']
# TODO-SP: Remove legacy use_packed detection block after all models are recompiled
captured = getattr(self._run_policy, 'captured', None)
if captured is not None:
use_packed = 'packed_npy_inputs' in getattr(captured, 'expected_names', [])
else:
use_packed = True
if 'model' in metadata:
model_metadata = metadata['model']
self.vision_output_slices = model_metadata['output_slices']
self.policy_output_slices = {}
self._policy_slices_list = []
self._combined_model_type = 'supercombo'
self._vision_input_names = [k for k in model_metadata['input_shapes'] if 'img' in k]
self._vision_input_names = [key for key in model_metadata['input_shapes'] if 'img' in key]
from openpilot.sunnypilot.modeld_v2.compile_modeld import make_supercombo_input_queues
frame_skip = derive_frame_skip({}, model_metadata['input_shapes'])
self.input_queues, self.numpy_inputs = make_supercombo_input_queues(model_metadata['input_shapes'], frame_skip, device=self.DEV)
self.input_queues, self.numpy_inputs = make_supercombo_input_queues(model_metadata['input_shapes'],
frame_skip, device=self.QUEUE_DEV, use_packed=use_packed)
else:
vision_metadata = metadata['vision']
policy_keys = [k for k in metadata if k != 'vision']
@@ -139,11 +156,12 @@ class ModelState(ModelStateBase):
policy_input_shapes = first_policy_metadata['input_shapes']
self._vision_input_names = [k for k in vision_input_shapes if 'img' in k]
frame_skip = derive_frame_skip(vision_input_shapes, policy_input_shapes)
self.input_queues, self.numpy_inputs = make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, device=self.DEV)
self.input_queues, self.numpy_inputs = make_split_input_queues(vision_input_shapes, policy_input_shapes,
frame_skip, device=self.QUEUE_DEV, use_packed=use_packed)
from openpilot.sunnypilot.modeld_v2.parse_model_outputs_split import Parser as SplitParser
from openpilot.sunnypilot.modeld_v2.parse_model_outputs import Parser as CombinedParser
self.parser = SplitParser() if self._combined_model_type != 'supercombo' else CombinedParser()
self._desire_key = next(key for key in self.numpy_inputs if key.startswith('desire'))
self._road_key = next(key for key in self._vision_input_names if 'big' not in key)
self._wide_key = next(key for key in self._vision_input_names if 'big' in key)
is_20hz = bundle.is20hz if bundle else self._combined_model_type in ('split', 'multi_policy')
if is_20hz:
@@ -153,20 +171,24 @@ class ModelState(ModelStateBase):
from openpilot.sunnypilot.modeld_v2.constants import ModelConstants
self.constants = ModelConstants()
if self._combined_model_type != 'supercombo':
from openpilot.sunnypilot.modeld_v2.parse_model_outputs_split import Parser as SplitParser
self.parser = SplitParser()
else:
from openpilot.sunnypilot.modeld_v2.parse_model_outputs import Parser as CombinedParser
self.parser = CombinedParser()
self.prev_desire = np.zeros(self.constants.DESIRE_LEN, dtype=np.float32)
self.full_frames: dict = {}
self._blob_cache: dict = {}
nv12_info = get_nv12_info(cam_w, cam_h)
self.frame_buf_params = dict.fromkeys(self._vision_input_names, nv12_info)
self._run_policy = jits[(cam_w, cam_h)]['run_policy']
self._warp_enqueue = jits[(cam_w, cam_h)]['warp_enqueue']
road_name = next(k for k in self._vision_input_names if 'big' not in k)
yuv_size = self.frame_buf_params[road_name][3]
yuv_size = self.frame_buf_params[self._road_key][3]
self._warp_enqueue(
**self.input_queues,
frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.DEV).contiguous().realize(),
big_frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.DEV).contiguous().realize())
frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.WARP_DEV).contiguous().realize(),
big_frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.WARP_DEV).contiguous().realize())
@property
@@ -179,30 +201,28 @@ class ModelState(ModelStateBase):
@property
def desire_key(self) -> str:
return next(k for k in self.numpy_inputs if k.startswith('desire'))
return self._desire_key
def run(self, bufs: dict[str, VisionBuf], transforms: dict[str, np.ndarray],
inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None:
from tinygrad.tensor import Tensor
for key in bufs.keys():
ptr = np.frombuffer(bufs[key].data, dtype=np.uint8).ctypes.data
yuv_size = self.frame_buf_params[key][3]
cache_key = (key, ptr)
if cache_key not in self._blob_cache:
self._blob_cache[cache_key] = Tensor.from_blob(ptr, (yuv_size,), dtype='uint8', device=self.DEV)
self._blob_cache[cache_key] = Tensor.from_blob(ptr, (yuv_size,), dtype='uint8', device=self.WARP_DEV)
self.full_frames[key] = self._blob_cache[cache_key]
desire_key = self.desire_key
inputs[desire_key][0] = 0
self.numpy_inputs[desire_key][:] = np.where(inputs[desire_key] - self.prev_desire > .99, inputs[desire_key], 0)
self.prev_desire[:] = inputs[desire_key]
for key in ('traffic_convention', 'lateral_control_params'):
for key in ('traffic_convention', 'lateral_control_params', 'action_t'):
if key in self.numpy_inputs and key in inputs:
self.numpy_inputs[key][:] = inputs[key]
road_key = next(n for n in bufs if 'big' not in n)
wide_key = next(n for n in bufs if 'big' in n)
road_key = self._road_key
wide_key = self._wide_key
self.numpy_inputs['tfm'][:, :] = transforms[road_key].reshape(3, 3)
self.numpy_inputs['big_tfm'][:, :] = transforms[wide_key].reshape(3, 3)
@@ -216,17 +236,26 @@ class ModelState(ModelStateBase):
model_output = raw_outputs.numpy().flatten()
sliced = {k: model_output[np.newaxis, v] for k, v in self.vision_output_slices.items()}
outputs = self.parser.parse_outputs(sliced)
if 'prev_feat' in self.numpy_inputs:
self.numpy_inputs['prev_feat'][:] = model_output[self.vision_output_slices['hidden_state']]
else:
vision_output = raw_outputs[0].numpy().flatten()
vision_sliced = {k: vision_output[np.newaxis, v] for k, v in self.vision_output_slices.items()}
outputs = self.parser.parse_vision_outputs(vision_sliced)
if 'prev_feat' in self.numpy_inputs and 'hidden_state' in self.vision_output_slices:
self.numpy_inputs['prev_feat'][:] = vision_output[self.vision_output_slices['hidden_state']]
for i, policy_slices in enumerate(self._policy_slices_list):
policy_output = raw_outputs[i + 1].numpy().flatten()
policy_sliced = {k: policy_output[np.newaxis, v] for k, v in policy_slices.items()}
parsed = self.parser.parse_policy_outputs(policy_sliced)
if 'off' in self._policy_keys[i] and self._has_on_policy:
if ('off' in self._policy_keys[i]
and self._has_on_policy
and any('plan' in self._policy_slices_list[j] for j, k in enumerate(self._policy_keys) if 'on' in k.lower())):
parsed.pop('plan', None)
outputs.update(parsed)
if 'planplus' in outputs and 'plan' in outputs:
@@ -237,17 +266,30 @@ class ModelState(ModelStateBase):
buf[0, :-1] = buf[0, 1:]
buf[0, -1, :] = outputs['desired_curvature'][0, :] if not self.mlsim else 0
# TODO-SP: This is a hack to prevent GPU corruption by calculating in CPU space, it can be removed on next recompile
if 'prev_feat' not in self.numpy_inputs and 'feat_q' in self.input_queues:
feat_val = self.input_queues['feat_q'].numpy()
self.input_queues['feat_q'].assign(feat_val).realize()
return outputs
def get_action_from_model(self, model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action,
lat_action_t: float, long_action_t: float, v_ego: float) -> log.ModelDataV2.Action:
plan = model_output['plan'][0]
desired_accel, should_stop = get_accel_from_plan(plan[:, Plan.VELOCITY][:, 0], plan[:, Plan.ACCELERATION][:, 0], self.constants.T_IDXS,
action_t=long_action_t)
if 'action' not in model_output:
plan = model_output['plan'][0]
desired_accel, should_stop = get_accel_from_plan(plan[:, Plan.VELOCITY][:, 0], plan[:, Plan.ACCELERATION][:, 0], self.constants.T_IDXS,
action_t=long_action_t)
curvature_plan = (plan + (self.PLANPLUS_CONTROL - 1.0) * model_output['planplus'][0]
if 'planplus' in model_output and self.PLANPLUS_CONTROL != 1.0 else plan)
desired_curvature = get_curvature_from_output(model_output, curvature_plan, v_ego, lat_action_t, self.mlsim)
else:
desired_accel = model_output['action'][0, 1]
desired_curvature = model_output['action'][0, 0] / (max(1.0, v_ego))**2
should_stop = (v_ego < 0.3 and desired_accel < 0.1)
desired_accel = smooth_value(desired_accel, prev_action.desiredAcceleration, self.LONG_SMOOTH_SECONDS)
curvature_plan = plan + (self.PLANPLUS_CONTROL - 1.0) * model_output['planplus'][0] if 'planplus' in model_output and self.PLANPLUS_CONTROL != 1.0 else plan
desired_curvature = get_curvature_from_output(model_output, curvature_plan, v_ego, lat_action_t, self.mlsim)
if self.generation is not None and self.generation >= 10: # smooth curvature for post FOF models
if v_ego > self.MIN_LAT_CONTROL_SPEED:
desired_curvature = smooth_value(desired_curvature, prev_action.desiredCurvature, self.LAT_SMOOTH_SECONDS)
@@ -325,6 +367,7 @@ def main(demo=False):
prev_action = log.ModelDataV2.Action()
DH = DesireHelper()
RELC = RoadEdgeLaneChangeController(DH)
meta_constants = load_meta_constants()
while True:
@@ -400,6 +443,12 @@ def main(demo=False):
bufs = {name: buf_extra if 'big' in name else buf_main for name in model.vision_input_names}
transforms = {name: model_transform_extra if 'big' in name else model_transform_main for name in model.vision_input_names}
frame_delay = DT_MDL # compensate for time passed since the frame was captured: current_time - timestamp_eof is 50ms on average
action_delay = DT_MDL / 2 # middle of the interval between model output (current state) and next frame (expected state)
lat_action_t = lat_delay + frame_delay + action_delay
long_action_t = long_delay + frame_delay + action_delay
inputs:dict[str, np.ndarray] = {
model.desire_key: vec_desire,
'traffic_convention': traffic_convention,
@@ -408,6 +457,9 @@ def main(demo=False):
if 'lateral_control_params' in model.numpy_inputs:
inputs['lateral_control_params'] = np.array([v_ego, lat_delay], dtype=np.float32)
if 'action_t' in model.numpy_inputs:
inputs['action_t'] = np.array([lat_action_t, long_action_t], dtype=np.float32)
mt1 = time.perf_counter()
model_output = model.run(bufs, transforms, inputs, prepare_only)
mt2 = time.perf_counter()
@@ -419,7 +471,7 @@ def main(demo=False):
posenet_send = messaging.new_message('cameraOdometry')
mdv2sp_send = messaging.new_message('modelDataV2SP')
action = model.get_action_from_model(model_output, prev_action, lat_delay + DT_MDL, long_delay + DT_MDL, v_ego)
action = model.get_action_from_model(model_output, prev_action, lat_action_t, long_action_t, v_ego)
prev_action = action
fill_model_msg(drivingdata_send, modelv2_send, model_output, action,
publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id,
@@ -429,7 +481,10 @@ def main(demo=False):
l_lane_change_prob = desire_state[log.Desire.laneChangeLeft]
r_lane_change_prob = desire_state[log.Desire.laneChangeRight]
lane_change_prob = l_lane_change_prob + r_lane_change_prob
DH.update(sm['carState'], sm['carControl'].latActive, lane_change_prob)
RELC.update(modelv2_send.modelV2.roadEdgeStds, modelv2_send.modelV2.laneLineProbs, v_ego)
mdv2sp_send.modelDataV2SP.leftLaneChangeEdgeBlock = RELC.left_edge_detected
mdv2sp_send.modelDataV2SP.rightLaneChangeEdgeBlock = RELC.right_edge_detected
DH.update(sm['carState'], sm['carControl'].latActive, lane_change_prob, RELC.left_edge_detected, RELC.right_edge_detected)
modelv2_send.modelV2.meta.laneChangeState = DH.lane_change_state
modelv2_send.modelV2.meta.laneChangeDirection = DH.lane_change_direction
mdv2sp_send.modelDataV2SP.laneTurnDirection = DH.lane_turn_direction

Some files were not shown because too many files have changed in this diff Show More