mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-24 01:33:46 +08:00
Compare commits
69 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c2f0f4a14 | |||
| b12fdf182d | |||
| 75b1deaf60 | |||
| a9930207ba | |||
| 742c104964 | |||
| 4183698fc6 | |||
| f06c82b2b8 | |||
| b23b4384f1 | |||
| 93bad13469 | |||
| 31e0a5b8cc | |||
| 732830b095 | |||
| 43d42594ef | |||
| e61039bb67 | |||
| 8e8225b6ae | |||
| 01bd291b78 | |||
| 61e28a0ac9 | |||
| c744f66b2a | |||
| 9b177b25b5 | |||
| b9d89a3e85 | |||
| 903fd2264e | |||
| 0f8142a15c | |||
| b95b5b1d53 | |||
| 3d0c3a8a45 | |||
| 9af23999d1 | |||
| 74a9bb5a4e | |||
| cf506e59b0 | |||
| 68d7fd09e2 | |||
| b70680aa86 | |||
| 823ff696ab | |||
| 9b530d520c | |||
| 3d35284a49 | |||
| f425d86457 | |||
| 98a9373346 | |||
| 35a7e43045 | |||
| b535c0845e | |||
| 0ed821d32d | |||
| 2317057411 | |||
| dc3b39a198 | |||
| ce5611f24c | |||
| f819386399 | |||
| e1812ec3d7 | |||
| e9935624f7 | |||
| 0fec51a5d9 | |||
| 3fa2d370bf | |||
| 0750072ef0 | |||
| fb93198a92 | |||
| a4789c9f61 | |||
| 7386073c71 | |||
| 7d8be7079c | |||
| 148929d2f1 | |||
| 13e4f301b9 | |||
| dc91ac13b1 | |||
| a129d591e7 | |||
| 8aa0cf327a | |||
| b78e44303d | |||
| feba46db30 | |||
| a8d501fcd9 | |||
| fb17126f68 | |||
| 693b1f08a3 | |||
| 6e81630e49 | |||
| 76dbf9412a | |||
| 68123093c3 | |||
| 73cbee1b85 | |||
| 0cb613b6ce | |||
| 7834d15127 | |||
| 71ce49a301 | |||
| fd7f75578d | |||
| 4c8452de78 | |||
| 7bebf0ef3c |
Binary file not shown.
@@ -2179,6 +2179,7 @@ struct DriverStateV2 {
|
||||
rightBlinkProb @8 :Float32;
|
||||
sunglassesProb @9 :Float32;
|
||||
phoneProb @13 :Float32;
|
||||
sleepProb @14 :Float32;
|
||||
notReadyProbDEPRECATED @12 :List(Float32);
|
||||
occludedProbDEPRECATED @10 :Float32;
|
||||
readyProbDEPRECATED @11 :List(Float32);
|
||||
|
||||
Binary file not shown.
@@ -367,6 +367,9 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"LoudBlindspotAlert", {PERSISTENT, BOOL, "0", "0", 0}},
|
||||
{"LowVoltageShutdown", {PERSISTENT, FLOAT, "11.8", "11.8", 3}},
|
||||
{"ManualUpdateInitiated", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
|
||||
{"AMapKey1", {PERSISTENT | DONT_LOG, STRING, "", "", 0}},
|
||||
{"AMapKey2", {PERSISTENT | DONT_LOG, STRING, "", "", 0}},
|
||||
{"ApiCache_NavDestinations", {PERSISTENT, JSON, "[]", "[]"}},
|
||||
{"MapAcceleration", {PERSISTENT, BOOL, "0", "0", 1}},
|
||||
{"MapboxPublicKey", {PERSISTENT | DONT_LOG, STRING, "", "", 0}},
|
||||
{"MapBoxRequests", {PERSISTENT, JSON, "{}", "{}"}},
|
||||
@@ -376,6 +379,10 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"MapGears", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"MapsSelected", {PERSISTENT, STRING, "", "", 0}},
|
||||
{"MapSpeedLimit", {CLEAR_ON_MANAGER_START, FLOAT, "0.0", "0.0"}},
|
||||
{"NavDesiresAllowed", {PERSISTENT, BOOL, "1", "0", 2}},
|
||||
{"NavLongitudinalAllowed", {PERSISTENT, BOOL, "1", "0", 2}},
|
||||
{"NavDestination", {PERSISTENT, STRING, "", ""}},
|
||||
{"NavInstructionState", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON, "{}", "{}"}},
|
||||
{"NextMapSpeedLimit", {CLEAR_ON_MANAGER_START, JSON, "{}", "{}"}},
|
||||
{"VisionSpeedLimit", {CLEAR_ON_MANAGER_START, FLOAT, "0.0", "0.0"}},
|
||||
{"VisionSpeedLimitConfidence", {CLEAR_ON_MANAGER_START, FLOAT, "0.0", "0.0"}},
|
||||
@@ -403,7 +410,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"NNFFModelName", {CLEAR_ON_MANAGER_START, STRING, "", "", 0}},
|
||||
{"NoLogging", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"NoUploads", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"NudgelessLaneChange", {PERSISTENT, BOOL, "1", "0", 0}},
|
||||
{"NudgelessLaneChange", {PERSISTENT, BOOL, "0", "0", 0}},
|
||||
{"NumericalTemp", {PERSISTENT, BOOL, "1", "0", 3}},
|
||||
{"Offset1", {PERSISTENT, FLOAT, "5.0", "0.0", 0}},
|
||||
{"Offset2", {PERSISTENT, FLOAT, "5.0", "0.0", 0}},
|
||||
|
||||
Binary file not shown.
+1
-58
@@ -33,64 +33,7 @@ function agnos_init {
|
||||
# StarPilot variables
|
||||
sudo chmod 0777 /cache
|
||||
|
||||
# Weston loads display color correction from /data/misc/display/color_cal/color_cal.
|
||||
# Prefer a factory /persist/comma/color_cal blob when present. Otherwise, derive a
|
||||
# Weston-compatible calibration blob from the device's legacy dwo gamma tables.
|
||||
COLOR_CAL_SRC="/persist/comma/color_cal"
|
||||
DWO_GAMMA_SRC="/persist/comma/dwo_gamma_curves"
|
||||
COLOR_CAL_DST_DIR="/data/misc/display/color_cal"
|
||||
COLOR_CAL_DST="${COLOR_CAL_DST_DIR}/color_cal"
|
||||
COLOR_CAL_HASH_PATH="${COLOR_CAL_DST_DIR}/source.sha256"
|
||||
DWO_REFERENCE="$DIR/tools/reference_dwo_gamma_curves.txt"
|
||||
DWO_GENERATOR="$DIR/tools/generate_color_cal_from_dwo.py"
|
||||
COLOR_CAL_UPDATED=0
|
||||
COLOR_CAL_TMP=""
|
||||
DWO_SOURCE_HASH=""
|
||||
|
||||
if [ -f "$COLOR_CAL_SRC" ]; then
|
||||
sudo mkdir -p "$COLOR_CAL_DST_DIR"
|
||||
if [ ! -f "$COLOR_CAL_DST" ] || ! cmp -s "$COLOR_CAL_SRC" "$COLOR_CAL_DST"; then
|
||||
sudo cp "$COLOR_CAL_SRC" "$COLOR_CAL_DST"
|
||||
sudo chown -R comma:comma "$COLOR_CAL_DST_DIR"
|
||||
sudo chmod 664 "$COLOR_CAL_DST"
|
||||
sudo rm -f "$COLOR_CAL_HASH_PATH"
|
||||
COLOR_CAL_UPDATED=1
|
||||
fi
|
||||
elif [ -f "$DWO_GAMMA_SRC" ] && [ -f "$DWO_REFERENCE" ] && [ -f "$DWO_GENERATOR" ]; then
|
||||
DWO_SOURCE_HASH="$(cat "$DWO_GAMMA_SRC" "$DWO_REFERENCE" "$DWO_GENERATOR" | sha256sum | awk '{print $1}')"
|
||||
if [ ! -f "$COLOR_CAL_DST" ] || [ ! -f "$COLOR_CAL_HASH_PATH" ] || [ "$(cat "$COLOR_CAL_HASH_PATH" 2>/dev/null)" != "$DWO_SOURCE_HASH" ]; then
|
||||
COLOR_CAL_TMP="$(mktemp)"
|
||||
if python3 "$DWO_GENERATOR" --reference "$DWO_REFERENCE" --input "$DWO_GAMMA_SRC" --output "$COLOR_CAL_TMP"; then
|
||||
sudo mkdir -p "$COLOR_CAL_DST_DIR"
|
||||
if [ ! -f "$COLOR_CAL_DST" ] || ! cmp -s "$COLOR_CAL_TMP" "$COLOR_CAL_DST"; then
|
||||
sudo cp "$COLOR_CAL_TMP" "$COLOR_CAL_DST"
|
||||
COLOR_CAL_UPDATED=1
|
||||
fi
|
||||
printf '%s' "$DWO_SOURCE_HASH" | sudo tee "$COLOR_CAL_HASH_PATH" >/dev/null
|
||||
sudo chown -R comma:comma "$COLOR_CAL_DST_DIR"
|
||||
sudo chmod 664 "$COLOR_CAL_DST" "$COLOR_CAL_HASH_PATH"
|
||||
fi
|
||||
rm -f "$COLOR_CAL_TMP"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$COLOR_CAL_UPDATED" = "1" ] && systemctl is-active --quiet weston.service; then
|
||||
sudo systemctl restart weston.service
|
||||
|
||||
# Weston can recreate wayland-0 as root on service restart before weston-ready
|
||||
# fixes ownership. Repair it here so the Qt UI can always reconnect.
|
||||
if [ -d /var/tmp/weston ]; then
|
||||
for _ in $(seq 1 50); do
|
||||
if [ -S /var/tmp/weston/wayland-0 ]; then
|
||||
sudo chown -R comma:comma /var/tmp/weston 2>/dev/null || true
|
||||
sudo chmod -R 700 /var/tmp/weston 2>/dev/null || true
|
||||
SOCKET_OWNER="$(stat -c '%U:%G' /var/tmp/weston/wayland-0 2>/dev/null || true)"
|
||||
[ "$SOCKET_OWNER" = "comma:comma" ] && break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
fi
|
||||
fi
|
||||
sudo rm -f /data/misc/display/color_cal/color_cal /data/misc/display/color_cal/source.sha256
|
||||
|
||||
# Check if AGNOS update is required
|
||||
if [ $(< /VERSION) != "$AGNOS_VERSION" ]; then
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import os
|
||||
from types import SimpleNamespace
|
||||
from typing import get_args
|
||||
|
||||
from collections import defaultdict
|
||||
@@ -32,7 +33,8 @@ def get_params_for_docs(platform) -> CarParams:
|
||||
cp_platform = platform if platform in interfaces else MOCK.MOCK
|
||||
CP: CarParams = interfaces[cp_platform].get_params(cp_platform, fingerprint=gen_empty_fingerprint(),
|
||||
car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)],
|
||||
alpha_long=True, is_release=False, docs=True)
|
||||
alpha_long=True, is_release=False, docs=True,
|
||||
starpilot_toggles=SimpleNamespace())
|
||||
return CP
|
||||
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ 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, Cable.usbc_coupler], has_connector=False)
|
||||
gm = BaseCarHarness("GM connector", parts=[Accessory.harness_box])
|
||||
|
||||
@@ -193,29 +193,43 @@ MIGRATION = {
|
||||
"HYUNDAI IONIQ PLUG-IN HYBRID 2019": HYUNDAI.HYUNDAI_IONIQ_PHEV_2019,
|
||||
"HYUNDAI IONIQ PHEV 2020": HYUNDAI.HYUNDAI_IONIQ_PHEV,
|
||||
"HYUNDAI KONA 2020": HYUNDAI.HYUNDAI_KONA,
|
||||
"HYUNDAI KONA 2ND GEN": HYUNDAI.HYUNDAI_KONA_2ND_GEN,
|
||||
"HYUNDAI KONA ELECTRIC 2019": HYUNDAI.HYUNDAI_KONA_EV,
|
||||
"HYUNDAI KONA ELECTRIC 2022": HYUNDAI.HYUNDAI_KONA_EV_2022,
|
||||
"HYUNDAI KONA ELECTRIC 2ND GEN": HYUNDAI.HYUNDAI_KONA_EV_2ND_GEN,
|
||||
"HYUNDAI KONA HYBRID 2020": HYUNDAI.HYUNDAI_KONA_HEV,
|
||||
"HYUNDAI KONA HYBRID 2ND GEN": HYUNDAI.HYUNDAI_KONA_HEV_2ND_GEN,
|
||||
"HYUNDAI SANTA FE 2019": HYUNDAI.HYUNDAI_SANTA_FE,
|
||||
"HYUNDAI SANTA FE 2022": HYUNDAI.HYUNDAI_SANTA_FE_2022,
|
||||
"HYUNDAI SANTA FE HYBRID 2022": HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022,
|
||||
"HYUNDAI SANTA FE HYBRID 5TH GEN": HYUNDAI.HYUNDAI_SANTA_FE_HEV_5TH_GEN,
|
||||
"HYUNDAI SANTA FE PlUG-IN HYBRID 2022": HYUNDAI.HYUNDAI_SANTA_FE_PHEV_2022,
|
||||
"HYUNDAI SONATA 2020": HYUNDAI.HYUNDAI_SONATA,
|
||||
"HYUNDAI SONATA 2024": HYUNDAI.HYUNDAI_SONATA_2024,
|
||||
"HYUNDAI SONATA 2019": HYUNDAI.HYUNDAI_SONATA_LF,
|
||||
"HYUNDAI STARIA 4TH GEN": HYUNDAI.HYUNDAI_STARIA_4TH_GEN,
|
||||
"HYUNDAI TUCSON 2019": HYUNDAI.HYUNDAI_TUCSON,
|
||||
"HYUNDAI TUCSON 2025": HYUNDAI.HYUNDAI_TUCSON_2025,
|
||||
"HYUNDAI TUCSON HYBRID 2025": HYUNDAI.HYUNDAI_TUCSON_HEV_2025,
|
||||
"HYUNDAI TUCSON PLUG-IN HYBRID 2025": HYUNDAI.HYUNDAI_TUCSON_PHEV_2025,
|
||||
"HYUNDAI PALISADE 2020": HYUNDAI.HYUNDAI_PALISADE,
|
||||
"HYUNDAI PALISADE 2023": HYUNDAI.HYUNDAI_PALISADE_2023,
|
||||
"HYUNDAI VELOSTER 2019": HYUNDAI.HYUNDAI_VELOSTER,
|
||||
"HYUNDAI SONATA HYBRID 2021": HYUNDAI.HYUNDAI_SONATA_HYBRID,
|
||||
"HYUNDAI SONATA HYBRID 2024": HYUNDAI.HYUNDAI_SONATA_HEV_2024,
|
||||
"HYUNDAI IONIQ 5 2022": HYUNDAI.HYUNDAI_IONIQ_5,
|
||||
"HYUNDAI IONIQ 5 2025": HYUNDAI.HYUNDAI_IONIQ_5_PE,
|
||||
"HYUNDAI IONIQ 5 N 2024": HYUNDAI.HYUNDAI_IONIQ_5_N,
|
||||
"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 SANTA CRUZ 2025": HYUNDAI.HYUNDAI_SANTA_CRUZ_2025,
|
||||
"HYUNDAI CUSTIN 1ST GEN": HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN,
|
||||
"KIA FORTE E 2018 & GT 2021": HYUNDAI.KIA_FORTE,
|
||||
"KIA K4 2025": HYUNDAI.KIA_K4_2025,
|
||||
"KIA K5 2021": HYUNDAI.KIA_K5_2021,
|
||||
"KIA K5 2025": HYUNDAI.KIA_K5_2025,
|
||||
"KIA K5 HYBRID 2020": HYUNDAI.KIA_K5_HEV_2020,
|
||||
"KIA K8 HYBRID 1ST GEN": HYUNDAI.KIA_K8_HEV_1ST_GEN,
|
||||
"KIA NIRO EV 2020": HYUNDAI.KIA_NIRO_EV,
|
||||
@@ -230,22 +244,29 @@ MIGRATION = {
|
||||
"KIA OPTIMA HYBRID 4TH GEN FACELIFT": HYUNDAI.KIA_OPTIMA_H_G4_FL,
|
||||
"KIA SELTOS 2021": HYUNDAI.KIA_SELTOS,
|
||||
"KIA SPORTAGE 5TH GEN": HYUNDAI.KIA_SPORTAGE_5TH_GEN,
|
||||
"KIA SPORTAGE 2026": HYUNDAI.KIA_SPORTAGE_2026,
|
||||
"KIA SPORTAGE HYBRID 2026": HYUNDAI.KIA_SPORTAGE_HEV_2026,
|
||||
"KIA SORENTO GT LINE 2018": HYUNDAI.KIA_SORENTO,
|
||||
"KIA SORENTO 4TH GEN": HYUNDAI.KIA_SORENTO_4TH_GEN,
|
||||
"KIA SORENTO 2024": HYUNDAI.KIA_SORENTO_2024,
|
||||
"KIA SORENTO HYBRID 4TH GEN": HYUNDAI.KIA_SORENTO_HEV_4TH_GEN,
|
||||
"KIA SORENTO HYBRID 4TH GEN LFA2": HYUNDAI.KIA_SORENTO_HEV_4TH_GEN_LFA2,
|
||||
"KIA STINGER GT2 2018": HYUNDAI.KIA_STINGER,
|
||||
"KIA STINGER 2022": HYUNDAI.KIA_STINGER_2022,
|
||||
"KIA CEED INTRO ED 2019": HYUNDAI.KIA_CEED,
|
||||
"KIA EV6 2022": HYUNDAI.KIA_EV6,
|
||||
"KIA EV6 2025": HYUNDAI.KIA_EV6_2025,
|
||||
"KIA EV9 2025": HYUNDAI.KIA_EV9,
|
||||
"KIA CARNIVAL 4TH GEN": HYUNDAI.KIA_CARNIVAL_4TH_GEN,
|
||||
"GENESIS GV60 ELECTRIC 1ST GEN": HYUNDAI.GENESIS_GV60_EV_1ST_GEN,
|
||||
"GENESIS G70 2018": HYUNDAI.GENESIS_G70,
|
||||
"GENESIS G70 2020": HYUNDAI.GENESIS_G70_2020,
|
||||
"GENESIS GV70 1ST GEN": HYUNDAI.GENESIS_GV70_1ST_GEN,
|
||||
"GENESIS GV70 ELECTRIFIED 2026": HYUNDAI.GENESIS_GV70_ELECTRIFIED_2ND_GEN,
|
||||
"GENESIS G80 2017": HYUNDAI.GENESIS_G80,
|
||||
"GENESIS G90 2017": HYUNDAI.GENESIS_G90,
|
||||
"GENESIS GV80 2023": HYUNDAI.GENESIS_GV80,
|
||||
"GENESIS GV80 2025": HYUNDAI.GENESIS_GV80_2025,
|
||||
"MAZDA CX-5": MAZDA.MAZDA_CX5,
|
||||
"MAZDA CX-9": MAZDA.MAZDA_CX9,
|
||||
"MAZDA 3": MAZDA.MAZDA_3,
|
||||
|
||||
@@ -92,6 +92,29 @@ def get_acc_dashboard_fcw_alert(hud_alert, CS):
|
||||
return 0
|
||||
|
||||
|
||||
def get_acc_dashboard_status_values(enabled, target_speed_kph, hud_control, CS):
|
||||
if enabled:
|
||||
return {
|
||||
"ACCCruiseState": 0,
|
||||
"ACCLeadCar": int(hud_control.leadVisible) & 0x1,
|
||||
"ACCResumeButton": 0,
|
||||
"ACCSpeedSetpoint": target_speed_kph,
|
||||
"ACCGapLevel": int(hud_control.leadDistanceBars) & 0x3,
|
||||
"ACCCmdActive": 1,
|
||||
}
|
||||
|
||||
# Replay the stock camera dashboard context when openpilot long is enabled
|
||||
# but openpilot itself is not actively driving the ACC cluster state.
|
||||
return {
|
||||
"ACCCruiseState": int(getattr(CS, "stock_acc_cruise_state", 0)) & 0x7,
|
||||
"ACCLeadCar": int(getattr(CS, "stock_acc_lead_car", 0)) & 0x1,
|
||||
"ACCResumeButton": int(getattr(CS, "stock_acc_resume_button", 0)) & 0x1,
|
||||
"ACCSpeedSetpoint": float(getattr(CS, "stock_acc_speed_setpoint_kph", 0.0)),
|
||||
"ACCGapLevel": int(getattr(CS, "stock_acc_gap_level", 0)) & 0x3,
|
||||
"ACCCmdActive": int(getattr(CS, "stock_acc_cmd_active", 0)) & 0x1,
|
||||
}
|
||||
|
||||
|
||||
ECM_CRUISE_SPOOF_CARS = {
|
||||
CAR.CHEVROLET_BOLT_CC_2017,
|
||||
CAR.CHEVROLET_BOLT_CC_2018_2021,
|
||||
@@ -703,9 +726,10 @@ class CarController(CarControllerBase):
|
||||
CS.auto_hold_engaged = False
|
||||
|
||||
if should_send_acc_dashboard_status(self.CP, dash_speed_spoof_active):
|
||||
acc_dashboard_status = get_acc_dashboard_status_values(CC.enabled, hud_v_cruise * CV.MS_TO_KPH, hud_control, CS)
|
||||
fcw_alert = get_acc_dashboard_fcw_alert(hud_alert, CS)
|
||||
can_sends.append(gmcan.create_acc_dashboard_command(self.packer_pt, CanBus.POWERTRAIN, CC.enabled,
|
||||
hud_v_cruise * CV.MS_TO_KPH, hud_control, fcw_alert))
|
||||
can_sends.append(gmcan.create_acc_dashboard_command(self.packer_pt, CanBus.POWERTRAIN,
|
||||
acc_dashboard_status, fcw_alert))
|
||||
|
||||
# Radar needs to know current speed and yaw rate (50hz),
|
||||
# and that ADAS is alive (10hz)
|
||||
|
||||
@@ -81,6 +81,12 @@ class CarState(CarStateBase):
|
||||
self.lkas_enabled = 0
|
||||
self.pcm_acc_status = AccState.OFF
|
||||
self.stock_fcw_alert = 0
|
||||
self.stock_acc_cruise_state = 0
|
||||
self.stock_acc_lead_car = 0
|
||||
self.stock_acc_resume_button = 0
|
||||
self.stock_acc_speed_setpoint_kph = 0.0
|
||||
self.stock_acc_gap_level = 0
|
||||
self.stock_acc_cmd_active = 0
|
||||
|
||||
def update_button_enable(self, buttonEvents: list[structs.CarState.ButtonEvent]):
|
||||
if not self.CP.pcmCruise:
|
||||
@@ -267,17 +273,25 @@ class CarState(CarStateBase):
|
||||
ret.cruiseState.enabled = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] != AccState.OFF
|
||||
ret.cruiseState.standstill = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.STANDSTILL
|
||||
self.stock_fcw_alert = 0
|
||||
ret.stockFcw = False
|
||||
if self.CP.networkLocation == NetworkLocation.fwdCamera and not self.CP.flags & GMFlags.NO_CAMERA.value:
|
||||
has_acc_dashboard_status = self.CP.carFingerprint not in CC_ONLY_CAR or self.CP.carFingerprint == CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL
|
||||
if has_acc_dashboard_status:
|
||||
acc_dashboard_status = cam_cp.vl["ASCMActiveCruiseControlStatus"]
|
||||
if self.CP.carFingerprint not in CC_ONLY_CAR:
|
||||
ret.cruiseState.speed = acc_dashboard_status["ACCSpeedSetpoint"] * CV.KPH_TO_MS
|
||||
self.stock_acc_cruise_state = int(acc_dashboard_status["ACCCruiseState"])
|
||||
self.stock_acc_lead_car = int(acc_dashboard_status["ACCLeadCar"])
|
||||
self.stock_acc_resume_button = int(acc_dashboard_status["ACCResumeButton"])
|
||||
self.stock_acc_speed_setpoint_kph = float(acc_dashboard_status["ACCSpeedSetpoint"])
|
||||
self.stock_acc_gap_level = int(acc_dashboard_status["ACCGapLevel"])
|
||||
self.stock_acc_cmd_active = int(acc_dashboard_status["ACCCmdActive"])
|
||||
# Preserve the stock camera FCW level from 0x370 so the controller can
|
||||
# replay it when that message is blocked and spoofed by openpilot long.
|
||||
self.stock_fcw_alert = int(acc_dashboard_status["FCWAlert"])
|
||||
ret.stockFcw = self.stock_fcw_alert != 0
|
||||
|
||||
if self.CP.carFingerprint not in (SDGM_CAR | ASCM_INT):
|
||||
if self.CP.carFingerprint not in SDGM_CAR:
|
||||
ret.stockAeb = cam_cp.vl["AEBCmd"]["AEBCmdActive"] != 0
|
||||
else:
|
||||
ret.stockAeb = False
|
||||
@@ -424,7 +438,7 @@ class CarState(CarStateBase):
|
||||
("ASCMSteeringButton", 33),
|
||||
]
|
||||
if CP.enableBsm:
|
||||
pt_messages.append(("BCMBlindSpotMonitor", 10))
|
||||
pt_messages.append(("BCMBlindSpotMonitor", 0))
|
||||
|
||||
if CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG.value:
|
||||
if ("ECMAcceleratorPos", 80) in pt_messages:
|
||||
@@ -466,8 +480,14 @@ class CarState(CarStateBase):
|
||||
("ASCMSteeringButton", 33),
|
||||
]
|
||||
if CP.enableBsm:
|
||||
cam_messages.append(("BCMBlindSpotMonitor", 10))
|
||||
elif CP.carFingerprint not in (SDGM_CAR | ASCM_INT):
|
||||
cam_messages.append(("BCMBlindSpotMonitor", 0))
|
||||
elif CP.carFingerprint in ASCM_INT:
|
||||
# Volt/ASCM-int variants don't reliably have AEBCmd present at startup,
|
||||
# but when it appears we still want to surface OEM AEB state.
|
||||
cam_messages += [
|
||||
("AEBCmd", 0),
|
||||
]
|
||||
elif CP.carFingerprint not in SDGM_CAR:
|
||||
cam_messages += [
|
||||
("AEBCmd", 10),
|
||||
]
|
||||
|
||||
@@ -216,6 +216,7 @@ FINGERPRINTS.update({
|
||||
CAR.CHEVROLET_BLAZER: FINGERPRINTS[CAR.CHEVROLET_TRAVERSE],
|
||||
CAR.CHEVROLET_MALIBU_SDGM: FINGERPRINTS[CAR.CHEVROLET_MALIBU_CC],
|
||||
CAR.BUICK_BABYENCLAVE: FINGERPRINTS[CAR.CHEVROLET_TRAVERSE],
|
||||
CAR.CHEVROLET_SILVERADO_CC: FINGERPRINTS[CAR.CHEVROLET_SILVERADO],
|
||||
})
|
||||
|
||||
FW_VERSIONS: dict[str, dict[tuple, list[bytes]]] = {
|
||||
|
||||
@@ -209,17 +209,18 @@ def create_friction_brake_command(packer, bus, apply_brake, idx, enabled, near_s
|
||||
return packer.make_can_msg("EBCMFrictionBrakeCmd", bus, values)
|
||||
|
||||
|
||||
def create_acc_dashboard_command(packer, bus, enabled, target_speed_kph, hud_control, fcw_alert):
|
||||
target_speed = min(target_speed_kph, 255)
|
||||
def create_acc_dashboard_command(packer, bus, status_values, fcw_alert):
|
||||
target_speed = min(max(float(status_values.get("ACCSpeedSetpoint", 0.0)), 0.0), 255.0)
|
||||
|
||||
values = {
|
||||
"ACCAlwaysOne": 1,
|
||||
"ACCResumeButton": 0,
|
||||
"ACCCruiseState": int(status_values.get("ACCCruiseState", 0)) & 0x7,
|
||||
"ACCResumeButton": int(status_values.get("ACCResumeButton", 0)) & 0x1,
|
||||
"ACCSpeedSetpoint": target_speed,
|
||||
"ACCGapLevel": hud_control.leadDistanceBars * enabled, # 3 "far", 0 "inactive"
|
||||
"ACCCmdActive": enabled,
|
||||
"ACCGapLevel": int(status_values.get("ACCGapLevel", 0)) & 0x3,
|
||||
"ACCCmdActive": int(status_values.get("ACCCmdActive", 0)) & 0x1,
|
||||
"ACCAlwaysOne2": 1,
|
||||
"ACCLeadCar": hud_control.leadVisible,
|
||||
"ACCLeadCar": int(status_values.get("ACCLeadCar", 0)) & 0x1,
|
||||
"FCWAlert": int(fcw_alert) & 0x3,
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,14 @@ NON_LINEAR_TORQUE_PARAMS = {
|
||||
"left": [3.8, 0.81, 0.24, 0.0465122],
|
||||
"right": [3.8, 0.81, 0.24, 0.0465122],
|
||||
},
|
||||
CAR.CHEVROLET_SILVERADO_CC: {
|
||||
"left": [3.8, 0.81, 0.24, 0.0465122],
|
||||
"right": [3.8, 0.81, 0.24, 0.0465122],
|
||||
},
|
||||
CAR.CHEVROLET_VOLT: {
|
||||
"left": [1.5, 1.0, 0.155, 0.0],
|
||||
"right": [1.5, 1.0, 0.155, 0.0],
|
||||
},
|
||||
}
|
||||
|
||||
PEDAL_MSG = 0x201
|
||||
@@ -85,6 +93,14 @@ VOLT_LONG_TEST_TUNE_CARS = {
|
||||
CAR.CHEVROLET_VOLT_CC,
|
||||
}
|
||||
|
||||
VOLT_BSM_CARS = {
|
||||
CAR.CHEVROLET_VOLT,
|
||||
CAR.CHEVROLET_VOLT_2019,
|
||||
CAR.CHEVROLET_VOLT_ASCM,
|
||||
CAR.CHEVROLET_VOLT_CAMERA,
|
||||
CAR.CHEVROLET_VOLT_CC,
|
||||
}
|
||||
|
||||
BOLT_PEDAL_LONG_CARS = {
|
||||
CAR.CHEVROLET_BOLT_CC_2017,
|
||||
CAR.CHEVROLET_BOLT_CC_2018_2021,
|
||||
@@ -201,7 +217,8 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.brand = "gm"
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.gm)]
|
||||
ret.autoResumeSng = False
|
||||
ret.enableBsm = 0x142 in fingerprint[CanBus.POWERTRAIN]
|
||||
# Some Volt installs don't expose the BSM frame during startup fingerprinting.
|
||||
ret.enableBsm = 0x142 in fingerprint[CanBus.POWERTRAIN] or candidate in VOLT_BSM_CARS
|
||||
has_sascm = 0x2FF in fingerprint[CanBus.POWERTRAIN]
|
||||
if has_sascm:
|
||||
ret.flags |= GMFlags.SASCM.value
|
||||
@@ -452,7 +469,7 @@ class CarInterface(CarInterfaceBase):
|
||||
# ACC Bolts use pedal for full longitudinal control, not just SNG.
|
||||
ret.flags |= GMFlags.PEDAL_LONG.value
|
||||
|
||||
elif candidate == CAR.CHEVROLET_SILVERADO:
|
||||
elif candidate in (CAR.CHEVROLET_SILVERADO, CAR.CHEVROLET_SILVERADO_CC):
|
||||
# On the Bolt, the ECM and camera independently check that you are either above 5 kph or at a stop
|
||||
# with foot on brake to allow engagement, but this platform only has that check in the camera.
|
||||
# TODO: check if this is split by EV/ICE with more platforms in the future
|
||||
@@ -489,7 +506,7 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.minSteerSpeed = 7 * CV.MPH_TO_MS
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
elif candidate == CAR.CADILLAC_XT5_CC:
|
||||
elif candidate in (CAR.CADILLAC_XT5, CAR.CADILLAC_XT5_CC):
|
||||
ret.steerActuatorDelay = 0.2
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
|
||||
@@ -3,12 +3,14 @@ from types import SimpleNamespace
|
||||
from parameterized import parameterized
|
||||
|
||||
from opendbc.can import CANPacker, CANParser
|
||||
from opendbc.car import Bus, DT_CTRL
|
||||
from opendbc.car import Bus, DT_CTRL, structs
|
||||
from opendbc.car.car_helpers import interfaces
|
||||
from opendbc.car.gm import gmcan
|
||||
from opendbc.car.gm.carstate import CarState as GMCarState
|
||||
from opendbc.car.gm.carcontroller import (
|
||||
VisualAlert,
|
||||
get_acc_dashboard_fcw_alert,
|
||||
get_acc_dashboard_status_values,
|
||||
should_send_acc_dashboard_status,
|
||||
should_send_cc_button_spam,
|
||||
should_spoof_dash_speed,
|
||||
@@ -130,6 +132,44 @@ class TestGMInterface:
|
||||
assert "ECMAcceleratorPos" not in pt_parser.vl
|
||||
assert "EBCMBrakePedalPosition" in pt_parser.vl
|
||||
|
||||
@parameterized.expand(VOLT_CARS)
|
||||
def test_volt_bsm_is_enabled_without_fingerprint_match(self, car_model):
|
||||
CarInterface = interfaces[car_model]
|
||||
car_params = CarInterface.get_params(car_model, _empty_fingerprint(), [], alpha_long=False, is_release=False, docs=False,
|
||||
starpilot_toggles=_test_starpilot_toggles())
|
||||
|
||||
assert car_params.enableBsm
|
||||
|
||||
def test_volt_bsm_parser_is_optional(self):
|
||||
cp = SimpleNamespace(
|
||||
carFingerprint=CAR.CHEVROLET_VOLT_ASCM,
|
||||
networkLocation=structs.CarParams.NetworkLocation.fwdCamera,
|
||||
flags=0,
|
||||
transmissionType=structs.CarParams.TransmissionType.direct,
|
||||
enableGasInterceptorDEPRECATED=False,
|
||||
enableBsm=True,
|
||||
)
|
||||
|
||||
pt_parser = GMCarState.get_can_parsers(cp)[Bus.pt]
|
||||
bsm_addr = pt_parser.dbc.name_to_msg["BCMBlindSpotMonitor"].address
|
||||
|
||||
assert "BCMBlindSpotMonitor" in pt_parser.vl
|
||||
assert pt_parser.message_states[bsm_addr].ignore_alive
|
||||
|
||||
def test_volt_ascm_cam_parser_includes_optional_aeb_cmd(self):
|
||||
cam_parser = GMCarState.get_can_parsers(SimpleNamespace(
|
||||
carFingerprint=CAR.CHEVROLET_VOLT_ASCM,
|
||||
networkLocation=structs.CarParams.NetworkLocation.fwdCamera,
|
||||
flags=0,
|
||||
transmissionType=structs.CarParams.TransmissionType.direct,
|
||||
enableGasInterceptorDEPRECATED=False,
|
||||
enableBsm=False,
|
||||
))[Bus.cam]
|
||||
aeb_addr = cam_parser.dbc.name_to_msg["AEBCmd"].address
|
||||
|
||||
assert "AEBCmd" in cam_parser.vl
|
||||
assert cam_parser.message_states[aeb_addr].ignore_alive
|
||||
|
||||
def test_bolt_gen2_pedal_cancel_remap_sets_alt_exp(self):
|
||||
CarInterface = interfaces[CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL]
|
||||
fingerprint = _empty_fingerprint()
|
||||
@@ -147,6 +187,30 @@ class TestGMInterface:
|
||||
assert car_params.alternativeExperience & ALTERNATIVE_EXPERIENCE.GM_REMAP_CANCEL_TO_DISTANCE
|
||||
assert car_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_BOLT_2022_PEDAL.value
|
||||
|
||||
def test_cadillac_xt5_sdgm_sascm_gates_alpha_long(self):
|
||||
CarInterface = interfaces[CAR.CADILLAC_XT5]
|
||||
fingerprint = _empty_fingerprint()
|
||||
fingerprint[0][0xBE] = 6
|
||||
|
||||
stock_params = CarInterface.get_params(CAR.CADILLAC_XT5, fingerprint, [], alpha_long=True, is_release=False,
|
||||
docs=False, starpilot_toggles=_test_starpilot_toggles())
|
||||
|
||||
assert stock_params.networkLocation == structs.CarParams.NetworkLocation.fwdCamera
|
||||
assert stock_params.pcmCruise
|
||||
assert stock_params.alphaLongitudinalAvailable is False
|
||||
assert stock_params.openpilotLongitudinalControl is False
|
||||
assert stock_params.safetyConfigs[0].safetyParam & GMSafetyFlags.HW_SDGM.value
|
||||
|
||||
fingerprint[0][0x2FF] = 8
|
||||
sascm_params = CarInterface.get_params(CAR.CADILLAC_XT5, fingerprint, [], alpha_long=True, is_release=False,
|
||||
docs=False, starpilot_toggles=_test_starpilot_toggles())
|
||||
|
||||
assert sascm_params.flags & GMFlags.SASCM.value
|
||||
assert sascm_params.alphaLongitudinalAvailable
|
||||
assert sascm_params.openpilotLongitudinalControl
|
||||
assert not sascm_params.pcmCruise
|
||||
assert sascm_params.safetyConfigs[0].safetyParam & GMSafetyFlags.HW_CAM_LONG.value
|
||||
|
||||
|
||||
class TestGMCarController:
|
||||
def test_dash_speed_spoof_respects_live_stock_acc_toggles(self):
|
||||
@@ -259,9 +323,14 @@ class TestGMCarController:
|
||||
msg = gmcan.create_acc_dashboard_command(
|
||||
packer,
|
||||
0,
|
||||
True,
|
||||
100,
|
||||
SimpleNamespace(leadDistanceBars=3, leadVisible=True),
|
||||
{
|
||||
"ACCCruiseState": 0,
|
||||
"ACCLeadCar": 1,
|
||||
"ACCResumeButton": 0,
|
||||
"ACCSpeedSetpoint": 100,
|
||||
"ACCGapLevel": 3,
|
||||
"ACCCmdActive": 1,
|
||||
},
|
||||
0x2,
|
||||
)
|
||||
|
||||
@@ -269,6 +338,24 @@ class TestGMCarController:
|
||||
|
||||
assert parser.vl["ASCMActiveCruiseControlStatus"]["FCWAlert"] == 2
|
||||
|
||||
def test_acc_dashboard_command_can_replay_stock_status_payload(self):
|
||||
packer = CANPacker(DBC[CAR.CHEVROLET_VOLT_ASCM][Bus.pt])
|
||||
msg = gmcan.create_acc_dashboard_command(
|
||||
packer,
|
||||
0,
|
||||
{
|
||||
"ACCCruiseState": 0,
|
||||
"ACCLeadCar": 1,
|
||||
"ACCResumeButton": 0,
|
||||
"ACCSpeedSetpoint": 50,
|
||||
"ACCGapLevel": 2,
|
||||
"ACCCmdActive": 0,
|
||||
},
|
||||
0x3,
|
||||
)
|
||||
|
||||
assert msg[1].hex() == "010023200113"
|
||||
|
||||
def test_acc_dashboard_fcw_alert_prefers_openpilot_alert(self):
|
||||
cs = SimpleNamespace(
|
||||
stock_fcw_alert=1,
|
||||
@@ -292,3 +379,53 @@ class TestGMCarController:
|
||||
)
|
||||
|
||||
assert get_acc_dashboard_fcw_alert(VisualAlert.none, cs) == 0x3
|
||||
|
||||
def test_acc_dashboard_fcw_alert_falls_back_to_stock_fcw_event(self):
|
||||
cs = SimpleNamespace(
|
||||
stock_fcw_alert=0,
|
||||
out=SimpleNamespace(stockAeb=False, stockFcw=True),
|
||||
)
|
||||
|
||||
assert get_acc_dashboard_fcw_alert(VisualAlert.none, cs) == 0x3
|
||||
|
||||
def test_acc_dashboard_status_values_use_openpilot_hud_when_enabled(self):
|
||||
cs = SimpleNamespace(
|
||||
stock_acc_cruise_state=5,
|
||||
stock_acc_lead_car=0,
|
||||
stock_acc_resume_button=1,
|
||||
stock_acc_speed_setpoint_kph=42.0,
|
||||
stock_acc_gap_level=1,
|
||||
stock_acc_cmd_active=0,
|
||||
)
|
||||
|
||||
values = get_acc_dashboard_status_values(True, 105.0, SimpleNamespace(leadDistanceBars=3, leadVisible=True), cs)
|
||||
|
||||
assert values == {
|
||||
"ACCCruiseState": 0,
|
||||
"ACCLeadCar": 1,
|
||||
"ACCResumeButton": 0,
|
||||
"ACCSpeedSetpoint": 105.0,
|
||||
"ACCGapLevel": 3,
|
||||
"ACCCmdActive": 1,
|
||||
}
|
||||
|
||||
def test_acc_dashboard_status_values_reuse_stock_camera_status_when_disabled(self):
|
||||
cs = SimpleNamespace(
|
||||
stock_acc_cruise_state=0,
|
||||
stock_acc_lead_car=1,
|
||||
stock_acc_resume_button=0,
|
||||
stock_acc_speed_setpoint_kph=50.0,
|
||||
stock_acc_gap_level=2,
|
||||
stock_acc_cmd_active=0,
|
||||
)
|
||||
|
||||
values = get_acc_dashboard_status_values(False, 0.0, SimpleNamespace(leadDistanceBars=0, leadVisible=False), cs)
|
||||
|
||||
assert values == {
|
||||
"ACCCruiseState": 0,
|
||||
"ACCLeadCar": 1,
|
||||
"ACCResumeButton": 0,
|
||||
"ACCSpeedSetpoint": 50.0,
|
||||
"ACCGapLevel": 2,
|
||||
"ACCCmdActive": 0,
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ class CAR(Platforms):
|
||||
)
|
||||
CHEVROLET_VOLT = GMASCMPlatformConfig(
|
||||
[GMCarDocs("Chevrolet Volt 2017-18", min_enable_speed=0, video="https://youtu.be/QeMCN_4TFfQ")],
|
||||
GMCarSpecs(mass=1607, wheelbase=2.69, steerRatio=15.7, centerToFrontRatio=0.45, tireStiffnessFactor=0.469, minEnableSpeed=-1),
|
||||
GMCarSpecs(mass=1607, wheelbase=2.69, steerRatio=15.7, centerToFrontRatio=0.45, tireStiffnessFactor=1.0, minEnableSpeed=-1), #tire stiffness factor hasn't been updated since 2018 and every other gm is on 1.0
|
||||
dbc_dict={
|
||||
Bus.pt: "gm_global_a_powertrain_volt",
|
||||
Bus.radar: "gm_global_a_object",
|
||||
@@ -329,6 +329,13 @@ class CAR(Platforms):
|
||||
],
|
||||
GMCarSpecs(mass=2994, wheelbase=3.75, steerRatio=16.3, tireStiffnessFactor=1.0),
|
||||
)
|
||||
CHEVROLET_SILVERADO_CC = GMPlatformConfig(
|
||||
[
|
||||
GMCarDocs("Chevrolet Silverado 1500 - No-ACC"),
|
||||
GMCarDocs("GMC Sierra 1500 - No-ACC"),
|
||||
],
|
||||
CHEVROLET_SILVERADO.specs,
|
||||
)
|
||||
CHEVROLET_EQUINOX = GMPlatformConfig(
|
||||
[GMCarDocs("Chevrolet Equinox 2019-22")],
|
||||
GMCarSpecs(mass=1588, wheelbase=2.72, steerRatio=14.4, centerToFrontRatio=0.4),
|
||||
@@ -353,6 +360,10 @@ class CAR(Platforms):
|
||||
[GMCarDocs("Cadillac XT4 2023", "Driver Assist Package")],
|
||||
GMCarSpecs(mass=1660, wheelbase=2.78, steerRatio=14.4, centerToFrontRatio=0.4),
|
||||
)
|
||||
CADILLAC_XT5 = GMSDGMPlatformConfig(
|
||||
[GMCarDocs("Cadillac XT5 2022", "Driver Assist Package")],
|
||||
CarSpecs(mass=1810, wheelbase=2.86, steerRatio=16.34, centerToFrontRatio=0.5),
|
||||
)
|
||||
CADILLAC_XT6 = GMPlatformConfig(
|
||||
[GMCarDocs("Cadillac XT6 2020", "Driver Assist Package")],
|
||||
GMCarSpecs(mass=2050, wheelbase=2.86, steerRatio=16.5, centerToFrontRatio=0.4),
|
||||
@@ -383,7 +394,7 @@ class CAR(Platforms):
|
||||
)
|
||||
CADILLAC_XT5_CC = GMPlatformConfig(
|
||||
[GMCarDocs("Cadillac XT5 - No-ACC")],
|
||||
CarSpecs(mass=1810, wheelbase=2.86, steerRatio=16.34, centerToFrontRatio=0.5),
|
||||
CADILLAC_XT5.specs,
|
||||
)
|
||||
CHEVROLET_EQUINOX_CC = GMPlatformConfig(
|
||||
[GMCarDocs("Chevrolet Equinox 2019-22 - No-ACC")],
|
||||
@@ -527,6 +538,7 @@ ALT_ACCS = {CAR.GMC_YUKON, CAR.GMC_YUKON_CC}
|
||||
# We're integrated at the Safety Data Gateway Module on these cars
|
||||
SDGM_CAR = {
|
||||
CAR.CADILLAC_XT4,
|
||||
CAR.CADILLAC_XT5,
|
||||
CAR.CADILLAC_XT6,
|
||||
CAR.CHEVROLET_TRAVERSE,
|
||||
CAR.CHEVROLET_BLAZER,
|
||||
@@ -549,6 +561,7 @@ CC_ONLY_CAR = {
|
||||
CAR.CADILLAC_XT5_CC,
|
||||
CAR.CHEVROLET_MALIBU_CC,
|
||||
CAR.CHEVROLET_MALIBU_HYBRID_CC,
|
||||
CAR.CHEVROLET_SILVERADO_CC,
|
||||
}
|
||||
CC_REGEN_PADDLE_CAR = {
|
||||
CAR.CHEVROLET_BOLT_CC_2018_2021,
|
||||
|
||||
@@ -7,7 +7,7 @@ from opendbc.car.lateral import apply_driver_steer_torque_limits, apply_steer_an
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.hyundai import hyundaicanfd, hyundaican
|
||||
from opendbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR
|
||||
from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR, CANFD_RADAR_LIVE_LONGITUDINAL_CAR
|
||||
from opendbc.car.interfaces import CarControllerBase
|
||||
from opendbc.car.vehicle_model import VehicleModel
|
||||
from openpilot.common.params import Params
|
||||
@@ -527,6 +527,7 @@ class CarController(CarControllerBase):
|
||||
|
||||
lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING
|
||||
lka_steering_long = lka_steering and self.long_active_ecu
|
||||
ccnc_non_hda2 = self.CP.flags & HyundaiFlags.CCNC and not lka_steering
|
||||
use_ioniq_6_dynamic_long_tuning = self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and self.long_active_ecu and \
|
||||
CC.actuators.longControlState == LongCtrlState.pid
|
||||
use_ioniq_6_smoothed_accel = use_ioniq_6_dynamic_long_tuning and CC.actuators.accel >= self._ioniq_6_long_tuning.actual_accel
|
||||
@@ -546,8 +547,13 @@ class CarController(CarControllerBase):
|
||||
|
||||
# LFA and HDA icons
|
||||
if self.frame % 5 == 0 and (not lka_steering or lka_steering_long):
|
||||
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CS.stock_lfahda_cluster_msg,
|
||||
lfa_icon=lfa_icon))
|
||||
if ccnc_non_hda2:
|
||||
can_sends.extend(hyundaicanfd.create_ccnc(self.packer, self.CAN, self.long_active_ecu, CC.enabled, CC.hudControl,
|
||||
CC.leftBlinker, CC.rightBlinker, CS.msg_161, CS.msg_162, CS.msg_1b5,
|
||||
CS.is_metric, CS.out, CS.out.cruiseState.available, lfa_icon))
|
||||
else:
|
||||
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CS.stock_lfahda_cluster_msg,
|
||||
lfa_icon=lfa_icon))
|
||||
|
||||
# blinkers
|
||||
if lka_steering and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
|
||||
@@ -577,7 +583,12 @@ class CarController(CarControllerBase):
|
||||
if self.long_active_ecu:
|
||||
if lka_steering:
|
||||
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
||||
else:
|
||||
# Ioniq 5/6: front radar treats ADAS_DRV's 0x100 broadcast as its host heartbeat
|
||||
# and stops publishing object tracks when it disappears. Spoof it periodically on
|
||||
# PT bus so the radar keeps tracking.
|
||||
if self.CP.carFingerprint in CANFD_RADAR_LIVE_LONGITUDINAL_CAR and self.frame % 4 == 0:
|
||||
can_sends.append(hyundaicanfd.create_accelerator_brake_alt_spoof(0, self.frame // 4, CS.out.brakePressed, CS.out.gasPressed))
|
||||
elif not ccnc_non_hda2:
|
||||
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame))
|
||||
if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and self.frame % 5 == 0:
|
||||
rear_stale = now_nanos - CS.blindspots_rear_corners_ts > CANFD_BLINDSPOT_STATUS_STALE_NS
|
||||
@@ -612,7 +623,8 @@ class CarController(CarControllerBase):
|
||||
acc_kwargs["jerk_lower"] = self._ioniq_6_long_tuning.jerk_lower
|
||||
acc_kwargs["jerk_upper"] = self._ioniq_6_long_tuning.jerk_upper
|
||||
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
|
||||
set_speed_in_units, hud_control, **acc_kwargs))
|
||||
set_speed_in_units, hud_control, cruise_info=CS.cruise_info if ccnc_non_hda2 else None,
|
||||
**acc_kwargs))
|
||||
self.accel_last = accel
|
||||
else:
|
||||
# button presses
|
||||
|
||||
@@ -7,7 +7,7 @@ from opendbc.can import CANDefine, CANParser
|
||||
from opendbc.car import Bus, create_button_events, structs
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from opendbc.car.hyundai.values import HyundaiFlags, HyundaiStarPilotFlags, CAR, DBC, Buttons, CarControllerParams, \
|
||||
from opendbc.car.hyundai.values import HyundaiFlags, HyundaiStarPilotFlags, HyundaiStarPilotSafetyFlags, CAR, DBC, Buttons, CarControllerParams, \
|
||||
hyundai_cancel_button_enables_cruise
|
||||
from opendbc.car.interfaces import CarStateBase
|
||||
|
||||
@@ -108,6 +108,9 @@ class CarState(CarStateBase):
|
||||
self.buttons_counter = 0
|
||||
|
||||
self.cruise_info = {}
|
||||
self.msg_161 = {}
|
||||
self.msg_162 = {}
|
||||
self.msg_1b5 = {}
|
||||
self.msg_364 = {}
|
||||
self.stock_lkas_msg = {}
|
||||
self.stock_lfa_msg = {}
|
||||
@@ -306,7 +309,7 @@ class CarState(CarStateBase):
|
||||
prev_lda_button = self.lda_button
|
||||
self.cruise_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwState"])
|
||||
self.main_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwMain"])
|
||||
if self.CP.flags & HyundaiFlags.HAS_LDA_BUTTON:
|
||||
if self.FPCP.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON:
|
||||
self.lda_button = cp.vl["BCM_PO_11"]["LDA_BTN"]
|
||||
|
||||
ret.buttonEvents = [*self.create_cruise_button_events(self.cruise_buttons[-1], prev_cruise_buttons),
|
||||
@@ -365,8 +368,16 @@ class CarState(CarStateBase):
|
||||
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
|
||||
ret.steerFaultTemporary = cp.vl["MDPS"]["LKA_FAULT"] != 0
|
||||
|
||||
left_blinker_sig, right_blinker_sig = self.get_canfd_blinker_sig_names(self.CP.carFingerprint,
|
||||
cp.vl["BLINKERS"]["USE_ALT_LAMP"] == 1)
|
||||
ccnc_non_hda2 = self.CP.flags & HyundaiFlags.CCNC and not self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING
|
||||
if ccnc_non_hda2:
|
||||
self.msg_161 = copy.copy(cp_cam.vl["CCNC_0x161"])
|
||||
self.msg_162 = copy.copy(cp_cam.vl["CCNC_0x162"])
|
||||
self.msg_1b5 = copy.copy(cp_cam.vl["FR_CMR_03_50ms"])
|
||||
cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp
|
||||
self.cruise_info = copy.copy(cp_cruise_info.vl["SCC_CONTROL"])
|
||||
|
||||
use_alt_lamp = cp.vl["BLINKERS"]["USE_ALT_LAMP"] == 1 or bool(self.CP.flags & HyundaiFlags.CCNC)
|
||||
left_blinker_sig, right_blinker_sig = self.get_canfd_blinker_sig_names(self.CP.carFingerprint, use_alt_lamp)
|
||||
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig],
|
||||
cp.vl["BLINKERS"][right_blinker_sig])
|
||||
self.left_blindspot_from_radar = False
|
||||
@@ -380,6 +391,9 @@ class CarState(CarStateBase):
|
||||
self.left_blindspot_from_radar)
|
||||
ret.rightBlindspot = (bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_RtIndSta"]) or
|
||||
self.right_blindspot_from_radar)
|
||||
elif self.CP.flags & HyundaiFlags.CCNC:
|
||||
ret.leftBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_LtIndSta"])
|
||||
ret.rightBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_RtIndSta"])
|
||||
else:
|
||||
ret.leftBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_LtIndSta"])
|
||||
ret.rightBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_RtIndSta"])
|
||||
@@ -487,6 +501,11 @@ class CarState(CarStateBase):
|
||||
else:
|
||||
cam_msgs.append(("FR_CMR_02_100ms", 0)) # optional: not all non-LKA CANFD cars have this on CAM bus
|
||||
cam_msgs.append(("FR_CMR_03_50ms", 0)) # optional: camera lead/cipv data is not present on every CAN-FD trim
|
||||
if CP.flags & HyundaiFlags.CCNC:
|
||||
cam_msgs += [
|
||||
("CCNC_0x161", 0),
|
||||
("CCNC_0x162", 0),
|
||||
]
|
||||
msgs += [
|
||||
("LFA", 0), # optional: may stop once OP takes over, but preserve stock UI fields when present
|
||||
("LFAHDA_CLUSTER", 0), # optional: carries cluster icon state on some variants
|
||||
|
||||
@@ -741,6 +741,27 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00SX2EMFC AT KOR LHD 1.00 1.00 99211-BF000 230410',
|
||||
b'\xf1\x00SX2EMFC AT USA LHD 1.00 1.02 99211-BF000 230823',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_KONA_2ND_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.03 99211-BE000 230517',
|
||||
b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.07 99211-BE000 240611',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ',
|
||||
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_KONA_HEV_2ND_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00SX2HMFC AT AUS RHD 1.00 1.00 99211-BE001 241015',
|
||||
b'\xf1\x00SX2HMFC AT EUR RHD 1.00 1.04 99211-BE000 231010',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ',
|
||||
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ',
|
||||
],
|
||||
},
|
||||
CAR.KIA_NIRO_EV: {
|
||||
@@ -1159,6 +1180,186 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00NQ5__ 1.00 1.04 99110CH100 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_SANTA_FE_HEV_5TH_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00MX5HMFC AT CAN LHD 1.00 1.07 99211-P6000 231218',
|
||||
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',
|
||||
b'\xf1\x00MX5HMFC AT USA LHD 1.00 1.09 99211-R6200 250519',
|
||||
],
|
||||
(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_SONATA_2024: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00DN8 MFC AT KOR LHD 1.00 1.01 99211-L1800 230512',
|
||||
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.01 99211-L1800 230512',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_SONATA_HEV_2024: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00DN8HMFC AT KOR LHD 1.00 1.01 99211-L1800 230512',
|
||||
b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.01 99211-L1800 230512',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ',
|
||||
],
|
||||
},
|
||||
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_5_N: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NE1N RDR ----- 1.00 1.00 99110-NI000 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.04 99211-NI000 231219',
|
||||
b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.00 99211-NI010 240712',
|
||||
b'\xf1\x00NE1NMFC AT USA LHD 1.00 1.04 99211-NI000 231219',
|
||||
],
|
||||
},
|
||||
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',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_TUCSON_2025: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N7050 C5A',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_TUCSON_HEV_2025: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55',
|
||||
b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 1.00 99211-N7030 C55',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NX4__ 1.00 1.02 99110N7000 ',
|
||||
b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ',
|
||||
b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_TUCSON_PHEV_2025: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N7030 C55',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_SANTA_CRUZ_2025: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NX4__ 1.00 1.00 99110K5500 ',
|
||||
],
|
||||
},
|
||||
CAR.KIA_K4_2025: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00CL4 MFC AT CAN LHD 1.00 1.02 99210-GG000 240708',
|
||||
b'\xf1\x00CL4 MFC AT USA LHD 1.00 1.02 99210-GG000 240708',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG000 ',
|
||||
b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG100 ',
|
||||
],
|
||||
},
|
||||
CAR.KIA_K5_2025: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.04 99210-L2500 240117',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00DL3_ RDR ----- 1.00 1.01 99110-L2500 ',
|
||||
],
|
||||
},
|
||||
CAR.KIA_SPORTAGE_2026: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NQ51.011.021.012551000HKP_NQ524_50509099211P1110',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NQ5__ 1.00 1.04 99110P1100 ',
|
||||
],
|
||||
},
|
||||
CAR.KIA_SORENTO_2024: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00MQ4 MFC AT AUS RHD 1.01 1.04 99210-P2550 231127',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-P2500 ',
|
||||
],
|
||||
},
|
||||
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_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 ',
|
||||
],
|
||||
(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',
|
||||
],
|
||||
},
|
||||
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_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.GENESIS_GV70_1ST_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00JK1 MFC AT CAN LHD 1.00 1.02 99211-IY000 230627',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import copy
|
||||
import numpy as np
|
||||
from opendbc.car import CanBusBase, CanData
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.crc import CRC16_XMODEM
|
||||
from opendbc.car.hyundai.values import HyundaiFlags
|
||||
|
||||
@@ -219,6 +220,102 @@ def create_lfahda_cluster(packer, CAN, enabled, base_values=None, lfa_icon=None)
|
||||
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
|
||||
|
||||
|
||||
def create_ccnc(packer, CAN, openpilot_longitudinal, enabled, hud, left_blinker, right_blinker, msg_161, msg_162, msg_1b5,
|
||||
is_metric, out, main_cruise_enabled, lfa_icon):
|
||||
for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS"):
|
||||
msg_162[fault] = 0
|
||||
|
||||
if msg_161["ALERTS_2"] == 5:
|
||||
msg_161.update({"ALERTS_2": 0, "SOUNDS_2": 0})
|
||||
if msg_161["ALERTS_3"] == 17:
|
||||
msg_161["ALERTS_3"] = 0
|
||||
if msg_161["ALERTS_5"] in (2, 5):
|
||||
msg_161["ALERTS_5"] = 0
|
||||
if msg_161["SOUNDS_4"] == 2 and msg_161["LFA_ICON"] in (3, 0):
|
||||
msg_161["SOUNDS_4"] = 0
|
||||
|
||||
lane_change_speed_min = 8.9408
|
||||
any_blinker = left_blinker or right_blinker
|
||||
curvature = {i: (31 if i == -1 else 13 - abs(i + 15)) if i < 0 else 15 + i for i in range(-15, 16)}
|
||||
|
||||
msg_161.update({
|
||||
"DAW_ICON": 0,
|
||||
"LKA_ICON": 0,
|
||||
"LFA_ICON": 2 if lfa_icon else 0,
|
||||
"CENTERLINE": 1 if lfa_icon else 0,
|
||||
"LANELINE_CURVATURE": curvature.get(max(-15, min(int(out.steeringAngleDeg / 4.5), 15)), 14) if lfa_icon and not any_blinker else 15,
|
||||
"LANELINE_LEFT": 0 if not lfa_icon else 1 if not hud.leftLaneVisible else 4 if hud.leftLaneDepart else 6 if any_blinker else 2,
|
||||
"LANELINE_RIGHT": 0 if not lfa_icon else 1 if not hud.rightLaneVisible else 4 if hud.rightLaneDepart else 6 if any_blinker else 2,
|
||||
"LCA_LEFT_ICON": 0 if not lfa_icon or out.vEgo < lane_change_speed_min else 1 if out.leftBlindspot else 2 if any_blinker else 4,
|
||||
"LCA_RIGHT_ICON": 0 if not lfa_icon or out.vEgo < lane_change_speed_min else 1 if out.rightBlindspot else 2 if any_blinker else 4,
|
||||
"LCA_LEFT_ARROW": 2 if left_blinker else 0,
|
||||
"LCA_RIGHT_ARROW": 2 if right_blinker else 0,
|
||||
})
|
||||
|
||||
if lfa_icon and any_blinker:
|
||||
left_lane_raw = msg_1b5["Info_LftLnPosVal"]
|
||||
right_lane_raw = msg_1b5["Info_RtLnPosVal"]
|
||||
scale_per_m = 15 / 1.7
|
||||
left_lane = abs(int(round(15 + (left_lane_raw - 1.7) * scale_per_m)))
|
||||
right_lane = abs(int(round(15 + (right_lane_raw - 1.7) * scale_per_m)))
|
||||
|
||||
if msg_1b5["Info_LftLnQualSta"] not in (2, 3):
|
||||
left_lane = 0
|
||||
if msg_1b5["Info_RtLnQualSta"] not in (2, 3):
|
||||
right_lane = 0
|
||||
|
||||
if left_lane_raw == -2.0248375:
|
||||
left_lane = 30 - right_lane
|
||||
if right_lane_raw == 2.0248375:
|
||||
right_lane = 30 - left_lane
|
||||
|
||||
if left_lane_raw == right_lane_raw == 0:
|
||||
left_lane = right_lane = 15
|
||||
elif left_lane_raw == 0:
|
||||
left_lane = 30 - right_lane
|
||||
elif right_lane_raw == 0:
|
||||
right_lane = 30 - left_lane
|
||||
|
||||
total = left_lane + right_lane
|
||||
if total == 0:
|
||||
left_lane = right_lane = 15
|
||||
else:
|
||||
left_lane = round((left_lane / total) * 30)
|
||||
right_lane = 30 - left_lane
|
||||
|
||||
msg_161["LANELINE_LEFT_POSITION"] = left_lane
|
||||
msg_161["LANELINE_RIGHT_POSITION"] = right_lane
|
||||
|
||||
if hud.leftLaneDepart or hud.rightLaneDepart:
|
||||
msg_162["VIBRATE"] = 1
|
||||
|
||||
if openpilot_longitudinal:
|
||||
if msg_161["ALERTS_3"] in (1, 2, 3, 4, 7, 8, 9, 10):
|
||||
msg_161["ALERTS_3"] = 0
|
||||
if msg_161["ALERTS_5"] == 4:
|
||||
msg_161["ALERTS_5"] = 0
|
||||
if msg_161["SOUNDS_3"] == 5:
|
||||
msg_161["SOUNDS_3"] = 0
|
||||
|
||||
cruise_speed = round(out.vCruiseCluster * (1 if is_metric else CV.KPH_TO_MPH))
|
||||
msg_161.update({
|
||||
"SETSPEED": 3 if enabled else 1,
|
||||
"SETSPEED_HUD": 0 if not main_cruise_enabled else 2 if enabled else 1,
|
||||
"SETSPEED_SPEED": 255 if not main_cruise_enabled else (40 if is_metric else 25) if cruise_speed > (145 if is_metric else 90) else cruise_speed,
|
||||
"DISTANCE": hud.leadDistanceBars,
|
||||
"DISTANCE_SPACING": 0 if not main_cruise_enabled else 1 if enabled else 3,
|
||||
"DISTANCE_LEAD": 0 if not main_cruise_enabled else 2 if enabled and hud.leadVisible else 1 if hud.leadVisible else 0,
|
||||
"DISTANCE_CAR": 0 if not main_cruise_enabled else 2 if enabled else 1,
|
||||
"SLA_ICON": 0,
|
||||
"NAV_ICON": 0,
|
||||
"TARGET": 0,
|
||||
})
|
||||
msg_162["LEAD"] = 0 if not main_cruise_enabled else 2 if enabled else 1
|
||||
msg_162["LEAD_DISTANCE"] = msg_1b5["Longitudinal_Distance"]
|
||||
|
||||
return [packer.make_can_msg(msg, CAN.ECAN, values) for msg, values in (("CCNC_0x161", msg_161), ("CCNC_0x162", msg_162))]
|
||||
|
||||
|
||||
def create_blindspot_status_messages(packer, CAN, rear_values, front_corner_values,
|
||||
left_blindspot=False, right_blindspot=False,
|
||||
left_blinker=False, right_blinker=False):
|
||||
@@ -463,7 +560,7 @@ def create_ioniq_6_cluster_lane_change_messages(CAN, frame, side=None):
|
||||
|
||||
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control,
|
||||
main_mode_acc=1, jerk_lower=None, jerk_upper=None, direct_accel=False,
|
||||
lead_distance=None, lead_rel_speed=None, lead_visible=None):
|
||||
lead_distance=None, lead_rel_speed=None, lead_visible=None, cruise_info=None):
|
||||
jerk = 5
|
||||
jn = jerk / 50
|
||||
if not enabled or gas_override:
|
||||
@@ -506,6 +603,8 @@ def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_ov
|
||||
"SET_ME_TMP_64": 0x64,
|
||||
"DISTANCE_SETTING": hud_control.leadDistanceBars,
|
||||
}
|
||||
if cruise_info:
|
||||
values.update({s: cruise_info[s] for s in ("ACC_ObjDist", "ACC_ObjRelSpd")})
|
||||
|
||||
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
|
||||
|
||||
@@ -603,3 +702,22 @@ def hkg_can_fd_checksum(address: int, sig, d: bytearray) -> int:
|
||||
elif len(d) == 32:
|
||||
crc ^= 0x9F5B
|
||||
return crc
|
||||
|
||||
|
||||
# Ioniq 5/6 / HKG LKA-steering: ADAS_DRV broadcasts ACCELERATOR_BRAKE_ALT (0x100) on bus 0.
|
||||
# The front radar uses this as its "host alive" heartbeat. When we disable ADAS_DRV the
|
||||
# radar stops publishing real object tracks. Spoof this message ourselves with valid CRC
|
||||
# and current pedal state so the radar keeps tracking.
|
||||
# Length is 24 bytes on Ioniq 6 (DBC declares 32 for ICE Hyundais, but EV firmware uses 24).
|
||||
# Byte template captured from a real ADAS broadcast; bytes 6-23 appear static / config.
|
||||
_ACCEL_BRAKE_ALT_TEMPLATE = bytes.fromhex("000000020000fcff000000000020000055ff000068000000")
|
||||
|
||||
def create_accelerator_brake_alt_spoof(bus: int, counter: int, brake_pressed: bool, accelerator_pressed: bool) -> CanData:
|
||||
d = bytearray(_ACCEL_BRAKE_ALT_TEMPLATE)
|
||||
d[2] = counter & 0xFF # COUNTER (bit 16, 8-bit)
|
||||
d[4] = (d[4] & ~0x01) | (0x01 if brake_pressed else 0x00) # BRAKE_PRESSED (bit 32)
|
||||
d[22] = (d[22] & ~0x01) | (0x01 if accelerator_pressed else 0x00) # ACCELERATOR_PEDAL_PRESSED (bit 176)
|
||||
crc = hkg_can_fd_checksum(0x100, None, d)
|
||||
d[0] = crc & 0xFF
|
||||
d[1] = (crc >> 8) & 0xFF
|
||||
return CanData(0x100, bytes(d), bus)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import time
|
||||
from opendbc.car import Bus, get_safety_config, structs, uds
|
||||
from opendbc.car import get_safety_config, structs, uds
|
||||
from opendbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, CarControllerParams, \
|
||||
from opendbc.car.hyundai.values import HyundaiFlags, CAR, CarControllerParams, \
|
||||
CANFD_UNSUPPORTED_LONGITUDINAL_CAR, \
|
||||
CANFD_SECURITYACCESS_CAR, \
|
||||
CANFD_RADAR_LIVE_LONGITUDINAL_CAR, \
|
||||
RADAR_LIVE_LONGITUDINAL_CAR, \
|
||||
UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags, \
|
||||
HyundaiStarPilotSafetyFlags, \
|
||||
hyundai_cancel_button_enables_cruise
|
||||
from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR
|
||||
from opendbc.car.hyundai.radar_interface import get_radar_track_config
|
||||
from opendbc.car.interfaces import CarInterfaceBase, ACCEL_MIN
|
||||
from opendbc.car.disable_ecu import disable_ecu, ecu_log
|
||||
from opendbc.car.hyundai.carcontroller import CarController
|
||||
@@ -70,6 +73,9 @@ class CarInterface(CarInterfaceBase):
|
||||
# this needs to be figured out for cars without an ADAS ECU
|
||||
# Cars in CANFD_SECURITYACCESS_CAR are known to have ADAS ECUs that work with SecurityAccess
|
||||
ret.alphaLongitudinalAvailable = False
|
||||
if lka_steering and ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
|
||||
# Angle-steering LKA platforms still need stock longitudinal validation.
|
||||
ret.alphaLongitudinalAvailable = False
|
||||
|
||||
ret.enableBsm = 0x1ba in fingerprint[CAN.ECAN]
|
||||
|
||||
@@ -115,6 +121,8 @@ class CarInterface(CarInterfaceBase):
|
||||
if ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
|
||||
ret.steerControlType = structs.CarParams.SteerControlType.angle
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ANGLE_STEERING.value
|
||||
if ret.flags & HyundaiFlags.CCNC and not ret.flags & HyundaiFlags.CANFD_LKA_STEERING:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CCNC.value
|
||||
|
||||
else:
|
||||
# Shared configuration for non CAN-FD cars
|
||||
@@ -138,9 +146,9 @@ class CarInterface(CarInterfaceBase):
|
||||
if ret.flags & HyundaiFlags.CAMERA_SCC:
|
||||
ret.safetyConfigs[0].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value
|
||||
|
||||
# These cars have the LFA button on the steering wheel
|
||||
# These cars expose an LKAS/LFA steering-wheel button that StarPilot can customize.
|
||||
if 0x391 in fingerprint[0] or ret.flags & HyundaiFlags.CAN_CANFD_BLENDED:
|
||||
ret.flags |= HyundaiFlags.HAS_LDA_BUTTON.value
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON.value
|
||||
if ret.flags & HyundaiFlags.CAN_CANFD_BLENDED:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAN_CANFD_BLENDED.value
|
||||
if hyundai_cancel_button_enables_cruise(candidate):
|
||||
@@ -168,13 +176,13 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# Common longitudinal control setup
|
||||
|
||||
ret.radarUnavailable = RADAR_START_ADDR not in fingerprint[1] or Bus.radar not in DBC[ret.carFingerprint]
|
||||
radar_config = get_radar_track_config(ret.carFingerprint)
|
||||
radar_tracks_available = radar_config is not None and radar_config.start_addr in fingerprint[radar_config.bus]
|
||||
ret.radarUnavailable = not radar_tracks_available
|
||||
if ret.flags & HyundaiFlags.NON_SCC:
|
||||
ret.alphaLongitudinalAvailable = False
|
||||
ret.openpilotLongitudinalControl = alpha_long and ret.alphaLongitudinalAvailable
|
||||
# When longitudinal is enabled, we disable the ADAS ECU which stops radar messages
|
||||
# Force radarUnavailable to prevent CAN Error from missing radar messages
|
||||
if ret.openpilotLongitudinalControl:
|
||||
if ret.openpilotLongitudinalControl and not (candidate in RADAR_LIVE_LONGITUDINAL_CAR and radar_tracks_available):
|
||||
ret.radarUnavailable = True
|
||||
ret.pcmCruise = not ret.openpilotLongitudinalControl
|
||||
apply_platform_longitudinal_params(ret)
|
||||
@@ -226,7 +234,7 @@ class CarInterface(CarInterfaceBase):
|
||||
params = Params()
|
||||
|
||||
if communication_control is None:
|
||||
if CP.carFingerprint == CAR.HYUNDAI_IONIQ_6:
|
||||
if CP.carFingerprint in CANFD_RADAR_LIVE_LONGITUDINAL_CAR:
|
||||
# Don't use 0x80 suppress bit so we can read the ECU response.
|
||||
# Use ENABLE_RX_DISABLE_TX (0x01) so the ECU can still receive from rear radars for BSM
|
||||
# while blocking SCC TX.
|
||||
|
||||
@@ -1,30 +1,58 @@
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
from opendbc.can import CANParser
|
||||
from opendbc.car import Bus, structs
|
||||
from opendbc.car.interfaces import RadarInterfaceBase
|
||||
from opendbc.car.hyundai.values import CAR, DBC
|
||||
from opendbc.car.hyundai.values import CAR, DBC, HYUNDAI_MANDO_FRONT_RADAR_DBC, HYUNDAI_MRR30_RADAR_DBC, \
|
||||
HYUNDAI_MRR35_RADAR_DBC
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
|
||||
RADAR_START_ADDR = 0x500
|
||||
RADAR_MSG_COUNT = 32
|
||||
MRR30_RADAR_START_ADDR = 0x210
|
||||
MRR30_RADAR_MSG_COUNT = 16
|
||||
MRR35_RADAR_START_ADDR = 0x3A5
|
||||
MRR35_RADAR_MSG_COUNT = 32
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RadarTrackConfig:
|
||||
start_addr: int
|
||||
msg_count: int
|
||||
radar_type: str
|
||||
bus: int = 1
|
||||
frequency: int = 50
|
||||
|
||||
|
||||
RADAR_TRACK_CONFIGS = {
|
||||
HYUNDAI_MANDO_FRONT_RADAR_DBC: RadarTrackConfig(RADAR_START_ADDR, RADAR_MSG_COUNT, "mando"),
|
||||
HYUNDAI_MRR30_RADAR_DBC: RadarTrackConfig(MRR30_RADAR_START_ADDR, MRR30_RADAR_MSG_COUNT, "mrr30"),
|
||||
HYUNDAI_MRR35_RADAR_DBC: RadarTrackConfig(MRR35_RADAR_START_ADDR, MRR35_RADAR_MSG_COUNT, "mrr35", bus=0, frequency=20),
|
||||
}
|
||||
|
||||
# POC for parsing corner radars: https://github.com/commaai/openpilot/pull/24221/
|
||||
|
||||
|
||||
def get_radar_can_parser(CP):
|
||||
if Bus.radar not in DBC[CP.carFingerprint]:
|
||||
def get_radar_track_config(car_fingerprint) -> RadarTrackConfig | None:
|
||||
radar_dbc = DBC[car_fingerprint].get(Bus.radar)
|
||||
return RADAR_TRACK_CONFIGS.get(radar_dbc)
|
||||
|
||||
|
||||
def get_radar_can_parser(CP, radar_config):
|
||||
if radar_config is None:
|
||||
return None
|
||||
|
||||
messages = [(f"RADAR_TRACK_{addr:x}", 50) for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT)]
|
||||
return CANParser(DBC[CP.carFingerprint][Bus.radar], messages, 1)
|
||||
messages = [(f"RADAR_TRACK_{addr:x}", radar_config.frequency) for addr in range(radar_config.start_addr, radar_config.start_addr + radar_config.msg_count)]
|
||||
return CANParser(DBC[CP.carFingerprint][Bus.radar], messages, radar_config.bus)
|
||||
|
||||
|
||||
class RadarInterface(RadarInterfaceBase):
|
||||
def __init__(self, CP):
|
||||
super().__init__(CP)
|
||||
self.radar_config = get_radar_track_config(CP.carFingerprint)
|
||||
self.updated_messages = set()
|
||||
self.trigger_msg = RADAR_START_ADDR + RADAR_MSG_COUNT - 1
|
||||
self.trigger_msg = (self.radar_config.start_addr + self.radar_config.msg_count - 1) if self.radar_config is not None else RADAR_START_ADDR
|
||||
self.track_id = 0
|
||||
|
||||
self.radar_off_can = CP.radarUnavailable
|
||||
@@ -33,7 +61,16 @@ class RadarInterface(RadarInterfaceBase):
|
||||
self.ioniq_6_radar_probe = CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and CP.openpilotLongitudinalControl and self.radar_off_can
|
||||
self.ioniq_6_radar_probe_logged = False
|
||||
self.ioniq_6_radar_probe_updates = 0
|
||||
self.rcp = get_radar_can_parser(CP)
|
||||
self.rcp = get_radar_can_parser(CP, self.radar_config)
|
||||
|
||||
# Precompute (addr, "RADAR_TRACK_xxx") pairs once. _update runs on the
|
||||
# CAN-driven card loop (core 4, shared with controlsd/selfdrived), so avoid
|
||||
# rebuilding 32 f-strings per radar frame.
|
||||
self.track_addrs: list[tuple[int, str]] = []
|
||||
if self.radar_config is not None:
|
||||
self.track_addrs = [(addr, f"RADAR_TRACK_{addr:x}")
|
||||
for addr in range(self.radar_config.start_addr,
|
||||
self.radar_config.start_addr + self.radar_config.msg_count)]
|
||||
|
||||
def update(self, can_strings):
|
||||
if self.ioniq_6_radar_probe and self.rcp is not None and not self.ioniq_6_radar_probe_logged:
|
||||
@@ -73,8 +110,56 @@ class RadarInterface(RadarInterfaceBase):
|
||||
if not self.rcp.can_valid:
|
||||
ret.errors.canError = True
|
||||
|
||||
for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT):
|
||||
msg = self.rcp.vl[f"RADAR_TRACK_{addr:x}"]
|
||||
if self.radar_config is None:
|
||||
return ret
|
||||
|
||||
radar_type = self.radar_config.radar_type
|
||||
vl = self.rcp.vl
|
||||
|
||||
for addr, track_name in self.track_addrs:
|
||||
msg = vl[track_name]
|
||||
|
||||
if radar_type == "mrr30":
|
||||
for i in ("1", "2"):
|
||||
track_key = addr * 2 + int(i) - 1
|
||||
if track_key not in self.pts:
|
||||
self.pts[track_key] = structs.RadarData.RadarPoint()
|
||||
self.pts[track_key].trackId = self.track_id
|
||||
self.track_id += 1
|
||||
|
||||
valid = msg[f"{i}_STATE"] in (3, 4)
|
||||
if valid:
|
||||
pt = self.pts[track_key]
|
||||
pt.measured = True
|
||||
pt.dRel = msg[f"{i}_LONG_DIST"]
|
||||
pt.yRel = msg[f"{i}_LAT_DIST"]
|
||||
pt.vRel = msg[f"{i}_REL_SPEED"]
|
||||
pt.aRel = float("nan")
|
||||
pt.yvRel = float("nan")
|
||||
else:
|
||||
del self.pts[track_key]
|
||||
continue
|
||||
|
||||
if radar_type == "mrr35":
|
||||
# Most of the 32 channels are empty each frame. Only allocate a point
|
||||
# when the channel is valid; drop it otherwise. Avoids the per-frame
|
||||
# alloc-then-delete churn on the ~27 idle channels.
|
||||
if msg["STATE"] in (3, 4):
|
||||
pt = self.pts.get(addr)
|
||||
if pt is None:
|
||||
pt = structs.RadarData.RadarPoint()
|
||||
pt.trackId = self.track_id
|
||||
self.track_id += 1
|
||||
self.pts[addr] = pt
|
||||
pt.measured = True
|
||||
pt.dRel = msg["LONG_DIST"]
|
||||
pt.yRel = msg["LAT_DIST"]
|
||||
pt.vRel = msg["REL_SPEED"]
|
||||
pt.aRel = msg["REL_ACCEL"]
|
||||
pt.yvRel = float("nan")
|
||||
elif addr in self.pts:
|
||||
del self.pts[addr]
|
||||
continue
|
||||
|
||||
if addr not in self.pts:
|
||||
self.pts[addr] = structs.RadarData.RadarPoint()
|
||||
|
||||
@@ -14,11 +14,12 @@ from opendbc.car.hyundai.carstate import CarState, decode_canfd_camera_lead, dec
|
||||
from opendbc.car.hyundai.interface import CarInterface
|
||||
from opendbc.car.hyundai import hyundaican, hyundaicanfd
|
||||
from opendbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR
|
||||
from opendbc.car.hyundai.radar_interface import MRR30_RADAR_START_ADDR, MRR35_RADAR_START_ADDR, RADAR_START_ADDR, get_radar_track_config
|
||||
from opendbc.car.hyundai.values import CAMERA_SCC_CAR, CANFD_CAR, CAN_GEARS, CAR, CHECKSUM, DATE_FW_ECUS, \
|
||||
HYBRID_CAR, EV_CAR, FW_QUERY_CONFIG, LEGACY_SAFETY_MODE_CAR, CANFD_FUZZY_WHITELIST, \
|
||||
UNSUPPORTED_LONGITUDINAL_CAR, PLATFORM_CODE_ECUS, HYUNDAI_VERSION_REQUEST_LONG, \
|
||||
CarControllerParams, DBC, HyundaiFlags, get_platform_codes, HyundaiSafetyFlags, Buttons
|
||||
CarControllerParams, DBC, HyundaiFlags, get_platform_codes, HyundaiSafetyFlags, \
|
||||
HyundaiStarPilotSafetyFlags, Buttons
|
||||
|
||||
LongCtrlState = CarControl.Actuators.LongControlState
|
||||
from opendbc.car.hyundai.fingerprints import FW_VERSIONS
|
||||
@@ -32,7 +33,12 @@ NO_DATES_PLATFORMS = {
|
||||
CAR.KIA_SPORTAGE_5TH_GEN,
|
||||
CAR.KIA_SPORTAGE_HEV_2026,
|
||||
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN,
|
||||
CAR.HYUNDAI_SANTA_CRUZ_2025,
|
||||
CAR.HYUNDAI_TUCSON_4TH_GEN,
|
||||
CAR.HYUNDAI_TUCSON_2025,
|
||||
CAR.HYUNDAI_TUCSON_HEV_2025,
|
||||
CAR.HYUNDAI_TUCSON_PHEV_2025,
|
||||
CAR.KIA_SPORTAGE_2026,
|
||||
# CAN
|
||||
CAR.HYUNDAI_ELANTRA,
|
||||
CAR.HYUNDAI_ELANTRA_GT_I30,
|
||||
@@ -65,6 +71,37 @@ HYUNDAI_NON_SCC_CARS = (
|
||||
)
|
||||
HYUNDAI_NON_SCC_FW_CARS = tuple(car_model for car_model in HYUNDAI_NON_SCC_CARS if car_model in FW_VERSIONS)
|
||||
|
||||
CCNC_NON_HDA2_CARS = (
|
||||
CAR.HYUNDAI_KONA_2ND_GEN,
|
||||
CAR.HYUNDAI_KONA_HEV_2ND_GEN,
|
||||
CAR.HYUNDAI_KONA_EV_2ND_GEN,
|
||||
CAR.HYUNDAI_SANTA_FE_HEV_5TH_GEN,
|
||||
CAR.HYUNDAI_SONATA_2024,
|
||||
CAR.HYUNDAI_SONATA_HEV_2024,
|
||||
CAR.HYUNDAI_IONIQ_5_N,
|
||||
CAR.HYUNDAI_TUCSON_2025,
|
||||
CAR.HYUNDAI_TUCSON_HEV_2025,
|
||||
CAR.HYUNDAI_TUCSON_PHEV_2025,
|
||||
CAR.HYUNDAI_SANTA_CRUZ_2025,
|
||||
CAR.KIA_K4_2025,
|
||||
CAR.KIA_K5_2025,
|
||||
CAR.KIA_SPORTAGE_2026,
|
||||
CAR.KIA_SORENTO_2024,
|
||||
)
|
||||
|
||||
ANGLE_STEERING_CARS = (
|
||||
CAR.HYUNDAI_SANTA_FE_HEV_5TH_GEN,
|
||||
CAR.HYUNDAI_IONIQ_5_PE,
|
||||
CAR.HYUNDAI_IONIQ_9,
|
||||
CAR.KIA_SPORTAGE_2026,
|
||||
CAR.KIA_SPORTAGE_HEV_2026,
|
||||
CAR.KIA_SORENTO_HEV_4TH_GEN_LFA2,
|
||||
CAR.KIA_EV6_2025,
|
||||
CAR.KIA_EV9,
|
||||
CAR.GENESIS_GV70_ELECTRIFIED_2ND_GEN,
|
||||
CAR.GENESIS_GV80_2025,
|
||||
)
|
||||
|
||||
|
||||
def get_test_toggles() -> SimpleNamespace:
|
||||
return SimpleNamespace(always_on_lateral_lkas=False, force_torque_controller=False, nnff=False, nnff_lite=False)
|
||||
@@ -83,12 +120,62 @@ class TestHyundaiFingerprint:
|
||||
assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEERING) == lka_steering
|
||||
|
||||
# radar available
|
||||
for radar in (True, False):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if radar:
|
||||
fingerprint[1][RADAR_START_ADDR] = 8
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False, None)
|
||||
assert CP.radarUnavailable != radar
|
||||
for candidate in (CAR.HYUNDAI_SONATA, CAR.GENESIS_G90):
|
||||
assert get_radar_track_config(candidate).start_addr == RADAR_START_ADDR
|
||||
for radar in (True, False):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if radar:
|
||||
fingerprint[1][RADAR_START_ADDR] = 8
|
||||
CP = CarInterface.get_params(candidate, fingerprint, [], False, False, False, None)
|
||||
assert CP.radarUnavailable != radar
|
||||
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[1][RADAR_START_ADDR] = 8
|
||||
CP = CarInterface.get_params(CAR.GENESIS_G90, fingerprint, [], True, False, False, None)
|
||||
assert CP.openpilotLongitudinalControl
|
||||
assert not CP.radarUnavailable
|
||||
|
||||
for candidate, radar_addr in (
|
||||
(CAR.HYUNDAI_IONIQ_5, MRR30_RADAR_START_ADDR),
|
||||
(CAR.HYUNDAI_IONIQ_5_N, MRR30_RADAR_START_ADDR),
|
||||
(CAR.KIA_EV6_2025, MRR30_RADAR_START_ADDR),
|
||||
(CAR.HYUNDAI_KONA_EV_2ND_GEN, MRR35_RADAR_START_ADDR),
|
||||
(CAR.HYUNDAI_IONIQ_6, MRR35_RADAR_START_ADDR),
|
||||
(CAR.HYUNDAI_IONIQ_9, MRR35_RADAR_START_ADDR),
|
||||
):
|
||||
radar_config = get_radar_track_config(candidate)
|
||||
assert radar_config.start_addr == radar_addr
|
||||
for radar in (True, False):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if radar:
|
||||
fingerprint[radar_config.bus][radar_addr] = 8
|
||||
CP = CarInterface.get_params(candidate, fingerprint, [], False, False, False, None)
|
||||
assert CP.radarUnavailable != radar
|
||||
|
||||
assert get_radar_track_config(CAR.HYUNDAI_IONIQ_6).start_addr == MRR35_RADAR_START_ADDR
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[1][MRR35_RADAR_START_ADDR] = 24
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, fingerprint, [], False, False, False, None)
|
||||
assert not CP.openpilotLongitudinalControl
|
||||
assert CP.radarUnavailable
|
||||
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, gen_empty_fingerprint(), [], True, False, False, None)
|
||||
assert CP.openpilotLongitudinalControl
|
||||
assert CP.radarUnavailable
|
||||
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[get_radar_track_config(CAR.HYUNDAI_IONIQ_6).bus][MRR35_RADAR_START_ADDR] = 24
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, fingerprint, [], True, False, False, None)
|
||||
assert CP.openpilotLongitudinalControl
|
||||
assert not CP.radarUnavailable
|
||||
assert get_radar_track_config(CAR.HYUNDAI_IONIQ_6).frequency == 20
|
||||
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[CanBus(None, fingerprint).CAM][0x50] = 32
|
||||
fingerprint[get_radar_track_config(CAR.HYUNDAI_IONIQ_5).bus][MRR30_RADAR_START_ADDR] = 32
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_5, fingerprint, [], True, False, False, None)
|
||||
assert CP.openpilotLongitudinalControl
|
||||
assert not CP.radarUnavailable
|
||||
|
||||
for candidate in HYUNDAI_NON_SCC_CARS:
|
||||
CP = CarInterface.get_params(candidate, gen_empty_fingerprint(), [], True, False, False, None)
|
||||
@@ -106,12 +193,42 @@ class TestHyundaiFingerprint:
|
||||
CP = CarInterface.get_params(CAR.KIA_SPORTAGE_HEV_2026, fingerprint, [], False, False, False, None)
|
||||
assert CP.flags & HyundaiFlags.SEND_LFA
|
||||
|
||||
@pytest.mark.parametrize("candidate", CCNC_NON_HDA2_CARS)
|
||||
def test_ccnc_non_hda2_platforms_set_ccnc_safety(self, candidate):
|
||||
CP = CarInterface.get_params(candidate, gen_empty_fingerprint(), [], False, False, False, None)
|
||||
|
||||
assert CP.flags & HyundaiFlags.CCNC
|
||||
assert CP.flags & HyundaiFlags.CANFD_CAMERA_SCC
|
||||
assert not (CP.flags & HyundaiFlags.CANFD_LKA_STEERING)
|
||||
assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CCNC
|
||||
assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CAMERA_SCC
|
||||
|
||||
@pytest.mark.parametrize("candidate", ANGLE_STEERING_CARS)
|
||||
def test_angle_steering_platforms_use_angle_control(self, candidate):
|
||||
CP = CarInterface.get_params(candidate, gen_empty_fingerprint(), [], False, False, False, None)
|
||||
|
||||
assert CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING
|
||||
assert CP.steerControlType == CarParams.SteerControlType.angle
|
||||
assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CANFD_ANGLE_STEERING
|
||||
|
||||
def test_ccnc_hda2_lka_layout_does_not_set_ccnc_safety_param(self):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
cam_can = CanBus(None, fingerprint).CAM
|
||||
fingerprint[cam_can] = {0x50: 16}
|
||||
|
||||
CP = CarInterface.get_params(CAR.KIA_K4_2025, fingerprint, [], False, False, False, None)
|
||||
|
||||
assert CP.flags & HyundaiFlags.CCNC
|
||||
assert CP.flags & HyundaiFlags.CANFD_LKA_STEERING
|
||||
assert not (CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CCNC)
|
||||
|
||||
def test_ioniq_6_hda1_layout_stays_non_lka(self):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[1] = {0x100: 8, 0x110: 8}
|
||||
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, fingerprint, [], False, False, False, None)
|
||||
|
||||
assert not (CP.flags & HyundaiFlags.CCNC)
|
||||
assert not (CP.flags & HyundaiFlags.CANFD_LKA_STEERING)
|
||||
assert bool(CP.flags & HyundaiFlags.CANFD_CAMERA_SCC)
|
||||
|
||||
@@ -121,6 +238,19 @@ class TestHyundaiFingerprint:
|
||||
assert palisade_2023.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CAN_CANFD_BLENDED
|
||||
assert palisade_2023.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CANCEL_BTN_ENABLE
|
||||
|
||||
def test_hyundai_lkas_button_sets_starpilot_safety_flag(self):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[0][0x391] = 8
|
||||
|
||||
sonata = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False, None)
|
||||
assert sonata.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON
|
||||
|
||||
sonata_without_lda = CarInterface.get_params(CAR.HYUNDAI_SONATA, gen_empty_fingerprint(), [], False, False, False, None)
|
||||
assert not (sonata_without_lda.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON)
|
||||
|
||||
palisade_2023 = CarInterface.get_params(CAR.HYUNDAI_PALISADE_2023, gen_empty_fingerprint(), [], True, False, False, None)
|
||||
assert palisade_2023.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON
|
||||
|
||||
def test_non_scc_flag_quirks(self):
|
||||
elantra_hev = CarInterface.get_params(CAR.HYUNDAI_ELANTRA_HEV_2022_NON_SCC, gen_empty_fingerprint(), [], True, False, False, None)
|
||||
assert elantra_hev.flags & HyundaiFlags.HYBRID
|
||||
@@ -604,6 +734,124 @@ class TestHyundaiFingerprint:
|
||||
assert parser.vl["SCC_CONTROL"]["ObjValid"] == 1
|
||||
assert parser.vl["SCC_CONTROL"]["OBJ_STATUS"] == 0
|
||||
|
||||
def test_canfd_acc_control_preserves_stock_ccnc_object_fields(self):
|
||||
CP = CarParams.new_message()
|
||||
CP.carFingerprint = CAR.HYUNDAI_SONATA_2024
|
||||
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CCNC)
|
||||
|
||||
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
|
||||
can_bus = CanBus(CP)
|
||||
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("SCC_CONTROL", 0)], can_bus.ECAN)
|
||||
|
||||
msg = hyundaicanfd.create_acc_control(packer, can_bus, enabled=True, accel_last=0.0, accel=0.1, stopping=False,
|
||||
gas_override=False, set_speed=42, hud_control=SimpleNamespace(leadDistanceBars=3),
|
||||
direct_accel=True, lead_distance=27.5, lead_rel_speed=-1.2, lead_visible=True,
|
||||
cruise_info={"ACC_ObjDist": 13.5, "ACC_ObjRelSpd": -0.4})
|
||||
parser.update([(1, [msg])])
|
||||
|
||||
assert parser.can_valid
|
||||
assert parser.vl["SCC_CONTROL"]["ACC_ObjDist"] == pytest.approx(13.5)
|
||||
assert parser.vl["SCC_CONTROL"]["ACC_ObjRelSpd"] == pytest.approx(-0.4)
|
||||
|
||||
def test_ccnc_hud_helper_clears_faults_and_generates_ui_fields(self):
|
||||
CP = CarParams.new_message()
|
||||
CP.carFingerprint = CAR.HYUNDAI_SONATA_2024
|
||||
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CCNC)
|
||||
CP.openpilotLongitudinalControl = True
|
||||
|
||||
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
|
||||
can_bus = CanBus(CP)
|
||||
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CCNC_0x161", 0), ("CCNC_0x162", 0)], can_bus.ECAN)
|
||||
|
||||
msg_161 = {
|
||||
"ALERTS_2": 5,
|
||||
"ALERTS_3": 17,
|
||||
"ALERTS_5": 5,
|
||||
"SOUNDS_3": 5,
|
||||
"SOUNDS_4": 2,
|
||||
"LFA_ICON": 3,
|
||||
}
|
||||
msg_162 = {fault: 1 for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS")}
|
||||
msg_162["VIBRATE"] = 0
|
||||
msg_1b5 = {
|
||||
"Info_LftLnPosVal": 1.4,
|
||||
"Info_RtLnPosVal": 1.9,
|
||||
"Info_LftLnQualSta": 3,
|
||||
"Info_RtLnQualSta": 3,
|
||||
"Longitudinal_Distance": 42.0,
|
||||
}
|
||||
hud = SimpleNamespace(leftLaneVisible=True, rightLaneVisible=True, leftLaneDepart=True, rightLaneDepart=False,
|
||||
leadDistanceBars=3, leadVisible=True)
|
||||
out = SimpleNamespace(steeringAngleDeg=22.5, vEgo=15.0, leftBlindspot=True, rightBlindspot=False,
|
||||
vCruiseCluster=88.0)
|
||||
|
||||
msgs = hyundaicanfd.create_ccnc(packer, can_bus, openpilot_longitudinal=True, enabled=True, hud=hud,
|
||||
left_blinker=False, right_blinker=False, msg_161=msg_161, msg_162=msg_162,
|
||||
msg_1b5=msg_1b5, is_metric=False, out=out, main_cruise_enabled=True, lfa_icon=2)
|
||||
parser.update([(1, msgs)])
|
||||
|
||||
assert parser.can_valid
|
||||
assert parser.vl["CCNC_0x161"]["DAW_ICON"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["LKA_ICON"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["LFA_ICON"] == 2
|
||||
assert parser.vl["CCNC_0x161"]["CENTERLINE"] == 1
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_CURVATURE"] == 20
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_LEFT"] == 4
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_RIGHT"] == 2
|
||||
assert parser.vl["CCNC_0x161"]["LCA_LEFT_ICON"] == 1
|
||||
assert parser.vl["CCNC_0x161"]["LCA_RIGHT_ICON"] == 4
|
||||
assert parser.vl["CCNC_0x161"]["ALERTS_2"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["ALERTS_3"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["ALERTS_5"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["SOUNDS_3"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["SOUNDS_4"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["SETSPEED"] == 3
|
||||
assert parser.vl["CCNC_0x161"]["SETSPEED_HUD"] == 2
|
||||
assert parser.vl["CCNC_0x161"]["SETSPEED_SPEED"] == 55
|
||||
assert parser.vl["CCNC_0x161"]["DISTANCE"] == 3
|
||||
assert parser.vl["CCNC_0x161"]["DISTANCE_LEAD"] == 2
|
||||
assert all(parser.vl["CCNC_0x162"][fault] == 0 for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS"))
|
||||
assert parser.vl["CCNC_0x162"]["VIBRATE"] == 1
|
||||
assert parser.vl["CCNC_0x162"]["LEAD"] == 2
|
||||
assert parser.vl["CCNC_0x162"]["LEAD_DISTANCE"] == pytest.approx(42.0)
|
||||
|
||||
def test_ccnc_hud_helper_generates_lane_position_animation_and_lca_arrows(self):
|
||||
CP = CarParams.new_message()
|
||||
CP.carFingerprint = CAR.HYUNDAI_SONATA_2024
|
||||
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CCNC)
|
||||
|
||||
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
|
||||
can_bus = CanBus(CP)
|
||||
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CCNC_0x161", 0), ("CCNC_0x162", 0)], can_bus.ECAN)
|
||||
hud = SimpleNamespace(leftLaneVisible=True, rightLaneVisible=True, leftLaneDepart=False, rightLaneDepart=False,
|
||||
leadDistanceBars=1, leadVisible=False)
|
||||
out = SimpleNamespace(steeringAngleDeg=0.0, vEgo=15.0, leftBlindspot=False, rightBlindspot=False,
|
||||
vCruiseCluster=55.0)
|
||||
msg_1b5 = {
|
||||
"Info_LftLnPosVal": 1.4,
|
||||
"Info_RtLnPosVal": 1.9,
|
||||
"Info_LftLnQualSta": 3,
|
||||
"Info_RtLnQualSta": 3,
|
||||
"Longitudinal_Distance": 0.0,
|
||||
}
|
||||
|
||||
msgs = hyundaicanfd.create_ccnc(packer, can_bus, openpilot_longitudinal=False, enabled=True, hud=hud,
|
||||
left_blinker=True, right_blinker=False,
|
||||
msg_161={"ALERTS_2": 0, "ALERTS_3": 0, "ALERTS_5": 0, "SOUNDS_4": 0, "LFA_ICON": 2},
|
||||
msg_162={fault: 0 for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS")},
|
||||
msg_1b5=msg_1b5, is_metric=True, out=out, main_cruise_enabled=True, lfa_icon=2)
|
||||
parser.update([(1, msgs)])
|
||||
|
||||
assert parser.can_valid
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_CURVATURE"] == 15
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_LEFT"] == 6
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_RIGHT"] == 6
|
||||
assert parser.vl["CCNC_0x161"]["LCA_LEFT_ICON"] == 2
|
||||
assert parser.vl["CCNC_0x161"]["LCA_LEFT_ARROW"] == 2
|
||||
assert parser.vl["CCNC_0x161"]["LCA_RIGHT_ARROW"] == 0
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_LEFT_POSITION"] == 12
|
||||
assert parser.vl["CCNC_0x161"]["LANELINE_RIGHT_POSITION"] == 18
|
||||
|
||||
def test_canfd_scc_lead_state_prefers_openpilot_lead_distance(self):
|
||||
CP = CarParams.new_message()
|
||||
CP.carFingerprint = CAR.KIA_EV6
|
||||
@@ -1196,7 +1444,7 @@ class TestHyundaiFingerprint:
|
||||
|
||||
# Hyundai places the ECU part number in their FW versions, assert all parsable
|
||||
# Some examples of valid formats: b"56310-L0010", b"56310L0010", b"56310/M6300"
|
||||
if car_model != CAR.KIA_SPORTAGE_HEV_2026:
|
||||
if car_model not in (CAR.KIA_SPORTAGE_2026, CAR.KIA_SPORTAGE_HEV_2026):
|
||||
assert all(b"-" in code for code, _ in codes), \
|
||||
f"FW does not have part number: {fw}"
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ SPORTAGE_HEV_2026_LOW_SPEED_JERK_SPEED = 11.0
|
||||
SPORTAGE_HEV_2026_LOW_SPEED_JERK_WIDTH = 5.0
|
||||
SPORTAGE_HEV_2026_MAX_ANGLE_RATE = 6.5
|
||||
SPORTAGE_HEV_2026_STEER_ANGLE_MAX = 220.0
|
||||
HYUNDAI_MANDO_FRONT_RADAR_DBC = "hyundai_kia_mando_front_radar_generated"
|
||||
HYUNDAI_MRR30_RADAR_DBC = "hyundai_mrr30_radar_generated"
|
||||
HYUNDAI_MRR35_RADAR_DBC = "hyundai_mrr35_radar_generated"
|
||||
|
||||
|
||||
class CarControllerParams:
|
||||
@@ -121,6 +124,7 @@ class HyundaiSafetyFlags(IntFlag):
|
||||
NON_SCC = 4096
|
||||
CAN_CANFD_BLENDED = 8192
|
||||
CANCEL_BTN_ENABLE = 16384
|
||||
CCNC = 32768
|
||||
|
||||
|
||||
class HyundaiStarPilotSafetyFlags(IntFlag):
|
||||
@@ -184,8 +188,6 @@ class HyundaiFlags(IntFlag):
|
||||
|
||||
MIN_STEER_32_MPH = 2 ** 23
|
||||
|
||||
HAS_LDA_BUTTON = 2 ** 24
|
||||
|
||||
FCEV = 2 ** 25
|
||||
|
||||
ALT_LIMITS_2 = 2 ** 26
|
||||
@@ -203,6 +205,9 @@ class HyundaiFlags(IntFlag):
|
||||
NON_SCC_NO_FCA = 2 ** 30
|
||||
NON_SCC_RADAR_FCA = 2 ** 31
|
||||
|
||||
# Connected Car Navigation Cockpit CAN-FD platforms.
|
||||
CCNC = 2 ** 24
|
||||
|
||||
|
||||
@dataclass
|
||||
class HyundaiCarDocs(CarDocs):
|
||||
@@ -222,7 +227,7 @@ class HyundaiPlatformConfig(PlatformConfig):
|
||||
|
||||
def init(self):
|
||||
if self.flags & HyundaiFlags.MANDO_RADAR:
|
||||
self.dbc_dict = {Bus.pt: "hyundai_kia_generic", Bus.radar: 'hyundai_kia_mando_front_radar_generated'}
|
||||
self.dbc_dict = {Bus.pt: "hyundai_kia_generic", Bus.radar: HYUNDAI_MANDO_FRONT_RADAR_DBC}
|
||||
|
||||
if self.flags & HyundaiFlags.MIN_STEER_32_MPH:
|
||||
self.specs = self.specs.override(minSteerSpeed=32 * CV.MPH_TO_MS)
|
||||
@@ -234,9 +239,12 @@ class HyundaiPlatformConfig(PlatformConfig):
|
||||
@dataclass
|
||||
class HyundaiCanFDPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: "hyundai_canfd_generated"})
|
||||
radar_dbc: str | None = None
|
||||
|
||||
def init(self):
|
||||
self.flags |= HyundaiFlags.CANFD
|
||||
if self.radar_dbc is not None:
|
||||
self.dbc_dict = {Bus.pt: "hyundai_canfd_generated", Bus.radar: self.radar_dbc}
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -342,6 +350,16 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2,
|
||||
)
|
||||
HYUNDAI_KONA_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_KONA_HEV_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Hybrid (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_KONA_EV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Electric 2018-21", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
CarSpecs(mass=1685, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
||||
@@ -353,10 +371,14 @@ class CAR(Platforms):
|
||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS,
|
||||
)
|
||||
HYUNDAI_KONA_EV_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw",
|
||||
car_parts=CarParts.common([CarHarness.hyundai_r]))],
|
||||
[
|
||||
HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw",
|
||||
car_parts=CarParts.common([CarHarness.hyundai_r])),
|
||||
HyundaiCarDocs("Hyundai Kona Electric (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||
],
|
||||
CarSpecs(mass=1740, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE,
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE | HyundaiFlags.CCNC,
|
||||
radar_dbc=HYUNDAI_MRR35_RADAR_DBC,
|
||||
)
|
||||
HYUNDAI_KONA_HEV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_i]))], # TODO: check packages,
|
||||
@@ -390,12 +412,27 @@ class CAR(Platforms):
|
||||
HYUNDAI_SANTA_FE.specs,
|
||||
flags=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])),
|
||||
HyundaiCarDocs("Hyundai Santa Fe Hybrid (without HDA II, LFA2) 2025-26", "Lane Follow Assist 2",
|
||||
car_parts=CarParts.common([CarHarness.hyundai_l])),
|
||||
],
|
||||
CarSpecs(mass=2035, wheelbase=2.81, steerRatio=13.72),
|
||||
flags=HyundaiFlags.CANFD_ANGLE_STEERING | HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_SONATA = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Sonata 2020-23", "All", video="https://www.youtube.com/watch?v=ix63r9kE3Fw",
|
||||
car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=1513, wheelbase=2.84, steerRatio=13.27 * 1.15, tireStiffnessFactor=0.65), # 15% higher at the center seems reasonable
|
||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8,
|
||||
)
|
||||
HYUNDAI_SONATA_2024 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Sonata (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=1556, wheelbase=2.84, steerRatio=12.81),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_SONATA_LF = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Sonata 2018-19", car_parts=CarParts.common([CarHarness.hyundai_e]))],
|
||||
CarSpecs(mass=1536, wheelbase=2.804, steerRatio=13.27 * 1.15), # 15% higher at the center seems reasonable
|
||||
@@ -441,6 +478,11 @@ class CAR(Platforms):
|
||||
HYUNDAI_SONATA.specs,
|
||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
||||
)
|
||||
HYUNDAI_SONATA_HEV_2024 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Sonata Hybrid (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=1616, wheelbase=2.84, steerRatio=13.27),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])),
|
||||
@@ -449,11 +491,37 @@ class CAR(Platforms):
|
||||
],
|
||||
CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65),
|
||||
flags=HyundaiFlags.EV,
|
||||
radar_dbc=HYUNDAI_MRR30_RADAR_DBC,
|
||||
)
|
||||
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,
|
||||
radar_dbc=HYUNDAI_MRR30_RADAR_DBC,
|
||||
)
|
||||
HYUNDAI_IONIQ_5_N = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Ioniq 5 N (with HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_s]))],
|
||||
CarSpecs(mass=2205, wheelbase=3.00, steerRatio=14.26, tireStiffnessFactor=1.3),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.CCNC,
|
||||
radar_dbc=HYUNDAI_MRR30_RADAR_DBC,
|
||||
)
|
||||
HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Ioniq 6 (with HDA II) 2023-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))],
|
||||
HYUNDAI_IONIQ_5.specs,
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE,
|
||||
radar_dbc=HYUNDAI_MRR35_RADAR_DBC,
|
||||
)
|
||||
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,
|
||||
radar_dbc=HYUNDAI_MRR35_RADAR_DBC,
|
||||
)
|
||||
HYUNDAI_TUCSON_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
@@ -464,11 +532,31 @@ class CAR(Platforms):
|
||||
],
|
||||
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||
)
|
||||
HYUNDAI_TUCSON_2025 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Tucson (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_TUCSON_HEV_2025 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Tucson Hybrid (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_TUCSON_PHEV_2025 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Tucson Plug-in Hybrid (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_SANTA_CRUZ_1ST_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Santa Cruz 2022-24", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||
# weight from Limited trim - the only supported trim, steering ratio according to Hyundai News https://www.hyundainews.com/assets/documents/original/48035-2022SantaCruzProductGuideSpecsv2081521.pdf
|
||||
CarSpecs(mass=1870, wheelbase=3, steerRatio=14.2),
|
||||
)
|
||||
HYUNDAI_SANTA_CRUZ_2025 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Santa Cruz (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||
CarSpecs(mass=1920, wheelbase=3, steerRatio=14.2),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
HYUNDAI_CUSTIN_1ST_GEN = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Custin 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
CarSpecs(mass=1690, wheelbase=3.055, steerRatio=17), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner
|
||||
@@ -483,11 +571,24 @@ class CAR(Platforms):
|
||||
],
|
||||
CarSpecs(mass=2878 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5)
|
||||
)
|
||||
KIA_K4_2025 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia K4 (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||
HyundaiCarDocs("Kia K4 (with HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_r])),
|
||||
],
|
||||
CarSpecs(mass=2987 * CV.LB_TO_KG, wheelbase=2.72, steerRatio=13.4),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
KIA_K5_2021 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K5 2021-24", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=3381 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5), # 2021 Kia K5 Steering Ratio (all trims)
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
)
|
||||
KIA_K5_2025 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K5 (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_m]))],
|
||||
CarSpecs(mass=3230 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
KIA_K5_HEV_2020 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K5 Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
KIA_K5_2021.specs,
|
||||
@@ -580,6 +681,13 @@ 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_2026 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia Sportage (without HDA II) 2026", car_parts=CarParts.common([CarHarness.hyundai_n])),
|
||||
],
|
||||
CarSpecs(mass=1735, wheelbase=2.756, steerRatio=13.7),
|
||||
flags=HyundaiFlags.CANFD_ANGLE_STEERING | HyundaiFlags.CCNC,
|
||||
)
|
||||
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),
|
||||
@@ -599,6 +707,11 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
|
||||
flags=HyundaiFlags.RADAR_SCC,
|
||||
)
|
||||
KIA_SORENTO_2024 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Sorento (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5),
|
||||
flags=HyundaiFlags.CCNC,
|
||||
)
|
||||
KIA_SORENTO_HEV_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia Sorento Hybrid 2021-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||
@@ -607,6 +720,13 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=4395 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
|
||||
flags=HyundaiFlags.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]))],
|
||||
@@ -630,6 +750,22 @@ 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,
|
||||
radar_dbc=HYUNDAI_MRR30_RADAR_DBC,
|
||||
)
|
||||
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,
|
||||
radar_dbc=HYUNDAI_MRR35_RADAR_DBC,
|
||||
)
|
||||
KIA_CARNIVAL_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia Carnival 2022-24", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||
@@ -680,6 +816,14 @@ 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,
|
||||
radar_dbc=HYUNDAI_MRR35_RADAR_DBC,
|
||||
)
|
||||
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),
|
||||
@@ -692,12 +836,24 @@ class CAR(Platforms):
|
||||
GENESIS_G90 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Genesis G90 2017-20", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=2200, wheelbase=3.15, steerRatio=12.069),
|
||||
flags=HyundaiFlags.MANDO_RADAR,
|
||||
)
|
||||
GENESIS_GV80 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Genesis GV80 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_m]))],
|
||||
CarSpecs(mass=2258, wheelbase=2.95, steerRatio=14.14),
|
||||
flags=HyundaiFlags.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,
|
||||
radar_dbc=HYUNDAI_MRR35_RADAR_DBC,
|
||||
)
|
||||
|
||||
# Hyundai non-SCC extensions
|
||||
HYUNDAI_BAYON_1ST_GEN_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
@@ -857,7 +1013,7 @@ PART_NUMBER_FW_PATTERN = re.compile(b'(?<=[0-9][.,][0-9]{2} )([0-9]{5}[-/]?[A-Z]
|
||||
# We've seen both ICE and hybrid for these platforms, and they have hybrid descriptors (e.g. MQ4 vs MQ4H)
|
||||
CANFD_FUZZY_WHITELIST = {CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_SORENTO_HEV_4TH_GEN, CAR.KIA_K8_HEV_1ST_GEN,
|
||||
# TODO: the hybrid variant is not out yet
|
||||
CAR.KIA_CARNIVAL_4TH_GEN}
|
||||
CAR.KIA_CARNIVAL_4TH_GEN, CAR.KIA_SORENTO_HEV_4TH_GEN_LFA2}
|
||||
|
||||
# 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
|
||||
@@ -951,9 +1107,11 @@ CAN_GEARS = {
|
||||
CANFD_CAR = CAR.with_flags(HyundaiFlags.CANFD)
|
||||
CANFD_RADAR_SCC_CAR = CAR.with_flags(HyundaiFlags.RADAR_SCC) # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR
|
||||
|
||||
# Cars with CANFD_NO_RADAR_DISABLE that now work with SecurityAccess handshake
|
||||
CANFD_SECURITYACCESS_CAR = {CAR.HYUNDAI_IONIQ_6, CAR.HYUNDAI_KONA_EV_2ND_GEN}
|
||||
# CAN-FD cars with ADAS ECUs that work with the communication-control path.
|
||||
CANFD_SECURITYACCESS_CAR = {CAR.HYUNDAI_IONIQ_5, CAR.HYUNDAI_IONIQ_6, CAR.HYUNDAI_KONA_EV_2ND_GEN}
|
||||
CANFD_UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.CANFD_NO_RADAR_DISABLE) - CANFD_SECURITYACCESS_CAR # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR
|
||||
CANFD_RADAR_LIVE_LONGITUDINAL_CAR = {CAR.HYUNDAI_IONIQ_5, CAR.HYUNDAI_IONIQ_6}
|
||||
RADAR_LIVE_LONGITUDINAL_CAR = CANFD_RADAR_LIVE_LONGITUDINAL_CAR | {CAR.GENESIS_G90}
|
||||
|
||||
CAMERA_SCC_CAR = CAR.with_flags(HyundaiFlags.CAMERA_SCC)
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ class CarInterfaceBase(ABC):
|
||||
not CP.openpilotLongitudinalControl:
|
||||
fp_ret.pcmCruiseSpeed = False
|
||||
|
||||
if CP.flags & HyundaiFlags.HAS_LDA_BUTTON:
|
||||
if 0x391 in fingerprint[0] or CP.flags & HyundaiFlags.CAN_CANFD_BLENDED:
|
||||
fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON.value
|
||||
if starpilot_toggles.always_on_lateral_lkas:
|
||||
fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value
|
||||
|
||||
@@ -22,9 +22,21 @@ non_tested_cars = [
|
||||
MOCK.MOCK,
|
||||
GM.CADILLAC_ATS,
|
||||
GM.CADILLAC_ESCALADE_ASCM,
|
||||
GM.CADILLAC_XT5,
|
||||
GM.HOLDEN_ASTRA,
|
||||
GM.CHEVROLET_MALIBU,
|
||||
HYUNDAI.GENESIS_G90,
|
||||
HYUNDAI.GENESIS_GV70_ELECTRIFIED_2ND_GEN,
|
||||
HYUNDAI.GENESIS_GV80_2025,
|
||||
HYUNDAI.HYUNDAI_IONIQ_5_PE,
|
||||
HYUNDAI.HYUNDAI_IONIQ_5_N,
|
||||
HYUNDAI.HYUNDAI_SANTA_FE_HEV_5TH_GEN,
|
||||
HYUNDAI.HYUNDAI_TUCSON_PHEV_2025,
|
||||
HYUNDAI.KIA_EV6_2025,
|
||||
HYUNDAI.KIA_EV9,
|
||||
HYUNDAI.KIA_SPORTAGE_2026,
|
||||
HYUNDAI.KIA_SORENTO_2024,
|
||||
HYUNDAI.KIA_SORENTO_HEV_4TH_GEN_LFA2,
|
||||
VOLKSWAGEN.VOLKSWAGEN_CRAFTER_MK2, # need a route from an ACC-equipped Crafter
|
||||
SUBARU.SUBARU_FORESTER_HYBRID,
|
||||
VOLKSWAGEN.PORSCHE_MACAN_MK1,
|
||||
@@ -143,6 +155,7 @@ routes = [
|
||||
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),
|
||||
CarTestRoute("f0709d2bc6ca451f/2022-10-15--08-13-54", HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN),
|
||||
CarTestRoute("6e7904b03a4aafc2/00000010--31034184b6", HYUNDAI.HYUNDAI_SANTA_CRUZ_2025),
|
||||
CarTestRoute("4dbd55df87507948/2022-03-01--09-45-38", HYUNDAI.HYUNDAI_SANTA_FE),
|
||||
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),
|
||||
@@ -156,11 +169,14 @@ routes = [
|
||||
CarTestRoute("6a42c1197b2a8179/2023-09-21--10-23-44", HYUNDAI.KIA_OPTIMA_H_G4_FL),
|
||||
CarTestRoute("c75a59efa0ecd502/2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS),
|
||||
CarTestRoute("5b7c365c50084530/2020-04-15--16-13-24", HYUNDAI.HYUNDAI_SONATA),
|
||||
CarTestRoute("4267ea8a353cdb36/00000262--8a427003c7", HYUNDAI.HYUNDAI_SONATA_2024, segment=34),
|
||||
CarTestRoute("b2a38c712dcf90bd/2020-05-18--18-12-48", HYUNDAI.HYUNDAI_SONATA_LF),
|
||||
CarTestRoute("c344fd2492c7a9d2/2023-12-11--09-03-23", HYUNDAI.HYUNDAI_STARIA_4TH_GEN),
|
||||
CarTestRoute("fb3fd42f0baaa2f8/2022-03-30--15-25-05", HYUNDAI.HYUNDAI_TUCSON),
|
||||
CarTestRoute("db68bbe12250812c/2022-12-05--00-54-12", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # 2023
|
||||
CarTestRoute("36e10531feea61a4/2022-07-25--13-37-42", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # hybrid
|
||||
CarTestRoute("a01ca5d4f394c812/00000000--e98b7e4414", HYUNDAI.HYUNDAI_TUCSON_2025),
|
||||
CarTestRoute("22f9090014364a87/00000002--4cc739c0b2", HYUNDAI.HYUNDAI_TUCSON_HEV_2025),
|
||||
CarTestRoute("5875672fc1d4bf57/2020-07-23--21-33-28", HYUNDAI.KIA_SORENTO),
|
||||
CarTestRoute("1d0d000db3370fd0/2023-01-04--22-28-42", HYUNDAI.KIA_SORENTO_4TH_GEN, segment=5),
|
||||
CarTestRoute("fc19648042eb6896/2023-08-16--11-43-27", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, segment=14),
|
||||
@@ -168,6 +184,7 @@ routes = [
|
||||
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("eb4eae1476647463/2023-08-26--18-07-04", HYUNDAI.HYUNDAI_IONIQ_6, segment=6), # LKA steering
|
||||
CarTestRoute("71e4e67d29034771/0000001b--b7b4774ec4", HYUNDAI.HYUNDAI_IONIQ_9),
|
||||
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
|
||||
@@ -178,11 +195,13 @@ routes = [
|
||||
CarTestRoute("ab59fe909f626921/2021-10-18--18-34-28", HYUNDAI.HYUNDAI_IONIQ_HEV_2022),
|
||||
CarTestRoute("22d955b2cd499c22/2020-08-10--19-58-21", HYUNDAI.HYUNDAI_KONA),
|
||||
CarTestRoute("0099bdb24d82951b/00000005--c38d940b04", HYUNDAI.HYUNDAI_KONA_2022),
|
||||
CarTestRoute("32025f26789d8fab/00000022--a499e8ffa3", HYUNDAI.HYUNDAI_KONA_2ND_GEN),
|
||||
CarTestRoute("efc48acf44b1e64d/2021-05-28--21-05-04", HYUNDAI.HYUNDAI_KONA_EV),
|
||||
CarTestRoute("f90d3cd06caeb6fa/2023-09-06--17-15-47", HYUNDAI.HYUNDAI_KONA_EV), # openpilot longitudinal enabled
|
||||
CarTestRoute("ff973b941a69366f/2022-07-28--22-01-19", HYUNDAI.HYUNDAI_KONA_EV_2022, segment=11),
|
||||
CarTestRoute("1618132d68afc876/2023-08-27--09-32-14", HYUNDAI.HYUNDAI_KONA_EV_2ND_GEN, segment=13),
|
||||
CarTestRoute("49f3c13141b6bc87/2021-07-28--08-05-13", HYUNDAI.HYUNDAI_KONA_HEV),
|
||||
CarTestRoute("97ca61196eb73e0d/00000052--4555329470", HYUNDAI.HYUNDAI_KONA_HEV_2ND_GEN),
|
||||
CarTestRoute("a74afe0cf708748f/0000000e--a2885a9a71", HYUNDAI.HYUNDAI_NEXO_1ST_GEN),
|
||||
CarTestRoute("a74afe0cf708748f/0000000c--b476a8fd00", HYUNDAI.HYUNDAI_NEXO_1ST_GEN), # openpilot longitudinal enabled
|
||||
CarTestRoute("5dddcbca6eb66c62/2020-07-26--13-24-19", HYUNDAI.KIA_STINGER),
|
||||
@@ -191,7 +210,9 @@ routes = [
|
||||
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("9b25e8c1484a1b67/2023-04-13--10-41-45", HYUNDAI.KIA_EV6),
|
||||
CarTestRoute("baf39eeaba1217ca/00000002--b36e3fa031", HYUNDAI.KIA_K4_2025),
|
||||
CarTestRoute("007d5e4ad9f86d13/2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021),
|
||||
CarTestRoute("c4a804b067623789/0000007c--163f831540", HYUNDAI.KIA_K5_2025),
|
||||
CarTestRoute("c58dfc9fc16590e0/2023-01-14--13-51-48", HYUNDAI.KIA_K5_HEV_2020),
|
||||
CarTestRoute("78ad5150de133637/2023-09-13--16-15-57", HYUNDAI.KIA_K8_HEV_1ST_GEN),
|
||||
CarTestRoute("50c6c9b85fd1ff03/2020-10-26--17-56-06", HYUNDAI.KIA_NIRO_EV),
|
||||
@@ -210,6 +231,7 @@ routes = [
|
||||
CarTestRoute("82e9cdd3f43bf83e/2021-05-15--02-42-51", HYUNDAI.HYUNDAI_ELANTRA_2021),
|
||||
CarTestRoute("715ac05b594e9c59/2021-06-20--16-21-07", HYUNDAI.HYUNDAI_ELANTRA_HEV_2021),
|
||||
CarTestRoute("7120aa90bbc3add7/2021-08-02--07-12-31", HYUNDAI.HYUNDAI_SONATA_HYBRID),
|
||||
CarTestRoute("bc40c72b728178f2/00000006--ee76ae8c42", HYUNDAI.HYUNDAI_SONATA_HEV_2024),
|
||||
CarTestRoute("715ac05b594e9c59/2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020),
|
||||
CarTestRoute("6b0d44d22df18134/2023-05-06--10-36-55", HYUNDAI.GENESIS_GV80),
|
||||
|
||||
|
||||
@@ -64,13 +64,25 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"VOLKSWAGEN_PASSAT_NMS" = [2.5, 2.5, 0.1]
|
||||
"VOLKSWAGEN_SHARAN_MK2" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_SANTA_CRUZ_1ST_GEN" = [2.7, 2.7, 0.1]
|
||||
"HYUNDAI_SANTA_CRUZ_2025" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_SANTA_FE_HEV_5TH_GEN" = [nan, 2.5, nan]
|
||||
"HYUNDAI_SONATA_2024" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_SONATA_HEV_2024" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_KONA_2ND_GEN" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_KONA_HEV_2ND_GEN" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_TUCSON_2025" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_TUCSON_HEV_2025" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_TUCSON_PHEV_2025" = [2.5, 2.5, 0.1]
|
||||
"KIA_SPORTAGE_5TH_GEN" = [2.6, 2.6, 0.1]
|
||||
"KIA_SPORTAGE_2026" = [nan, 2.5, nan]
|
||||
"KIA_SPORTAGE_HEV_2026" = [nan, 2.5, nan]
|
||||
"GENESIS_GV70_1ST_GEN" = [2.42, 2.42, 0.1]
|
||||
"GENESIS_GV60_EV_1ST_GEN" = [2.5, 2.5, 0.1]
|
||||
"GMC_YUKON" = [1.2, 2.5, 0.26]
|
||||
"KIA_SORENTO_4TH_GEN" = [2.5, 2.5, 0.1]
|
||||
"KIA_SORENTO_2024" = [2.5, 2.5, 0.1]
|
||||
"KIA_SORENTO_HEV_4TH_GEN" = [2.5, 2.5, 0.1]
|
||||
"KIA_SORENTO_HEV_4TH_GEN_LFA2" = [nan, 2.5, nan]
|
||||
"KIA_NIRO_HEV_2ND_GEN" = [2.42, 2.5, 0.12]
|
||||
"KIA_NIRO_EV_2ND_GEN" = [2.05, 2.5, 0.14]
|
||||
"GENESIS_GV80" = [2.5, 2.5, 0.1]
|
||||
@@ -78,15 +90,24 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"GMC_ACADIA" = [1.6, 1.6, 0.2]
|
||||
"LEXUS_IS_TSS2" = [2.0, 2.0, 0.1]
|
||||
"HYUNDAI_KONA_EV_2ND_GEN" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_IONIQ_5_PE" = [nan, 2.5, nan]
|
||||
"HYUNDAI_IONIQ_5_N" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_IONIQ_6" = [3.0, 3.0, 0.09]
|
||||
"HYUNDAI_IONIQ_9" = [nan, 2.5, nan]
|
||||
"HYUNDAI_AZERA_6TH_GEN" = [1.8, 1.8, 0.1]
|
||||
"HYUNDAI_AZERA_HEV_6TH_GEN" = [1.8, 1.8, 0.1]
|
||||
"KIA_K8_HEV_1ST_GEN" = [2.5, 2.5, 0.1]
|
||||
"KIA_K4_2025" = [2.5, 2.5, 0.1]
|
||||
"KIA_K5_2025" = [2.5, 2.5, 0.1]
|
||||
"KIA_EV6_2025" = [nan, 2.5, nan]
|
||||
"KIA_EV9" = [nan, 2.5, nan]
|
||||
"HYUNDAI_CUSTIN_1ST_GEN" = [2.5, 2.5, 0.1]
|
||||
"LEXUS_GS_F" = [2.5, 2.5, 0.08]
|
||||
"HYUNDAI_STARIA_4TH_GEN" = [1.8, 2.0, 0.15]
|
||||
"GENESIS_GV70_ELECTRIFIED_1ST_GEN" = [1.9, 1.9, 0.09]
|
||||
"GENESIS_GV70_ELECTRIFIED_2ND_GEN" = [nan, 2.5, nan]
|
||||
"GENESIS_G80_2ND_GEN_FL" = [2.5819356441497803, 2.5, 0.11244568973779678]
|
||||
"GENESIS_GV80_2025" = [nan, 2.5, nan]
|
||||
# Note that some Rivians achieve significantly less lateral acceleration than this
|
||||
"RIVIAN_R1_GEN1" = [2.8, 2.5, 0.07]
|
||||
"HYUNDAI_NEXO_1ST_GEN" = [2.5, 2.5, 0.1]
|
||||
|
||||
@@ -109,10 +109,12 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"SUBARU_ASCENT" = "SUBARU_FORESTER"
|
||||
|
||||
"CADILLAC_CT6_CC" = "CHEVROLET_VOLT"
|
||||
"CADILLAC_XT5" = "GMC_ACADIA"
|
||||
"CADILLAC_XT5_CC" = "GMC_ACADIA"
|
||||
"BUICK_BABYENCLAVE" = "GMC_ACADIA"
|
||||
"CHEVROLET_EQUINOX_CC" = "CHEVROLET_EQUINOX"
|
||||
"GMC_YUKON_CC" = "CHEVROLET_SILVERADO"
|
||||
"CHEVROLET_TRAILBLAZER_CC" = "CHEVROLET_TRAILBLAZER"
|
||||
"CHEVROLET_SILVERADO_CC" = "CHEVROLET_SILVERADO"
|
||||
|
||||
"CHEVROLET_TRAX" = "CHEVROLET_VOLT"
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbc_name = os.path.basename(__file__).replace(".py", ".dbc")
|
||||
hyundai_path = os.path.dirname(os.path.realpath(__file__))
|
||||
with open(os.path.join(hyundai_path, dbc_name), "w", encoding="utf-8") as f:
|
||||
f.write("""
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: XXX
|
||||
""")
|
||||
|
||||
for a in range(0x210, 0x210 + 16):
|
||||
f.write(f"""
|
||||
BO_ {a} RADAR_TRACK_{a:x}: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
""")
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbc_name = os.path.basename(__file__).replace(".py", ".dbc")
|
||||
hyundai_path = os.path.dirname(os.path.realpath(__file__))
|
||||
with open(os.path.join(hyundai_path, dbc_name), "w", encoding="utf-8") as f:
|
||||
f.write("""
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: XXX
|
||||
""")
|
||||
|
||||
for a in range(0x3A5, 0x3A5 + 32):
|
||||
f.write(f"""
|
||||
BO_ {a} RADAR_TRACK_{a:x}: 24 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_1 : 25|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_3 : 28|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ COUNTER_3 : 31|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_2 : 38|7@0- (1,0) [0|127] "" XXX
|
||||
SG_ COUNTER_256 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_6 : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ STATE : 54|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ NEW_SIGNAL_8 : 62|7@0- (1,0) [0|127] "" XXX
|
||||
SG_ LONG_DIST : 63|12@1+ (0.05,0) [0|8191] "m" XXX
|
||||
SG_ LAT_DIST : 76|12@1- (0.05,0) [0|127] "" XXX
|
||||
SG_ REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ NEW_SIGNAL_4 : 103|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LAT_DIST_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ REL_ACCEL : 118|10@1- (0.02,0) [0|1023] "" XXX
|
||||
SG_ NEW_SIGNAL_18 : 129|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_5 : 133|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_10 : 138|5@1+ (1,0) [0|31] "" XXX
|
||||
SG_ NEW_SIGNAL_11 : 149|6@0+ (1,0) [0|63] "" XXX
|
||||
SG_ NEW_SIGNAL_7 : 152|10@1+ (1,0) [0|1023] "" XXX
|
||||
SG_ NEW_SIGNAL_9 : 162|9@1- (1,0) [0|511] "" XXX
|
||||
SG_ NEW_SIGNAL_13 : 175|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_12 : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_14 : 181|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_15 : 183|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_16 : 185|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_17 : 187|2@0+ (1,0) [0|3] "" XXX
|
||||
""")
|
||||
@@ -0,0 +1,424 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT";
|
||||
|
||||
CM_ "hyundai_mrr30_radar.dbc starts here";
|
||||
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: XXX
|
||||
|
||||
BO_ 528 RADAR_TRACK_210: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 529 RADAR_TRACK_211: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 530 RADAR_TRACK_212: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 531 RADAR_TRACK_213: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 532 RADAR_TRACK_214: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 533 RADAR_TRACK_215: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 534 RADAR_TRACK_216: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 535 RADAR_TRACK_217: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 536 RADAR_TRACK_218: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 537 RADAR_TRACK_219: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 538 RADAR_TRACK_21a: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 539 RADAR_TRACK_21b: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 540 RADAR_TRACK_21c: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 541 RADAR_TRACK_21d: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 542 RADAR_TRACK_21e: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
|
||||
BO_ 543 RADAR_TRACK_21f: 32 RADAR
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_COUNTER_255 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 1_STATE_ALT : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_3 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 1_LONG_DIST : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 1_REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ 1_NEW_SIGNAL_1 : 102|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 1_LAT_ACCEL : 104|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 1_REL_ACCEL : 118|10@1- (1,0) [0|1023] "" XXX
|
||||
SG_ 2_COUNTER_255 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ 2_STATE_ALT : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_STATE : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_3 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ 2_LONG_DIST : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_LAT_DIST : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ 2_REL_SPEED : 216|14@1- (0.01,0) [0|65535] "" XXX
|
||||
SG_ 2_NEW_SIGNAL_1 : 230|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ 2_LAT_ACCEL : 232|13@1- (1,0) [0|8191] "" XXX
|
||||
SG_ 2_REL_ACCEL : 246|10@1- (1,0) [0|1023] "" XXX
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,9 @@
|
||||
#define HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(e_can, longitudinal) \
|
||||
{0x1A0, e_can, 32, .check_relay = (longitudinal)}, /* SCC_CONTROL */ \
|
||||
|
||||
#define HYUNDAI_CANFD_MRR35_RADAR_TRACK_START 0x3A5
|
||||
#define HYUNDAI_CANFD_MRR35_RADAR_TRACK_END 0x3C4
|
||||
|
||||
#define HYUNDAI_CANFD_BLINDSPOT_DASH_TX_MSGS(e_can) \
|
||||
{0x1BA, e_can, 24, .check_relay = false}, /* BLINDSPOTS_REAR_CORNERS */ \
|
||||
{0x1E5, e_can, 16, .check_relay = false}, /* BLINDSPOTS_FRONT_CORNER_1 */ \
|
||||
@@ -56,6 +59,7 @@
|
||||
static bool hyundai_canfd_alt_buttons = false;
|
||||
static bool hyundai_canfd_lka_steering_alt = false;
|
||||
static bool hyundai_canfd_angle_steering = false;
|
||||
static bool hyundai_ccnc = false;
|
||||
|
||||
static unsigned int hyundai_canfd_get_lka_addr(void) {
|
||||
return hyundai_canfd_lka_steering_alt ? 0x110U : 0x50U;
|
||||
@@ -80,6 +84,15 @@ static void hyundai_canfd_rx_all_hook(const CANPacket_t *msg) {
|
||||
SAFETY_UNUSED(msg);
|
||||
}
|
||||
|
||||
static bool hyundai_canfd_fwd_hook(int bus_num, int addr) {
|
||||
const bool mrr35_radar_track = (addr >= HYUNDAI_CANFD_MRR35_RADAR_TRACK_START) && (addr <= HYUNDAI_CANFD_MRR35_RADAR_TRACK_END);
|
||||
|
||||
// On LKA-steering long-control cars using live MRR35 radar tracks, openpilot parses
|
||||
// the tracks directly from bus 0. Forwarding them to bus 2 creates a returned TX copy
|
||||
// of every object frame on the logged CAN stream without adding planner data.
|
||||
return hyundai_longitudinal && hyundai_canfd_lka_steering && (bus_num == 0) && mrr35_radar_track;
|
||||
}
|
||||
|
||||
static void hyundai_canfd_rx_hook(const CANPacket_t *msg) {
|
||||
|
||||
const unsigned pt_bus = hyundai_canfd_lka_steering ? 1U : 0U;
|
||||
@@ -289,6 +302,7 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT = 128;
|
||||
const uint16_t HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32;
|
||||
const uint16_t HYUNDAI_PARAM_CANFD_ANGLE_STEERING = 1024;
|
||||
const uint16_t HYUNDAI_PARAM_CCNC = 32768U;
|
||||
|
||||
static const CanMsg HYUNDAI_CANFD_LKA_STEERING_TX_MSGS[] = {
|
||||
HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1)
|
||||
@@ -304,6 +318,7 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(1, true)
|
||||
HYUNDAI_CANFD_BLINDSPOT_DASH_TX_MSGS(1)
|
||||
{0x51, 0, 32, .check_relay = false}, // ADRV_0x51
|
||||
{0x100, 0, 24, .check_relay = false}, // Ioniq 5/6: ACCELERATOR_BRAKE_ALT radar heartbeat spoof
|
||||
{0x730, 1, 8, .check_relay = false}, // tester present for ADAS ECU disable
|
||||
{0x160, 1, 16, .check_relay = false}, // ADRV_0x160
|
||||
{0x1EA, 1, 32, .check_relay = false}, // ADRV_0x1ea
|
||||
@@ -335,12 +350,22 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \
|
||||
{0x160, 0, 16, .check_relay = (longitudinal)}, /* ADRV_0x160 */ \
|
||||
|
||||
#define HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(longitudinal) \
|
||||
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) \
|
||||
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) \
|
||||
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \
|
||||
{0x161, 0, 32, .check_relay = true}, /* CCNC_0x161 */ \
|
||||
{0x162, 0, 32, .check_relay = true}, /* CCNC_0x162 */ \
|
||||
{0x7C4, 2, 8, .check_relay = true}, /* camera support frame */ \
|
||||
{0xEA, 2, 24, .check_relay = true}, /* MDPS support frame */ \
|
||||
|
||||
hyundai_common_init(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_lka_steering_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT);
|
||||
hyundai_canfd_angle_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ANGLE_STEERING);
|
||||
hyundai_ccnc = GET_FLAG(param, HYUNDAI_PARAM_CCNC);
|
||||
|
||||
safety_config ret;
|
||||
if (hyundai_longitudinal) {
|
||||
@@ -367,6 +392,10 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
HYUNDAI_CANFD_BLINDSPOT_DASH_TX_MSGS(0)
|
||||
};
|
||||
|
||||
static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = {
|
||||
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(true)
|
||||
};
|
||||
|
||||
if (hyundai_canfd_alt_buttons) {
|
||||
SET_RX_CHECKS(hyundai_canfd_alt_buttons_long_rx_checks, ret);
|
||||
} else {
|
||||
@@ -374,7 +403,11 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
}
|
||||
|
||||
if (hyundai_camera_scc) {
|
||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
||||
if (hyundai_ccnc) {
|
||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret);
|
||||
} else {
|
||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
||||
}
|
||||
} else {
|
||||
SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret);
|
||||
}
|
||||
@@ -435,7 +468,15 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(false)
|
||||
};
|
||||
|
||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
||||
static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = {
|
||||
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(false)
|
||||
};
|
||||
|
||||
if (hyundai_ccnc) {
|
||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret);
|
||||
} else {
|
||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
||||
}
|
||||
|
||||
if (hyundai_canfd_alt_buttons) {
|
||||
SET_RX_CHECKS(hyundai_canfd_alt_buttons_rx_checks, ret);
|
||||
@@ -456,4 +497,5 @@ const safety_hooks hyundai_canfd_hooks = {
|
||||
.get_counter = hyundai_canfd_get_counter,
|
||||
.get_checksum = hyundai_canfd_get_checksum,
|
||||
.compute_checksum = hyundai_common_canfd_compute_checksum,
|
||||
.fwd = hyundai_canfd_fwd_hook,
|
||||
};
|
||||
|
||||
@@ -26,6 +26,8 @@ ALL_GAS_EV_HYBRID_COMBOS = [
|
||||
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
|
||||
]
|
||||
|
||||
MRR35_RADAR_TRACK_ADDRS = list(range(0x3A5, 0x3C5))
|
||||
|
||||
|
||||
def _set_value(msg: bytearray, sig, ival: int) -> None:
|
||||
i = sig.lsb // 8
|
||||
@@ -422,6 +424,37 @@ class TestHyundaiCanfdLFASteeringAltButtons(TestHyundaiCanfdLFASteeringAltButton
|
||||
pass
|
||||
|
||||
|
||||
class TestHyundaiCanfdCCNCSupportFrames(common.SafetyTestBase):
|
||||
TX_MSGS = [[0x161, 0], [0x162, 0], [0x7C4, 2], [0xEA, 2]]
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
|
||||
def _set_hooks(self, param):
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, param)
|
||||
self.safety.init_tests()
|
||||
|
||||
def test_ccnc_support_frames_require_ccnc_flag(self):
|
||||
support_msgs = (
|
||||
self.packer.make_can_msg_safety("CCNC_0x161", 0, {}),
|
||||
self.packer.make_can_msg_safety("CCNC_0x162", 0, {}),
|
||||
common.make_msg(2, 0x7C4, 8),
|
||||
common.make_msg(2, 0xEA, 24),
|
||||
)
|
||||
|
||||
for longitudinal in (False, True):
|
||||
base_param = HyundaiSafetyFlags.CAMERA_SCC | (HyundaiSafetyFlags.LONG if longitudinal else 0)
|
||||
|
||||
self._set_hooks(base_param)
|
||||
for msg in support_msgs:
|
||||
self.assertFalse(self._tx(msg))
|
||||
|
||||
self._set_hooks(base_param | HyundaiSafetyFlags.CCNC)
|
||||
for msg in support_msgs:
|
||||
self.assertTrue(self._tx(msg))
|
||||
|
||||
|
||||
class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase):
|
||||
|
||||
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
|
||||
@@ -485,6 +518,7 @@ class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanf
|
||||
[0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]]
|
||||
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4), 1: (0x1a0,)} # LKAS, CAM_0x2A4, SCC_CONTROL
|
||||
FWD_BLACKLISTED_ADDRS = {0: MRR35_RADAR_TRACK_ADDRS, 2: [0x50, 0x2a4]}
|
||||
|
||||
DISABLED_ECU_UDS_MSG = (0x730, 1)
|
||||
DISABLED_ECU_ACTUATION_MSG = (0x1a0, 1)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
extern const uint8_t gitversion[19];
|
||||
const uint8_t gitversion[19] = "DEV-da88d20b-DEBUG";
|
||||
const uint8_t gitversion[19] = "DEV-b12fdf18-DEBUG";
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
DEV-da88d20b-DEBUG
|
||||
DEV-b12fdf18-DEBUG
|
||||
@@ -27,18 +27,20 @@ env_var_truthy() {
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./onroad [jobs] (--c3 | --c4 | --raybig | --all | --replay-only) [--prefix name] <route-or-replay-args...>
|
||||
./onroad [jobs] (--c3 | --c4 | --raybig | --all | --replay-only) [-nav] [--prefix name] <route-or-replay-args...>
|
||||
|
||||
Examples:
|
||||
./onroad --c3 f08912a233c1584f/2022-08-11--18-02-41/1
|
||||
./onroad --c4 f08912a233c1584f/2022-08-11--18-02-41/1 --start 30
|
||||
./onroad --all f08912a233c1584f/2022-08-11--18-02-41/1
|
||||
./onroad --c3 <route>
|
||||
./onroad --c4 <route> --start 30
|
||||
./onroad --c4 -nav <route>
|
||||
./onroad --all <route>
|
||||
./onroad --replay-only --demo --no-vipc --no-loop
|
||||
|
||||
Notes:
|
||||
- This is host/dev only. It uses the isolated host worktree and does not touch the device path.
|
||||
- A private comma connect route still requires tools/lib/auth.py before replay can download it.
|
||||
- Use multiple UI flags together if you want more than one desktop UI at once.
|
||||
- -nav injects a fake navigation demo stream and blocks replay from publishing navInstruction/navRoute.
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -53,7 +55,9 @@ REPLAY_ARGS=()
|
||||
UI_TARGETS=()
|
||||
LEGACY_UI_SELECTION=""
|
||||
REPLAY_ONLY=0
|
||||
NAV_DEMO=0
|
||||
REPLAY_PID=""
|
||||
NAV_PID=""
|
||||
UI_PIDS=()
|
||||
|
||||
parse_args() {
|
||||
@@ -83,6 +87,10 @@ parse_args() {
|
||||
REPLAY_ONLY=1
|
||||
shift
|
||||
;;
|
||||
-nav|--nav)
|
||||
NAV_DEMO=1
|
||||
shift
|
||||
;;
|
||||
--ui)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Missing value for --ui" >&2
|
||||
@@ -194,6 +202,9 @@ cleanup() {
|
||||
if [[ -n "${REPLAY_PID}" ]]; then
|
||||
kill "${REPLAY_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [[ -n "${NAV_PID}" ]]; then
|
||||
kill "${NAV_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
for pid in "${UI_PIDS[@]-}"; do
|
||||
if [[ -n "${pid}" ]]; then
|
||||
@@ -203,6 +214,9 @@ cleanup() {
|
||||
if [[ -n "${REPLAY_PID}" ]]; then
|
||||
wait "${REPLAY_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [[ -n "${NAV_PID}" ]]; then
|
||||
wait "${NAV_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
if [[ -n "${OPENPILOT_PREFIX:-}" && "${OPENPILOT_PREFIX}" == desktop-onroad-* ]]; then
|
||||
echo "Cleaning up temporary prefix environment (${OPENPILOT_PREFIX})..."
|
||||
@@ -214,6 +228,68 @@ cleanup() {
|
||||
exit "${exit_code}"
|
||||
}
|
||||
|
||||
append_blocked_service_names() {
|
||||
local existing="$1"
|
||||
local required="$2"
|
||||
local combined="${existing}"
|
||||
|
||||
if [[ -n "${combined}" ]]; then
|
||||
combined+=",${required}"
|
||||
else
|
||||
combined="${required}"
|
||||
fi
|
||||
|
||||
local deduped=()
|
||||
local seen=","
|
||||
local part=""
|
||||
local parts=()
|
||||
IFS=',' read -r -a parts <<< "${combined}"
|
||||
for part in "${parts[@]-}"; do
|
||||
part="${part// /}"
|
||||
if [[ -z "${part}" ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ "${seen}" != *",${part},"* ]]; then
|
||||
deduped+=("${part}")
|
||||
seen+="${part},"
|
||||
fi
|
||||
done
|
||||
|
||||
local joined=""
|
||||
for part in "${deduped[@]-}"; do
|
||||
if [[ -n "${joined}" ]]; then
|
||||
joined+=","
|
||||
fi
|
||||
joined+="${part}"
|
||||
done
|
||||
|
||||
printf '%s' "${joined}"
|
||||
}
|
||||
|
||||
ensure_nav_demo_replay_blocklist() {
|
||||
local nav_services="navInstruction,navRoute"
|
||||
local idx=0
|
||||
|
||||
for ((idx=0; idx<${#REPLAY_ARGS[@]}; idx++)); do
|
||||
case "${REPLAY_ARGS[$idx]}" in
|
||||
-b|--block)
|
||||
if (( idx + 1 >= ${#REPLAY_ARGS[@]} )); then
|
||||
echo "Missing value for ${REPLAY_ARGS[$idx]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
REPLAY_ARGS[$((idx + 1))]="$(append_blocked_service_names "${REPLAY_ARGS[$((idx + 1))]}" "${nav_services}")"
|
||||
return
|
||||
;;
|
||||
--block=*)
|
||||
REPLAY_ARGS[$idx]="--block=$(append_blocked_service_names "${REPLAY_ARGS[$idx]#*=}" "${nav_services}")"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
REPLAY_ARGS=(-b "${nav_services}" "${REPLAY_ARGS[@]}")
|
||||
}
|
||||
|
||||
prepare_env() {
|
||||
source .venv/bin/activate
|
||||
|
||||
@@ -238,6 +314,7 @@ prepare_env() {
|
||||
export SP_C4_FAKE_WIFI=0
|
||||
export SP_RAYBIG_FAKE_WIFI=0
|
||||
export SP_ALLOW_DESKTOP_FAKE_WIFI=0
|
||||
export SP_ONROAD_NAV_DEMO="${NAV_DEMO}"
|
||||
|
||||
if [[ "$(uname -s)" == "Darwin" ]] || env_var_truthy "${ZMQ:-0}"; then
|
||||
export OPENPILOT_ZMQ_NAMESPACE="${PREFIX_ARG:-${OPENPILOT_ZMQ_NAMESPACE:-desktop-onroad-$$}}"
|
||||
@@ -250,6 +327,8 @@ prepare_env() {
|
||||
|
||||
seed_params() {
|
||||
"${ROOT_DIR}/.venv/bin/python3" - <<'PY'
|
||||
import os
|
||||
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.system.version import terms_version, training_version
|
||||
|
||||
@@ -260,6 +339,8 @@ params.put_bool("OpenpilotEnabledToggle", True)
|
||||
params.put_bool("IsDriverViewEnabled", False)
|
||||
params.put_bool("ForceOnroad", False)
|
||||
params.put_bool("ForceOffroad", False)
|
||||
if os.getenv("SP_ONROAD_NAV_DEMO", "").lower() in {"1", "true", "yes", "on"}:
|
||||
params.put_bool("NavigationUI", True)
|
||||
PY
|
||||
}
|
||||
|
||||
@@ -302,6 +383,18 @@ launch_replay() {
|
||||
fi
|
||||
}
|
||||
|
||||
launch_nav_demo() {
|
||||
echo "Starting fake nav demo publisher..."
|
||||
"${ROOT_DIR}/.venv/bin/python3" "${ROOT_DIR}/tools/replay/fake_nav_demo.py" &
|
||||
NAV_PID=$!
|
||||
|
||||
sleep 0.5
|
||||
if ! kill -0 "${NAV_PID}" >/dev/null 2>&1; then
|
||||
wait "${NAV_PID}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
launch_c3_ui() {
|
||||
local os_ext="linux"
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
@@ -339,6 +432,10 @@ else
|
||||
dedupe_ui_targets
|
||||
fi
|
||||
|
||||
if [[ "${NAV_DEMO}" == "1" ]]; then
|
||||
ensure_nav_demo_replay_blocklist
|
||||
fi
|
||||
|
||||
if [[ ${#REPLAY_ARGS[@]} -eq 0 ]]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
@@ -378,6 +475,10 @@ seed_starpilot_theme
|
||||
echo "Starting replay: ${REPLAY_ARGS[*]}"
|
||||
launch_replay
|
||||
|
||||
if [[ "${NAV_DEMO}" == "1" ]]; then
|
||||
launch_nav_demo
|
||||
fi
|
||||
|
||||
if [[ ${#UI_TARGETS[@]} -eq 0 ]]; then
|
||||
echo "Replay is running without UI windows. Press Ctrl-C to stop."
|
||||
wait "${REPLAY_PID}"
|
||||
|
||||
+145
-22
@@ -3,6 +3,7 @@ import argparse
|
||||
import codecs
|
||||
import os
|
||||
import pickle
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -10,11 +11,18 @@ import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
if str(REPO_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(REPO_ROOT))
|
||||
|
||||
from openpilot.selfdrive.modeld.constants import ModelConstants
|
||||
from openpilot.starpilot.common.model_versions import uses_combined_driving_artifacts
|
||||
|
||||
DEFAULT_INPUT_ROOT = Path("/data/openpilot/uncompiledmodels")
|
||||
DEFAULT_OUTPUT_ROOT = Path("/data/openpilot/compiledmodels")
|
||||
COMPILE_SCRIPT = REPO_ROOT / "tinygrad_repo/examples/openpilot/compile3.py"
|
||||
COMBINED_COMPILE_SCRIPT = REPO_ROOT / "selfdrive/modeld/compile_modeld.py"
|
||||
MODEL_VERSIONS_CACHE = Path("/data/models/.model_versions.json")
|
||||
DM_MODEL_KEY = "dm"
|
||||
DM_MODEL_NAME = "dmonitoring_model"
|
||||
DM_TARGET_ALIASES = {DM_MODEL_KEY, "dmonitoring", DM_MODEL_NAME}
|
||||
@@ -26,7 +34,33 @@ COMPONENT_ALIASES = {
|
||||
"driving_policy": ("driving_policy", "policy"),
|
||||
"driving_vision": ("driving_vision", "vision"),
|
||||
}
|
||||
REQUIRED_COMPONENTS = {"driving_policy", "driving_vision"}
|
||||
MEDMODEL_INPUT_SIZE = (512, 256)
|
||||
DEFAULT_CAMERA_RESOLUTIONS = (
|
||||
(1928, 1208),
|
||||
(1344, 760),
|
||||
)
|
||||
|
||||
|
||||
def build_compile_env(*, combined: bool = False) -> dict[str, str]:
|
||||
env = os.environ.copy()
|
||||
existing_pythonpath = env.get("PYTHONPATH", "")
|
||||
env["PYTHONPATH"] = f"{REPO_ROOT}:{existing_pythonpath}" if existing_pythonpath else str(REPO_ROOT)
|
||||
|
||||
numeric_defaults = {
|
||||
"DEBUG": "0",
|
||||
"FLOAT16": "1",
|
||||
"IMAGE": "2",
|
||||
"JIT_BATCH_SIZE": "0",
|
||||
"NOLOCALS": "1",
|
||||
}
|
||||
for key, default in numeric_defaults.items():
|
||||
value = env.get(key)
|
||||
try:
|
||||
int(str(value), 0)
|
||||
except (TypeError, ValueError):
|
||||
env[key] = default
|
||||
|
||||
return env
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
@@ -37,6 +71,7 @@ def parse_args() -> argparse.Namespace:
|
||||
parser.add_argument("--dm", action="store_true", help="Compile the driver monitoring model into dmonitoring_model_tinygrad.pkl.")
|
||||
parser.add_argument("--input-dir", type=Path, default=DEFAULT_INPUT_ROOT, help="Directory containing staged ONNX files. Flat root files like driving_policy.onnx are preferred.")
|
||||
parser.add_argument("--output-dir", type=Path, default=DEFAULT_OUTPUT_ROOT, help="Directory for compiled tinygrad pkls and metadata.")
|
||||
parser.add_argument("--version", help="Model version. v16+ uses the combined driving_tinygrad artifact path. If omitted, split-policy staged models default to the combined build.")
|
||||
parser.add_argument("--list", action="store_true", help="List detected staged models and exit.")
|
||||
parser.add_argument("--force", action="store_true", help="Legacy no-op. Compiled outputs are always cleared before a build.")
|
||||
|
||||
@@ -66,14 +101,6 @@ def detect_component(path: Path) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def normalize_model_files(model_files: dict[str, Path]) -> dict[str, Path]:
|
||||
normalized = dict(model_files)
|
||||
on_policy_path = normalized.pop("driving_on_policy", None)
|
||||
if on_policy_path is not None and "driving_policy" not in normalized and "driving_off_policy" in normalized:
|
||||
normalized["driving_policy"] = on_policy_path
|
||||
return normalized
|
||||
|
||||
|
||||
def find_staged_dm(input_root: Path) -> Path | None:
|
||||
if not input_root.is_dir():
|
||||
return None
|
||||
@@ -107,7 +134,6 @@ def find_staged_models(input_root: Path) -> dict[str, dict[str, Path]]:
|
||||
component = detect_component(onnx_file)
|
||||
if component:
|
||||
model_files[component] = onnx_file
|
||||
model_files = normalize_model_files(model_files)
|
||||
if model_files:
|
||||
found[child.name] = model_files
|
||||
|
||||
@@ -137,7 +163,7 @@ def find_staged_models(input_root: Path) -> dict[str, dict[str, Path]]:
|
||||
flat_root_files[component] = onnx_file
|
||||
|
||||
if flat_root_files:
|
||||
found["_root"] = normalize_model_files(flat_root_files)
|
||||
found["_root"] = flat_root_files
|
||||
|
||||
return found
|
||||
|
||||
@@ -156,7 +182,7 @@ def resolve_model_files(input_root: Path, model_key: str) -> dict[str, Path]:
|
||||
component = detect_component(onnx_file)
|
||||
if component:
|
||||
prefixed_files[component] = onnx_file
|
||||
return normalize_model_files(prefixed_files)
|
||||
return prefixed_files
|
||||
|
||||
|
||||
def get_metadata_value_by_name(model, name: str):
|
||||
@@ -190,17 +216,94 @@ def write_metadata(onnx_path: Path, output_path: Path) -> None:
|
||||
|
||||
|
||||
def compile_component(onnx_path: Path, output_path: Path) -> None:
|
||||
env = os.environ.copy()
|
||||
existing_pythonpath = env.get("PYTHONPATH", "")
|
||||
env["PYTHONPATH"] = f"{REPO_ROOT}:{existing_pythonpath}" if existing_pythonpath else str(REPO_ROOT)
|
||||
subprocess.run(
|
||||
[sys.executable, str(COMPILE_SCRIPT), str(onnx_path), str(output_path)],
|
||||
cwd=REPO_ROOT,
|
||||
env=env,
|
||||
env=build_compile_env(combined=False),
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
def compile_combined_model(component_paths: dict[str, Path], output_path: Path) -> None:
|
||||
vision_path = component_paths["driving_vision"]
|
||||
off_policy_path = component_paths["driving_off_policy"]
|
||||
on_policy_path = component_paths.get("driving_on_policy") or component_paths.get("driving_policy")
|
||||
if on_policy_path is None:
|
||||
raise ValueError("Combined compile requires driving_on_policy.onnx (or driving_policy.onnx) alongside driving_off_policy.onnx")
|
||||
|
||||
frame_skip = ModelConstants.MODEL_RUN_FREQ // ModelConstants.MODEL_CONTEXT_FREQ
|
||||
camera_resolutions = [f"{width}x{height}" for width, height in DEFAULT_CAMERA_RESOLUTIONS]
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(COMBINED_COMPILE_SCRIPT),
|
||||
"--model-size",
|
||||
f"{MEDMODEL_INPUT_SIZE[0]}x{MEDMODEL_INPUT_SIZE[1]}",
|
||||
"--camera-resolutions",
|
||||
*camera_resolutions,
|
||||
"--vision-onnx",
|
||||
str(vision_path),
|
||||
"--off-policy-onnx",
|
||||
str(off_policy_path),
|
||||
"--on-policy-onnx",
|
||||
str(on_policy_path),
|
||||
"--output",
|
||||
str(output_path),
|
||||
"--frame-skip",
|
||||
str(frame_skip),
|
||||
],
|
||||
cwd=REPO_ROOT,
|
||||
env=build_compile_env(combined=True),
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
def infer_model_version(model_key: str, explicit_version: str | None) -> str:
|
||||
if explicit_version:
|
||||
return explicit_version.strip()
|
||||
|
||||
if MODEL_VERSIONS_CACHE.is_file():
|
||||
try:
|
||||
version_map = json.loads(MODEL_VERSIONS_CACHE.read_text())
|
||||
version = version_map.get(model_key)
|
||||
if isinstance(version, str) and version.strip():
|
||||
return version.strip()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
def should_use_combined_artifacts(model_version: str, model_files: dict[str, Path]) -> bool:
|
||||
if uses_combined_driving_artifacts(model_version):
|
||||
return True
|
||||
if model_version.strip():
|
||||
return False
|
||||
|
||||
has_vision = "driving_vision" in model_files
|
||||
has_off_policy = "driving_off_policy" in model_files
|
||||
has_on_policy = "driving_on_policy" in model_files or "driving_policy" in model_files
|
||||
return has_vision and has_off_policy and has_on_policy
|
||||
|
||||
|
||||
def resolve_split_component_inputs(model_files: dict[str, Path]) -> dict[str, Path]:
|
||||
resolved: dict[str, Path] = {}
|
||||
|
||||
vision_path = model_files.get("driving_vision")
|
||||
if vision_path is not None:
|
||||
resolved["driving_vision"] = vision_path
|
||||
|
||||
policy_path = model_files.get("driving_policy") or model_files.get("driving_on_policy")
|
||||
if policy_path is not None:
|
||||
resolved["driving_policy"] = policy_path
|
||||
|
||||
off_policy_path = model_files.get("driving_off_policy")
|
||||
if off_policy_path is not None:
|
||||
resolved["driving_off_policy"] = off_policy_path
|
||||
|
||||
return resolved
|
||||
|
||||
|
||||
def clear_existing_outputs(output_dir: Path) -> list[Path]:
|
||||
removed = []
|
||||
for existing in sorted(output_dir.iterdir()):
|
||||
@@ -277,18 +380,38 @@ def main() -> int:
|
||||
f"or optionally {args.input_dir / model_key}/*.onnx"
|
||||
)
|
||||
|
||||
missing = sorted(REQUIRED_COMPONENTS - set(files))
|
||||
if missing:
|
||||
raise SystemExit(f"Missing required ONNX files for {model_key}: {', '.join(missing)}")
|
||||
model_version = infer_model_version(model_key, args.version)
|
||||
use_combined_artifacts = should_use_combined_artifacts(model_version, files)
|
||||
|
||||
args.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
print(f"Compiling {model_key} from {args.input_dir} -> {args.output_dir}")
|
||||
mode_label = "combined" if use_combined_artifacts else "split"
|
||||
version_label = model_version or ("auto-combined" if use_combined_artifacts else "legacy-default")
|
||||
print(f"Compiling {model_key} ({version_label}, {mode_label}) from {args.input_dir} -> {args.output_dir}")
|
||||
|
||||
removed = clear_existing_outputs(args.output_dir)
|
||||
if removed:
|
||||
print(f" cleared {len(removed)} existing output entries")
|
||||
|
||||
for component, onnx_path in sorted(files.items()):
|
||||
if use_combined_artifacts:
|
||||
required_components = {"driving_vision", "driving_off_policy"}
|
||||
if not (files.get("driving_on_policy") or files.get("driving_policy")):
|
||||
required_components.add("driving_on_policy")
|
||||
missing = sorted(component for component in required_components if component not in files)
|
||||
if missing:
|
||||
raise SystemExit(f"Missing required ONNX files for combined compile of {model_key}: {', '.join(missing)}")
|
||||
|
||||
output_pkl = args.output_dir / f"{model_key}_driving_tinygrad.pkl"
|
||||
compile_combined_model(files, output_pkl)
|
||||
print(f" saved {output_pkl.name}")
|
||||
print("Done.")
|
||||
return 0
|
||||
|
||||
split_components = resolve_split_component_inputs(files)
|
||||
missing = sorted(component for component in ("driving_policy", "driving_vision") if component not in split_components)
|
||||
if missing:
|
||||
raise SystemExit(f"Missing required ONNX files for {model_key}: {', '.join(missing)}")
|
||||
|
||||
for component, onnx_path in sorted(split_components.items()):
|
||||
output_pkl = args.output_dir / f"{model_key}_{component}_tinygrad.pkl"
|
||||
output_metadata = args.output_dir / f"{model_key}_{component}_metadata.pkl"
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import json
|
||||
|
||||
import numpy as np
|
||||
|
||||
from cereal import log
|
||||
from openpilot.common.constants import CV
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import DT_MDL
|
||||
|
||||
LaneChangeState = log.LaneChangeState
|
||||
@@ -7,6 +12,8 @@ LaneChangeDirection = log.LaneChangeDirection
|
||||
|
||||
LANE_CHANGE_SPEED_MIN = 20 * CV.MPH_TO_MS
|
||||
LANE_CHANGE_TIME_MAX = 10.
|
||||
NAV_TURN_DISTANCE_SPEED_BREAKPOINTS = [0.0, 5.0, 10.0]
|
||||
NAV_TURN_DISTANCE_BREAKPOINTS = [20.0, 25.0, 30.0]
|
||||
|
||||
DESIRES = {
|
||||
LaneChangeDirection.none: {
|
||||
@@ -40,6 +47,8 @@ TURN_DESIRES = {
|
||||
|
||||
class DesireHelper:
|
||||
def __init__(self):
|
||||
self.params = Params()
|
||||
self.params_memory = Params(memory=True)
|
||||
self.lane_change_state = LaneChangeState.off
|
||||
self.lane_change_direction = LaneChangeDirection.none
|
||||
self.lane_change_timer = 0.0
|
||||
@@ -51,6 +60,95 @@ class DesireHelper:
|
||||
self.lane_change_completed = False
|
||||
|
||||
self.lane_change_wait_timer = 0.0
|
||||
self.nav_desires_allowed = False
|
||||
self._nav_param_counter = -1
|
||||
self._nav_instruction_state_raw: object = None
|
||||
self._nav_instruction_state: dict[str, object] = {}
|
||||
|
||||
def _update_nav_params(self):
|
||||
self._nav_param_counter += 1
|
||||
if self._nav_param_counter % 60 == 0:
|
||||
self.nav_desires_allowed = self.params.get_bool("NavDesiresAllowed")
|
||||
|
||||
raw = self.params_memory.get("NavInstructionState") or {}
|
||||
if raw == self._nav_instruction_state_raw:
|
||||
return
|
||||
|
||||
self._nav_instruction_state_raw = raw
|
||||
if not raw:
|
||||
self._nav_instruction_state = {}
|
||||
return
|
||||
|
||||
if isinstance(raw, dict):
|
||||
self._nav_instruction_state = raw
|
||||
return
|
||||
|
||||
if isinstance(raw, str):
|
||||
try:
|
||||
parsed = json.loads(raw)
|
||||
self._nav_instruction_state = parsed if isinstance(parsed, dict) else {}
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self._nav_instruction_state = {}
|
||||
|
||||
@staticmethod
|
||||
def _nav_keep_direction_is_clear(carstate, lane_change_direction):
|
||||
return not (
|
||||
(lane_change_direction == LaneChangeDirection.left and carstate.leftBlindspot) or
|
||||
(lane_change_direction == LaneChangeDirection.right and carstate.rightBlindspot)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _nav_torque_applied(carstate, lane_change_direction):
|
||||
return carstate.steeringPressed and (
|
||||
(lane_change_direction == LaneChangeDirection.left and carstate.steeringTorque > 0) or
|
||||
(lane_change_direction == LaneChangeDirection.right and carstate.steeringTorque < 0)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _nav_turn_is_imminent(carstate, maneuver_distance):
|
||||
try:
|
||||
distance = float(maneuver_distance)
|
||||
except (TypeError, ValueError):
|
||||
return False
|
||||
|
||||
return distance <= float(np.interp(carstate.vEgo, NAV_TURN_DISTANCE_SPEED_BREAKPOINTS, NAV_TURN_DISTANCE_BREAKPOINTS))
|
||||
|
||||
def _navigation_desire(self, carstate, lateral_active, starpilotPlan, starpilot_toggles):
|
||||
self._update_nav_params()
|
||||
if not self.nav_desires_allowed or not lateral_active or not bool(self._nav_instruction_state.get("valid", False)):
|
||||
return log.Desire.none
|
||||
|
||||
modifier = str(self._nav_instruction_state.get("maneuverModifier", ""))
|
||||
if modifier == "":
|
||||
return log.Desire.none
|
||||
|
||||
maneuver_distance = self._nav_instruction_state.get("maneuverDistance", 0.0)
|
||||
|
||||
if modifier == "slightLeft":
|
||||
lane_change_direction = LaneChangeDirection.left
|
||||
desired_lane_width = starpilotPlan.laneWidthLeft
|
||||
nudgeless_allowed = starpilot_toggles.nudgeless and desired_lane_width >= starpilot_toggles.lane_detection_width
|
||||
if not carstate.rightBlinker and self._nav_keep_direction_is_clear(carstate, lane_change_direction):
|
||||
if self._nav_torque_applied(carstate, lane_change_direction) or nudgeless_allowed:
|
||||
return log.Desire.keepLeft
|
||||
elif modifier == "slightRight":
|
||||
lane_change_direction = LaneChangeDirection.right
|
||||
desired_lane_width = starpilotPlan.laneWidthRight
|
||||
nudgeless_allowed = starpilot_toggles.nudgeless and desired_lane_width >= starpilot_toggles.lane_detection_width
|
||||
if not carstate.leftBlinker and self._nav_keep_direction_is_clear(carstate, lane_change_direction):
|
||||
if self._nav_torque_applied(carstate, lane_change_direction) or nudgeless_allowed:
|
||||
return log.Desire.keepRight
|
||||
elif modifier in ("left", "sharpLeft"):
|
||||
if not carstate.rightBlinker and not carstate.leftBlindspot and carstate.vEgo < starpilot_toggles.minimum_lane_change_speed and not carstate.standstill and self._nav_turn_is_imminent(carstate, maneuver_distance):
|
||||
return log.Desire.turnLeft
|
||||
elif modifier in ("right", "sharpRight"):
|
||||
if not carstate.leftBlinker and not carstate.rightBlindspot and carstate.vEgo < starpilot_toggles.minimum_lane_change_speed and not carstate.standstill and self._nav_turn_is_imminent(carstate, maneuver_distance):
|
||||
return log.Desire.turnRight
|
||||
|
||||
return log.Desire.none
|
||||
|
||||
@staticmethod
|
||||
def get_lane_change_direction(CS):
|
||||
@@ -155,3 +253,7 @@ class DesireHelper:
|
||||
self.lane_change_completed = False
|
||||
|
||||
self.lane_change_wait_timer = 0.0
|
||||
|
||||
nav_desire = self._navigation_desire(carstate, lateral_active, starpilotPlan, starpilot_toggles)
|
||||
if nav_desire != log.Desire.none and self.lane_change_state == LaneChangeState.off:
|
||||
self.desire = nav_desire
|
||||
|
||||
@@ -244,10 +244,10 @@ VOLT_STANDARD_CENTER_TAPER_LAT_WIDTH = 0.018
|
||||
VOLT_STANDARD_CENTER_TAPER_SPEED = 20.0
|
||||
VOLT_STANDARD_CENTER_TAPER_SPEED_WIDTH = 2.5
|
||||
|
||||
SONATA_HYBRID_BASE_LAT_ACCEL_FACTOR_MULT = 1.04
|
||||
SONATA_HYBRID_FF_REDUCTION_LEFT = 0.07
|
||||
SONATA_HYBRID_FF_REDUCTION_RIGHT = 0.22
|
||||
SONATA_HYBRID_FF_ONSET = 0.22
|
||||
SONATA_HYBRID_BASE_LAT_ACCEL_FACTOR_MULT = 1.05
|
||||
SONATA_HYBRID_FF_REDUCTION_LEFT = 0.09
|
||||
SONATA_HYBRID_FF_REDUCTION_RIGHT = 0.24
|
||||
SONATA_HYBRID_FF_ONSET = 0.18
|
||||
SONATA_HYBRID_FF_ONSET_WIDTH = 0.08
|
||||
SONATA_HYBRID_FF_CUTOFF = 1.35
|
||||
SONATA_HYBRID_FF_CUTOFF_WIDTH = 0.40
|
||||
@@ -257,15 +257,15 @@ SONATA_HYBRID_TURN_IN_BOOST_LEFT = 0.12
|
||||
SONATA_HYBRID_TURN_IN_BOOST_RIGHT = 0.00
|
||||
SONATA_HYBRID_UNWIND_TAPER_LEFT = 0.18
|
||||
SONATA_HYBRID_UNWIND_TAPER_RIGHT = 0.10
|
||||
SONATA_HYBRID_CENTER_TAPER_MAX = 0.05
|
||||
SONATA_HYBRID_CENTER_TAPER_LAT = 0.14
|
||||
SONATA_HYBRID_CENTER_TAPER_MAX = 0.07
|
||||
SONATA_HYBRID_CENTER_TAPER_LAT = 0.16
|
||||
SONATA_HYBRID_CENTER_TAPER_LAT_WIDTH = 0.025
|
||||
SONATA_HYBRID_CENTER_TAPER_SPEED = 22.0
|
||||
SONATA_HYBRID_CENTER_TAPER_SPEED_WIDTH = 2.5
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_MAX = 0.12
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_LAT = 0.09
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_MAX = 0.14
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_LAT = 0.10
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_LAT_WIDTH = 0.02
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_SPEED_MAX = 6.0
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_SPEED_MAX = 7.5
|
||||
SONATA_HYBRID_LOW_SPEED_CENTER_TAPER_SPEED_WIDTH = 1.0
|
||||
|
||||
ELANTRA_NON_SCC_FF_ADJUST_LEFT = 0.02
|
||||
@@ -281,21 +281,21 @@ ELANTRA_NON_SCC_TURN_IN_BOOST_RIGHT = 0.12
|
||||
ELANTRA_NON_SCC_UNWIND_TAPER_LEFT = 0.22
|
||||
ELANTRA_NON_SCC_UNWIND_TAPER_RIGHT = 0.12
|
||||
|
||||
KIA_FORTE_BASE_LAT_ACCEL_FACTOR_MULT = 1.08
|
||||
KIA_FORTE_FF_REDUCTION_LEFT = 0.08
|
||||
KIA_FORTE_FF_REDUCTION_RIGHT = 0.20
|
||||
KIA_FORTE_BASE_LAT_ACCEL_FACTOR_MULT = 1.10
|
||||
KIA_FORTE_FF_REDUCTION_LEFT = 0.10
|
||||
KIA_FORTE_FF_REDUCTION_RIGHT = 0.24
|
||||
KIA_FORTE_FF_ONSET = 0.16
|
||||
KIA_FORTE_FF_ONSET_WIDTH = 0.06
|
||||
KIA_FORTE_FF_CUTOFF = 1.20
|
||||
KIA_FORTE_FF_CUTOFF_WIDTH = 0.36
|
||||
KIA_FORTE_TRANSITION_SPEED = 9.0
|
||||
KIA_FORTE_PHASE_SCALE = 0.10
|
||||
KIA_FORTE_TURN_IN_BOOST_LEFT = 0.06
|
||||
KIA_FORTE_TURN_IN_BOOST_LEFT = 0.10
|
||||
KIA_FORTE_TURN_IN_BOOST_RIGHT = 0.00
|
||||
KIA_FORTE_UNWIND_TAPER_LEFT = 0.18
|
||||
KIA_FORTE_UNWIND_TAPER_RIGHT = 0.08
|
||||
KIA_FORTE_CENTER_TAPER_MAX = 0.11
|
||||
KIA_FORTE_CENTER_TAPER_LAT = 0.14
|
||||
KIA_FORTE_UNWIND_TAPER_LEFT = 0.26
|
||||
KIA_FORTE_UNWIND_TAPER_RIGHT = 0.04
|
||||
KIA_FORTE_CENTER_TAPER_MAX = 0.14
|
||||
KIA_FORTE_CENTER_TAPER_LAT = 0.16
|
||||
KIA_FORTE_CENTER_TAPER_LAT_WIDTH = 0.03
|
||||
KIA_FORTE_CENTER_TAPER_SPEED = 24.0
|
||||
KIA_FORTE_CENTER_TAPER_SPEED_WIDTH = 2.5
|
||||
@@ -325,27 +325,32 @@ GENESIS_G90_TURN_IN_FRICTION_BOOST_RIGHT = 0.14
|
||||
GENESIS_G90_UNWIND_FRICTION_REDUCTION_LEFT = 0.04
|
||||
GENESIS_G90_UNWIND_FRICTION_REDUCTION_RIGHT = 0.30
|
||||
|
||||
IONIQ_5_BASE_LAT_ACCEL_FACTOR_MULT = 1.18
|
||||
IONIQ_5_BASE_LAT_ACCEL_FACTOR_MULT = 1.22
|
||||
IONIQ_5_FF_ONSET = 0.10
|
||||
IONIQ_5_FF_ONSET_WIDTH = 0.05
|
||||
IONIQ_5_FF_CUTOFF = 1.20
|
||||
IONIQ_5_FF_CUTOFF_WIDTH = 0.30
|
||||
IONIQ_5_TRANSITION_SPEED = 11.0
|
||||
IONIQ_5_PHASE_SCALE = 0.10
|
||||
IONIQ_5_FF_REDUCTION_LEFT = 0.10
|
||||
IONIQ_5_FF_REDUCTION_LEFT = 0.14
|
||||
IONIQ_5_FF_REDUCTION_RIGHT = 0.18
|
||||
IONIQ_5_TURN_IN_BOOST_LEFT = 0.04
|
||||
IONIQ_5_TURN_IN_BOOST_RIGHT = 0.00
|
||||
IONIQ_5_UNWIND_TAPER_LEFT = 0.40
|
||||
IONIQ_5_UNWIND_TAPER_RIGHT = 0.70
|
||||
IONIQ_5_UNWIND_TAPER_LEFT = 0.52
|
||||
IONIQ_5_UNWIND_TAPER_RIGHT = 0.82
|
||||
IONIQ_5_TURN_IN_THRESHOLD_REDUCTION_LEFT = 0.05
|
||||
IONIQ_5_TURN_IN_THRESHOLD_REDUCTION_RIGHT = 0.00
|
||||
IONIQ_5_UNWIND_THRESHOLD_INCREASE_LEFT = 0.18
|
||||
IONIQ_5_UNWIND_THRESHOLD_INCREASE_RIGHT = 0.32
|
||||
IONIQ_5_UNWIND_THRESHOLD_INCREASE_LEFT = 0.24
|
||||
IONIQ_5_UNWIND_THRESHOLD_INCREASE_RIGHT = 0.38
|
||||
IONIQ_5_TURN_IN_FRICTION_BOOST_LEFT = 0.02
|
||||
IONIQ_5_TURN_IN_FRICTION_BOOST_RIGHT = 0.00
|
||||
IONIQ_5_UNWIND_FRICTION_REDUCTION_LEFT = 0.15
|
||||
IONIQ_5_UNWIND_FRICTION_REDUCTION_RIGHT = 0.26
|
||||
IONIQ_5_UNWIND_FRICTION_REDUCTION_LEFT = 0.22
|
||||
IONIQ_5_UNWIND_FRICTION_REDUCTION_RIGHT = 0.32
|
||||
IONIQ_5_CENTER_TAPER_MAX = 0.08
|
||||
IONIQ_5_CENTER_TAPER_LAT = 0.16
|
||||
IONIQ_5_CENTER_TAPER_LAT_WIDTH = 0.03
|
||||
IONIQ_5_CENTER_TAPER_SPEED = 20.0
|
||||
IONIQ_5_CENTER_TAPER_SPEED_WIDTH = 2.5
|
||||
|
||||
IONIQ_EV_OLD_BASE_LAT_ACCEL_FACTOR_MULT = 1.16
|
||||
IONIQ_EV_OLD_FF_REDUCTION_LEFT = 0.16
|
||||
@@ -439,7 +444,7 @@ IONIQ_6_OUTPUT_DIRECTIONAL_TAPER_BLEND = 0.97
|
||||
KIA_EV6_LATERAL_TESTING_GROUND_ID = testing_ground.id_6
|
||||
KIA_EV6_LATERAL_TESTING_GROUND_VARIANT = "C"
|
||||
KIA_EV6_FF_GAIN_LEFT = 0.07
|
||||
KIA_EV6_FF_GAIN_RIGHT = 0.10
|
||||
KIA_EV6_FF_GAIN_RIGHT = 0.075
|
||||
KIA_EV6_FF_ONSET = 0.08
|
||||
KIA_EV6_FF_ONSET_WIDTH = 0.04
|
||||
KIA_EV6_FF_CUTOFF = 0.60
|
||||
@@ -447,20 +452,25 @@ KIA_EV6_FF_CUTOFF_WIDTH = 0.14
|
||||
KIA_EV6_TRANSITION_SPEED = 11.0
|
||||
KIA_EV6_PHASE_SCALE = 0.09
|
||||
KIA_EV6_TURN_IN_BOOST_LEFT = 0.14
|
||||
KIA_EV6_TURN_IN_BOOST_RIGHT = 0.22
|
||||
KIA_EV6_UNWIND_TAPER_LEFT = 0.26
|
||||
KIA_EV6_UNWIND_TAPER_RIGHT = 0.34
|
||||
KIA_EV6_TURN_IN_BOOST_RIGHT = 0.16
|
||||
KIA_EV6_UNWIND_TAPER_LEFT = 0.40
|
||||
KIA_EV6_UNWIND_TAPER_RIGHT = 0.36
|
||||
KIA_EV6_FRICTION_MULT = 1.01
|
||||
KIA_EV6_FRICTION_LAT_RISE = 0.18
|
||||
KIA_EV6_FRICTION_JERK_RISE = 0.22
|
||||
KIA_EV6_TURN_IN_THRESHOLD_REDUCTION_LEFT = 0.10
|
||||
KIA_EV6_TURN_IN_THRESHOLD_REDUCTION_RIGHT = 0.14
|
||||
KIA_EV6_UNWIND_THRESHOLD_INCREASE_LEFT = 0.14
|
||||
KIA_EV6_UNWIND_THRESHOLD_INCREASE_LEFT = 0.22
|
||||
KIA_EV6_UNWIND_THRESHOLD_INCREASE_RIGHT = 0.18
|
||||
KIA_EV6_TURN_IN_FRICTION_BOOST_LEFT = 0.03
|
||||
KIA_EV6_TURN_IN_FRICTION_BOOST_RIGHT = 0.05
|
||||
KIA_EV6_UNWIND_FRICTION_REDUCTION_LEFT = 0.12
|
||||
KIA_EV6_UNWIND_FRICTION_REDUCTION_RIGHT = 0.15
|
||||
KIA_EV6_UNWIND_FRICTION_REDUCTION_LEFT = 0.22
|
||||
KIA_EV6_UNWIND_FRICTION_REDUCTION_RIGHT = 0.16
|
||||
KIA_EV6_CENTER_TAPER_MAX = 0.08
|
||||
KIA_EV6_CENTER_TAPER_LAT = 0.16
|
||||
KIA_EV6_CENTER_TAPER_LAT_WIDTH = 0.035
|
||||
KIA_EV6_CENTER_TAPER_SPEED = 18.0
|
||||
KIA_EV6_CENTER_TAPER_SPEED_WIDTH = 3.0
|
||||
|
||||
VOLT_PLEXY_LATERAL_TESTING_GROUND_ID = testing_ground.id_7
|
||||
VOLT_PLEXY_FF_GAIN_LEFT = 0.12
|
||||
@@ -1211,6 +1221,13 @@ def get_ioniq_5_friction_scale(v_ego: float, desired_lateral_accel: float, desir
|
||||
return min(max(friction_scale, 0.86), 1.04)
|
||||
|
||||
|
||||
def get_ioniq_5_center_taper_scale(desired_lateral_accel: float, v_ego: float) -> float:
|
||||
speed_weight = _ioniq_5_sigmoid((v_ego - IONIQ_5_CENTER_TAPER_SPEED) / IONIQ_5_CENTER_TAPER_SPEED_WIDTH)
|
||||
center_weight = _ioniq_5_sigmoid((IONIQ_5_CENTER_TAPER_LAT - abs(desired_lateral_accel)) / IONIQ_5_CENTER_TAPER_LAT_WIDTH)
|
||||
reduction = IONIQ_5_CENTER_TAPER_MAX * speed_weight * center_weight
|
||||
return 1.0 - reduction
|
||||
|
||||
|
||||
def _ioniq_ev_old_sigmoid(x: float) -> float:
|
||||
return _sigmoid(x)
|
||||
|
||||
@@ -1454,6 +1471,13 @@ def get_kia_ev6_friction_scale(v_ego: float, desired_lateral_accel: float, desir
|
||||
return min(max(friction_scale, 0.90), 1.10)
|
||||
|
||||
|
||||
def get_kia_ev6_center_taper_scale(desired_lateral_accel: float, v_ego: float) -> float:
|
||||
speed_weight = _kia_ev6_sigmoid((v_ego - KIA_EV6_CENTER_TAPER_SPEED) / KIA_EV6_CENTER_TAPER_SPEED_WIDTH)
|
||||
center_weight = _kia_ev6_sigmoid((KIA_EV6_CENTER_TAPER_LAT - abs(desired_lateral_accel)) / KIA_EV6_CENTER_TAPER_LAT_WIDTH)
|
||||
reduction = KIA_EV6_CENTER_TAPER_MAX * speed_weight * center_weight
|
||||
return 1.0 - reduction
|
||||
|
||||
|
||||
def volt_plexy_lateral_testing_ground_active() -> bool:
|
||||
return testing_ground.use(VOLT_PLEXY_LATERAL_TESTING_GROUND_ID)
|
||||
|
||||
@@ -1687,11 +1711,13 @@ class LatControlTorque(LatControl):
|
||||
kia_forte_active = self.is_kia_forte
|
||||
kia_ev6_test_active = self.is_kia_ev6 and kia_ev6_lateral_testing_ground_active()
|
||||
volt_plexy_test_active = self.is_volt_cc and volt_plexy_lateral_testing_ground_active()
|
||||
ioniq_5_center_taper = get_ioniq_5_center_taper_scale(setpoint, CS.vEgo) if ioniq_5_active else 1.0
|
||||
volt_standard_center_taper = get_volt_standard_center_taper_scale(setpoint, CS.vEgo) if volt_standard_test_active else 1.0
|
||||
ioniq_ev_old_center_taper = get_ioniq_ev_old_center_taper_scale(setpoint, CS.vEgo) if ioniq_ev_old_active else 1.0
|
||||
ioniq_6_center_taper = get_ioniq_6_center_taper_scale(setpoint, CS.vEgo) if ioniq_6_active else 1.0
|
||||
sonata_hybrid_center_taper = get_sonata_hybrid_center_taper_scale(setpoint, CS.vEgo) if sonata_hybrid_active else 1.0
|
||||
kia_forte_center_taper = get_kia_forte_center_taper_scale(setpoint, CS.vEgo) if kia_forte_active else 1.0
|
||||
kia_ev6_center_taper = get_kia_ev6_center_taper_scale(setpoint, CS.vEgo) if kia_ev6_test_active else 1.0
|
||||
civic_bosch_modified_a_center_taper = get_civic_bosch_modified_a_center_taper_scale(setpoint, CS.vEgo) if (
|
||||
self.is_civic_bosch_modified and civic_bosch_modified_a_lateral_testing_ground_active()
|
||||
) else 1.0
|
||||
@@ -1714,9 +1740,10 @@ class LatControlTorque(LatControl):
|
||||
friction_threshold = get_genesis_g90_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk)
|
||||
friction_scale = get_genesis_g90_friction_scale(CS.vEgo, setpoint, desired_lateral_jerk)
|
||||
elif ioniq_5_active:
|
||||
ff *= get_ioniq_5_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo)
|
||||
ff *= get_ioniq_5_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo) * ioniq_5_center_taper
|
||||
friction_threshold = get_ioniq_5_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk)
|
||||
friction_scale = get_ioniq_5_friction_scale(CS.vEgo, setpoint, desired_lateral_jerk)
|
||||
friction_scale = 1.0 + ((friction_scale - 1.0) * ioniq_5_center_taper)
|
||||
elif ioniq_ev_old_active:
|
||||
ff *= get_ioniq_ev_old_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo) * ioniq_ev_old_center_taper
|
||||
friction_scale = 1.0 + ((friction_scale - 1.0) * ioniq_ev_old_center_taper)
|
||||
@@ -1732,9 +1759,10 @@ class LatControlTorque(LatControl):
|
||||
elif kia_forte_active:
|
||||
ff *= get_kia_forte_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo) * kia_forte_center_taper
|
||||
elif kia_ev6_test_active:
|
||||
ff *= get_kia_ev6_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo)
|
||||
ff *= get_kia_ev6_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo) * kia_ev6_center_taper
|
||||
friction_threshold = get_kia_ev6_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk)
|
||||
friction_scale = get_kia_ev6_friction_scale(CS.vEgo, setpoint, desired_lateral_jerk)
|
||||
friction_scale = 1.0 + ((friction_scale - 1.0) * kia_ev6_center_taper)
|
||||
elif volt_plexy_test_active:
|
||||
ff *= get_volt_plexy_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo)
|
||||
friction_threshold = get_volt_plexy_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk)
|
||||
|
||||
@@ -8,6 +8,7 @@ from openpilot.common.constants import CV
|
||||
from openpilot.common.filter_simple import FirstOrderFilter
|
||||
from openpilot.common.realtime import DT_MDL
|
||||
from openpilot.selfdrive.modeld.constants import ModelConstants
|
||||
from openpilot.starpilot.common.model_versions import is_tinygrad_model_version
|
||||
from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState
|
||||
from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import LongitudinalMpc
|
||||
from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import desired_follow_distance
|
||||
@@ -434,7 +435,7 @@ class LongitudinalPlanner:
|
||||
|
||||
@property
|
||||
def mlsim(self):
|
||||
return self.generation in ("v8", "v10", "v11", "v12", "v13", "v14", "v15")
|
||||
return is_tinygrad_model_version(self.generation)
|
||||
|
||||
def get_mpc_mode(self) -> str:
|
||||
if not self.mlsim:
|
||||
|
||||
@@ -43,6 +43,7 @@ from openpilot.selfdrive.controls.lib.latcontrol_torque import (
|
||||
get_ioniq_5_ff_scale,
|
||||
get_ioniq_5_friction_scale,
|
||||
get_ioniq_5_friction_threshold,
|
||||
get_ioniq_5_center_taper_scale,
|
||||
get_ioniq_ev_old_center_taper_scale,
|
||||
get_ioniq_ev_old_ff_scale,
|
||||
get_ioniq_6_center_taper_scale,
|
||||
@@ -53,6 +54,7 @@ from openpilot.selfdrive.controls.lib.latcontrol_torque import (
|
||||
get_ioniq_6_friction_threshold,
|
||||
get_kia_forte_center_taper_scale,
|
||||
get_kia_forte_ff_scale,
|
||||
get_kia_ev6_center_taper_scale,
|
||||
get_kia_ev6_ff_scale,
|
||||
get_kia_ev6_friction_scale,
|
||||
get_kia_ev6_friction_threshold,
|
||||
@@ -338,6 +340,10 @@ class TestLatControl:
|
||||
assert unwind_left_scale < 1.0
|
||||
assert unwind_right_scale < unwind_left_scale
|
||||
|
||||
def test_ioniq_5_center_taper_curve(self):
|
||||
assert get_ioniq_5_center_taper_scale(0.0, 25.0) < get_ioniq_5_center_taper_scale(0.0, 10.0)
|
||||
assert get_ioniq_5_center_taper_scale(0.0, 25.0) < get_ioniq_5_center_taper_scale(0.20, 25.0) <= 1.0
|
||||
|
||||
def test_ioniq_ev_old_ff_scale_curve(self):
|
||||
assert get_ioniq_ev_old_ff_scale(0.0, 0.0, 20.0) == 1.0
|
||||
assert get_ioniq_ev_old_ff_scale(0.35, 0.0, 20.0) > get_ioniq_ev_old_ff_scale(-0.35, 0.0, 20.0)
|
||||
@@ -420,7 +426,7 @@ class TestLatControl:
|
||||
right_turn_in = get_kia_ev6_friction_threshold(6.0, -0.5, -0.8)
|
||||
left_unwind = get_kia_ev6_friction_threshold(6.0, 0.5, -0.8)
|
||||
right_unwind = get_kia_ev6_friction_threshold(6.0, -0.5, 0.8)
|
||||
assert right_turn_in < left_turn_in < base < left_unwind < right_unwind
|
||||
assert right_turn_in < left_turn_in < base < right_unwind < left_unwind
|
||||
|
||||
def test_kia_ev6_friction_scale_curve(self):
|
||||
base = get_kia_ev6_friction_scale(25.0, 0.5, 0.8)
|
||||
@@ -493,7 +499,7 @@ class TestLatControl:
|
||||
_, _, lac_log = controller.update(True, CS, VM, params, False, 0.0025, False, 0.2, None, None, starpilot_toggles)
|
||||
|
||||
assert lac_log.active
|
||||
assert controller.torque_params.latAccelFactor == pytest.approx(CP.lateralTuning.torque.latAccelFactor * 1.18)
|
||||
assert controller.torque_params.latAccelFactor == pytest.approx(CP.lateralTuning.torque.latAccelFactor * 1.22)
|
||||
|
||||
def test_ioniq_6_default_update_path(self):
|
||||
controller, VM, CS, params, starpilot_toggles = self._build_torque_controller(HYUNDAI.HYUNDAI_IONIQ_6)
|
||||
@@ -521,7 +527,7 @@ class TestLatControl:
|
||||
_, _, lac_log = controller.update(True, CS, VM, params, False, 0.0025, False, 0.2, None, None, starpilot_toggles)
|
||||
|
||||
assert lac_log.active
|
||||
assert controller.torque_params.latAccelFactor == pytest.approx(CP.lateralTuning.torque.latAccelFactor * 1.08)
|
||||
assert controller.torque_params.latAccelFactor == pytest.approx(CP.lateralTuning.torque.latAccelFactor * 1.10)
|
||||
|
||||
def test_ioniq_6_update_path_does_not_post_taper_output(self, monkeypatch):
|
||||
base_controller, VM, CS, params, starpilot_toggles = self._build_torque_controller(HYUNDAI.HYUNDAI_IONIQ_6)
|
||||
@@ -688,6 +694,25 @@ class TestLatControl:
|
||||
|
||||
assert lac_log.active
|
||||
|
||||
def test_kia_ev6_ff_scale_curve(self):
|
||||
assert get_kia_ev6_ff_scale(0.0, 0.0, 20.0) == 1.0
|
||||
steady_left = get_kia_ev6_ff_scale(0.45, 0.0, 25.0)
|
||||
steady_right = get_kia_ev6_ff_scale(-0.45, 0.0, 25.0)
|
||||
turn_in_left = get_kia_ev6_ff_scale(0.45, 0.7, 10.0)
|
||||
turn_in_right = get_kia_ev6_ff_scale(-0.45, -0.7, 10.0)
|
||||
unwind_left = get_kia_ev6_ff_scale(0.45, -0.7, 10.0)
|
||||
unwind_right = get_kia_ev6_ff_scale(-0.45, 0.7, 10.0)
|
||||
assert steady_left > 1.0
|
||||
assert steady_right > steady_left
|
||||
assert turn_in_left > steady_left
|
||||
assert turn_in_right > steady_right
|
||||
assert unwind_left < steady_left
|
||||
assert unwind_right < steady_right
|
||||
|
||||
def test_kia_ev6_center_taper_curve(self):
|
||||
assert get_kia_ev6_center_taper_scale(0.0, 25.0) < get_kia_ev6_center_taper_scale(0.0, 10.0)
|
||||
assert get_kia_ev6_center_taper_scale(0.0, 25.0) < get_kia_ev6_center_taper_scale(0.20, 25.0) <= 1.0
|
||||
|
||||
def test_volt_plexy_testing_ground_update_path(self, monkeypatch):
|
||||
controller, VM, CS, params, starpilot_toggles = self._build_torque_controller(GM.CHEVROLET_VOLT_CC)
|
||||
monkeypatch.setattr(latcontrol_torque, "volt_plexy_lateral_testing_ground_active", lambda: True)
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from cereal import log
|
||||
|
||||
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper, LaneChangeDirection, LaneChangeState
|
||||
|
||||
|
||||
def make_car_state(**overrides):
|
||||
defaults = {
|
||||
"vEgo": 20.0,
|
||||
"leftBlinker": False,
|
||||
"rightBlinker": False,
|
||||
"leftBlindspot": False,
|
||||
"rightBlindspot": False,
|
||||
"steeringPressed": False,
|
||||
"steeringTorque": 0.0,
|
||||
"standstill": False,
|
||||
}
|
||||
defaults.update(overrides)
|
||||
return SimpleNamespace(**defaults)
|
||||
|
||||
|
||||
def make_toggles(**overrides):
|
||||
defaults = {
|
||||
"lane_changes": True,
|
||||
"lane_change_delay": 0.0,
|
||||
"lane_detection_width": 3.0,
|
||||
"minimum_lane_change_speed": 10.0,
|
||||
"nudgeless": True,
|
||||
"one_lane_change": False,
|
||||
"use_turn_desires": False,
|
||||
}
|
||||
defaults.update(overrides)
|
||||
return SimpleNamespace(**defaults)
|
||||
|
||||
|
||||
def make_plan(**overrides):
|
||||
defaults = {
|
||||
"laneWidthLeft": 4.0,
|
||||
"laneWidthRight": 4.0,
|
||||
}
|
||||
defaults.update(overrides)
|
||||
return SimpleNamespace(**defaults)
|
||||
|
||||
def test_nav_desires_keep_left_when_route_requests_it():
|
||||
helper = DesireHelper()
|
||||
helper.nav_desires_allowed = True
|
||||
helper._update_nav_params = lambda: None
|
||||
helper._nav_instruction_state = {"valid": True, "maneuverModifier": "slightLeft"}
|
||||
|
||||
helper.update(
|
||||
make_car_state(vEgo=20.0),
|
||||
True,
|
||||
0.0,
|
||||
make_plan(laneWidthLeft=4.2),
|
||||
make_toggles(nudgeless=True),
|
||||
)
|
||||
|
||||
assert helper.desire == log.Desire.keepLeft
|
||||
|
||||
|
||||
def test_nav_desires_turn_right_below_lane_change_speed():
|
||||
helper = DesireHelper()
|
||||
helper.nav_desires_allowed = True
|
||||
helper._update_nav_params = lambda: None
|
||||
helper._nav_instruction_state = {"valid": True, "maneuverModifier": "right", "maneuverDistance": 10.0}
|
||||
|
||||
helper.update(
|
||||
make_car_state(vEgo=5.0),
|
||||
True,
|
||||
0.0,
|
||||
make_plan(),
|
||||
make_toggles(minimum_lane_change_speed=10.0),
|
||||
)
|
||||
|
||||
assert helper.desire == log.Desire.turnRight
|
||||
|
||||
|
||||
def test_nav_desires_turn_right_waits_until_turn_is_close():
|
||||
helper = DesireHelper()
|
||||
helper.nav_desires_allowed = True
|
||||
helper._update_nav_params = lambda: None
|
||||
helper._nav_instruction_state = {"valid": True, "maneuverModifier": "right", "maneuverDistance": 300.0}
|
||||
|
||||
helper.update(
|
||||
make_car_state(vEgo=5.0),
|
||||
True,
|
||||
0.0,
|
||||
make_plan(),
|
||||
make_toggles(minimum_lane_change_speed=10.0),
|
||||
)
|
||||
|
||||
assert helper.desire == log.Desire.none
|
||||
|
||||
|
||||
def test_nav_desires_do_not_override_lane_change_state_machine():
|
||||
helper = DesireHelper()
|
||||
helper.nav_desires_allowed = True
|
||||
helper._update_nav_params = lambda: None
|
||||
helper._nav_instruction_state = {"valid": True, "maneuverModifier": "slightRight"}
|
||||
helper.lane_change_state = LaneChangeState.laneChangeStarting
|
||||
helper.lane_change_direction = LaneChangeDirection.left
|
||||
helper.lane_change_ll_prob = 0.5
|
||||
|
||||
helper.update(
|
||||
make_car_state(vEgo=25.0, leftBlinker=True),
|
||||
True,
|
||||
0.5,
|
||||
make_plan(),
|
||||
make_toggles(),
|
||||
)
|
||||
|
||||
assert helper.desire == log.Desire.laneChangeLeft
|
||||
|
||||
|
||||
def test_nav_desires_disabled_leave_desire_unchanged():
|
||||
helper = DesireHelper()
|
||||
helper.nav_desires_allowed = False
|
||||
helper._update_nav_params = lambda: None
|
||||
helper._nav_instruction_state = {"valid": True, "maneuverModifier": "left"}
|
||||
|
||||
helper.update(
|
||||
make_car_state(vEgo=5.0),
|
||||
True,
|
||||
0.0,
|
||||
make_plan(),
|
||||
make_toggles(minimum_lane_change_speed=10.0),
|
||||
)
|
||||
|
||||
assert helper.desire == log.Desire.none
|
||||
@@ -6,8 +6,12 @@ from types import SimpleNamespace
|
||||
|
||||
|
||||
class FakeParams:
|
||||
def __init__(self, values=None):
|
||||
self.values = dict(values or {})
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
return None
|
||||
key = args[0] if args else None
|
||||
return self.values.get(key)
|
||||
|
||||
def get_float(self, *args, **kwargs):
|
||||
return 0.0
|
||||
@@ -16,10 +20,10 @@ class FakeParams:
|
||||
pass
|
||||
|
||||
|
||||
def make_vcruise(*, red_light=False, raw_model_stopped=False, forcing_stop=False):
|
||||
def make_vcruise(*, red_light=False, raw_model_stopped=False, forcing_stop=False, nav_state=None):
|
||||
planner = SimpleNamespace(
|
||||
params=FakeParams(),
|
||||
params_memory=FakeParams(),
|
||||
params_memory=FakeParams({"NavInstructionState": nav_state or {}}),
|
||||
lead_one=SimpleNamespace(status=False, dRel=float("inf"), vLead=0.0),
|
||||
starpilot_cem=SimpleNamespace(stop_light_detected=red_light),
|
||||
tracking_lead=False,
|
||||
@@ -35,10 +39,11 @@ def make_vcruise(*, red_light=False, raw_model_stopped=False, forcing_stop=False
|
||||
return planner, vcruise
|
||||
|
||||
|
||||
def make_sm(*, standstill=True):
|
||||
def make_sm(*, standstill=True, min_steer_speed=0.0):
|
||||
return {
|
||||
"carControl": SimpleNamespace(longActive=True),
|
||||
"carState": SimpleNamespace(standstill=standstill, gasPressed=False, vCruiseCluster=0.0, vEgoCluster=0.0),
|
||||
"carParams": SimpleNamespace(minSteerSpeed=min_steer_speed),
|
||||
"starpilotCarState": SimpleNamespace(accelPressed=False, dashboardStopSign=0, dashboardSpeedLimit=0),
|
||||
}
|
||||
|
||||
@@ -48,6 +53,7 @@ def make_toggles():
|
||||
force_stops=True,
|
||||
force_standstill=False,
|
||||
curve_speed_controller=False,
|
||||
nav_longitudinal_allowed=False,
|
||||
speed_limit_controller=False,
|
||||
show_speed_limits=False,
|
||||
force_stop_distance_offset=0,
|
||||
@@ -133,3 +139,164 @@ def test_force_stop_stays_committed_while_moving_even_if_scene_opens():
|
||||
assert result == pytest.approx(0.0)
|
||||
assert vcruise.force_stop_timer >= 0.5
|
||||
assert vcruise.forcing_stop
|
||||
|
||||
|
||||
def test_nav_turn_speed_control_default_off():
|
||||
_, vcruise = make_vcruise(nav_state={
|
||||
"valid": True,
|
||||
"maneuverType": "turn",
|
||||
"maneuverModifier": "right",
|
||||
"maneuverDistance": 30.0,
|
||||
"nextManeuverType": "",
|
||||
"nextManeuverModifier": "",
|
||||
"nextManeuverDistance": 0.0,
|
||||
})
|
||||
|
||||
result = vcruise.update(
|
||||
controls_enabled=True,
|
||||
now=0.0,
|
||||
time_validated=True,
|
||||
v_cruise=20.0,
|
||||
v_ego=20.0,
|
||||
sm=make_sm(standstill=False),
|
||||
starpilot_toggles=make_toggles(),
|
||||
)
|
||||
|
||||
assert result == pytest.approx(20.0)
|
||||
assert vcruise.nav_turn_target == pytest.approx(0.0)
|
||||
|
||||
|
||||
def test_nav_turn_speed_control_slows_for_imminent_turn():
|
||||
_, vcruise = make_vcruise(nav_state={
|
||||
"valid": True,
|
||||
"maneuverType": "turn",
|
||||
"maneuverModifier": "right",
|
||||
"maneuverDistance": 30.0,
|
||||
"nextManeuverType": "",
|
||||
"nextManeuverModifier": "",
|
||||
"nextManeuverDistance": 0.0,
|
||||
})
|
||||
|
||||
toggles = make_toggles()
|
||||
toggles.nav_longitudinal_allowed = True
|
||||
result = vcruise.update(
|
||||
controls_enabled=True,
|
||||
now=0.0,
|
||||
time_validated=True,
|
||||
v_cruise=20.0,
|
||||
v_ego=20.0,
|
||||
sm=make_sm(standstill=False),
|
||||
starpilot_toggles=toggles,
|
||||
)
|
||||
|
||||
assert result < 20.0
|
||||
assert result == pytest.approx(vcruise.nav_turn_target)
|
||||
assert result > 0.0
|
||||
|
||||
|
||||
def test_nav_turn_speed_control_ignores_distant_turn():
|
||||
_, vcruise = make_vcruise(nav_state={
|
||||
"valid": True,
|
||||
"maneuverType": "turn",
|
||||
"maneuverModifier": "right",
|
||||
"maneuverDistance": 400.0,
|
||||
"nextManeuverType": "",
|
||||
"nextManeuverModifier": "",
|
||||
"nextManeuverDistance": 0.0,
|
||||
})
|
||||
|
||||
toggles = make_toggles()
|
||||
toggles.nav_longitudinal_allowed = True
|
||||
result = vcruise.update(
|
||||
controls_enabled=True,
|
||||
now=0.0,
|
||||
time_validated=True,
|
||||
v_cruise=20.0,
|
||||
v_ego=20.0,
|
||||
sm=make_sm(standstill=False),
|
||||
starpilot_toggles=toggles,
|
||||
)
|
||||
|
||||
assert result == pytest.approx(20.0)
|
||||
assert vcruise.nav_turn_target == pytest.approx(0.0)
|
||||
|
||||
|
||||
def test_nav_turn_speed_control_ignores_off_ramp():
|
||||
_, vcruise = make_vcruise(nav_state={
|
||||
"valid": True,
|
||||
"maneuverType": "off ramp",
|
||||
"maneuverModifier": "slightRight",
|
||||
"maneuverDistance": 40.0,
|
||||
"nextManeuverType": "",
|
||||
"nextManeuverModifier": "",
|
||||
"nextManeuverDistance": 0.0,
|
||||
})
|
||||
|
||||
toggles = make_toggles()
|
||||
toggles.nav_longitudinal_allowed = True
|
||||
result = vcruise.update(
|
||||
controls_enabled=True,
|
||||
now=0.0,
|
||||
time_validated=True,
|
||||
v_cruise=30.0,
|
||||
v_ego=30.0,
|
||||
sm=make_sm(standstill=False),
|
||||
starpilot_toggles=toggles,
|
||||
)
|
||||
|
||||
assert result == pytest.approx(30.0)
|
||||
assert vcruise.nav_turn_target == pytest.approx(0.0)
|
||||
|
||||
|
||||
def test_nav_turn_speed_control_respects_car_min_steer_speed():
|
||||
_, vcruise = make_vcruise(nav_state={
|
||||
"valid": True,
|
||||
"maneuverType": "turn",
|
||||
"maneuverModifier": "uturn",
|
||||
"maneuverDistance": 8.0,
|
||||
"nextManeuverType": "",
|
||||
"nextManeuverModifier": "",
|
||||
"nextManeuverDistance": 0.0,
|
||||
})
|
||||
|
||||
toggles = make_toggles()
|
||||
toggles.nav_longitudinal_allowed = True
|
||||
result = vcruise.update(
|
||||
controls_enabled=True,
|
||||
now=0.0,
|
||||
time_validated=True,
|
||||
v_cruise=20.0,
|
||||
v_ego=20.0,
|
||||
sm=make_sm(standstill=False, min_steer_speed=7.0 * CV.MPH_TO_MS),
|
||||
starpilot_toggles=toggles,
|
||||
)
|
||||
|
||||
assert result == pytest.approx(vcruise.nav_turn_target)
|
||||
assert vcruise.nav_turn_target >= 7.0 * CV.MPH_TO_MS
|
||||
|
||||
|
||||
def test_nav_turn_speed_control_does_not_floor_steer_to_zero_cars():
|
||||
_, vcruise = make_vcruise(nav_state={
|
||||
"valid": True,
|
||||
"maneuverType": "turn",
|
||||
"maneuverModifier": "uturn",
|
||||
"maneuverDistance": 8.0,
|
||||
"nextManeuverType": "",
|
||||
"nextManeuverModifier": "",
|
||||
"nextManeuverDistance": 0.0,
|
||||
})
|
||||
|
||||
toggles = make_toggles()
|
||||
toggles.nav_longitudinal_allowed = True
|
||||
result = vcruise.update(
|
||||
controls_enabled=True,
|
||||
now=0.0,
|
||||
time_validated=True,
|
||||
v_cruise=20.0,
|
||||
v_ego=20.0,
|
||||
sm=make_sm(standstill=False, min_steer_speed=0.0),
|
||||
starpilot_toggles=toggles,
|
||||
)
|
||||
|
||||
assert result == pytest.approx(vcruise.nav_turn_target)
|
||||
assert vcruise.nav_turn_target == pytest.approx(5.0 * CV.MPH_TO_MS)
|
||||
|
||||
@@ -283,7 +283,6 @@ def main():
|
||||
filter_initialized = False
|
||||
critcal_services = ["accelerometer", "gyroscope", "cameraOdometry"]
|
||||
observation_input_invalid = defaultdict(int)
|
||||
|
||||
input_invalid_limit = {s: round(INPUT_INVALID_LIMIT * (SERVICE_LIST[s].frequency / 20.)) for s in critcal_services}
|
||||
input_invalid_threshold = {s: input_invalid_limit[s] - 0.5 for s in critcal_services}
|
||||
input_invalid_decay = {s: calculate_invalid_input_decay(input_invalid_limit[s], INPUT_INVALID_RECOVERY, SERVICE_LIST[s].frequency) for s in critcal_services}
|
||||
|
||||
@@ -45,326 +45,326 @@ const static double MAHA_THRESH_31 = 3.8414588206941227;
|
||||
* *
|
||||
* This file is part of 'ekf' *
|
||||
******************************************************************************/
|
||||
void err_fun(double *nom_x, double *delta_x, double *out_3568804456057098654) {
|
||||
out_3568804456057098654[0] = delta_x[0] + nom_x[0];
|
||||
out_3568804456057098654[1] = delta_x[1] + nom_x[1];
|
||||
out_3568804456057098654[2] = delta_x[2] + nom_x[2];
|
||||
out_3568804456057098654[3] = delta_x[3] + nom_x[3];
|
||||
out_3568804456057098654[4] = delta_x[4] + nom_x[4];
|
||||
out_3568804456057098654[5] = delta_x[5] + nom_x[5];
|
||||
out_3568804456057098654[6] = delta_x[6] + nom_x[6];
|
||||
out_3568804456057098654[7] = delta_x[7] + nom_x[7];
|
||||
out_3568804456057098654[8] = delta_x[8] + nom_x[8];
|
||||
void err_fun(double *nom_x, double *delta_x, double *out_1972702472511725479) {
|
||||
out_1972702472511725479[0] = delta_x[0] + nom_x[0];
|
||||
out_1972702472511725479[1] = delta_x[1] + nom_x[1];
|
||||
out_1972702472511725479[2] = delta_x[2] + nom_x[2];
|
||||
out_1972702472511725479[3] = delta_x[3] + nom_x[3];
|
||||
out_1972702472511725479[4] = delta_x[4] + nom_x[4];
|
||||
out_1972702472511725479[5] = delta_x[5] + nom_x[5];
|
||||
out_1972702472511725479[6] = delta_x[6] + nom_x[6];
|
||||
out_1972702472511725479[7] = delta_x[7] + nom_x[7];
|
||||
out_1972702472511725479[8] = delta_x[8] + nom_x[8];
|
||||
}
|
||||
void inv_err_fun(double *nom_x, double *true_x, double *out_1840397183166108031) {
|
||||
out_1840397183166108031[0] = -nom_x[0] + true_x[0];
|
||||
out_1840397183166108031[1] = -nom_x[1] + true_x[1];
|
||||
out_1840397183166108031[2] = -nom_x[2] + true_x[2];
|
||||
out_1840397183166108031[3] = -nom_x[3] + true_x[3];
|
||||
out_1840397183166108031[4] = -nom_x[4] + true_x[4];
|
||||
out_1840397183166108031[5] = -nom_x[5] + true_x[5];
|
||||
out_1840397183166108031[6] = -nom_x[6] + true_x[6];
|
||||
out_1840397183166108031[7] = -nom_x[7] + true_x[7];
|
||||
out_1840397183166108031[8] = -nom_x[8] + true_x[8];
|
||||
void inv_err_fun(double *nom_x, double *true_x, double *out_3741555659818717473) {
|
||||
out_3741555659818717473[0] = -nom_x[0] + true_x[0];
|
||||
out_3741555659818717473[1] = -nom_x[1] + true_x[1];
|
||||
out_3741555659818717473[2] = -nom_x[2] + true_x[2];
|
||||
out_3741555659818717473[3] = -nom_x[3] + true_x[3];
|
||||
out_3741555659818717473[4] = -nom_x[4] + true_x[4];
|
||||
out_3741555659818717473[5] = -nom_x[5] + true_x[5];
|
||||
out_3741555659818717473[6] = -nom_x[6] + true_x[6];
|
||||
out_3741555659818717473[7] = -nom_x[7] + true_x[7];
|
||||
out_3741555659818717473[8] = -nom_x[8] + true_x[8];
|
||||
}
|
||||
void H_mod_fun(double *state, double *out_8921258435077713963) {
|
||||
out_8921258435077713963[0] = 1.0;
|
||||
out_8921258435077713963[1] = 0.0;
|
||||
out_8921258435077713963[2] = 0.0;
|
||||
out_8921258435077713963[3] = 0.0;
|
||||
out_8921258435077713963[4] = 0.0;
|
||||
out_8921258435077713963[5] = 0.0;
|
||||
out_8921258435077713963[6] = 0.0;
|
||||
out_8921258435077713963[7] = 0.0;
|
||||
out_8921258435077713963[8] = 0.0;
|
||||
out_8921258435077713963[9] = 0.0;
|
||||
out_8921258435077713963[10] = 1.0;
|
||||
out_8921258435077713963[11] = 0.0;
|
||||
out_8921258435077713963[12] = 0.0;
|
||||
out_8921258435077713963[13] = 0.0;
|
||||
out_8921258435077713963[14] = 0.0;
|
||||
out_8921258435077713963[15] = 0.0;
|
||||
out_8921258435077713963[16] = 0.0;
|
||||
out_8921258435077713963[17] = 0.0;
|
||||
out_8921258435077713963[18] = 0.0;
|
||||
out_8921258435077713963[19] = 0.0;
|
||||
out_8921258435077713963[20] = 1.0;
|
||||
out_8921258435077713963[21] = 0.0;
|
||||
out_8921258435077713963[22] = 0.0;
|
||||
out_8921258435077713963[23] = 0.0;
|
||||
out_8921258435077713963[24] = 0.0;
|
||||
out_8921258435077713963[25] = 0.0;
|
||||
out_8921258435077713963[26] = 0.0;
|
||||
out_8921258435077713963[27] = 0.0;
|
||||
out_8921258435077713963[28] = 0.0;
|
||||
out_8921258435077713963[29] = 0.0;
|
||||
out_8921258435077713963[30] = 1.0;
|
||||
out_8921258435077713963[31] = 0.0;
|
||||
out_8921258435077713963[32] = 0.0;
|
||||
out_8921258435077713963[33] = 0.0;
|
||||
out_8921258435077713963[34] = 0.0;
|
||||
out_8921258435077713963[35] = 0.0;
|
||||
out_8921258435077713963[36] = 0.0;
|
||||
out_8921258435077713963[37] = 0.0;
|
||||
out_8921258435077713963[38] = 0.0;
|
||||
out_8921258435077713963[39] = 0.0;
|
||||
out_8921258435077713963[40] = 1.0;
|
||||
out_8921258435077713963[41] = 0.0;
|
||||
out_8921258435077713963[42] = 0.0;
|
||||
out_8921258435077713963[43] = 0.0;
|
||||
out_8921258435077713963[44] = 0.0;
|
||||
out_8921258435077713963[45] = 0.0;
|
||||
out_8921258435077713963[46] = 0.0;
|
||||
out_8921258435077713963[47] = 0.0;
|
||||
out_8921258435077713963[48] = 0.0;
|
||||
out_8921258435077713963[49] = 0.0;
|
||||
out_8921258435077713963[50] = 1.0;
|
||||
out_8921258435077713963[51] = 0.0;
|
||||
out_8921258435077713963[52] = 0.0;
|
||||
out_8921258435077713963[53] = 0.0;
|
||||
out_8921258435077713963[54] = 0.0;
|
||||
out_8921258435077713963[55] = 0.0;
|
||||
out_8921258435077713963[56] = 0.0;
|
||||
out_8921258435077713963[57] = 0.0;
|
||||
out_8921258435077713963[58] = 0.0;
|
||||
out_8921258435077713963[59] = 0.0;
|
||||
out_8921258435077713963[60] = 1.0;
|
||||
out_8921258435077713963[61] = 0.0;
|
||||
out_8921258435077713963[62] = 0.0;
|
||||
out_8921258435077713963[63] = 0.0;
|
||||
out_8921258435077713963[64] = 0.0;
|
||||
out_8921258435077713963[65] = 0.0;
|
||||
out_8921258435077713963[66] = 0.0;
|
||||
out_8921258435077713963[67] = 0.0;
|
||||
out_8921258435077713963[68] = 0.0;
|
||||
out_8921258435077713963[69] = 0.0;
|
||||
out_8921258435077713963[70] = 1.0;
|
||||
out_8921258435077713963[71] = 0.0;
|
||||
out_8921258435077713963[72] = 0.0;
|
||||
out_8921258435077713963[73] = 0.0;
|
||||
out_8921258435077713963[74] = 0.0;
|
||||
out_8921258435077713963[75] = 0.0;
|
||||
out_8921258435077713963[76] = 0.0;
|
||||
out_8921258435077713963[77] = 0.0;
|
||||
out_8921258435077713963[78] = 0.0;
|
||||
out_8921258435077713963[79] = 0.0;
|
||||
out_8921258435077713963[80] = 1.0;
|
||||
void H_mod_fun(double *state, double *out_4845788339544047954) {
|
||||
out_4845788339544047954[0] = 1.0;
|
||||
out_4845788339544047954[1] = 0.0;
|
||||
out_4845788339544047954[2] = 0.0;
|
||||
out_4845788339544047954[3] = 0.0;
|
||||
out_4845788339544047954[4] = 0.0;
|
||||
out_4845788339544047954[5] = 0.0;
|
||||
out_4845788339544047954[6] = 0.0;
|
||||
out_4845788339544047954[7] = 0.0;
|
||||
out_4845788339544047954[8] = 0.0;
|
||||
out_4845788339544047954[9] = 0.0;
|
||||
out_4845788339544047954[10] = 1.0;
|
||||
out_4845788339544047954[11] = 0.0;
|
||||
out_4845788339544047954[12] = 0.0;
|
||||
out_4845788339544047954[13] = 0.0;
|
||||
out_4845788339544047954[14] = 0.0;
|
||||
out_4845788339544047954[15] = 0.0;
|
||||
out_4845788339544047954[16] = 0.0;
|
||||
out_4845788339544047954[17] = 0.0;
|
||||
out_4845788339544047954[18] = 0.0;
|
||||
out_4845788339544047954[19] = 0.0;
|
||||
out_4845788339544047954[20] = 1.0;
|
||||
out_4845788339544047954[21] = 0.0;
|
||||
out_4845788339544047954[22] = 0.0;
|
||||
out_4845788339544047954[23] = 0.0;
|
||||
out_4845788339544047954[24] = 0.0;
|
||||
out_4845788339544047954[25] = 0.0;
|
||||
out_4845788339544047954[26] = 0.0;
|
||||
out_4845788339544047954[27] = 0.0;
|
||||
out_4845788339544047954[28] = 0.0;
|
||||
out_4845788339544047954[29] = 0.0;
|
||||
out_4845788339544047954[30] = 1.0;
|
||||
out_4845788339544047954[31] = 0.0;
|
||||
out_4845788339544047954[32] = 0.0;
|
||||
out_4845788339544047954[33] = 0.0;
|
||||
out_4845788339544047954[34] = 0.0;
|
||||
out_4845788339544047954[35] = 0.0;
|
||||
out_4845788339544047954[36] = 0.0;
|
||||
out_4845788339544047954[37] = 0.0;
|
||||
out_4845788339544047954[38] = 0.0;
|
||||
out_4845788339544047954[39] = 0.0;
|
||||
out_4845788339544047954[40] = 1.0;
|
||||
out_4845788339544047954[41] = 0.0;
|
||||
out_4845788339544047954[42] = 0.0;
|
||||
out_4845788339544047954[43] = 0.0;
|
||||
out_4845788339544047954[44] = 0.0;
|
||||
out_4845788339544047954[45] = 0.0;
|
||||
out_4845788339544047954[46] = 0.0;
|
||||
out_4845788339544047954[47] = 0.0;
|
||||
out_4845788339544047954[48] = 0.0;
|
||||
out_4845788339544047954[49] = 0.0;
|
||||
out_4845788339544047954[50] = 1.0;
|
||||
out_4845788339544047954[51] = 0.0;
|
||||
out_4845788339544047954[52] = 0.0;
|
||||
out_4845788339544047954[53] = 0.0;
|
||||
out_4845788339544047954[54] = 0.0;
|
||||
out_4845788339544047954[55] = 0.0;
|
||||
out_4845788339544047954[56] = 0.0;
|
||||
out_4845788339544047954[57] = 0.0;
|
||||
out_4845788339544047954[58] = 0.0;
|
||||
out_4845788339544047954[59] = 0.0;
|
||||
out_4845788339544047954[60] = 1.0;
|
||||
out_4845788339544047954[61] = 0.0;
|
||||
out_4845788339544047954[62] = 0.0;
|
||||
out_4845788339544047954[63] = 0.0;
|
||||
out_4845788339544047954[64] = 0.0;
|
||||
out_4845788339544047954[65] = 0.0;
|
||||
out_4845788339544047954[66] = 0.0;
|
||||
out_4845788339544047954[67] = 0.0;
|
||||
out_4845788339544047954[68] = 0.0;
|
||||
out_4845788339544047954[69] = 0.0;
|
||||
out_4845788339544047954[70] = 1.0;
|
||||
out_4845788339544047954[71] = 0.0;
|
||||
out_4845788339544047954[72] = 0.0;
|
||||
out_4845788339544047954[73] = 0.0;
|
||||
out_4845788339544047954[74] = 0.0;
|
||||
out_4845788339544047954[75] = 0.0;
|
||||
out_4845788339544047954[76] = 0.0;
|
||||
out_4845788339544047954[77] = 0.0;
|
||||
out_4845788339544047954[78] = 0.0;
|
||||
out_4845788339544047954[79] = 0.0;
|
||||
out_4845788339544047954[80] = 1.0;
|
||||
}
|
||||
void f_fun(double *state, double dt, double *out_3277027219914288776) {
|
||||
out_3277027219914288776[0] = state[0];
|
||||
out_3277027219914288776[1] = state[1];
|
||||
out_3277027219914288776[2] = state[2];
|
||||
out_3277027219914288776[3] = state[3];
|
||||
out_3277027219914288776[4] = state[4];
|
||||
out_3277027219914288776[5] = dt*((-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]))*state[6] - 9.8100000000000005*state[8] + stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*state[1]) + (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*state[4])) + state[5];
|
||||
out_3277027219914288776[6] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*state[4])) + state[6];
|
||||
out_3277027219914288776[7] = state[7];
|
||||
out_3277027219914288776[8] = state[8];
|
||||
void f_fun(double *state, double dt, double *out_4185306989729419910) {
|
||||
out_4185306989729419910[0] = state[0];
|
||||
out_4185306989729419910[1] = state[1];
|
||||
out_4185306989729419910[2] = state[2];
|
||||
out_4185306989729419910[3] = state[3];
|
||||
out_4185306989729419910[4] = state[4];
|
||||
out_4185306989729419910[5] = dt*((-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]))*state[6] - 9.8100000000000005*state[8] + stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*state[1]) + (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*state[4])) + state[5];
|
||||
out_4185306989729419910[6] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*state[4])) + state[6];
|
||||
out_4185306989729419910[7] = state[7];
|
||||
out_4185306989729419910[8] = state[8];
|
||||
}
|
||||
void F_fun(double *state, double dt, double *out_370955893725369602) {
|
||||
out_370955893725369602[0] = 1;
|
||||
out_370955893725369602[1] = 0;
|
||||
out_370955893725369602[2] = 0;
|
||||
out_370955893725369602[3] = 0;
|
||||
out_370955893725369602[4] = 0;
|
||||
out_370955893725369602[5] = 0;
|
||||
out_370955893725369602[6] = 0;
|
||||
out_370955893725369602[7] = 0;
|
||||
out_370955893725369602[8] = 0;
|
||||
out_370955893725369602[9] = 0;
|
||||
out_370955893725369602[10] = 1;
|
||||
out_370955893725369602[11] = 0;
|
||||
out_370955893725369602[12] = 0;
|
||||
out_370955893725369602[13] = 0;
|
||||
out_370955893725369602[14] = 0;
|
||||
out_370955893725369602[15] = 0;
|
||||
out_370955893725369602[16] = 0;
|
||||
out_370955893725369602[17] = 0;
|
||||
out_370955893725369602[18] = 0;
|
||||
out_370955893725369602[19] = 0;
|
||||
out_370955893725369602[20] = 1;
|
||||
out_370955893725369602[21] = 0;
|
||||
out_370955893725369602[22] = 0;
|
||||
out_370955893725369602[23] = 0;
|
||||
out_370955893725369602[24] = 0;
|
||||
out_370955893725369602[25] = 0;
|
||||
out_370955893725369602[26] = 0;
|
||||
out_370955893725369602[27] = 0;
|
||||
out_370955893725369602[28] = 0;
|
||||
out_370955893725369602[29] = 0;
|
||||
out_370955893725369602[30] = 1;
|
||||
out_370955893725369602[31] = 0;
|
||||
out_370955893725369602[32] = 0;
|
||||
out_370955893725369602[33] = 0;
|
||||
out_370955893725369602[34] = 0;
|
||||
out_370955893725369602[35] = 0;
|
||||
out_370955893725369602[36] = 0;
|
||||
out_370955893725369602[37] = 0;
|
||||
out_370955893725369602[38] = 0;
|
||||
out_370955893725369602[39] = 0;
|
||||
out_370955893725369602[40] = 1;
|
||||
out_370955893725369602[41] = 0;
|
||||
out_370955893725369602[42] = 0;
|
||||
out_370955893725369602[43] = 0;
|
||||
out_370955893725369602[44] = 0;
|
||||
out_370955893725369602[45] = dt*(stiffness_front*(-state[2] - state[3] + state[7])/(mass*state[1]) + (-stiffness_front - stiffness_rear)*state[5]/(mass*state[4]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[6]/(mass*state[4]));
|
||||
out_370955893725369602[46] = -dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*pow(state[1], 2));
|
||||
out_370955893725369602[47] = -dt*stiffness_front*state[0]/(mass*state[1]);
|
||||
out_370955893725369602[48] = -dt*stiffness_front*state[0]/(mass*state[1]);
|
||||
out_370955893725369602[49] = dt*((-1 - (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*pow(state[4], 2)))*state[6] - (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*pow(state[4], 2)));
|
||||
out_370955893725369602[50] = dt*(-stiffness_front*state[0] - stiffness_rear*state[0])/(mass*state[4]) + 1;
|
||||
out_370955893725369602[51] = dt*(-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]));
|
||||
out_370955893725369602[52] = dt*stiffness_front*state[0]/(mass*state[1]);
|
||||
out_370955893725369602[53] = -9.8100000000000005*dt;
|
||||
out_370955893725369602[54] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front - pow(center_to_rear, 2)*stiffness_rear)*state[6]/(rotational_inertia*state[4]));
|
||||
out_370955893725369602[55] = -center_to_front*dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*pow(state[1], 2));
|
||||
out_370955893725369602[56] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
|
||||
out_370955893725369602[57] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
|
||||
out_370955893725369602[58] = dt*(-(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*pow(state[4], 2)) - (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*pow(state[4], 2)));
|
||||
out_370955893725369602[59] = dt*(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(rotational_inertia*state[4]);
|
||||
out_370955893725369602[60] = dt*(-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])/(rotational_inertia*state[4]) + 1;
|
||||
out_370955893725369602[61] = center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
|
||||
out_370955893725369602[62] = 0;
|
||||
out_370955893725369602[63] = 0;
|
||||
out_370955893725369602[64] = 0;
|
||||
out_370955893725369602[65] = 0;
|
||||
out_370955893725369602[66] = 0;
|
||||
out_370955893725369602[67] = 0;
|
||||
out_370955893725369602[68] = 0;
|
||||
out_370955893725369602[69] = 0;
|
||||
out_370955893725369602[70] = 1;
|
||||
out_370955893725369602[71] = 0;
|
||||
out_370955893725369602[72] = 0;
|
||||
out_370955893725369602[73] = 0;
|
||||
out_370955893725369602[74] = 0;
|
||||
out_370955893725369602[75] = 0;
|
||||
out_370955893725369602[76] = 0;
|
||||
out_370955893725369602[77] = 0;
|
||||
out_370955893725369602[78] = 0;
|
||||
out_370955893725369602[79] = 0;
|
||||
out_370955893725369602[80] = 1;
|
||||
void F_fun(double *state, double dt, double *out_8252178874365212967) {
|
||||
out_8252178874365212967[0] = 1;
|
||||
out_8252178874365212967[1] = 0;
|
||||
out_8252178874365212967[2] = 0;
|
||||
out_8252178874365212967[3] = 0;
|
||||
out_8252178874365212967[4] = 0;
|
||||
out_8252178874365212967[5] = 0;
|
||||
out_8252178874365212967[6] = 0;
|
||||
out_8252178874365212967[7] = 0;
|
||||
out_8252178874365212967[8] = 0;
|
||||
out_8252178874365212967[9] = 0;
|
||||
out_8252178874365212967[10] = 1;
|
||||
out_8252178874365212967[11] = 0;
|
||||
out_8252178874365212967[12] = 0;
|
||||
out_8252178874365212967[13] = 0;
|
||||
out_8252178874365212967[14] = 0;
|
||||
out_8252178874365212967[15] = 0;
|
||||
out_8252178874365212967[16] = 0;
|
||||
out_8252178874365212967[17] = 0;
|
||||
out_8252178874365212967[18] = 0;
|
||||
out_8252178874365212967[19] = 0;
|
||||
out_8252178874365212967[20] = 1;
|
||||
out_8252178874365212967[21] = 0;
|
||||
out_8252178874365212967[22] = 0;
|
||||
out_8252178874365212967[23] = 0;
|
||||
out_8252178874365212967[24] = 0;
|
||||
out_8252178874365212967[25] = 0;
|
||||
out_8252178874365212967[26] = 0;
|
||||
out_8252178874365212967[27] = 0;
|
||||
out_8252178874365212967[28] = 0;
|
||||
out_8252178874365212967[29] = 0;
|
||||
out_8252178874365212967[30] = 1;
|
||||
out_8252178874365212967[31] = 0;
|
||||
out_8252178874365212967[32] = 0;
|
||||
out_8252178874365212967[33] = 0;
|
||||
out_8252178874365212967[34] = 0;
|
||||
out_8252178874365212967[35] = 0;
|
||||
out_8252178874365212967[36] = 0;
|
||||
out_8252178874365212967[37] = 0;
|
||||
out_8252178874365212967[38] = 0;
|
||||
out_8252178874365212967[39] = 0;
|
||||
out_8252178874365212967[40] = 1;
|
||||
out_8252178874365212967[41] = 0;
|
||||
out_8252178874365212967[42] = 0;
|
||||
out_8252178874365212967[43] = 0;
|
||||
out_8252178874365212967[44] = 0;
|
||||
out_8252178874365212967[45] = dt*(stiffness_front*(-state[2] - state[3] + state[7])/(mass*state[1]) + (-stiffness_front - stiffness_rear)*state[5]/(mass*state[4]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[6]/(mass*state[4]));
|
||||
out_8252178874365212967[46] = -dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*pow(state[1], 2));
|
||||
out_8252178874365212967[47] = -dt*stiffness_front*state[0]/(mass*state[1]);
|
||||
out_8252178874365212967[48] = -dt*stiffness_front*state[0]/(mass*state[1]);
|
||||
out_8252178874365212967[49] = dt*((-1 - (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*pow(state[4], 2)))*state[6] - (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*pow(state[4], 2)));
|
||||
out_8252178874365212967[50] = dt*(-stiffness_front*state[0] - stiffness_rear*state[0])/(mass*state[4]) + 1;
|
||||
out_8252178874365212967[51] = dt*(-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]));
|
||||
out_8252178874365212967[52] = dt*stiffness_front*state[0]/(mass*state[1]);
|
||||
out_8252178874365212967[53] = -9.8100000000000005*dt;
|
||||
out_8252178874365212967[54] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front - pow(center_to_rear, 2)*stiffness_rear)*state[6]/(rotational_inertia*state[4]));
|
||||
out_8252178874365212967[55] = -center_to_front*dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*pow(state[1], 2));
|
||||
out_8252178874365212967[56] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
|
||||
out_8252178874365212967[57] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
|
||||
out_8252178874365212967[58] = dt*(-(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*pow(state[4], 2)) - (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*pow(state[4], 2)));
|
||||
out_8252178874365212967[59] = dt*(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(rotational_inertia*state[4]);
|
||||
out_8252178874365212967[60] = dt*(-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])/(rotational_inertia*state[4]) + 1;
|
||||
out_8252178874365212967[61] = center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
|
||||
out_8252178874365212967[62] = 0;
|
||||
out_8252178874365212967[63] = 0;
|
||||
out_8252178874365212967[64] = 0;
|
||||
out_8252178874365212967[65] = 0;
|
||||
out_8252178874365212967[66] = 0;
|
||||
out_8252178874365212967[67] = 0;
|
||||
out_8252178874365212967[68] = 0;
|
||||
out_8252178874365212967[69] = 0;
|
||||
out_8252178874365212967[70] = 1;
|
||||
out_8252178874365212967[71] = 0;
|
||||
out_8252178874365212967[72] = 0;
|
||||
out_8252178874365212967[73] = 0;
|
||||
out_8252178874365212967[74] = 0;
|
||||
out_8252178874365212967[75] = 0;
|
||||
out_8252178874365212967[76] = 0;
|
||||
out_8252178874365212967[77] = 0;
|
||||
out_8252178874365212967[78] = 0;
|
||||
out_8252178874365212967[79] = 0;
|
||||
out_8252178874365212967[80] = 1;
|
||||
}
|
||||
void h_25(double *state, double *unused, double *out_8154090013633331696) {
|
||||
out_8154090013633331696[0] = state[6];
|
||||
void h_25(double *state, double *unused, double *out_4739826667919645243) {
|
||||
out_4739826667919645243[0] = state[6];
|
||||
}
|
||||
void H_25(double *state, double *unused, double *out_8415923992877417251) {
|
||||
out_8415923992877417251[0] = 0;
|
||||
out_8415923992877417251[1] = 0;
|
||||
out_8415923992877417251[2] = 0;
|
||||
out_8415923992877417251[3] = 0;
|
||||
out_8415923992877417251[4] = 0;
|
||||
out_8415923992877417251[5] = 0;
|
||||
out_8415923992877417251[6] = 1;
|
||||
out_8415923992877417251[7] = 0;
|
||||
out_8415923992877417251[8] = 0;
|
||||
void H_25(double *state, double *unused, double *out_2698629402266667542) {
|
||||
out_2698629402266667542[0] = 0;
|
||||
out_2698629402266667542[1] = 0;
|
||||
out_2698629402266667542[2] = 0;
|
||||
out_2698629402266667542[3] = 0;
|
||||
out_2698629402266667542[4] = 0;
|
||||
out_2698629402266667542[5] = 0;
|
||||
out_2698629402266667542[6] = 1;
|
||||
out_2698629402266667542[7] = 0;
|
||||
out_2698629402266667542[8] = 0;
|
||||
}
|
||||
void h_24(double *state, double *unused, double *out_7351280482288278166) {
|
||||
out_7351280482288278166[0] = state[4];
|
||||
out_7351280482288278166[1] = state[5];
|
||||
void h_24(double *state, double *unused, double *out_6091047700113278923) {
|
||||
out_6091047700113278923[0] = state[4];
|
||||
out_6091047700113278923[1] = state[5];
|
||||
}
|
||||
void H_24(double *state, double *unused, double *out_8301956961654820296) {
|
||||
out_8301956961654820296[0] = 0;
|
||||
out_8301956961654820296[1] = 0;
|
||||
out_8301956961654820296[2] = 0;
|
||||
out_8301956961654820296[3] = 0;
|
||||
out_8301956961654820296[4] = 1;
|
||||
out_8301956961654820296[5] = 0;
|
||||
out_8301956961654820296[6] = 0;
|
||||
out_8301956961654820296[7] = 0;
|
||||
out_8301956961654820296[8] = 0;
|
||||
out_8301956961654820296[9] = 0;
|
||||
out_8301956961654820296[10] = 0;
|
||||
out_8301956961654820296[11] = 0;
|
||||
out_8301956961654820296[12] = 0;
|
||||
out_8301956961654820296[13] = 0;
|
||||
out_8301956961654820296[14] = 1;
|
||||
out_8301956961654820296[15] = 0;
|
||||
out_8301956961654820296[16] = 0;
|
||||
out_8301956961654820296[17] = 0;
|
||||
void H_24(double *state, double *unused, double *out_2121692102389320721) {
|
||||
out_2121692102389320721[0] = 0;
|
||||
out_2121692102389320721[1] = 0;
|
||||
out_2121692102389320721[2] = 0;
|
||||
out_2121692102389320721[3] = 0;
|
||||
out_2121692102389320721[4] = 1;
|
||||
out_2121692102389320721[5] = 0;
|
||||
out_2121692102389320721[6] = 0;
|
||||
out_2121692102389320721[7] = 0;
|
||||
out_2121692102389320721[8] = 0;
|
||||
out_2121692102389320721[9] = 0;
|
||||
out_2121692102389320721[10] = 0;
|
||||
out_2121692102389320721[11] = 0;
|
||||
out_2121692102389320721[12] = 0;
|
||||
out_2121692102389320721[13] = 0;
|
||||
out_2121692102389320721[14] = 1;
|
||||
out_2121692102389320721[15] = 0;
|
||||
out_2121692102389320721[16] = 0;
|
||||
out_2121692102389320721[17] = 0;
|
||||
}
|
||||
void h_30(double *state, double *unused, double *out_4292406537204830044) {
|
||||
out_4292406537204830044[0] = state[4];
|
||||
void h_30(double *state, double *unused, double *out_7687552658275130204) {
|
||||
out_7687552658275130204[0] = state[4];
|
||||
}
|
||||
void H_30(double *state, double *unused, double *out_1499233651385800496) {
|
||||
out_1499233651385800496[0] = 0;
|
||||
out_1499233651385800496[1] = 0;
|
||||
out_1499233651385800496[2] = 0;
|
||||
out_1499233651385800496[3] = 0;
|
||||
out_1499233651385800496[4] = 1;
|
||||
out_1499233651385800496[5] = 0;
|
||||
out_1499233651385800496[6] = 0;
|
||||
out_1499233651385800496[7] = 0;
|
||||
out_1499233651385800496[8] = 0;
|
||||
void H_30(double *state, double *unused, double *out_2569290455123427472) {
|
||||
out_2569290455123427472[0] = 0;
|
||||
out_2569290455123427472[1] = 0;
|
||||
out_2569290455123427472[2] = 0;
|
||||
out_2569290455123427472[3] = 0;
|
||||
out_2569290455123427472[4] = 1;
|
||||
out_2569290455123427472[5] = 0;
|
||||
out_2569290455123427472[6] = 0;
|
||||
out_2569290455123427472[7] = 0;
|
||||
out_2569290455123427472[8] = 0;
|
||||
}
|
||||
void h_26(double *state, double *unused, double *out_7000316085453517212) {
|
||||
out_7000316085453517212[0] = state[7];
|
||||
void h_26(double *state, double *unused, double *out_7946639312164568029) {
|
||||
out_7946639312164568029[0] = state[7];
|
||||
}
|
||||
void H_26(double *state, double *unused, double *out_6289316761958078141) {
|
||||
out_6289316761958078141[0] = 0;
|
||||
out_6289316761958078141[1] = 0;
|
||||
out_6289316761958078141[2] = 0;
|
||||
out_6289316761958078141[3] = 0;
|
||||
out_6289316761958078141[4] = 0;
|
||||
out_6289316761958078141[5] = 0;
|
||||
out_6289316761958078141[6] = 0;
|
||||
out_6289316761958078141[7] = 1;
|
||||
out_6289316761958078141[8] = 0;
|
||||
void H_26(double *state, double *unused, double *out_1042873916607388682) {
|
||||
out_1042873916607388682[0] = 0;
|
||||
out_1042873916607388682[1] = 0;
|
||||
out_1042873916607388682[2] = 0;
|
||||
out_1042873916607388682[3] = 0;
|
||||
out_1042873916607388682[4] = 0;
|
||||
out_1042873916607388682[5] = 0;
|
||||
out_1042873916607388682[6] = 0;
|
||||
out_1042873916607388682[7] = 1;
|
||||
out_1042873916607388682[8] = 0;
|
||||
}
|
||||
void h_27(double *state, double *unused, double *out_3964284714812858416) {
|
||||
out_3964284714812858416[0] = state[3];
|
||||
void h_27(double *state, double *unused, double *out_3665830151724581410) {
|
||||
out_3665830151724581410[0] = state[3];
|
||||
}
|
||||
void H_27(double *state, double *unused, double *out_3673996963186225407) {
|
||||
out_3673996963186225407[0] = 0;
|
||||
out_3673996963186225407[1] = 0;
|
||||
out_3673996963186225407[2] = 0;
|
||||
out_3673996963186225407[3] = 1;
|
||||
out_3673996963186225407[4] = 0;
|
||||
out_3673996963186225407[5] = 0;
|
||||
out_3673996963186225407[6] = 0;
|
||||
out_3673996963186225407[7] = 0;
|
||||
out_3673996963186225407[8] = 0;
|
||||
void H_27(double *state, double *unused, double *out_394527143323002561) {
|
||||
out_394527143323002561[0] = 0;
|
||||
out_394527143323002561[1] = 0;
|
||||
out_394527143323002561[2] = 0;
|
||||
out_394527143323002561[3] = 1;
|
||||
out_394527143323002561[4] = 0;
|
||||
out_394527143323002561[5] = 0;
|
||||
out_394527143323002561[6] = 0;
|
||||
out_394527143323002561[7] = 0;
|
||||
out_394527143323002561[8] = 0;
|
||||
}
|
||||
void h_29(double *state, double *unused, double *out_3689090652528352527) {
|
||||
out_3689090652528352527[0] = state[1];
|
||||
void h_29(double *state, double *unused, double *out_8290868542951607721) {
|
||||
out_8290868542951607721[0] = state[1];
|
||||
}
|
||||
void H_29(double *state, double *unused, double *out_989002307071408312) {
|
||||
out_989002307071408312[0] = 0;
|
||||
out_989002307071408312[1] = 1;
|
||||
out_989002307071408312[2] = 0;
|
||||
out_989002307071408312[3] = 0;
|
||||
out_989002307071408312[4] = 0;
|
||||
out_989002307071408312[5] = 0;
|
||||
out_989002307071408312[6] = 0;
|
||||
out_989002307071408312[7] = 0;
|
||||
out_989002307071408312[8] = 0;
|
||||
void H_29(double *state, double *unused, double *out_3079521799437819656) {
|
||||
out_3079521799437819656[0] = 0;
|
||||
out_3079521799437819656[1] = 1;
|
||||
out_3079521799437819656[2] = 0;
|
||||
out_3079521799437819656[3] = 0;
|
||||
out_3079521799437819656[4] = 0;
|
||||
out_3079521799437819656[5] = 0;
|
||||
out_3079521799437819656[6] = 0;
|
||||
out_3079521799437819656[7] = 0;
|
||||
out_3079521799437819656[8] = 0;
|
||||
}
|
||||
void h_28(double *state, double *unused, double *out_1914000772745856672) {
|
||||
out_1914000772745856672[0] = state[0];
|
||||
void h_28(double *state, double *unused, double *out_6846547824895893173) {
|
||||
out_6846547824895893173[0] = state[0];
|
||||
}
|
||||
void H_28(double *state, double *unused, double *out_6071401324140938886) {
|
||||
out_6071401324140938886[0] = 1;
|
||||
out_6071401324140938886[1] = 0;
|
||||
out_6071401324140938886[2] = 0;
|
||||
out_6071401324140938886[3] = 0;
|
||||
out_6071401324140938886[4] = 0;
|
||||
out_6071401324140938886[5] = 0;
|
||||
out_6071401324140938886[6] = 0;
|
||||
out_6071401324140938886[7] = 0;
|
||||
out_6071401324140938886[8] = 0;
|
||||
void H_28(double *state, double *unused, double *out_2002877217631710918) {
|
||||
out_2002877217631710918[0] = 1;
|
||||
out_2002877217631710918[1] = 0;
|
||||
out_2002877217631710918[2] = 0;
|
||||
out_2002877217631710918[3] = 0;
|
||||
out_2002877217631710918[4] = 0;
|
||||
out_2002877217631710918[5] = 0;
|
||||
out_2002877217631710918[6] = 0;
|
||||
out_2002877217631710918[7] = 0;
|
||||
out_2002877217631710918[8] = 0;
|
||||
}
|
||||
void h_31(double *state, double *unused, double *out_8205050127743358283) {
|
||||
out_8205050127743358283[0] = state[8];
|
||||
void h_31(double *state, double *unused, double *out_3141445982834403942) {
|
||||
out_3141445982834403942[0] = state[8];
|
||||
}
|
||||
void H_31(double *state, double *unused, double *out_8385278031000456823) {
|
||||
out_8385278031000456823[0] = 0;
|
||||
out_8385278031000456823[1] = 0;
|
||||
out_8385278031000456823[2] = 0;
|
||||
out_8385278031000456823[3] = 0;
|
||||
out_8385278031000456823[4] = 0;
|
||||
out_8385278031000456823[5] = 0;
|
||||
out_8385278031000456823[6] = 0;
|
||||
out_8385278031000456823[7] = 0;
|
||||
out_8385278031000456823[8] = 1;
|
||||
void H_31(double *state, double *unused, double *out_2729275364143627970) {
|
||||
out_2729275364143627970[0] = 0;
|
||||
out_2729275364143627970[1] = 0;
|
||||
out_2729275364143627970[2] = 0;
|
||||
out_2729275364143627970[3] = 0;
|
||||
out_2729275364143627970[4] = 0;
|
||||
out_2729275364143627970[5] = 0;
|
||||
out_2729275364143627970[6] = 0;
|
||||
out_2729275364143627970[7] = 0;
|
||||
out_2729275364143627970[8] = 1;
|
||||
}
|
||||
#include <eigen3/Eigen/Dense>
|
||||
#include <iostream>
|
||||
@@ -518,68 +518,68 @@ void car_update_28(double *in_x, double *in_P, double *in_z, double *in_R, doubl
|
||||
void car_update_31(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea) {
|
||||
update<1, 3, 0>(in_x, in_P, h_31, H_31, NULL, in_z, in_R, in_ea, MAHA_THRESH_31);
|
||||
}
|
||||
void car_err_fun(double *nom_x, double *delta_x, double *out_3568804456057098654) {
|
||||
err_fun(nom_x, delta_x, out_3568804456057098654);
|
||||
void car_err_fun(double *nom_x, double *delta_x, double *out_1972702472511725479) {
|
||||
err_fun(nom_x, delta_x, out_1972702472511725479);
|
||||
}
|
||||
void car_inv_err_fun(double *nom_x, double *true_x, double *out_1840397183166108031) {
|
||||
inv_err_fun(nom_x, true_x, out_1840397183166108031);
|
||||
void car_inv_err_fun(double *nom_x, double *true_x, double *out_3741555659818717473) {
|
||||
inv_err_fun(nom_x, true_x, out_3741555659818717473);
|
||||
}
|
||||
void car_H_mod_fun(double *state, double *out_8921258435077713963) {
|
||||
H_mod_fun(state, out_8921258435077713963);
|
||||
void car_H_mod_fun(double *state, double *out_4845788339544047954) {
|
||||
H_mod_fun(state, out_4845788339544047954);
|
||||
}
|
||||
void car_f_fun(double *state, double dt, double *out_3277027219914288776) {
|
||||
f_fun(state, dt, out_3277027219914288776);
|
||||
void car_f_fun(double *state, double dt, double *out_4185306989729419910) {
|
||||
f_fun(state, dt, out_4185306989729419910);
|
||||
}
|
||||
void car_F_fun(double *state, double dt, double *out_370955893725369602) {
|
||||
F_fun(state, dt, out_370955893725369602);
|
||||
void car_F_fun(double *state, double dt, double *out_8252178874365212967) {
|
||||
F_fun(state, dt, out_8252178874365212967);
|
||||
}
|
||||
void car_h_25(double *state, double *unused, double *out_8154090013633331696) {
|
||||
h_25(state, unused, out_8154090013633331696);
|
||||
void car_h_25(double *state, double *unused, double *out_4739826667919645243) {
|
||||
h_25(state, unused, out_4739826667919645243);
|
||||
}
|
||||
void car_H_25(double *state, double *unused, double *out_8415923992877417251) {
|
||||
H_25(state, unused, out_8415923992877417251);
|
||||
void car_H_25(double *state, double *unused, double *out_2698629402266667542) {
|
||||
H_25(state, unused, out_2698629402266667542);
|
||||
}
|
||||
void car_h_24(double *state, double *unused, double *out_7351280482288278166) {
|
||||
h_24(state, unused, out_7351280482288278166);
|
||||
void car_h_24(double *state, double *unused, double *out_6091047700113278923) {
|
||||
h_24(state, unused, out_6091047700113278923);
|
||||
}
|
||||
void car_H_24(double *state, double *unused, double *out_8301956961654820296) {
|
||||
H_24(state, unused, out_8301956961654820296);
|
||||
void car_H_24(double *state, double *unused, double *out_2121692102389320721) {
|
||||
H_24(state, unused, out_2121692102389320721);
|
||||
}
|
||||
void car_h_30(double *state, double *unused, double *out_4292406537204830044) {
|
||||
h_30(state, unused, out_4292406537204830044);
|
||||
void car_h_30(double *state, double *unused, double *out_7687552658275130204) {
|
||||
h_30(state, unused, out_7687552658275130204);
|
||||
}
|
||||
void car_H_30(double *state, double *unused, double *out_1499233651385800496) {
|
||||
H_30(state, unused, out_1499233651385800496);
|
||||
void car_H_30(double *state, double *unused, double *out_2569290455123427472) {
|
||||
H_30(state, unused, out_2569290455123427472);
|
||||
}
|
||||
void car_h_26(double *state, double *unused, double *out_7000316085453517212) {
|
||||
h_26(state, unused, out_7000316085453517212);
|
||||
void car_h_26(double *state, double *unused, double *out_7946639312164568029) {
|
||||
h_26(state, unused, out_7946639312164568029);
|
||||
}
|
||||
void car_H_26(double *state, double *unused, double *out_6289316761958078141) {
|
||||
H_26(state, unused, out_6289316761958078141);
|
||||
void car_H_26(double *state, double *unused, double *out_1042873916607388682) {
|
||||
H_26(state, unused, out_1042873916607388682);
|
||||
}
|
||||
void car_h_27(double *state, double *unused, double *out_3964284714812858416) {
|
||||
h_27(state, unused, out_3964284714812858416);
|
||||
void car_h_27(double *state, double *unused, double *out_3665830151724581410) {
|
||||
h_27(state, unused, out_3665830151724581410);
|
||||
}
|
||||
void car_H_27(double *state, double *unused, double *out_3673996963186225407) {
|
||||
H_27(state, unused, out_3673996963186225407);
|
||||
void car_H_27(double *state, double *unused, double *out_394527143323002561) {
|
||||
H_27(state, unused, out_394527143323002561);
|
||||
}
|
||||
void car_h_29(double *state, double *unused, double *out_3689090652528352527) {
|
||||
h_29(state, unused, out_3689090652528352527);
|
||||
void car_h_29(double *state, double *unused, double *out_8290868542951607721) {
|
||||
h_29(state, unused, out_8290868542951607721);
|
||||
}
|
||||
void car_H_29(double *state, double *unused, double *out_989002307071408312) {
|
||||
H_29(state, unused, out_989002307071408312);
|
||||
void car_H_29(double *state, double *unused, double *out_3079521799437819656) {
|
||||
H_29(state, unused, out_3079521799437819656);
|
||||
}
|
||||
void car_h_28(double *state, double *unused, double *out_1914000772745856672) {
|
||||
h_28(state, unused, out_1914000772745856672);
|
||||
void car_h_28(double *state, double *unused, double *out_6846547824895893173) {
|
||||
h_28(state, unused, out_6846547824895893173);
|
||||
}
|
||||
void car_H_28(double *state, double *unused, double *out_6071401324140938886) {
|
||||
H_28(state, unused, out_6071401324140938886);
|
||||
void car_H_28(double *state, double *unused, double *out_2002877217631710918) {
|
||||
H_28(state, unused, out_2002877217631710918);
|
||||
}
|
||||
void car_h_31(double *state, double *unused, double *out_8205050127743358283) {
|
||||
h_31(state, unused, out_8205050127743358283);
|
||||
void car_h_31(double *state, double *unused, double *out_3141445982834403942) {
|
||||
h_31(state, unused, out_3141445982834403942);
|
||||
}
|
||||
void car_H_31(double *state, double *unused, double *out_8385278031000456823) {
|
||||
H_31(state, unused, out_8385278031000456823);
|
||||
void car_H_31(double *state, double *unused, double *out_2729275364143627970) {
|
||||
H_31(state, unused, out_2729275364143627970);
|
||||
}
|
||||
void car_predict(double *in_x, double *in_P, double *in_Q, double dt) {
|
||||
predict(in_x, in_P, in_Q, dt);
|
||||
|
||||
@@ -9,27 +9,27 @@ void car_update_27(double *in_x, double *in_P, double *in_z, double *in_R, doubl
|
||||
void car_update_29(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
|
||||
void car_update_28(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
|
||||
void car_update_31(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
|
||||
void car_err_fun(double *nom_x, double *delta_x, double *out_3568804456057098654);
|
||||
void car_inv_err_fun(double *nom_x, double *true_x, double *out_1840397183166108031);
|
||||
void car_H_mod_fun(double *state, double *out_8921258435077713963);
|
||||
void car_f_fun(double *state, double dt, double *out_3277027219914288776);
|
||||
void car_F_fun(double *state, double dt, double *out_370955893725369602);
|
||||
void car_h_25(double *state, double *unused, double *out_8154090013633331696);
|
||||
void car_H_25(double *state, double *unused, double *out_8415923992877417251);
|
||||
void car_h_24(double *state, double *unused, double *out_7351280482288278166);
|
||||
void car_H_24(double *state, double *unused, double *out_8301956961654820296);
|
||||
void car_h_30(double *state, double *unused, double *out_4292406537204830044);
|
||||
void car_H_30(double *state, double *unused, double *out_1499233651385800496);
|
||||
void car_h_26(double *state, double *unused, double *out_7000316085453517212);
|
||||
void car_H_26(double *state, double *unused, double *out_6289316761958078141);
|
||||
void car_h_27(double *state, double *unused, double *out_3964284714812858416);
|
||||
void car_H_27(double *state, double *unused, double *out_3673996963186225407);
|
||||
void car_h_29(double *state, double *unused, double *out_3689090652528352527);
|
||||
void car_H_29(double *state, double *unused, double *out_989002307071408312);
|
||||
void car_h_28(double *state, double *unused, double *out_1914000772745856672);
|
||||
void car_H_28(double *state, double *unused, double *out_6071401324140938886);
|
||||
void car_h_31(double *state, double *unused, double *out_8205050127743358283);
|
||||
void car_H_31(double *state, double *unused, double *out_8385278031000456823);
|
||||
void car_err_fun(double *nom_x, double *delta_x, double *out_1972702472511725479);
|
||||
void car_inv_err_fun(double *nom_x, double *true_x, double *out_3741555659818717473);
|
||||
void car_H_mod_fun(double *state, double *out_4845788339544047954);
|
||||
void car_f_fun(double *state, double dt, double *out_4185306989729419910);
|
||||
void car_F_fun(double *state, double dt, double *out_8252178874365212967);
|
||||
void car_h_25(double *state, double *unused, double *out_4739826667919645243);
|
||||
void car_H_25(double *state, double *unused, double *out_2698629402266667542);
|
||||
void car_h_24(double *state, double *unused, double *out_6091047700113278923);
|
||||
void car_H_24(double *state, double *unused, double *out_2121692102389320721);
|
||||
void car_h_30(double *state, double *unused, double *out_7687552658275130204);
|
||||
void car_H_30(double *state, double *unused, double *out_2569290455123427472);
|
||||
void car_h_26(double *state, double *unused, double *out_7946639312164568029);
|
||||
void car_H_26(double *state, double *unused, double *out_1042873916607388682);
|
||||
void car_h_27(double *state, double *unused, double *out_3665830151724581410);
|
||||
void car_H_27(double *state, double *unused, double *out_394527143323002561);
|
||||
void car_h_29(double *state, double *unused, double *out_8290868542951607721);
|
||||
void car_H_29(double *state, double *unused, double *out_3079521799437819656);
|
||||
void car_h_28(double *state, double *unused, double *out_6846547824895893173);
|
||||
void car_H_28(double *state, double *unused, double *out_2002877217631710918);
|
||||
void car_h_31(double *state, double *unused, double *out_3141445982834403942);
|
||||
void car_H_31(double *state, double *unused, double *out_2729275364143627970);
|
||||
void car_predict(double *in_x, double *in_P, double *in_Q, double dt);
|
||||
void car_set_mass(double x);
|
||||
void car_set_rotational_inertia(double x);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,18 +5,18 @@ void pose_update_4(double *in_x, double *in_P, double *in_z, double *in_R, doubl
|
||||
void pose_update_10(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
|
||||
void pose_update_13(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
|
||||
void pose_update_14(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
|
||||
void pose_err_fun(double *nom_x, double *delta_x, double *out_3667758909157266385);
|
||||
void pose_inv_err_fun(double *nom_x, double *true_x, double *out_3255008687637156165);
|
||||
void pose_H_mod_fun(double *state, double *out_1678148223451849404);
|
||||
void pose_f_fun(double *state, double dt, double *out_4390690219844123460);
|
||||
void pose_F_fun(double *state, double dt, double *out_5251920544283288288);
|
||||
void pose_h_4(double *state, double *unused, double *out_2086181486544094617);
|
||||
void pose_H_4(double *state, double *unused, double *out_141550502454447457);
|
||||
void pose_h_10(double *state, double *unused, double *out_2304974017593414723);
|
||||
void pose_H_10(double *state, double *unused, double *out_521311265061217175);
|
||||
void pose_h_13(double *state, double *unused, double *out_6563098082746675966);
|
||||
void pose_H_13(double *state, double *unused, double *out_3070723322877885344);
|
||||
void pose_h_14(double *state, double *unused, double *out_4832039927491863335);
|
||||
void pose_H_14(double *state, double *unused, double *out_3821690353885037072);
|
||||
void pose_err_fun(double *nom_x, double *delta_x, double *out_867342344380239798);
|
||||
void pose_inv_err_fun(double *nom_x, double *true_x, double *out_2946458972277190645);
|
||||
void pose_H_mod_fun(double *state, double *out_8034808007713849348);
|
||||
void pose_f_fun(double *state, double dt, double *out_5448742405462655453);
|
||||
void pose_F_fun(double *state, double dt, double *out_582733379073092242);
|
||||
void pose_h_4(double *state, double *unused, double *out_959952002277923346);
|
||||
void pose_H_4(double *state, double *unused, double *out_1467574399937880926);
|
||||
void pose_h_10(double *state, double *unused, double *out_315403293584823803);
|
||||
void pose_H_10(double *state, double *unused, double *out_2334763542090568144);
|
||||
void pose_h_13(double *state, double *unused, double *out_5013407308002664142);
|
||||
void pose_H_13(double *state, double *unused, double *out_4679848225270213727);
|
||||
void pose_h_14(double *state, double *unused, double *out_6338305732819674146);
|
||||
void pose_H_14(double *state, double *unused, double *out_1615214032357491370);
|
||||
void pose_predict(double *in_x, double *in_P, double *in_Q, double dt);
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import atexit
|
||||
import os
|
||||
import pickle
|
||||
import time
|
||||
from collections import defaultdict, namedtuple
|
||||
from functools import partial
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def _patch_tinygrad_fetch_fw():
|
||||
import hashlib
|
||||
import pathlib
|
||||
|
||||
import zstandard
|
||||
from tinygrad import helpers
|
||||
|
||||
original_fetch_fw = getattr(helpers, "fetch_fw", None)
|
||||
if original_fetch_fw is None:
|
||||
return
|
||||
|
||||
def fetch_fw(path, name, sha256):
|
||||
firmware_path = pathlib.Path(f"/lib/firmware/{path}/{name}.zst")
|
||||
if firmware_path.is_file():
|
||||
blob = zstandard.ZstdDecompressor().stream_reader(firmware_path.read_bytes()).read()
|
||||
if hashlib.sha256(blob).hexdigest() == sha256:
|
||||
return blob
|
||||
return original_fetch_fw(path, name, sha256)
|
||||
|
||||
helpers.fetch_fw = fetch_fw
|
||||
|
||||
|
||||
_patch_tinygrad_fetch_fw()
|
||||
|
||||
from tinygrad.device import Device
|
||||
from tinygrad.engine.jit import TinyJit
|
||||
from tinygrad.helpers import Context
|
||||
from tinygrad.tensor import Tensor
|
||||
|
||||
|
||||
NV12Frame = namedtuple("NV12Frame", ["width", "height", "stride", "y_height", "uv_height", "size"])
|
||||
WARP_INPUTS = ["img_q", "big_img_q", "tfm", "big_tfm"]
|
||||
POLICY_INPUTS = ["feat_q", "desire_q", "desire", "traffic_convention", "action_t"]
|
||||
|
||||
WARP_DEV = os.getenv("WARP_DEV")
|
||||
|
||||
|
||||
def make_random_images(keys, shape, device=None):
|
||||
return {key: Tensor.randint(shape, low=0, high=256, dtype="uint8", device=device).realize() for key in keys}
|
||||
|
||||
|
||||
class _BlobTensorInputs(dict):
|
||||
_backing_arrays: dict[str, np.ndarray]
|
||||
|
||||
|
||||
def make_random_blob_images(keys, shape, device=None):
|
||||
blob_shape = shape if isinstance(shape, tuple) else (shape,)
|
||||
backing_arrays = {
|
||||
key: np.random.randint(0, 256, size=blob_shape, dtype=np.uint8)
|
||||
for key in keys
|
||||
}
|
||||
inputs = _BlobTensorInputs({
|
||||
key: Tensor.from_blob(array.ctypes.data, array.shape, dtype="uint8", device=device).realize()
|
||||
for key, array in backing_arrays.items()
|
||||
})
|
||||
# Keep the numpy storage alive for the duration of the JIT capture/replay call.
|
||||
inputs._backing_arrays = backing_arrays
|
||||
return inputs
|
||||
|
||||
|
||||
def warp_perspective_tinygrad(src_flat, matrix_inverse, dst_shape, src_shape, stride_pad, border_fill_val=None):
|
||||
width_dst, height_dst = dst_shape
|
||||
height_src, width_src = src_shape
|
||||
|
||||
x = Tensor.arange(width_dst, device=WARP_DEV).reshape(1, width_dst).expand(height_dst, width_dst).reshape(-1)
|
||||
y = Tensor.arange(height_dst, device=WARP_DEV).reshape(height_dst, 1).expand(height_dst, width_dst).reshape(-1)
|
||||
|
||||
# Inline 3x3 matmul as elementwise to avoid reduce ops and enable fusion with gather.
|
||||
src_x = matrix_inverse[0, 0] * x + matrix_inverse[0, 1] * y + matrix_inverse[0, 2]
|
||||
src_y = matrix_inverse[1, 0] * x + matrix_inverse[1, 1] * y + matrix_inverse[1, 2]
|
||||
src_w = matrix_inverse[2, 0] * x + matrix_inverse[2, 1] * y + matrix_inverse[2, 2]
|
||||
|
||||
src_x = src_x / src_w
|
||||
src_y = src_y / src_w
|
||||
|
||||
x_round = Tensor.round(src_x)
|
||||
y_round = Tensor.round(src_y)
|
||||
x_nn_clipped = x_round.clip(0, width_src - 1).cast("int")
|
||||
y_nn_clipped = y_round.clip(0, height_src - 1).cast("int")
|
||||
idx = y_nn_clipped * (width_src + stride_pad) + x_nn_clipped
|
||||
sampled = src_flat[idx]
|
||||
|
||||
if border_fill_val is None:
|
||||
return sampled
|
||||
|
||||
in_bounds = ((x_round >= 0) & (x_round <= width_src - 1) &
|
||||
(y_round >= 0) & (y_round <= height_src - 1)).cast(sampled.dtype)
|
||||
return sampled * in_bounds + Tensor(border_fill_val, dtype=sampled.dtype) * (1 - in_bounds)
|
||||
|
||||
|
||||
def frames_to_tensor(frames):
|
||||
height = (frames.shape[0] * 2) // 3
|
||||
width = frames.shape[1]
|
||||
return Tensor.cat(
|
||||
frames[0:height:2, 0::2],
|
||||
frames[1:height:2, 0::2],
|
||||
frames[0:height:2, 1::2],
|
||||
frames[1:height:2, 1::2],
|
||||
frames[height:height + height // 4].reshape((height // 2, width // 2)),
|
||||
frames[height + height // 4:height + height // 2].reshape((height // 2, width // 2)),
|
||||
dim=0,
|
||||
).reshape((6, height // 2, width // 2))
|
||||
|
||||
|
||||
def make_frame_prepare(nv12: NV12Frame, model_w, model_h):
|
||||
cam_w, cam_h, stride, y_height, uv_height, _ = nv12
|
||||
uv_offset = stride * y_height
|
||||
stride_pad = stride - cam_w
|
||||
|
||||
def frame_prepare_tinygrad(input_frame, matrix_inverse):
|
||||
# UV_SCALE @ M_inv @ UV_SCALE_INV simplifies to elementwise scaling.
|
||||
matrix_inverse_uv = matrix_inverse * Tensor([[1.0, 1.0, 0.5], [1.0, 1.0, 0.5], [2.0, 2.0, 1.0]], device=WARP_DEV)
|
||||
# Deinterleave NV12 UV plane (UVUV... -> separate U, V).
|
||||
uv = input_frame[uv_offset:uv_offset + uv_height * stride].reshape(uv_height, stride)
|
||||
with Context(SPLIT_REDUCEOP=0):
|
||||
y = warp_perspective_tinygrad(
|
||||
input_frame[:cam_h * stride],
|
||||
matrix_inverse,
|
||||
(model_w, model_h),
|
||||
(cam_h, cam_w),
|
||||
stride_pad,
|
||||
).realize()
|
||||
u = warp_perspective_tinygrad(
|
||||
uv[:cam_h // 2, :cam_w:2].flatten(),
|
||||
matrix_inverse_uv,
|
||||
(model_w // 2, model_h // 2),
|
||||
(cam_h // 2, cam_w // 2),
|
||||
0,
|
||||
).realize()
|
||||
v = warp_perspective_tinygrad(
|
||||
uv[:cam_h // 2, 1:cam_w:2].flatten(),
|
||||
matrix_inverse_uv,
|
||||
(model_w // 2, model_h // 2),
|
||||
(cam_h // 2, cam_w // 2),
|
||||
0,
|
||||
).realize()
|
||||
yuv = y.cat(u).cat(v).reshape((model_h * 3 // 2, model_w))
|
||||
return frames_to_tensor(yuv)
|
||||
|
||||
return frame_prepare_tinygrad
|
||||
|
||||
|
||||
def make_tensor_inputs(vision_input_shapes, policy_input_shapes, frame_skip, device):
|
||||
img = vision_input_shapes["img"]
|
||||
n_frames = img[1] // 6
|
||||
img_buf_shape = (frame_skip * (n_frames - 1) + 1, 6, img[2], img[3])
|
||||
|
||||
features_buffer = policy_input_shapes["features_buffer"]
|
||||
desire_pulse = policy_input_shapes["desire_pulse"]
|
||||
|
||||
return {
|
||||
"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 * (features_buffer[1] - 1) + 1, features_buffer[0], features_buffer[2]), dtype=np.float32),
|
||||
device=device,
|
||||
).contiguous().realize(),
|
||||
"desire_q": Tensor(
|
||||
np.zeros((frame_skip * desire_pulse[1], desire_pulse[0], desire_pulse[2]), dtype=np.float32),
|
||||
device=device,
|
||||
).contiguous().realize(),
|
||||
}
|
||||
|
||||
|
||||
def make_npy_inputs(policy_input_shapes):
|
||||
desire_pulse = policy_input_shapes["desire_pulse"]
|
||||
traffic_convention = policy_input_shapes["traffic_convention"]
|
||||
|
||||
npy = {
|
||||
"desire": np.zeros(desire_pulse[2], dtype=np.float32),
|
||||
"traffic_convention": np.zeros(traffic_convention, dtype=np.float32),
|
||||
"tfm": np.zeros((3, 3), dtype=np.float32),
|
||||
"big_tfm": np.zeros((3, 3), dtype=np.float32),
|
||||
}
|
||||
if "action_t" in policy_input_shapes:
|
||||
npy["action_t"] = np.zeros(policy_input_shapes["action_t"], dtype=np.float32)
|
||||
npy_tensors = {key: Tensor(value, device="NPY").realize() for key, value in npy.items()}
|
||||
return npy, npy_tensors
|
||||
|
||||
|
||||
def make_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, device):
|
||||
tensor_inputs = make_tensor_inputs(vision_input_shapes, policy_input_shapes, frame_skip, device)
|
||||
npy, npy_tensors = make_npy_inputs(policy_input_shapes)
|
||||
return {**tensor_inputs, **npy_tensors}, npy
|
||||
|
||||
|
||||
def shift_and_sample(buf, new_val, sample_fn):
|
||||
buf.assign(buf[1:].cat(new_val, dim=0).contiguous())
|
||||
return sample_fn(buf)
|
||||
|
||||
|
||||
def sample_skip(buf, frame_skip):
|
||||
return buf[::frame_skip].contiguous().flatten(0, 1).unsqueeze(0)
|
||||
|
||||
|
||||
def sample_desire(buf, frame_skip):
|
||||
return buf.reshape(-1, frame_skip, *buf.shape[1:]).max(1).flatten(0, 1).unsqueeze(0)
|
||||
|
||||
|
||||
def make_warp(nv12, model_w, model_h, frame_skip):
|
||||
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
|
||||
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
|
||||
|
||||
def warp_enqueue(img_q, big_img_q, tfm, big_tfm, frame, big_frame):
|
||||
tfm = tfm.to(WARP_DEV)
|
||||
big_tfm = big_tfm.to(WARP_DEV)
|
||||
Tensor.realize(tfm, big_tfm)
|
||||
|
||||
warped_frame = frame_prepare(frame, tfm).unsqueeze(0).to(Device.DEFAULT)
|
||||
warped_big_frame = frame_prepare(big_frame, big_tfm).unsqueeze(0).to(Device.DEFAULT)
|
||||
img = shift_and_sample(img_q, warped_frame, sample_skip_fn)
|
||||
big_img = shift_and_sample(big_img_q, warped_big_frame, sample_skip_fn)
|
||||
return img, big_img
|
||||
|
||||
return warp_enqueue
|
||||
|
||||
|
||||
def make_run_policy(vision_runner, off_policy_runner, on_policy_runner, vision_features_slice, frame_skip):
|
||||
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
|
||||
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
|
||||
|
||||
def run_policy(img, big_img, feat_q, desire_q, desire, traffic_convention, action_t):
|
||||
desire = desire.to(Device.DEFAULT)
|
||||
traffic_convention = traffic_convention.to(Device.DEFAULT)
|
||||
action_t = action_t.to(Device.DEFAULT)
|
||||
Tensor.realize(desire, traffic_convention, action_t)
|
||||
|
||||
desire_buf = shift_and_sample(desire_q, desire.reshape(1, 1, -1), sample_desire_fn)
|
||||
vision_out = next(iter(vision_runner({"img": img, "big_img": 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)
|
||||
|
||||
inputs = {
|
||||
"features_buffer": feat_buf,
|
||||
"desire_pulse": desire_buf,
|
||||
"traffic_convention": traffic_convention,
|
||||
"action_t": action_t,
|
||||
}
|
||||
on_policy_out = next(iter(on_policy_runner(inputs).values())).cast("float32")
|
||||
off_policy_out = next(iter(off_policy_runner(inputs).values())).cast("float32")
|
||||
return vision_out, on_policy_out, off_policy_out
|
||||
|
||||
return run_policy
|
||||
|
||||
|
||||
def compile_jit(jit, make_random_inputs, input_keys, frame_skip, vision_metadata, policy_metadata):
|
||||
vision_input_shapes = vision_metadata["input_shapes"]
|
||||
policy_input_shapes = policy_metadata["input_shapes"]
|
||||
|
||||
seed = 42
|
||||
validation_rtol = 5e-3 if Device.DEFAULT == "QCOM" else 0.0
|
||||
validation_atol = 5e-3 if Device.DEFAULT == "QCOM" else 0.0
|
||||
|
||||
def arrays_match(lhs, rhs):
|
||||
if lhs.shape != rhs.shape:
|
||||
return False
|
||||
if np.issubdtype(lhs.dtype, np.floating) or np.issubdtype(rhs.dtype, np.floating):
|
||||
return np.allclose(lhs, rhs, rtol=validation_rtol, atol=validation_atol, equal_nan=True)
|
||||
return np.array_equal(lhs, rhs)
|
||||
|
||||
def random_inputs_run(fn, current_seed, test_val=None, test_buffers=None, expect_match=True):
|
||||
input_queues, npy = make_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, Device.DEFAULT)
|
||||
np.random.seed(current_seed)
|
||||
Tensor.manual_seed(current_seed)
|
||||
|
||||
testing = test_val is not None or test_buffers is not None
|
||||
n_runs = 1 if testing else 3
|
||||
|
||||
for idx in range(n_runs):
|
||||
for value in npy.values():
|
||||
value[:] = np.random.randn(*value.shape).astype(value.dtype)
|
||||
Device.default.synchronize()
|
||||
random_inputs = make_random_inputs()
|
||||
start = time.perf_counter()
|
||||
outs = fn(**{key: input_queues[key] for key in input_keys}, **random_inputs)
|
||||
mid = time.perf_counter()
|
||||
Device.default.synchronize()
|
||||
end = time.perf_counter()
|
||||
print(f" [{idx + 1}/{n_runs}] enqueue {(mid - start) * 1e3:6.2f} ms -- total {(end - start) * 1e3:6.2f} ms")
|
||||
|
||||
if idx == 0:
|
||||
val = [np.copy(value.numpy()) for value in outs]
|
||||
buffers = [np.copy(value.numpy().copy()) for value in input_queues.values()]
|
||||
|
||||
if Device.DEFAULT != "QCOM":
|
||||
if test_val is not None:
|
||||
match = all(arrays_match(lhs, rhs) for lhs, rhs in zip(val, test_val, strict=True))
|
||||
assert match == expect_match, f"outputs {'differ from' if expect_match else 'match'} baseline (seed={current_seed})"
|
||||
if test_buffers is not None:
|
||||
match = all(arrays_match(lhs, rhs) for lhs, rhs in zip(buffers, test_buffers, strict=True))
|
||||
assert match == expect_match, f"buffers {'differ from' if expect_match else 'match'} baseline (seed={current_seed})"
|
||||
return val, buffers
|
||||
|
||||
print("capture + replay")
|
||||
test_val, test_buffers = random_inputs_run(jit, seed)
|
||||
print("pickle round trip")
|
||||
jit = pickle.loads(pickle.dumps(jit))
|
||||
random_inputs_run(jit, seed, test_val, test_buffers, expect_match=True)
|
||||
random_inputs_run(jit, seed + 1, test_val, test_buffers, expect_match=False)
|
||||
return jit
|
||||
|
||||
|
||||
def _parse_size(size):
|
||||
width, height = size.lower().split("x")
|
||||
return int(width), int(height)
|
||||
|
||||
|
||||
def read_file_chunked_to_shm(path):
|
||||
from openpilot.common.file_chunker import read_file_chunked
|
||||
from openpilot.system.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 f:
|
||||
f.write(read_file_chunked(path))
|
||||
return shm_path
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from tinygrad.nn.onnx import OnnxRunner
|
||||
from openpilot.selfdrive.modeld.get_model_metadata import make_metadata_dict
|
||||
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
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, help="camera resolutions WxH (one or more)")
|
||||
parser.add_argument("--vision-onnx", required=True)
|
||||
parser.add_argument("--off-policy-onnx", required=True)
|
||||
parser.add_argument("--on-policy-onnx", required=True)
|
||||
parser.add_argument("--output", required=True)
|
||||
parser.add_argument("--frame-skip", type=int, required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
out = defaultdict(dict)
|
||||
vision_path = read_file_chunked_to_shm(args.vision_onnx)
|
||||
off_policy_path = read_file_chunked_to_shm(args.off_policy_onnx)
|
||||
on_policy_path = read_file_chunked_to_shm(args.on_policy_onnx)
|
||||
model_w, model_h = args.model_size
|
||||
|
||||
vision_runner = OnnxRunner(vision_path)
|
||||
off_policy_runner = OnnxRunner(off_policy_path)
|
||||
on_policy_runner = OnnxRunner(on_policy_path)
|
||||
vision_metadata = make_metadata_dict(vision_path)
|
||||
off_policy_metadata = make_metadata_dict(off_policy_path)
|
||||
on_policy_metadata = make_metadata_dict(on_policy_path)
|
||||
assert off_policy_metadata["input_shapes"] == on_policy_metadata["input_shapes"]
|
||||
|
||||
run_policy_jit = TinyJit(
|
||||
make_run_policy(
|
||||
vision_runner,
|
||||
off_policy_runner,
|
||||
on_policy_runner,
|
||||
vision_metadata["output_slices"]["hidden_state"],
|
||||
args.frame_skip,
|
||||
),
|
||||
prune=True,
|
||||
)
|
||||
|
||||
out["metadata"]["vision"] = vision_metadata
|
||||
out["metadata"]["off_policy"] = off_policy_metadata
|
||||
out["metadata"]["on_policy"] = on_policy_metadata
|
||||
out["tensor_inputs"] = make_tensor_inputs(vision_metadata["input_shapes"], on_policy_metadata["input_shapes"], args.frame_skip, Device.DEFAULT)
|
||||
|
||||
make_random_model_inputs = partial(make_random_images, keys=["img", "big_img"], shape=vision_metadata["input_shapes"]["img"])
|
||||
out["run_policy"] = compile_jit(run_policy_jit, make_random_model_inputs, POLICY_INPUTS, args.frame_skip, vision_metadata, on_policy_metadata)
|
||||
|
||||
for cam_w, cam_h in args.camera_resolutions:
|
||||
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
|
||||
# Capture warp against blob-backed frames so the JIT ABI matches runtime VisionBuf inputs.
|
||||
make_random_warp_inputs = partial(make_random_blob_images, keys=["frame", "big_frame"], shape=nv12.size, device=WARP_DEV)
|
||||
warp_enqueue = TinyJit(make_warp(nv12, model_w, model_h, args.frame_skip), prune=True)
|
||||
out[(cam_w, cam_h)] = compile_jit(warp_enqueue, make_random_warp_inputs, WARP_INPUTS, args.frame_skip, vision_metadata, on_policy_metadata)
|
||||
|
||||
with open(args.output, "wb") as f:
|
||||
pickle.dump(out, f)
|
||||
print(f"Saved JITs to {args.output} ({os.path.getsize(args.output) / 1e6:.2f} MB)")
|
||||
@@ -66,7 +66,7 @@ def dm_warp_pkl_path(w, h):
|
||||
return MODELS_DIR / f'dm_warp_{w}x{h}_tinygrad.pkl'
|
||||
|
||||
|
||||
def warp_perspective_tinygrad(src_flat, M_inv, dst_shape, src_shape, stride_pad):
|
||||
def warp_perspective_tinygrad(src_flat, M_inv, dst_shape, src_shape, stride_pad, border_fill_val=None):
|
||||
w_dst, h_dst = dst_shape
|
||||
h_src, w_src = src_shape
|
||||
|
||||
@@ -81,11 +81,19 @@ def warp_perspective_tinygrad(src_flat, M_inv, dst_shape, src_shape, stride_pad)
|
||||
src_x = src_x / src_w
|
||||
src_y = src_y / src_w
|
||||
|
||||
x_nn_clipped = Tensor.round(src_x).clip(0, w_src - 1).cast('int')
|
||||
y_nn_clipped = Tensor.round(src_y).clip(0, h_src - 1).cast('int')
|
||||
x_round = Tensor.round(src_x)
|
||||
y_round = Tensor.round(src_y)
|
||||
x_nn_clipped = x_round.clip(0, w_src - 1).cast('int')
|
||||
y_nn_clipped = y_round.clip(0, h_src - 1).cast('int')
|
||||
idx = y_nn_clipped * (w_src + stride_pad) + x_nn_clipped
|
||||
|
||||
return src_flat[idx]
|
||||
sampled = src_flat[idx]
|
||||
if border_fill_val is None:
|
||||
return sampled
|
||||
|
||||
in_bounds = ((x_round >= 0) & (x_round <= w_src - 1) &
|
||||
(y_round >= 0) & (y_round <= h_src - 1)).cast(sampled.dtype)
|
||||
return sampled * in_bounds + Tensor(border_fill_val, dtype=sampled.dtype) * (1 - in_bounds)
|
||||
|
||||
|
||||
def frames_to_tensor(frames, model_w, model_h):
|
||||
@@ -152,7 +160,9 @@ def make_warp_dm(cam_w, cam_h, dm_w, dm_h):
|
||||
|
||||
def warp_dm(input_frame, M_inv):
|
||||
M_inv = M_inv.to(Device.DEFAULT)
|
||||
result = warp_perspective_tinygrad(input_frame[:cam_h*stride], M_inv, (dm_w, dm_h), (cam_h, cam_w), stride_pad).reshape(-1, dm_h * dm_w)
|
||||
result = warp_perspective_tinygrad(
|
||||
input_frame[:cam_h*stride], M_inv, (dm_w, dm_h), (cam_h, cam_w), stride_pad, border_fill_val=16
|
||||
).reshape(-1, dm_h * dm_w)
|
||||
return result
|
||||
return warp_dm
|
||||
|
||||
|
||||
@@ -80,6 +80,11 @@ def parse_model_output(model_output):
|
||||
parsed[f'face_descs_{ds_suffix}_std'] = safe_exp(face_descs[:, -6:])
|
||||
for key in ['face_prob', 'left_eye_prob', 'right_eye_prob', 'left_blink_prob', 'right_blink_prob', 'sunglasses_prob', 'using_phone_prob']:
|
||||
parsed[f'{key}_{ds_suffix}'] = sigmoid(model_output[f'{key}_{ds_suffix}'])
|
||||
sleep_key = f'sleep_prob_{ds_suffix}'
|
||||
if sleep_key in model_output:
|
||||
parsed[sleep_key] = sigmoid(model_output[sleep_key])
|
||||
else:
|
||||
parsed[sleep_key] = np.zeros((1, 1), dtype=np.float32)
|
||||
return parsed
|
||||
|
||||
|
||||
@@ -95,6 +100,7 @@ def fill_driver_data(msg, model_output, ds_suffix):
|
||||
msg.rightBlinkProb = model_output[f'right_blink_prob_{ds_suffix}'][0, 0].item()
|
||||
msg.sunglassesProb = model_output[f'sunglasses_prob_{ds_suffix}'][0, 0].item()
|
||||
msg.phoneProb = model_output[f'using_phone_prob_{ds_suffix}'][0, 0].item()
|
||||
msg.sleepProb = model_output[f'sleep_prob_{ds_suffix}'][0, 0].item()
|
||||
|
||||
|
||||
def get_driverstate_packet(model_output, frame_id: int, location_ts: int, exec_time: float, gpu_exec_time: float):
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import pathlib
|
||||
import onnx
|
||||
import codecs
|
||||
import pickle
|
||||
import pathlib
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
import onnx
|
||||
|
||||
def get_name_and_shape(value_info:onnx.ValueInfoProto) -> tuple[str, tuple[int,...]]:
|
||||
shape = tuple([int(dim.dim_value) for dim in value_info.type.tensor_type.shape.dim])
|
||||
name = value_info.name
|
||||
@@ -17,19 +18,23 @@ def get_metadata_value_by_name(model:onnx.ModelProto, name:str) -> str | Any:
|
||||
return prop.value
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
model_path = pathlib.Path(sys.argv[1])
|
||||
|
||||
def make_metadata_dict(model_path: str | pathlib.Path) -> dict[str, Any]:
|
||||
model = onnx.load(str(model_path))
|
||||
output_slices = get_metadata_value_by_name(model, 'output_slices')
|
||||
assert output_slices is not None, 'output_slices not found in metadata'
|
||||
|
||||
metadata = {
|
||||
return {
|
||||
'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])
|
||||
'output_shapes': dict([get_name_and_shape(x) for x in model.graph.output]),
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
model_path = pathlib.Path(sys.argv[1])
|
||||
metadata = make_metadata_dict(model_path)
|
||||
|
||||
metadata_path = model_path.parent / (model_path.stem + '_metadata.pkl')
|
||||
with open(metadata_path, 'wb') as f:
|
||||
pickle.dump(metadata, f)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from tinygrad.device import Device
|
||||
|
||||
MODELS_DIR = Path(__file__).resolve().parent / "models"
|
||||
TG_INPUT_DEVICES_PATH = MODELS_DIR / "tg_input_devices.json"
|
||||
USBGPU_VID = 0xADD1
|
||||
USBGPU_PID = 0x0001
|
||||
|
||||
|
||||
def _default_tinygrad_backend() -> str:
|
||||
env_dev = os.getenv("DEV", "").strip()
|
||||
if env_dev:
|
||||
return env_dev.split(":", 1)[0].split("+", 1)[-1] or env_dev
|
||||
|
||||
try:
|
||||
default = Device.DEFAULT
|
||||
except Exception:
|
||||
default = ""
|
||||
|
||||
if isinstance(default, str) and default:
|
||||
return default.split(":", 1)[0].split("+", 1)[-1] or default
|
||||
return "QCOM" if Path("/dev/kgsl-3d0").exists() else "CPU"
|
||||
|
||||
|
||||
def _load_tg_devices() -> dict:
|
||||
if not TG_INPUT_DEVICES_PATH.is_file():
|
||||
return {}
|
||||
with open(TG_INPUT_DEVICES_PATH) as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def _fallback_tg_devices(process_name: str, usbgpu: bool) -> dict[str, str]:
|
||||
backend = _default_tinygrad_backend()
|
||||
if process_name == "selfdrive.modeld.dmonitoringmodeld":
|
||||
return {"DEV": backend}
|
||||
|
||||
queue_dev = backend
|
||||
if usbgpu:
|
||||
try:
|
||||
available = {name.split(":", 1)[0] for name in Device.get_available_devices()}
|
||||
except Exception:
|
||||
available = set()
|
||||
if "AMD" in available:
|
||||
queue_dev = "AMD"
|
||||
return {"WARP_DEV": backend, "QUEUE_DEV": queue_dev}
|
||||
|
||||
|
||||
def get_tg_input_devices(process_name: str, usbgpu: bool) -> dict[str, str]:
|
||||
tg_devices = _load_tg_devices()
|
||||
process_devices = tg_devices.get(process_name, {})
|
||||
profile = "usbgpu" if usbgpu else "default"
|
||||
if profile in process_devices:
|
||||
return process_devices[profile]
|
||||
return _fallback_tg_devices(process_name, usbgpu)
|
||||
|
||||
|
||||
def modeld_pkl_path(usbgpu: bool):
|
||||
prefix = "big_" if usbgpu else ""
|
||||
return MODELS_DIR / f"{prefix}driving_tinygrad.pkl"
|
||||
|
||||
|
||||
def usbgpu_present() -> bool:
|
||||
for d in Path("/sys/bus/usb/devices").glob("*"):
|
||||
try:
|
||||
if int((d / "idVendor").read_text(), 16) == USBGPU_VID and \
|
||||
int((d / "idProduct").read_text(), 16) == USBGPU_PID:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
@@ -28,6 +28,11 @@ from openpilot.selfdrive.modeld.fill_model_msg import fill_model_msg, fill_pose_
|
||||
from openpilot.selfdrive.modeld.constants import ModelConstants, Plan
|
||||
from openpilot.selfdrive.modeld.models.commonmodel_pyx import DrivingModelFrame, CLContext
|
||||
from openpilot.selfdrive.modeld.runners.tinygrad_helpers import qcom_tensor_from_opencl_address
|
||||
from openpilot.starpilot.common.model_versions import (
|
||||
is_tinygrad_model_version,
|
||||
uses_combined_driving_artifacts,
|
||||
uses_split_off_policy_artifacts,
|
||||
)
|
||||
from openpilot.starpilot.common.starpilot_variables import get_starpilot_toggles, MODELS_PATH, params_memory
|
||||
|
||||
|
||||
@@ -309,7 +314,7 @@ class ModelState:
|
||||
self.is_v14 = (self.policy_generation == "v14")
|
||||
self.is_v15 = (self.policy_generation == "v15")
|
||||
self.is_v9 = (self.policy_generation == "v9")
|
||||
self.mlsim = (self.policy_generation in ("v8", "v10", "v11", "v12", "v13", "v14", "v15"))
|
||||
self.mlsim = is_tinygrad_model_version(self.policy_generation)
|
||||
self.policy_has_plan = 'plan' in self.policy_output_slices
|
||||
|
||||
self.frames = {name: DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP) for name in self.vision_input_names}
|
||||
@@ -334,7 +339,7 @@ class ModelState:
|
||||
self.off_policy_output: np.ndarray | None = None
|
||||
|
||||
off_policy_metadata = None
|
||||
if self.policy_generation in ("v12", "v13", "v14", "v15") or OFF_POLICY_METADATA_PATH.is_file() or OFF_POLICY_PKL_PATH.is_file():
|
||||
if uses_split_off_policy_artifacts(self.policy_generation) or OFF_POLICY_METADATA_PATH.is_file() or OFF_POLICY_PKL_PATH.is_file():
|
||||
resolved_off_policy_meta = ensure_artifact(OFF_POLICY_METADATA_PATH, "driving_off_policy_metadata.pkl", optional=True)
|
||||
if resolved_off_policy_meta is not None:
|
||||
with open(resolved_off_policy_meta, 'rb') as f:
|
||||
@@ -453,14 +458,14 @@ class ModelState:
|
||||
self.full_prev_desired_curv[0,-1,:] = policy_outputs_dict['desired_curvature'][0, :]
|
||||
|
||||
if self.prev_desired_curv_key is not None:
|
||||
# v9/v10/v11/v12/v13/v14/v15 models expect zeros for prev_desired_curv(s); others use history
|
||||
if self.is_v9 or self.is_v10 or self.is_v11 or self.is_v12 or self.is_v13 or self.is_v14 or self.is_v15:
|
||||
# Tinygrad-era policy models expect zeros for prev_desired_curv(s); older ones use history.
|
||||
if is_tinygrad_model_version(self.policy_generation):
|
||||
self.numpy_inputs[self.prev_desired_curv_key][:] = 0 * self.full_prev_desired_curv[0, self.temporal_idxs]
|
||||
else:
|
||||
self.numpy_inputs[self.prev_desired_curv_key][:] = self.full_prev_desired_curv[0, self.temporal_idxs]
|
||||
|
||||
if self.off_policy_enabled and self.off_policy_prev_desired_curv_key is not None:
|
||||
if self.is_v9 or self.is_v12 or self.is_v13 or self.is_v14 or self.is_v15:
|
||||
if self.is_v9 or uses_split_off_policy_artifacts(self.policy_generation) or uses_combined_driving_artifacts(self.policy_generation):
|
||||
self.off_policy_numpy_inputs[self.off_policy_prev_desired_curv_key][:] = 0 * self.full_prev_desired_curv[0, self.temporal_idxs]
|
||||
else:
|
||||
self.off_policy_numpy_inputs[self.off_policy_prev_desired_curv_key][:] = self.full_prev_desired_curv[0, self.temporal_idxs]
|
||||
@@ -486,6 +491,13 @@ class ModelState:
|
||||
|
||||
|
||||
def main(demo=False):
|
||||
params = Params()
|
||||
selected_version = _resolve_mirrored_param(params, "ModelVersion", "DrivingModelVersion")
|
||||
if uses_combined_driving_artifacts(selected_version):
|
||||
from openpilot.selfdrive.modeld.modeld_v16 import main as combined_main
|
||||
|
||||
return combined_main(demo=demo)
|
||||
|
||||
cloudlog.warning("modeld init")
|
||||
|
||||
sentry.set_tag("daemon", PROCESS_NAME)
|
||||
@@ -527,8 +539,6 @@ def main(demo=False):
|
||||
sm = SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "carControl", "liveDelay", "starpilotPlan"])
|
||||
|
||||
publish_state = PublishState()
|
||||
params = Params()
|
||||
|
||||
# setup filter to track dropped frames
|
||||
frame_dropped_filter = FirstOrderFilter(0., 10., 1. / ModelConstants.MODEL_FREQ)
|
||||
frame_id = 0
|
||||
|
||||
@@ -0,0 +1,459 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import pickle
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from openpilot.system.hardware import TICI
|
||||
|
||||
os.environ["GMMU"] = "0" # noop on qcom, improves load path when a USB GPU is present
|
||||
os.environ["DEV"] = "QCOM" if TICI else "LLVM"
|
||||
|
||||
import cereal.messaging as messaging
|
||||
import numpy as np
|
||||
from cereal import car, log
|
||||
from msgq.visionipc import VisionBuf, VisionIpcClient, VisionStreamType
|
||||
from opendbc.car.car_helpers import get_demo_car_params
|
||||
from setproctitle import setproctitle
|
||||
from tinygrad.tensor import Tensor
|
||||
|
||||
from openpilot.common.file_chunker import read_file_chunked
|
||||
from openpilot.common.filter_simple import FirstOrderFilter
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import DT_MDL, config_realtime_process
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
from openpilot.common.transformations.camera import DEVICE_CAMERAS
|
||||
from openpilot.common.transformations.model import get_warp_matrix
|
||||
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import smooth_value
|
||||
from openpilot.selfdrive.modeld.compile_modeld import POLICY_INPUTS, WARP_INPUTS, make_npy_inputs, make_tensor_inputs
|
||||
from openpilot.selfdrive.modeld.constants import ModelConstants
|
||||
from openpilot.selfdrive.modeld.fill_model_msg import PublishState, fill_model_msg, fill_pose_msg
|
||||
from openpilot.selfdrive.modeld.helpers import get_tg_input_devices
|
||||
from openpilot.selfdrive.modeld.parse_model_outputs import Parser
|
||||
from openpilot.starpilot.assets.model_manager import ModelManager
|
||||
from openpilot.starpilot.common.model_versions import uses_combined_driving_artifacts
|
||||
from openpilot.starpilot.common.starpilot_variables import MODELS_PATH, get_starpilot_toggles, params_memory
|
||||
from openpilot.system import sentry
|
||||
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
||||
|
||||
|
||||
PROCESS_NAME = "selfdrive.modeld.modeld"
|
||||
SEND_RAW_PRED = os.getenv("SEND_RAW_PRED")
|
||||
|
||||
BUILTIN_MODEL_KEY = "sc2"
|
||||
BUILTIN_MODEL_ALIASES = {BUILTIN_MODEL_KEY, "sc"}
|
||||
|
||||
LAT_SMOOTH_SECONDS = 0.0
|
||||
LONG_SMOOTH_SECONDS = 0.3
|
||||
MIN_LAT_CONTROL_SPEED = 0.3
|
||||
|
||||
|
||||
def _get_param_str(params: Params, key: str, default: str = "") -> str:
|
||||
try:
|
||||
value = params.get(key)
|
||||
except Exception:
|
||||
return default
|
||||
if value is None:
|
||||
return default
|
||||
if isinstance(value, bytes):
|
||||
try:
|
||||
return value.decode("utf-8")
|
||||
except Exception:
|
||||
return default
|
||||
if isinstance(value, (dict, list)):
|
||||
return default
|
||||
return str(value)
|
||||
|
||||
|
||||
def _get_default_param_str(params: Params, key: str) -> str:
|
||||
try:
|
||||
value = params.get_default_value(key)
|
||||
except Exception:
|
||||
return ""
|
||||
if value is None:
|
||||
return ""
|
||||
if isinstance(value, bytes):
|
||||
try:
|
||||
return value.decode("utf-8")
|
||||
except Exception:
|
||||
return ""
|
||||
return str(value)
|
||||
|
||||
|
||||
def _resolve_mirrored_param(params: Params, primary_key: str, secondary_key: str) -> str:
|
||||
primary_val = _get_param_str(params, primary_key).strip()
|
||||
secondary_val = _get_param_str(params, secondary_key).strip()
|
||||
if primary_val == secondary_val:
|
||||
return secondary_val or primary_val
|
||||
|
||||
primary_default = _get_default_param_str(params, primary_key).strip()
|
||||
secondary_default = _get_default_param_str(params, secondary_key).strip()
|
||||
primary_non_default = bool(primary_val) and primary_val != primary_default
|
||||
secondary_non_default = bool(secondary_val) and secondary_val != secondary_default
|
||||
|
||||
if secondary_non_default:
|
||||
return secondary_val
|
||||
if primary_non_default:
|
||||
return primary_val
|
||||
return secondary_val or primary_val
|
||||
|
||||
|
||||
def _canonical_model_id(model_id: str) -> str:
|
||||
key = (model_id or "").strip().lower()
|
||||
return BUILTIN_MODEL_KEY if key in BUILTIN_MODEL_ALIASES else key
|
||||
|
||||
|
||||
def _combined_model_path(model_id: str, use_builtin_model: bool) -> Path:
|
||||
if use_builtin_model:
|
||||
return Path(__file__).parent / "models" / "driving_tinygrad.pkl"
|
||||
return MODELS_PATH / f"{model_id}_driving_tinygrad.pkl"
|
||||
|
||||
|
||||
def get_action_from_model(model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action, v_ego: float) -> log.ModelDataV2.Action:
|
||||
desired_curv_unscaled, desired_accel = model_output["action"][0]
|
||||
desired_curvature = float(desired_curv_unscaled) / max(1.0, v_ego) ** 2
|
||||
should_stop = (v_ego < 0.3 and desired_accel < 0.1)
|
||||
|
||||
desired_accel = smooth_value(float(desired_accel), prev_action.desiredAcceleration, LONG_SMOOTH_SECONDS)
|
||||
if v_ego > MIN_LAT_CONTROL_SPEED:
|
||||
desired_curvature = smooth_value(desired_curvature, prev_action.desiredCurvature, LAT_SMOOTH_SECONDS)
|
||||
else:
|
||||
desired_curvature = prev_action.desiredCurvature
|
||||
|
||||
return log.ModelDataV2.Action(
|
||||
desiredCurvature=float(desired_curvature),
|
||||
desiredAcceleration=float(desired_accel),
|
||||
shouldStop=bool(should_stop),
|
||||
)
|
||||
|
||||
|
||||
class FrameMeta:
|
||||
frame_id: int = 0
|
||||
timestamp_sof: int = 0
|
||||
timestamp_eof: int = 0
|
||||
|
||||
def __init__(self, vipc=None):
|
||||
if vipc is not None:
|
||||
self.frame_id, self.timestamp_sof, self.timestamp_eof = vipc.frame_id, vipc.timestamp_sof, vipc.timestamp_eof
|
||||
|
||||
|
||||
class ModelState:
|
||||
prev_desire: np.ndarray
|
||||
|
||||
def __init__(self, cam_w: int, cam_h: int, usbgpu: bool):
|
||||
params = Params()
|
||||
model_id_raw = _resolve_mirrored_param(params, "Model", "DrivingModel") or BUILTIN_MODEL_KEY
|
||||
self.model_id = _canonical_model_id(model_id_raw)
|
||||
self.model_version = _resolve_mirrored_param(params, "ModelVersion", "DrivingModelVersion")
|
||||
if not uses_combined_driving_artifacts(self.model_version):
|
||||
raise ValueError(f"Combined runtime requested for non-combined version {self.model_version!r}")
|
||||
|
||||
use_builtin_model = self.model_id == BUILTIN_MODEL_KEY
|
||||
model_path = _combined_model_path(self.model_id, use_builtin_model)
|
||||
if not model_path.is_file():
|
||||
if use_builtin_model:
|
||||
raise FileNotFoundError(
|
||||
f"Missing builtin combined model artifact: {model_path}. "
|
||||
"Rebuild/deploy the combined builtin model before selecting this version."
|
||||
)
|
||||
|
||||
cloudlog.error(f"Missing combined model artifact {model_path}, downloading {self.model_id}...")
|
||||
ModelManager(params, params_memory).download_model(self.model_id)
|
||||
if not model_path.is_file():
|
||||
raise FileNotFoundError(model_path)
|
||||
|
||||
jits = pickle.loads(read_file_chunked(model_path))
|
||||
|
||||
vision_metadata = jits["metadata"]["vision"]
|
||||
off_policy_metadata = jits["metadata"]["off_policy"]
|
||||
on_policy_metadata = jits["metadata"]["on_policy"]
|
||||
|
||||
self.vision_input_shapes = vision_metadata["input_shapes"]
|
||||
self.vision_input_names = list(self.vision_input_shapes.keys())
|
||||
self.vision_output_slices = vision_metadata["output_slices"]
|
||||
self.off_policy_output_slices = off_policy_metadata["output_slices"]
|
||||
self.policy_input_shapes = on_policy_metadata["input_shapes"]
|
||||
self.policy_output_slices = on_policy_metadata["output_slices"]
|
||||
self.desire_key = "desire_pulse" if "desire_pulse" in self.policy_input_shapes else next(
|
||||
key for key in self.policy_input_shapes if key.startswith("desire")
|
||||
)
|
||||
|
||||
self.frame_skip = ModelConstants.MODEL_RUN_FREQ // ModelConstants.MODEL_CONTEXT_FREQ
|
||||
input_devices = get_tg_input_devices(PROCESS_NAME, usbgpu)
|
||||
self.WARP_DEV, self.QUEUE_DEV = input_devices["WARP_DEV"], input_devices["QUEUE_DEV"]
|
||||
tensor_inputs = jits.get("tensor_inputs")
|
||||
if tensor_inputs is None:
|
||||
tensor_inputs = make_tensor_inputs(self.vision_input_shapes, self.policy_input_shapes, self.frame_skip, device=self.QUEUE_DEV)
|
||||
self.npy, npy_tensors = make_npy_inputs(self.policy_input_shapes)
|
||||
self.input_queues = {**tensor_inputs, **npy_tensors}
|
||||
self.full_frames: dict[str, Tensor] = {}
|
||||
self._blob_cache: dict[tuple[str, int], Tensor] = {}
|
||||
self.parser = Parser()
|
||||
self.frame_buf_params = {key: get_nv12_info(cam_w, cam_h) for key in ("img", "big_img")}
|
||||
self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32)
|
||||
|
||||
camera_jit = jits[(cam_w, cam_h)]
|
||||
self.split_warp_layout = "run_policy" in jits and not isinstance(camera_jit, dict)
|
||||
if self.split_warp_layout:
|
||||
self.run_policy = jits["run_policy"]
|
||||
self.warp_enqueue = camera_jit
|
||||
else:
|
||||
self.run_policy = camera_jit["run_policy"]
|
||||
self.warp_enqueue = camera_jit["warp_enqueue"]
|
||||
|
||||
def slice_outputs(self, model_outputs: np.ndarray, output_slices: dict[str, slice]) -> dict[str, np.ndarray]:
|
||||
return {key: model_outputs[np.newaxis, value] for key, value in output_slices.items()}
|
||||
|
||||
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:
|
||||
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.WARP_DEV)
|
||||
self.full_frames[key] = self._blob_cache[cache_key]
|
||||
|
||||
inputs[self.desire_key][0] = 0
|
||||
self.npy["desire"][:] = np.where(inputs[self.desire_key] - self.prev_desire > 0.99, inputs[self.desire_key], 0)
|
||||
self.prev_desire[:] = inputs[self.desire_key]
|
||||
self.npy["traffic_convention"][:] = inputs["traffic_convention"]
|
||||
if "action_t" in self.npy:
|
||||
self.npy["action_t"][:] = inputs["action_t"]
|
||||
self.npy["tfm"][:, :] = transforms["img"][:, :]
|
||||
self.npy["big_tfm"][:, :] = transforms["big_img"][:, :]
|
||||
|
||||
if self.split_warp_layout:
|
||||
img, big_img = self.warp_enqueue(
|
||||
**{key: self.input_queues[key] for key in WARP_INPUTS},
|
||||
frame=self.full_frames["img"],
|
||||
big_frame=self.full_frames["big_img"],
|
||||
)
|
||||
if prepare_only:
|
||||
return None
|
||||
policy_inputs = {key: self.input_queues[key] for key in POLICY_INPUTS if key in self.input_queues}
|
||||
vision_output, policy_output, off_policy_output = self.run_policy(**policy_inputs, img=img, big_img=big_img)
|
||||
else:
|
||||
if prepare_only:
|
||||
self.warp_enqueue(**self.input_queues, frame=self.full_frames["img"], big_frame=self.full_frames["big_img"])
|
||||
return None
|
||||
vision_output, policy_output, off_policy_output = self.run_policy(
|
||||
**self.input_queues,
|
||||
frame=self.full_frames["img"],
|
||||
big_frame=self.full_frames["big_img"],
|
||||
)
|
||||
|
||||
vision_output = vision_output.numpy().flatten()
|
||||
policy_output = policy_output.numpy().flatten()
|
||||
off_policy_output = off_policy_output.numpy().flatten()
|
||||
|
||||
vision_outputs_dict = self.parser.parse_vision_outputs(self.slice_outputs(vision_output, self.vision_output_slices))
|
||||
off_policy_outputs_dict = self.parser.parse_off_policy_outputs(self.slice_outputs(off_policy_output, self.off_policy_output_slices))
|
||||
policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(policy_output, self.policy_output_slices))
|
||||
combined_outputs_dict = {**vision_outputs_dict, **off_policy_outputs_dict, **policy_outputs_dict}
|
||||
|
||||
if SEND_RAW_PRED:
|
||||
combined_outputs_dict["raw_pred"] = np.concatenate([vision_output.copy(), policy_output.copy(), off_policy_output.copy()])
|
||||
return combined_outputs_dict
|
||||
|
||||
|
||||
def main(demo=False):
|
||||
cloudlog.warning("modeld init")
|
||||
|
||||
sentry.set_tag("daemon", PROCESS_NAME)
|
||||
cloudlog.bind(daemon=PROCESS_NAME)
|
||||
setproctitle(PROCESS_NAME)
|
||||
config_realtime_process(7, 54)
|
||||
|
||||
# Combined downloaded models currently ship one runtime artifact, so stay on the default
|
||||
# queue profile until a separate USBGPU artifact path exists for custom models.
|
||||
usbgpu = False
|
||||
|
||||
while True:
|
||||
available_streams = VisionIpcClient.available_streams("camerad", block=False)
|
||||
if available_streams:
|
||||
use_extra_client = VisionStreamType.VISION_STREAM_WIDE_ROAD in available_streams and VisionStreamType.VISION_STREAM_ROAD in available_streams
|
||||
main_wide_camera = VisionStreamType.VISION_STREAM_ROAD not in available_streams
|
||||
break
|
||||
time.sleep(0.1)
|
||||
|
||||
vipc_client_main_stream = VisionStreamType.VISION_STREAM_WIDE_ROAD if main_wide_camera else VisionStreamType.VISION_STREAM_ROAD
|
||||
vipc_client_main = VisionIpcClient("camerad", vipc_client_main_stream, True)
|
||||
vipc_client_extra = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_WIDE_ROAD, False)
|
||||
cloudlog.warning(f"vision stream set up, main_wide_camera: {main_wide_camera}, use_extra_client: {use_extra_client}")
|
||||
|
||||
while not vipc_client_main.connect(False):
|
||||
time.sleep(0.1)
|
||||
while use_extra_client and not vipc_client_extra.connect(False):
|
||||
time.sleep(0.1)
|
||||
|
||||
cloudlog.warning(f"connected main cam with buffer size: {vipc_client_main.buffer_len} ({vipc_client_main.width} x {vipc_client_main.height})")
|
||||
if use_extra_client:
|
||||
cloudlog.warning(f"connected extra cam with buffer size: {vipc_client_extra.buffer_len} ({vipc_client_extra.width} x {vipc_client_extra.height})")
|
||||
|
||||
start_time = time.monotonic()
|
||||
cloudlog.warning("loading combined model")
|
||||
model = ModelState(vipc_client_main.width, vipc_client_main.height, usbgpu)
|
||||
cloudlog.warning(f"combined model loaded in {time.monotonic() - start_time:.1f}s, modeld starting")
|
||||
|
||||
pm = messaging.PubMaster(["modelV2", "drivingModelData", "cameraOdometry", "starpilotModelV2"])
|
||||
sm = messaging.SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "carControl", "liveDelay", "starpilotPlan"])
|
||||
|
||||
publish_state = PublishState()
|
||||
params = Params()
|
||||
|
||||
frame_dropped_filter = FirstOrderFilter(0.0, 10.0, 1.0 / ModelConstants.MODEL_RUN_FREQ)
|
||||
last_vipc_frame_id = 0
|
||||
run_count = 0
|
||||
|
||||
model_transform_main = np.zeros((3, 3), dtype=np.float32)
|
||||
model_transform_extra = np.zeros((3, 3), dtype=np.float32)
|
||||
live_calib_seen = False
|
||||
buf_main, buf_extra = None, None
|
||||
meta_main = FrameMeta()
|
||||
meta_extra = FrameMeta()
|
||||
|
||||
if demo:
|
||||
CP = get_demo_car_params()
|
||||
else:
|
||||
CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams)
|
||||
cloudlog.info("modeld got CarParams: %s", CP.brand)
|
||||
|
||||
long_delay = CP.longitudinalActuatorDelay + LONG_SMOOTH_SECONDS
|
||||
prev_action = log.ModelDataV2.Action()
|
||||
desire_helper = DesireHelper()
|
||||
starpilot_toggles = get_starpilot_toggles(sm)
|
||||
|
||||
while True:
|
||||
while meta_main.timestamp_sof < meta_extra.timestamp_sof + 25000000:
|
||||
buf_main = vipc_client_main.recv()
|
||||
meta_main = FrameMeta(vipc_client_main)
|
||||
if buf_main is None:
|
||||
break
|
||||
|
||||
if buf_main is None:
|
||||
cloudlog.debug("vipc_client_main no frame")
|
||||
continue
|
||||
|
||||
if use_extra_client:
|
||||
while True:
|
||||
buf_extra = vipc_client_extra.recv()
|
||||
meta_extra = FrameMeta(vipc_client_extra)
|
||||
if buf_extra is None or meta_main.timestamp_sof < meta_extra.timestamp_sof + 25000000:
|
||||
break
|
||||
|
||||
if buf_extra is None:
|
||||
cloudlog.debug("vipc_client_extra no frame")
|
||||
continue
|
||||
|
||||
if abs(meta_main.timestamp_sof - meta_extra.timestamp_sof) > 10000000:
|
||||
cloudlog.error(
|
||||
f"frames out of sync! main: {meta_main.frame_id} ({meta_main.timestamp_sof / 1e9:.5f}), "
|
||||
f"extra: {meta_extra.frame_id} ({meta_extra.timestamp_sof / 1e9:.5f})"
|
||||
)
|
||||
else:
|
||||
buf_extra = buf_main
|
||||
meta_extra = meta_main
|
||||
|
||||
sm.update(0)
|
||||
desire = desire_helper.desire
|
||||
is_rhd = sm["driverMonitoringState"].isRHD
|
||||
frame_id = sm["roadCameraState"].frameId
|
||||
v_ego = max(sm["carState"].vEgo, 0.0)
|
||||
lat_delay = sm["liveDelay"].lateralDelay + LAT_SMOOTH_SECONDS
|
||||
|
||||
if sm.updated["liveCalibration"] and sm.seen["roadCameraState"] and sm.seen["deviceState"]:
|
||||
device_from_calib_euler = np.array(sm["liveCalibration"].rpyCalib, dtype=np.float32)
|
||||
dc = DEVICE_CAMERAS[(str(sm["deviceState"].deviceType), str(sm["roadCameraState"].sensor))]
|
||||
model_transform_main = get_warp_matrix(
|
||||
device_from_calib_euler,
|
||||
dc.ecam.intrinsics if main_wide_camera else dc.fcam.intrinsics,
|
||||
False,
|
||||
).astype(np.float32)
|
||||
model_transform_extra = get_warp_matrix(device_from_calib_euler, dc.ecam.intrinsics, True).astype(np.float32)
|
||||
live_calib_seen = True
|
||||
|
||||
traffic_convention = np.zeros(2, dtype=np.float32)
|
||||
traffic_convention[int(is_rhd)] = 1
|
||||
|
||||
vec_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32)
|
||||
if 0 <= desire < ModelConstants.DESIRE_LEN:
|
||||
vec_desire[desire] = 1
|
||||
|
||||
vipc_dropped_frames = max(0, meta_main.frame_id - last_vipc_frame_id - 1)
|
||||
frames_dropped = frame_dropped_filter.update(min(vipc_dropped_frames, 10))
|
||||
if run_count < 10:
|
||||
frame_dropped_filter.x = 0.0
|
||||
frames_dropped = 0.0
|
||||
run_count += 1
|
||||
|
||||
frame_drop_ratio = frames_dropped / (1 + frames_dropped)
|
||||
prepare_only = vipc_dropped_frames > 0
|
||||
if prepare_only:
|
||||
cloudlog.error(f"skipping model eval. Dropped {vipc_dropped_frames} frames")
|
||||
|
||||
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
|
||||
action_delay = DT_MDL / 2
|
||||
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,
|
||||
}
|
||||
if "action_t" in model.npy:
|
||||
inputs["action_t"] = np.array([lat_action_t, long_action_t], dtype=np.float32)
|
||||
|
||||
start = time.perf_counter()
|
||||
model_output = model.run(bufs, transforms, inputs, prepare_only)
|
||||
end = time.perf_counter()
|
||||
model_execution_time = end - start
|
||||
|
||||
if model_output is not None:
|
||||
modelv2_send = messaging.new_message("modelV2")
|
||||
starpilot_modelv2_send = messaging.new_message("starpilotModelV2")
|
||||
drivingdata_send = messaging.new_message("drivingModelData")
|
||||
posenet_send = messaging.new_message("cameraOdometry")
|
||||
|
||||
action = get_action_from_model(model_output, prev_action, 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,
|
||||
frame_drop_ratio,
|
||||
meta_main.timestamp_eof,
|
||||
model_execution_time,
|
||||
live_calib_seen,
|
||||
)
|
||||
|
||||
desire_state = modelv2_send.modelV2.meta.desireState
|
||||
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
|
||||
desire_helper.update(sm["carState"], sm["carControl"].latActive, lane_change_prob, sm["starpilotPlan"], starpilot_toggles)
|
||||
modelv2_send.modelV2.meta.laneChangeState = desire_helper.lane_change_state
|
||||
modelv2_send.modelV2.meta.laneChangeDirection = desire_helper.lane_change_direction
|
||||
starpilot_modelv2_send.starpilotModelV2.turnDirection = desire_helper.turn_direction
|
||||
drivingdata_send.drivingModelData.meta.laneChangeState = desire_helper.lane_change_state
|
||||
drivingdata_send.drivingModelData.meta.laneChangeDirection = desire_helper.lane_change_direction
|
||||
|
||||
fill_pose_msg(posenet_send, model_output, meta_main.frame_id, vipc_dropped_frames, meta_main.timestamp_eof, live_calib_seen)
|
||||
pm.send("modelV2", modelv2_send)
|
||||
pm.send("starpilotModelV2", starpilot_modelv2_send)
|
||||
pm.send("drivingModelData", drivingdata_send)
|
||||
pm.send("cameraOdometry", posenet_send)
|
||||
|
||||
last_vipc_frame_id = meta_main.frame_id
|
||||
if sm.updated["starpilotPlan"]:
|
||||
starpilot_toggles = get_starpilot_toggles(sm)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -120,6 +120,12 @@ class Parser:
|
||||
if 'lead_prob' in outs:
|
||||
self.parse_binary_crossentropy('lead_prob', outs)
|
||||
|
||||
def parse_off_policy_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
|
||||
self.split_outputs(outs)
|
||||
if 'desire_state' in outs:
|
||||
self.parse_categorical_crossentropy('desire_state', outs, out_shape=(ModelConstants.DESIRE_PRED_WIDTH,))
|
||||
return outs
|
||||
|
||||
def parse_vision_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
|
||||
self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
|
||||
self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,))
|
||||
|
||||
@@ -57,7 +57,7 @@ class DRIVER_MONITOR_SETTINGS:
|
||||
self._YAW_MIN_OFFSET = -0.0246
|
||||
|
||||
self._DCAM_UNCERTAIN_ALERT_THRESHOLD = 0.1
|
||||
self._DCAM_UNCERTAIN_RESET_COUNT = int(20 / self._DT_DMON)
|
||||
self._DCAM_UNCERTAIN_RESET_COUNT = int(2 / self._DT_DMON)
|
||||
self._POSESTD_THRESHOLD = 0.3
|
||||
self._HI_STD_FALLBACK_TIME = int(10 / self._DT_DMON) # fall back to wheel touch if model is uncertain for 10s
|
||||
self._DISTRACTED_FILTER_TS = 0.25 # 0.6Hz
|
||||
|
||||
Binary file not shown.
@@ -957,10 +957,16 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
# ten times the regular interval, or the average interval is more than 10% too high.
|
||||
EventName.commIssue: {
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Communication Issue Between Processes"),
|
||||
ET.PERMANENT: Alert("Communication Issue Between Processes", "",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOWER, VisualAlert.none, AudibleAlert.none, 1., creation_delay=30.),
|
||||
ET.NO_ENTRY: comm_issue_alert,
|
||||
},
|
||||
EventName.commIssueAvgFreq: {
|
||||
ET.SOFT_DISABLE: soft_disable_alert("Low Communication Rate Between Processes"),
|
||||
ET.PERMANENT: Alert("Low Communication Rate Between Processes", "",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOWER, VisualAlert.none, AudibleAlert.none, 1., creation_delay=30.),
|
||||
ET.NO_ENTRY: NoEntryAlert("Low Communication Rate Between Processes"),
|
||||
},
|
||||
|
||||
|
||||
@@ -161,7 +161,6 @@ class SelfdriveD:
|
||||
|
||||
self.cancel_pressed_previously = False
|
||||
self.distance_pressed_previously = False
|
||||
|
||||
self.display_timer = 0
|
||||
self.last_below_steer_speed_alert_time = -float("inf")
|
||||
self.last_steer_saturated_alert_time = -float("inf")
|
||||
|
||||
@@ -17,11 +17,15 @@ from openpilot.starpilot.assets.model_manager import (
|
||||
MODEL_DOWNLOAD_ALL_PARAM,
|
||||
MODEL_DOWNLOAD_PARAM,
|
||||
ModelManager,
|
||||
TINYGRAD_VERSIONS,
|
||||
canonical_model_key,
|
||||
is_builtin_model_key,
|
||||
model_key_aliases,
|
||||
)
|
||||
from openpilot.starpilot.common.model_versions import (
|
||||
is_tinygrad_model_version,
|
||||
uses_combined_driving_artifacts,
|
||||
uses_split_off_policy_artifacts,
|
||||
)
|
||||
from openpilot.starpilot.common.starpilot_variables import MODELS_PATH, update_starpilot_toggles
|
||||
from openpilot.system.ui.lib.application import FontWeight, MouseEvent, MousePos, gui_app
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
@@ -674,7 +678,7 @@ class StarPilotDrivingModelLayout(_SettingsPage):
|
||||
if f"{model_key}.thneed" in files:
|
||||
return True
|
||||
|
||||
if version in TINYGRAD_VERSIONS:
|
||||
if is_tinygrad_model_version(version):
|
||||
required_files = set(self._required_files_for_version(model_key, version))
|
||||
return required_files.issubset(files)
|
||||
|
||||
@@ -684,6 +688,9 @@ class StarPilotDrivingModelLayout(_SettingsPage):
|
||||
return any(file.startswith(f"{model_key}.") or file.startswith(f"{model_key}_") for file in files)
|
||||
|
||||
def _required_files_for_version(self, key: str, version: str) -> list[str]:
|
||||
if uses_combined_driving_artifacts(version):
|
||||
return [f"{key}_driving_tinygrad.pkl"]
|
||||
|
||||
files = [
|
||||
f"{key}_driving_policy_tinygrad.pkl",
|
||||
f"{key}_driving_vision_tinygrad.pkl",
|
||||
@@ -691,7 +698,7 @@ class StarPilotDrivingModelLayout(_SettingsPage):
|
||||
f"{key}_driving_vision_metadata.pkl",
|
||||
]
|
||||
|
||||
if version in {"v12", "v13", "v14", "v15"}:
|
||||
if uses_split_off_policy_artifacts(version):
|
||||
files.extend(
|
||||
[
|
||||
f"{key}_driving_off_policy_tinygrad.pkl",
|
||||
|
||||
@@ -242,6 +242,11 @@ class StarPilotLateralLayout(_SettingsPage):
|
||||
get_state=lambda: self._params.get_bool("TurnDesires"),
|
||||
set_state=lambda s: self._params.put_bool("TurnDesires", s),
|
||||
visible=lambda: self._params.get_bool("LateralTune")),
|
||||
SettingRow("NavDesiresAllowed", "toggle", tr_noop("Use Route Desires"),
|
||||
subtitle=tr_noop("Allow an active navigation route to request keep-left, keep-right, and low-speed turn desires."),
|
||||
get_state=lambda: self._params.get_bool("NavDesiresAllowed"),
|
||||
set_state=lambda s: self._params.put_bool("NavDesiresAllowed", s),
|
||||
visible=lambda: self._params.get_bool("LateralTune")),
|
||||
SettingRow("NNFF", "toggle", tr_noop("Neural Network Feedforward (NNFF)"),
|
||||
subtitle=tr_noop("Use the full neural-network feedforward steering controller when available."),
|
||||
get_state=lambda: self._params.get_bool("NNFF"),
|
||||
|
||||
@@ -382,6 +382,11 @@ class StarPilotLongitudinalTuneLayout(_SettingsPage):
|
||||
get_state=lambda: self._params.get_bool("TacoTune"),
|
||||
set_state=lambda s: self._params.put_bool("TacoTune", s),
|
||||
visible=self._longitudinal_enabled),
|
||||
SettingRow("NavLongitudinalAllowed", "toggle", tr_noop("Use Route Speed Control"),
|
||||
subtitle=tr_noop("Allow an active navigation route to reduce cruise speed for upcoming turns, ramps, and roundabouts."),
|
||||
get_state=lambda: self._params.get_bool("NavLongitudinalAllowed"),
|
||||
set_state=lambda s: self._params.put_bool("NavLongitudinalAllowed", s),
|
||||
visible=self._longitudinal_enabled),
|
||||
], column_pair="detection_tune"),
|
||||
]
|
||||
self._manager_view = AetherSettingsView(
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
import time
|
||||
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.selfdrive.ui.lib.starpilot_status import get_border_color, get_mode_transition_banner_text
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.system.ui.lib.application import FontWeight
|
||||
from openpilot.system.ui.widgets.label import UnifiedLabel
|
||||
|
||||
|
||||
class ModeTransitionBanner:
|
||||
SHOW_TIME_SECONDS = 2.5
|
||||
|
||||
def __init__(self, *, font_size: int = 34, width: int = 520, height: int = 72, top_margin: int = 22):
|
||||
self._last_mode: str | None = None
|
||||
self._visible_until = 0.0
|
||||
self._width = width
|
||||
self._height = height
|
||||
self._top_margin = top_margin
|
||||
self._label = UnifiedLabel(
|
||||
"",
|
||||
font_size,
|
||||
FontWeight.BOLD,
|
||||
text_color=rl.WHITE,
|
||||
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
|
||||
alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE,
|
||||
)
|
||||
|
||||
def update(self):
|
||||
current_mode = get_mode_transition_banner_text(ui_state) if ui_state.started else None
|
||||
|
||||
if not ui_state.started:
|
||||
self._last_mode = None
|
||||
self._visible_until = 0.0
|
||||
return
|
||||
|
||||
if not ui_state.params.get_bool("ShowModeStatusBanner", default=True):
|
||||
self._last_mode = current_mode
|
||||
self._visible_until = 0.0
|
||||
return
|
||||
|
||||
if self._last_mode is None:
|
||||
self._last_mode = current_mode
|
||||
return
|
||||
|
||||
if current_mode != self._last_mode:
|
||||
self._last_mode = current_mode
|
||||
if current_mode is not None:
|
||||
self._label.set_text(f"{current_mode} MODE")
|
||||
self._visible_until = time.monotonic() + self.SHOW_TIME_SECONDS
|
||||
|
||||
def render(self, rect: rl.Rectangle):
|
||||
if (not ui_state.started or
|
||||
not ui_state.params.get_bool("ShowModeStatusBanner", default=True) or
|
||||
time.monotonic() > self._visible_until):
|
||||
return
|
||||
|
||||
banner_width = min(rect.width - 120, self._width)
|
||||
banner_rect = rl.Rectangle(
|
||||
rect.x + (rect.width - banner_width) / 2,
|
||||
rect.y + self._top_margin,
|
||||
banner_width,
|
||||
self._height,
|
||||
)
|
||||
|
||||
rl.draw_rectangle_rounded(banner_rect, 0.3, 12, rl.Color(0, 0, 0, 175))
|
||||
rl.draw_rectangle_rounded_lines_ex(banner_rect, 0.3, 12, 4, get_border_color(ui_state))
|
||||
self._label.render(banner_rect)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user