IQ.Pilot Release Commit @ 6d177d4
This commit is contained in:
@@ -6,63 +6,18 @@ It does not replace the repository-wide license files for IQ.Pilot itself or any
|
||||
|
||||
## Credits:
|
||||
|
||||
### Hyundai / Kia / Genesis (HKG) - Sunnypilot
|
||||
|
||||
#### Contributors
|
||||
|
||||
Full credit for the Hyundai / Kia / Genesis port, along with the HKG-specific tuning work used in this tree, belongs to:
|
||||
|
||||
- Jason Wen
|
||||
- James Vecellio-Grant
|
||||
- sunnypilot
|
||||
|
||||
#### Attribution
|
||||
|
||||
This repository carries HKG-side tuning and port lineage that originated from, and/or is verbatim their work. They are the authors of the Sunnypilot-side HKG port and its tuning, and are accredited as such, IQ.Lvbs claims no copyright, credit, or authorship of the components listed below.
|
||||
|
||||
#### Upstream License Notice
|
||||
|
||||
The HKG work attributed above is acknowledged here under LICENSE notice:
|
||||
|
||||
```text
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Jason Wen, James Vecellio-Grant, Sunnypilot, and a number of other contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
#### Scope
|
||||
|
||||
This licensing is limited to `iqdbc_repo/iqdbc/car/hyundai` and `iqdbc_repo/iqdbc/iqpilot/car/hyundai`.
|
||||
|
||||
### Hyundai / Kia / Genesis (HKG) - carrotpilot
|
||||
|
||||
#### Contributors
|
||||
|
||||
Full credit for the carrotpilot-side HKG tuning lineage carried in this tree belongs to:
|
||||
Full credit for the Hyundai / Kia / Genesis port and its HKG-specific tuning belongs to:
|
||||
|
||||
- carrotpilot devs (ajoutam)
|
||||
- carrotpilot
|
||||
- ajouatom
|
||||
|
||||
#### Attribution
|
||||
|
||||
This repository carries HKG-side tuning and port lineage that originated from, and/or is verbatim their work. They are the authors of the carrotpilot-side HKG tuning credited here, and are accredited as such, IQ.Lvbs claims no copyright, credit, or authorship of the components listed below.
|
||||
This repository carries the carrotpilot HKG implementation from `ajouatom/openpilot`, imported from commit `b54d44efd514bc61f86f08b01c23a6c190885c07`. IQ.Lvbs claims no copyright, credit, or authorship over that implementation.
|
||||
|
||||
#### Upstream License Notice
|
||||
|
||||
@@ -80,7 +35,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
#### Scope
|
||||
|
||||
This licensing is limited to `iqdbc_repo/iqdbc/car/hyundai` and `iqdbc_repo/iqdbc/iqpilot/car/hyundai`.
|
||||
This licensing is limited to the Hyundai/Kia/Genesis car, DBC, and safety implementations and the supporting schema and compatibility changes required by that port.
|
||||
|
||||
### Honda
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import math
|
||||
import numbers
|
||||
import time
|
||||
from collections import defaultdict, deque
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
@@ -154,7 +155,7 @@ class CANParser:
|
||||
self.last_nonempty_nanos: int = 0
|
||||
self._last_update_nanos: int = 0
|
||||
|
||||
def _add_message(self, name_or_addr: str | int, freq: int | None = None) -> None:
|
||||
def _add_message(self, name_or_addr: str | int, freq: int | None = None, ignore_counter: bool = False) -> None:
|
||||
if isinstance(name_or_addr, numbers.Number):
|
||||
msg = self.dbc.addr_to_msg.get(int(name_or_addr))
|
||||
else:
|
||||
@@ -171,16 +172,15 @@ class CANParser:
|
||||
self.vl_all[msg.name] = self.vl_all[msg.address]
|
||||
self.ts_nanos[msg.address] = {s: 0 for s in signal_names}
|
||||
self.ts_nanos[msg.name] = self.ts_nanos[msg.address]
|
||||
self.dat[msg.address] = b""
|
||||
self.dat[msg.name] = b""
|
||||
|
||||
state = MessageState(
|
||||
address=msg.address,
|
||||
name=msg.name,
|
||||
size=msg.size,
|
||||
signals=list(msg.sigs.values()),
|
||||
ignore_alive=freq is not None and math.isnan(freq),
|
||||
ignore_counter=ignore_counter,
|
||||
)
|
||||
state.first_seen_nanos = time.monotonic_ns()
|
||||
if freq is not None and freq > 0:
|
||||
state.frequency = freq
|
||||
else:
|
||||
|
||||
@@ -238,6 +238,42 @@ struct CarState {
|
||||
fuelTankLevelL @63 :Float32; # raw fuel tank level in liters (konn3kt: VW PQ Kombi_1.Tankinhalt)
|
||||
batteryDetails @65 :BatteryDetails;
|
||||
|
||||
# carrotpilot HKG extension state
|
||||
vCluRatio @68 :Float32;
|
||||
logCarrot @69 :Text;
|
||||
softHoldActive @70 :Int16;
|
||||
activateCruise @71 :Int16;
|
||||
latEnabled @72 :Bool;
|
||||
pcmCruiseGap @73 :Int16;
|
||||
speedLimit @74 :Float32;
|
||||
speedLimitDistance @75 :Float32;
|
||||
gearStep @76 :Int16;
|
||||
tpms @77 :Tpms;
|
||||
useLaneLineSpeed @78 :Float32;
|
||||
leftLatDist @79 :Float32;
|
||||
rightLatDist @80 :Float32;
|
||||
leftLongDist @81 :Float32;
|
||||
rightLongDist @82 :Float32;
|
||||
carrotCruise @83 :Int16;
|
||||
leftLaneLine @84 :Int16;
|
||||
rightLaneLine @85 :Int16;
|
||||
datetime @86 :UInt64;
|
||||
leftRearLongDist @87 :Float32;
|
||||
rightRearLongDist @88 :Float32;
|
||||
leftRearLatDist @89 :Float32;
|
||||
rightRearLatDist @90 :Float32;
|
||||
trailerConnected @91 :Bool;
|
||||
ureaGauge @92 :Float32;
|
||||
evModeActive @93 :Bool;
|
||||
evModeValid @94 :Bool;
|
||||
|
||||
struct Tpms {
|
||||
fl @0 :Float32;
|
||||
fr @1 :Float32;
|
||||
rl @2 :Float32;
|
||||
rr @3 :Float32;
|
||||
}
|
||||
|
||||
struct BatteryDetails {
|
||||
capacity @0 :Float32;
|
||||
charge @1 :Float32;
|
||||
@@ -302,13 +338,16 @@ struct CarState {
|
||||
setCruise @9;
|
||||
resumeCruise @10;
|
||||
gapAdjustCruise @11;
|
||||
lfaButton @12;
|
||||
paddleLeft @13;
|
||||
paddleRight @14;
|
||||
}
|
||||
}
|
||||
|
||||
# deprecated
|
||||
errorsDEPRECATED @0 :List(OnroadEventDEPRECATED.EventName);
|
||||
gasDEPRECATED @3 :Float32; # this is user pedal only
|
||||
brakeLightsDEPRECATED @19 :Bool;
|
||||
gas @3 :Float32; # this is user pedal only
|
||||
brakeLights @19 :Bool;
|
||||
steeringRateLimitedDEPRECATED @29 :Bool;
|
||||
canMonoTimesDEPRECATED @12: List(UInt64);
|
||||
canRcvTimeoutDEPRECATED @49 :Bool;
|
||||
@@ -346,6 +385,18 @@ struct RadarData @0x888ad6581cf0aacb {
|
||||
|
||||
# some radars flag measurements VS estimates
|
||||
measured @6 :Bool;
|
||||
|
||||
vLead @7 :Float32; # m/s
|
||||
aLead @8 :Float32; # m/s^2
|
||||
jLead @9 :Float32; # m/s^3
|
||||
radarSource @10 :RadarSource;
|
||||
|
||||
enum RadarSource {
|
||||
frontRadar @0;
|
||||
scc @1;
|
||||
corner235 @2;
|
||||
corner180 @3;
|
||||
}
|
||||
}
|
||||
|
||||
enum ErrorDEPRECATED {
|
||||
@@ -401,6 +452,8 @@ struct CarControl {
|
||||
brake @1: Float32; # [0.0, 1.0]
|
||||
torqueOutputCan @8: Float32; # value sent over can to the car
|
||||
speed @6: Float32; # m/s
|
||||
jerk @9: Float32; # m/s^3
|
||||
aTarget @10: Float32; # m/s^2
|
||||
|
||||
enum LongControlState @0xe40f3a917d908282{
|
||||
off @0;
|
||||
@@ -436,6 +489,12 @@ struct CarControl {
|
||||
leadFollowTime @11: Float32;
|
||||
leadDistance @12: Float32;
|
||||
driverUnresponsive @13: Bool;
|
||||
activeCarrot @14: Int16;
|
||||
leadRelSpeed @15: Float32;
|
||||
leadDPath @16: Float32;
|
||||
leadRadar @17: Int16;
|
||||
modelDesire @18: Int16;
|
||||
atcDistance @19: Float32;
|
||||
|
||||
# not used with the dash, TODO: separate structs for dash UI and device UI
|
||||
audibleAlert @5: AudibleAlert;
|
||||
@@ -499,6 +558,7 @@ struct CarParams {
|
||||
enableBsm @56 :Bool; # blind spot monitoring
|
||||
flags @64 :UInt32; # flags for car specific quirks
|
||||
alphaLongitudinalAvailable @71 :Bool;
|
||||
extFlags @79 :UInt32; # carrotpilot HKG extension flags
|
||||
|
||||
minEnableSpeed @7 :Float32;
|
||||
minSteerSpeed @8 :Float32;
|
||||
@@ -595,7 +655,7 @@ struct CarParams {
|
||||
kpV @1 :List(Float32);
|
||||
kiBP @2 :List(Float32);
|
||||
kiV @3 :List(Float32);
|
||||
kfDEPRECATED @6 :Float32;
|
||||
kf @6 :Float32;
|
||||
deadzoneBPDEPRECATED @4 :List(Float32);
|
||||
deadzoneVDEPRECATED @5 :List(Float32);
|
||||
}
|
||||
@@ -768,11 +828,11 @@ struct CarParams {
|
||||
maxSteeringAngleDegDEPRECATED @54 :Float32;
|
||||
longitudinalActuatorDelayLowerBoundDEPRECATED @61 :Float32;
|
||||
stoppingControlDEPRECATED @31 :Bool; # Does the car allow full control even at lows speeds when stopping
|
||||
radarTimeStepDEPRECATED @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard
|
||||
radarTimeStep @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard
|
||||
enableDsuDEPRECATED @5 :Bool; # driving support unit
|
||||
vEgoStartingDEPRECATED @59 :Float32;
|
||||
startAccelDEPRECATED @32 :Float32;
|
||||
startingStateDEPRECATED @70 :Bool;
|
||||
vEgoStarting @59 :Float32;
|
||||
startAccel @32 :Float32;
|
||||
startingState @70 :Bool;
|
||||
vEgoStoppingDEPRECATED @29 :Float32;
|
||||
stoppingDecelRateDEPRECATED @52 :Float32;
|
||||
}
|
||||
|
||||
@@ -1,31 +1,47 @@
|
||||
import numpy as np
|
||||
from iqdbc.can import CANPacker
|
||||
from iqdbc.car import Bus, DT_CTRL, make_tester_present_msg, structs
|
||||
from iqdbc.car.lateral import apply_driver_steer_torque_limits, common_fault_avoidance
|
||||
from iqdbc.car.lateral import apply_driver_steer_torque_limits, apply_std_steer_angle_limits, common_fault_avoidance
|
||||
from iqdbc.car.common.conversions import Conversions as CV
|
||||
from iqdbc.car.hyundai import hyundaicanfd, hyundaican
|
||||
from iqdbc.car.hyundai.carstate import CarState
|
||||
from iqdbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR, CAN_GEARS, HyundaiExtFlags
|
||||
from iqdbc.car.interfaces import CarControllerBase
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.escc import EsccCarController
|
||||
from iqdbc.iqpilot.car.hyundai.longitudinal.controller import LongitudinalController
|
||||
from iqdbc.iqpilot.car.hyundai.lead_data_ext import LeadDataCarController
|
||||
from iqdbc.iqpilot.car.hyundai.aol import AolCarController
|
||||
from iqdbc.car.vehicle_model import VehicleModel
|
||||
|
||||
VisualAlert = structs.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = structs.CarControl.Actuators.LongControlState
|
||||
|
||||
|
||||
from openpilot.common.params import Params
|
||||
|
||||
# EPS faults if you apply torque while the steering angle is above 90 degrees for more than 1 second
|
||||
# All slightly below EPS thresholds to avoid fault
|
||||
MAX_ANGLE = 85
|
||||
MAX_ANGLE_FRAMES = 89
|
||||
MAX_ANGLE_CONSECUTIVE_FRAMES = 2
|
||||
DRIVER_TORQUE_FILTER_TAU = 0.12
|
||||
PRE_OVERRIDE_PREDICTION_TIME = 0.15
|
||||
PRE_OVERRIDE_START_RATIO = 0.90
|
||||
PRE_OVERRIDE_FULL_RATIO = 1.05
|
||||
PRE_OVERRIDE_RAW_MIN_RATIO = 0.70
|
||||
PRE_OVERRIDE_FILTERED_MIN_RATIO = 0.65
|
||||
PRE_OVERRIDE_MIN_RATE_RATIO = 0.50
|
||||
PRE_OVERRIDE_CONFIRM_FRAMES = 2
|
||||
PRE_OVERRIDE_MAX_TORQUE_DELTA = -10.0
|
||||
LOW_SPEED_ANGLE_RATE_RAMP_SPEED = 15.0 * CV.KPH_TO_MS
|
||||
MID_SPEED_ANGLE_RATE_LIMIT_SPEED = 40.0 * CV.KPH_TO_MS
|
||||
|
||||
|
||||
def _use_stock_lkas_request_path(CP) -> bool:
|
||||
return CP.carFingerprint == CAR.HYUNDAI_PALISADE
|
||||
|
||||
vibrate_intervals = [
|
||||
(0.0, 0.5),
|
||||
(1.0, 1.5),
|
||||
#(2.5, 3.0),
|
||||
#(3.5, 4.0),
|
||||
(5.0, 5.5),
|
||||
(6.0, 6.5),
|
||||
(7.5, 8.0),
|
||||
]
|
||||
|
||||
def process_hud_alert(enabled, fingerprint, hud_control):
|
||||
sys_warning = (hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw))
|
||||
@@ -50,14 +66,75 @@ def process_hud_alert(enabled, fingerprint, hud_control):
|
||||
|
||||
return sys_warning, sys_state, left_lane_warning, right_lane_warning
|
||||
|
||||
def rate_limit(x, x_last, lo, hi):
|
||||
return float(np.clip(x, x_last + lo, x_last + hi))
|
||||
|
||||
class CarController(CarControllerBase, EsccCarController, LeadDataCarController, LongitudinalController, AolCarController):
|
||||
def __init__(self, dbc_names, CP, CP_IQ):
|
||||
CarControllerBase.__init__(self, dbc_names, CP, CP_IQ)
|
||||
EsccCarController.__init__(self, CP, CP_IQ)
|
||||
AolCarController.__init__(self)
|
||||
LeadDataCarController.__init__(self, CP)
|
||||
LongitudinalController.__init__(self, CP, CP_IQ)
|
||||
def apply_steer_angle_limits_physics(desired_sw_deg: float,
|
||||
last_sw_deg: float,
|
||||
v_ego: float,
|
||||
steering_sw_deg: float,
|
||||
lat_active: bool,
|
||||
wheelbase_m: float,
|
||||
steer_ratio: float,
|
||||
steer_sw_max_deg: float,
|
||||
model_v2=None) -> float:
|
||||
max_lat_accel = 8.5 # m/s^2
|
||||
max_lat_jerk = 4.0 # m/s^3
|
||||
y_std_1s = 0.1
|
||||
if model_v2 is not None and len(model_v2.position.yStd) > 10:
|
||||
model_y_std_1s = float(model_v2.position.yStd[10])
|
||||
if np.isfinite(model_y_std_1s) and model_y_std_1s >= 0.0:
|
||||
y_std_1s = model_y_std_1s
|
||||
max_sw_rate_deg_per_tick = float(np.interp(y_std_1s, [0.1, 0.2, 0.4], [2.0, 1.5, 0.8]))
|
||||
v = max(float(v_ego), 1.0)
|
||||
|
||||
target_sw = float(np.clip(desired_sw_deg, -steer_sw_max_deg, steer_sw_max_deg))
|
||||
if v_ego < MID_SPEED_ANGLE_RATE_LIMIT_SPEED:
|
||||
# Keep low/mid-speed angle commands quieter without reducing LKAS_ANGLE_MAX_TORQUE.
|
||||
# Allow the angle, but slow the arrival: 0~15 kph ramps 0.8->1.1 deg/tick,
|
||||
# then 15~40 kph tapers 1.1->0.8 deg/tick. Above 40 kph, physics limits take over.
|
||||
low_mid_speed_cap = float(np.interp(v_ego,
|
||||
[0.0, LOW_SPEED_ANGLE_RATE_RAMP_SPEED, MID_SPEED_ANGLE_RATE_LIMIT_SPEED],
|
||||
[0.8, 1.1, 0.8]))
|
||||
max_sw_rate_deg_per_tick = min(max_sw_rate_deg_per_tick, low_mid_speed_cap)
|
||||
|
||||
target_rw = target_sw / steer_ratio
|
||||
last_rw = float(last_sw_deg) / steer_ratio
|
||||
|
||||
# --- accel limit ---
|
||||
rw_max_rad = np.arctan((max_lat_accel * wheelbase_m) / (v * v))
|
||||
rw_max = float(np.degrees(rw_max_rad))
|
||||
|
||||
# --- jerk -> rate limit ---
|
||||
sec2 = 1.2
|
||||
max_drw_dt = (max_lat_jerk * wheelbase_m) / (v * v * sec2) # rad/s
|
||||
max_drw_per_tick = max_drw_dt * DT_CTRL # rad/tick
|
||||
max_drw_per_tick_deg = float(np.degrees(max_drw_per_tick))
|
||||
|
||||
err = abs(target_sw - last_sw_deg)
|
||||
if err > 20.0:
|
||||
max_sw_rate_deg_per_tick = min(max_sw_rate_deg_per_tick, 1.0)
|
||||
|
||||
max_drw_per_tick_deg = min(
|
||||
max_drw_per_tick_deg,
|
||||
max_sw_rate_deg_per_tick / steer_ratio
|
||||
)
|
||||
|
||||
# --- rate limit ---
|
||||
cmd_rw = rate_limit(target_rw, last_rw, -max_drw_per_tick_deg, max_drw_per_tick_deg)
|
||||
|
||||
# --- accel clip ---
|
||||
cmd_rw = float(np.clip(cmd_rw, -rw_max, rw_max))
|
||||
|
||||
if not lat_active:
|
||||
cmd_rw = float(steering_sw_deg) / steer_ratio
|
||||
|
||||
cmd_sw = cmd_rw * steer_ratio
|
||||
return float(np.clip(cmd_sw, -steer_sw_max_deg, steer_sw_max_deg))
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_names, CP, CP_IQ=None):
|
||||
super().__init__(dbc_names, CP, CP_IQ or structs.IQCarParams())
|
||||
self.CAN = CanBus(CP)
|
||||
self.params = CarControllerParams(CP)
|
||||
self.packer = CANPacker(dbc_names[Bus.pt])
|
||||
@@ -68,56 +145,302 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
|
||||
self.car_fingerprint = CP.carFingerprint
|
||||
self.last_button_frame = 0
|
||||
|
||||
self.hyundai_jerk = HyundaiJerk()
|
||||
self.speedCameraHapticEndFrame = 0
|
||||
self.hapticFeedbackWhenSpeedCamera = 0
|
||||
self.max_angle_frames = MAX_ANGLE_FRAMES
|
||||
self.blinking_signal = False # 1Hz
|
||||
self.blinking_frame = int(1.0 / DT_CTRL)
|
||||
self.soft_hold_mode = 2
|
||||
|
||||
self.activateCruise = 0
|
||||
self.button_wait = 12
|
||||
self.cruise_buttons_msg_values = None
|
||||
self.cruise_buttons_msg_cnt = 0
|
||||
self.button_spamming_count = 0
|
||||
self.prev_clu_speed = 0
|
||||
self.button_spam1 = 8
|
||||
self.button_spam2 = 30
|
||||
self.button_spam3 = 1
|
||||
|
||||
self.apply_angle_last = 0
|
||||
self.lkas_max_torque = 0
|
||||
self.angle_max_torque = 250
|
||||
self.steering_pressed_prev = False
|
||||
self.recovering_from_override = False
|
||||
self.full_recovery_frames = 0
|
||||
self.repeated_override_count = 0
|
||||
self.override_latched = False
|
||||
self.override_release_frames = 0
|
||||
self.driver_torque_filtered = 0.0
|
||||
self.driver_torque_filtered_prev = 0.0
|
||||
self.pre_override_frames = 0
|
||||
|
||||
self.lkas11_active = False
|
||||
|
||||
self.canfd_debug = 0
|
||||
self.MainMode_ACC_trigger = 0
|
||||
self.LFA_trigger = 0
|
||||
|
||||
self.activeCarrot = 0
|
||||
self.camera_scc_params = Params().get_int("HyundaiCameraSCC")
|
||||
self.is_ldws_car = Params().get_bool("IsLdwsCar")
|
||||
self.enable_corner_radar = 0
|
||||
|
||||
self.steerDeltaUpOrg = self.steerDeltaUp = self.steerDeltaUpLC = self.params.STEER_DELTA_UP
|
||||
self.steerDeltaDownOrg = self.steerDeltaDown = self.steerDeltaDownLC = self.params.STEER_DELTA_DOWN
|
||||
|
||||
def update(self, CC, CC_IQ, CS, now_nanos):
|
||||
EsccCarController.update(self, CS)
|
||||
LeadDataCarController.update(self, CC_IQ)
|
||||
AolCarController.update(self, self.CP, CC, CC_IQ, self.frame)
|
||||
if self.frame % 2 == 0:
|
||||
LongitudinalController.update(self, CC, CS)
|
||||
|
||||
if self.frame % 50 == 0:
|
||||
params = Params()
|
||||
self.max_angle_frames = params.get_int("MaxAngleFrames")
|
||||
steerMax = params.get_int("CustomSteerMax")
|
||||
steerDeltaUp = params.get_int("CustomSteerDeltaUp")
|
||||
steerDeltaDown = params.get_int("CustomSteerDeltaDown")
|
||||
steerDeltaUpLC = params.get_int("CustomSteerDeltaUpLC")
|
||||
steerDeltaDownLC = params.get_int("CustomSteerDeltaDownLC")
|
||||
if steerMax > 0:
|
||||
self.params.STEER_MAX = steerMax
|
||||
if steerDeltaUp > 0:
|
||||
self.steerDeltaUp = steerDeltaUp
|
||||
#self.params.ANGLE_TORQUE_UP_RATE = steerDeltaUp
|
||||
else:
|
||||
self.steerDeltaUp = self.steerDeltaUpOrg
|
||||
if steerDeltaDown > 0:
|
||||
self.steerDeltaDown = steerDeltaDown
|
||||
#self.params.ANGLE_TORQUE_DOWN_RATE = steerDeltaDown
|
||||
else:
|
||||
self.steerDeltaDown = self.steerDeltaDownOrg
|
||||
|
||||
if steerDeltaUpLC > 0:
|
||||
self.steerDeltaUpLC = steerDeltaUpLC
|
||||
else:
|
||||
self.steerDeltaUpLC = self.steerDeltaUp
|
||||
if steerDeltaDownLC > 0:
|
||||
self.steerDeltaDownLC = steerDeltaDownLC
|
||||
else:
|
||||
self.steerDeltaDownLC = self.steerDeltaDown
|
||||
|
||||
self.soft_hold_mode = 1 if params.get_int("AutoCruiseControl") > 1 else 2
|
||||
self.hapticFeedbackWhenSpeedCamera = int(params.get_int("HapticFeedbackWhenSpeedCamera"))
|
||||
|
||||
self.button_spam1 = params.get_int("CruiseButtonTest1")
|
||||
self.button_spam2 = params.get_int("CruiseButtonTest2")
|
||||
self.button_spam3 = params.get_int("CruiseButtonTest3")
|
||||
self.speed_from_pcm = params.get_int("SpeedFromPCM")
|
||||
|
||||
self.canfd_debug = params.get_int("CanfdDebug")
|
||||
self.camera_scc_params = params.get_int("HyundaiCameraSCC")
|
||||
self.enable_corner_radar = params.get_int("EnableCornerRadar")
|
||||
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
|
||||
if hud_control.modelDesire in [3,4]:
|
||||
self.params.STEER_DELTA_UP = self.steerDeltaUpLC
|
||||
self.params.STEER_DELTA_DOWN = self.steerDeltaDownLC
|
||||
else:
|
||||
self.params.STEER_DELTA_UP = self.steerDeltaUp
|
||||
self.params.STEER_DELTA_DOWN = self.steerDeltaDown
|
||||
|
||||
angle_control = self.CP.flags & HyundaiFlags.ANGLE_CONTROL
|
||||
|
||||
# steering torque
|
||||
new_torque = int(round(actuators.torque * self.params.STEER_MAX))
|
||||
apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params)
|
||||
|
||||
# >90 degree steering fault prevention
|
||||
self.angle_limit_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringAngleDeg) >= MAX_ANGLE, CC.latActive,
|
||||
self.angle_limit_counter, MAX_ANGLE_FRAMES,
|
||||
self.angle_limit_counter, self.max_angle_frames,
|
||||
MAX_ANGLE_CONSECUTIVE_FRAMES)
|
||||
|
||||
#apply_angle = apply_std_steer_angle_limits(actuators.steeringAngleDeg, self.apply_angle_last, CS.out.vEgoRaw,
|
||||
# CS.out.steeringAngleDeg, CC.latActive, self.params.ANGLE_LIMITS)
|
||||
|
||||
apply_angle = apply_steer_angle_limits_physics(
|
||||
actuators.steeringAngleDeg,
|
||||
self.apply_angle_last,
|
||||
CS.out.vEgoRaw,
|
||||
CS.out.steeringAngleDeg,
|
||||
CC.latActive,
|
||||
self.CP.wheelbase,
|
||||
self.CP.steerRatio,
|
||||
self.params.ANGLE_LIMITS.STEER_ANGLE_MAX,
|
||||
CS.modelV2,
|
||||
)
|
||||
|
||||
|
||||
if angle_control:
|
||||
apply_steer_req = CC.latActive
|
||||
|
||||
angle_torque_cap = self.angle_max_torque
|
||||
|
||||
steering_pressed_rising = CS.out.steeringPressed and not self.steering_pressed_prev
|
||||
if steering_pressed_rising:
|
||||
if 0 < self.full_recovery_frames < int(5.0 / DT_CTRL):
|
||||
self.repeated_override_count = min(self.repeated_override_count + 1, 3)
|
||||
self.full_recovery_frames = 0
|
||||
self.recovering_from_override = True
|
||||
|
||||
torque_threshold = max(self.params.STEER_THRESHOLD, 1.0)
|
||||
# Filter signed torque so alternating sensor noise cancels out before its
|
||||
# magnitude is used for pre-override prediction.
|
||||
driver_torque = float(CS.out.steeringTorque)
|
||||
driver_torque_abs = abs(driver_torque)
|
||||
if not CC.latActive:
|
||||
self.driver_torque_filtered = driver_torque
|
||||
self.driver_torque_filtered_prev = driver_torque
|
||||
self.pre_override_frames = 0
|
||||
else:
|
||||
torque_filter_alpha = DT_CTRL / (DRIVER_TORQUE_FILTER_TAU + DT_CTRL)
|
||||
self.driver_torque_filtered_prev = self.driver_torque_filtered
|
||||
self.driver_torque_filtered += torque_filter_alpha * (driver_torque - self.driver_torque_filtered)
|
||||
|
||||
driver_torque_filtered_abs = abs(self.driver_torque_filtered)
|
||||
driver_torque_filtered_prev_abs = abs(self.driver_torque_filtered_prev)
|
||||
driver_torque_rate = max(0.0, (driver_torque_filtered_abs - driver_torque_filtered_prev_abs) / DT_CTRL)
|
||||
torque_ratio = driver_torque_filtered_abs / torque_threshold
|
||||
raw_torque_ratio = driver_torque_abs / torque_threshold
|
||||
predicted_torque_ratio = (
|
||||
driver_torque_filtered_abs + driver_torque_rate * PRE_OVERRIDE_PREDICTION_TIME
|
||||
) / torque_threshold
|
||||
pre_override_candidate = (
|
||||
CC.latActive and
|
||||
not CS.out.steeringPressed and
|
||||
raw_torque_ratio > PRE_OVERRIDE_RAW_MIN_RATIO and
|
||||
torque_ratio > PRE_OVERRIDE_FILTERED_MIN_RATIO and
|
||||
predicted_torque_ratio > PRE_OVERRIDE_START_RATIO and
|
||||
driver_torque_rate > torque_threshold * PRE_OVERRIDE_MIN_RATE_RATIO
|
||||
)
|
||||
self.pre_override_frames = self.pre_override_frames + 1 if pre_override_candidate else 0
|
||||
pre_override_yield = 0.0
|
||||
if self.pre_override_frames >= PRE_OVERRIDE_CONFIRM_FRAMES:
|
||||
pre_override_yield = float(np.interp(
|
||||
predicted_torque_ratio,
|
||||
[PRE_OVERRIDE_START_RATIO, PRE_OVERRIDE_FULL_RATIO],
|
||||
[0.0, 1.0],
|
||||
))
|
||||
recovery_allowed = False
|
||||
|
||||
if CS.out.steeringPressed:
|
||||
# Start yielding immediately when driver override is confirmed.
|
||||
self.override_latched = True
|
||||
self.override_release_frames = 0
|
||||
torque_delta = -20.0
|
||||
elif pre_override_yield > 0.0:
|
||||
# Start handing off gently before steeringPressed flips to avoid a sharp torque drop.
|
||||
torque_delta = PRE_OVERRIDE_MAX_TORQUE_DELTA * pre_override_yield
|
||||
elif self.lkas_max_torque >= self.angle_max_torque:
|
||||
# Once fully recovered, hold full authority until the next driver override.
|
||||
torque_delta = 0.0
|
||||
elif self.override_latched:
|
||||
# Hold reduced authority until driver torque stays below 60% for 0.2 seconds.
|
||||
self.override_release_frames = self.override_release_frames + 1 if torque_ratio < 0.6 else 0
|
||||
if self.override_release_frames >= int(0.2 / DT_CTRL):
|
||||
self.override_latched = False
|
||||
self.override_release_frames = 0
|
||||
recovery_allowed = True
|
||||
else:
|
||||
torque_delta = 0.0
|
||||
else:
|
||||
recovery_allowed = True
|
||||
|
||||
if recovery_allowed:
|
||||
# Use one-second model uncertainty to set the base torque recovery time.
|
||||
# Missing or invalid model data falls back to a moderate 1.5-second recovery.
|
||||
y_std_1s = 0.2
|
||||
if CS.modelV2 is not None and len(CS.modelV2.position.yStd) > 10:
|
||||
model_y_std_1s = float(CS.modelV2.position.yStd[10])
|
||||
if np.isfinite(model_y_std_1s) and model_y_std_1s >= 0.0:
|
||||
y_std_1s = model_y_std_1s
|
||||
|
||||
recovery_time = float(np.interp(y_std_1s, [0.1, 0.2, 0.3, 0.4], [0.5, 0.8, 1.5, 3.0]))
|
||||
recovery_time = max(recovery_time, float(np.interp(
|
||||
self.repeated_override_count,
|
||||
[0, 1, 2, 3],
|
||||
[0.1, 1.0, 2.0, 3.0],
|
||||
)))
|
||||
base_rate_up = (self.angle_max_torque - self.params.ANGLE_MIN_TORQUE) * DT_CTRL / recovery_time
|
||||
|
||||
# During recovery, taper the rate to zero. Only steeringPressed can reduce authority.
|
||||
torque_delta = base_rate_up * float(np.interp(torque_ratio, [0.6, 0.8], [1.0, 0.0]))
|
||||
self.lkas_max_torque = float(np.clip(self.lkas_max_torque + torque_delta,
|
||||
self.params.ANGLE_MIN_TORQUE, angle_torque_cap))
|
||||
|
||||
if not CS.out.steeringPressed and self.recovering_from_override and self.lkas_max_torque >= self.angle_max_torque:
|
||||
self.recovering_from_override = False
|
||||
self.full_recovery_frames = 1
|
||||
elif not CS.out.steeringPressed and self.full_recovery_frames > 0:
|
||||
self.full_recovery_frames += 1
|
||||
if self.full_recovery_frames >= int(5.0 / DT_CTRL):
|
||||
self.full_recovery_frames = 0
|
||||
self.repeated_override_count = 0
|
||||
|
||||
if not CC.latActive:
|
||||
apply_torque = 0
|
||||
if self.apply_torque_last > 0:
|
||||
self.apply_torque_last = max(self.apply_torque_last - self.params.STEER_DELTA_DOWN, 0)
|
||||
elif self.apply_torque_last < 0:
|
||||
self.apply_torque_last = min(self.apply_torque_last + self.params.STEER_DELTA_DOWN, 0)
|
||||
else:
|
||||
self.apply_torque_last = apply_torque
|
||||
self.lkas_max_torque = 0
|
||||
self.recovering_from_override = False
|
||||
self.full_recovery_frames = 0
|
||||
self.repeated_override_count = 0
|
||||
self.override_latched = False
|
||||
self.override_release_frames = 0
|
||||
self.driver_torque_filtered = 0.0
|
||||
self.driver_torque_filtered_prev = 0.0
|
||||
self.pre_override_frames = 0
|
||||
|
||||
if not _use_stock_lkas_request_path(self.CP) and apply_torque == 0 and CC.latActive and CS.out.steeringPressed:
|
||||
apply_steer_req = False
|
||||
self.steering_pressed_prev = CS.out.steeringPressed if CC.latActive else False
|
||||
|
||||
self.apply_angle_last = apply_angle
|
||||
|
||||
# Hold torque with induced temporary fault when cutting the actuation bit
|
||||
# FIXME: we don't use this with CAN FD?
|
||||
torque_fault = False if _use_stock_lkas_request_path(self.CP) else (CC.latActive and not apply_steer_req)
|
||||
torque_fault = CC.latActive and not apply_steer_req
|
||||
|
||||
self.apply_torque_last = apply_torque
|
||||
|
||||
# accel + longitudinal
|
||||
accel = float(np.clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX))
|
||||
stopping = actuators.longControlState == LongCtrlState.stopping
|
||||
set_speed_in_units = hud_control.setSpeed * (CV.MS_TO_KPH if CS.is_metric else CV.MS_TO_MPH)
|
||||
|
||||
# HUD messages
|
||||
sys_warning, sys_state, left_lane_warning, right_lane_warning = process_hud_alert(CC.enabled, self.car_fingerprint,
|
||||
hud_control)
|
||||
|
||||
active_speed_decel = hud_control.activeCarrot == 3 and self.activeCarrot != 3 # 3: Speed Decel
|
||||
self.activeCarrot = hud_control.activeCarrot
|
||||
if active_speed_decel and self.speedCameraHapticEndFrame < 0: # 과속카메라 감속시작
|
||||
self.speedCameraHapticEndFrame = self.frame + (8.0 / DT_CTRL) #8초간 켜줌.
|
||||
elif not active_speed_decel:
|
||||
self.speedCameraHapticEndFrame = -1
|
||||
|
||||
if 0 <= self.speedCameraHapticEndFrame - self.frame < int(8.0 / DT_CTRL) and self.hapticFeedbackWhenSpeedCamera > 0:
|
||||
t = (self.frame - (self.speedCameraHapticEndFrame - int(8.0 / DT_CTRL))) * DT_CTRL
|
||||
|
||||
for start, end in vibrate_intervals:
|
||||
if start <= t < end:
|
||||
left_lane_warning = right_lane_warning = self.hapticFeedbackWhenSpeedCamera
|
||||
break
|
||||
|
||||
if self.frame >= self.speedCameraHapticEndFrame:
|
||||
self.speedCameraHapticEndFrame = -1
|
||||
|
||||
if self.frame % self.blinking_frame == 0:
|
||||
self.blinking_signal = True
|
||||
elif self.frame % self.blinking_frame == self.blinking_frame / 2:
|
||||
self.blinking_signal = False
|
||||
|
||||
|
||||
|
||||
can_sends = []
|
||||
|
||||
# *** common hyundai stuff ***
|
||||
|
||||
# tester present - w/ no response (keeps relevant ECU disabled)
|
||||
if self.frame % 100 == 0 and not ((self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC) or self.ESCC.enabled) and \
|
||||
self.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 100 == 0 and not (self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC) and self.CP.openpilotLongitudinalControl:
|
||||
# for longitudinal control, either radar or ADAS driving ECU
|
||||
addr, bus = 0x7d0, self.CAN.ECAN if self.CP.flags & HyundaiFlags.CANFD else 0
|
||||
if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value:
|
||||
if self.CP.flags & HyundaiFlags.CANFD_HDA2.value:
|
||||
addr, bus = 0x730, self.CAN.ECAN
|
||||
can_sends.append(make_tester_present_msg(addr, bus, suppress_response=True))
|
||||
|
||||
@@ -125,40 +448,135 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
|
||||
if self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
|
||||
can_sends.append(make_tester_present_msg(0x7b1, self.CAN.ECAN, suppress_response=True))
|
||||
|
||||
# *** CAN/CAN FD specific ***
|
||||
camera_scc = self.CP.flags & HyundaiFlags.CAMERA_SCC
|
||||
# CAN-FD platforms
|
||||
if self.CP.flags & HyundaiFlags.CANFD:
|
||||
can_sends.extend(self.create_canfd_msgs(apply_steer_req, apply_torque, set_speed_in_units, accel,
|
||||
stopping, hud_control, CS, CC))
|
||||
hda2 = self.CP.flags & HyundaiFlags.CANFD_HDA2
|
||||
hda2_long = hda2 and self.CP.openpilotLongitudinalControl
|
||||
# steering control
|
||||
if camera_scc:
|
||||
can_sends.extend(hyundaicanfd.create_steering_messages_camera_scc(self.frame, self.packer, self.CP, self.CAN, CC, apply_steer_req, apply_torque, CS, apply_angle, self.lkas_max_torque, angle_control))
|
||||
else:
|
||||
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, apply_angle, self.lkas_max_torque, angle_control))
|
||||
|
||||
# prevent LFA from activating on HDA2 by sending "no lane lines detected" to ADAS ECU
|
||||
if self.frame % 5 == 0 and hda2 and not camera_scc:
|
||||
can_sends.extend(hyundaicanfd.create_suppress_lfa(self.packer, self.CAN, CS))
|
||||
|
||||
# LFA and HDA icons
|
||||
if self.frame % 5 == 0 and (not hda2 or hda2_long or camera_scc):
|
||||
can_sends.extend(hyundaicanfd.create_lfahda_cluster(self.packer, CS, self.CAN, CC.longActive, CC.latActive))
|
||||
if not camera_scc:
|
||||
can_sends.extend(hyundaicanfd.create_lfa_icon_non_camera_scc(self.packer, CS, self.CAN, CC))
|
||||
|
||||
# blinkers
|
||||
if hda2 and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
|
||||
can_sends.extend(hyundaicanfd.create_spas_messages(self.packer, self.CAN, self.frame, CC.leftBlinker, CC.rightBlinker))
|
||||
|
||||
if self.camera_scc_params in [2, 3]:
|
||||
self.canfd_toggle_adas(CC, CS)
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
self.hyundai_jerk.make_jerk(self.CP, CS, accel, actuators, hud_control)
|
||||
self.hyundai_jerk.check_carrot_cruise(CC, CS, hud_control, stopping, accel, actuators.aTarget)
|
||||
|
||||
if True: #not camera_scc:
|
||||
can_sends.extend(hyundaicanfd.create_ccnc_messages(self.CP, self.packer, self.CAN, self.frame, CC, CS, hud_control, apply_angle, left_lane_warning, right_lane_warning, self.enable_corner_radar, stopping, self.canfd_debug))
|
||||
if hda2:
|
||||
can_sends.extend(hyundaicanfd.create_adrv_messages(self.CP, self.packer, self.CAN, self.frame))
|
||||
else:
|
||||
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.CP, self.packer, self.CAN, self.frame))
|
||||
if self.frame % 2 == 0:
|
||||
if self.CP.flags & HyundaiFlags.CAMERA_SCC.value:
|
||||
msg = hyundaicanfd.create_acc_control_scc2(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
|
||||
set_speed_in_units, hud_control, self.hyundai_jerk, CS)
|
||||
if msg is not None:
|
||||
can_sends.append(msg)
|
||||
can_sends.extend(hyundaicanfd.create_tcs_messages(self.packer, self.CAN, CS)) # for sorento SCC radar...
|
||||
else:
|
||||
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, self.hyundai_jerk.jerk_u, self.hyundai_jerk.jerk_l, CS))
|
||||
self.accel_last = accel
|
||||
else:
|
||||
# button presses
|
||||
if self.camera_scc_params == 3: # camera scc but stock long
|
||||
send_button = self.make_spam_button(CC, CS)
|
||||
can_sends.extend(hyundaicanfd.forward_button_message(self.packer, self.CAN, self.frame, CS, send_button, self.MainMode_ACC_trigger, self.LFA_trigger))
|
||||
else:
|
||||
can_sends.extend(self.create_button_messages(CC, CS, use_clu11=False))
|
||||
else:
|
||||
can_sends.extend(self.create_can_msgs(apply_steer_req, apply_torque, torque_fault, set_speed_in_units, accel,
|
||||
stopping, hud_control, actuators, CS, CC))
|
||||
if CS.lkas11 is not None:
|
||||
if self.lkas11_active:
|
||||
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_torque, apply_steer_req,
|
||||
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
|
||||
hud_control.leftLaneVisible, hud_control.rightLaneVisible,
|
||||
left_lane_warning, right_lane_warning, self.is_ldws_car))
|
||||
self.lkas11_active = True
|
||||
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
can_sends.extend(self.create_button_messages(CC, CS, use_clu11=True))
|
||||
if self.CP.carFingerprint in CAN_GEARS["send_mdps12"] and CS.mdps12 is not None: # send mdps12 to LKAS to prevent LKAS error
|
||||
can_sends.append(hyundaican.create_mdps12(self.packer, self.frame, CS.mdps12))
|
||||
|
||||
casper_ev = self.CP.carFingerprint == CAR.HYUNDAI_CASPER_EV
|
||||
if self.frame % 2 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
self.hyundai_jerk.make_jerk(self.CP, CS, accel, actuators, hud_control)
|
||||
self.hyundai_jerk.check_carrot_cruise(CC, CS, hud_control, stopping, accel, actuators.aTarget)
|
||||
#jerk = 3.0 if actuators.longControlState == LongCtrlState.pid else 1.0
|
||||
use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value
|
||||
if camera_scc:
|
||||
|
||||
can_sends.extend(hyundaican.create_acc_commands_scc(self.packer, CC.enabled, accel, self.hyundai_jerk, int(self.frame / 2),
|
||||
hud_control, set_speed_in_units, stopping,
|
||||
CC.cruiseControl.override, casper_ev, CS, self.soft_hold_mode))
|
||||
else:
|
||||
can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled, accel, self.hyundai_jerk, int(self.frame / 2),
|
||||
hud_control, set_speed_in_units, stopping,
|
||||
CC.cruiseControl.override, use_fca, self.CP, CS, self.soft_hold_mode))
|
||||
|
||||
|
||||
# 20 Hz LFA MFA message
|
||||
if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value:
|
||||
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC, self.blinking_signal))
|
||||
|
||||
# 5 Hz ACC options
|
||||
if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
if camera_scc:
|
||||
if CS.scc13 is not None:
|
||||
if casper_ev:
|
||||
#can_sends.append(hyundaican.create_acc_opt_copy(CS, self.packer))
|
||||
pass
|
||||
pass
|
||||
else:
|
||||
can_sends.extend(hyundaican.create_acc_opt(self.packer, self.CP))
|
||||
|
||||
# 2 Hz front radar options
|
||||
if self.frame % 50 == 0 and self.CP.openpilotLongitudinalControl and not camera_scc:
|
||||
can_sends.append(hyundaican.create_frt_radar_opt(self.packer))
|
||||
|
||||
new_actuators = actuators.as_builder()
|
||||
new_actuators.torque = apply_torque / self.params.STEER_MAX
|
||||
new_actuators.torqueOutputCan = apply_torque
|
||||
new_actuators.accel = self.tuning.actual_accel
|
||||
# torqueOutputCan reflects the steering authority value actually sent over CAN.
|
||||
# Torque-control platforms send the signed torque command, while angle-control
|
||||
# platforms send LKAS_ANGLE_MAX_TORQUE alongside the requested angle.
|
||||
new_actuators.torqueOutputCan = self.lkas_max_torque if angle_control else apply_torque
|
||||
new_actuators.steeringAngleDeg = float(apply_angle)
|
||||
new_actuators.accel = accel
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
||||
def create_can_msgs(self, apply_steer_req, apply_torque, torque_fault, set_speed_in_units, accel, stopping, hud_control, actuators, CS, CC):
|
||||
|
||||
def create_button_messages(self, CC: structs.CarControl, CS: CarState, use_clu11: bool):
|
||||
can_sends = []
|
||||
if CS.out.brakePressed or CS.out.brakeHoldActive:
|
||||
return can_sends
|
||||
if use_clu11:
|
||||
if CS.clu11 is None:
|
||||
return can_sends
|
||||
|
||||
# HUD messages
|
||||
sys_warning, sys_state, left_lane_warning, right_lane_warning = process_hud_alert(CC.enabled, self.car_fingerprint,
|
||||
hud_control)
|
||||
|
||||
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_torque, apply_steer_req,
|
||||
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
|
||||
hud_control.leftLaneVisible, hud_control.rightLaneVisible,
|
||||
left_lane_warning, right_lane_warning,
|
||||
self.lkas_icon))
|
||||
|
||||
# Button messages
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
if CC.cruiseControl.cancel:
|
||||
can_sends.append(hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.CANCEL, self.CP))
|
||||
elif CC.cruiseControl.resume:
|
||||
elif False: #CC.cruiseControl.resume:
|
||||
# send resume at a max freq of 10Hz
|
||||
if (self.frame - self.last_button_frame) * DT_CTRL > 0.1:
|
||||
# send 25 messages at a time to increases the likelihood of resume being accepted
|
||||
@@ -166,81 +584,205 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
|
||||
if (self.frame - self.last_button_frame) * DT_CTRL >= 0.15:
|
||||
self.last_button_frame = self.frame
|
||||
|
||||
if self.frame % 2 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
# TODO: unclear if this is needed
|
||||
jerk = 3.0 if actuators.longControlState == LongCtrlState.pid else 1.0
|
||||
use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value
|
||||
can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled, accel, jerk, int(self.frame / 2),
|
||||
self.lead_data, hud_control, set_speed_in_units, stopping,
|
||||
CC.cruiseControl.override, use_fca, self.CP,
|
||||
CS.main_cruise_enabled, self.tuning, self.ESCC))
|
||||
if self.last_button_frame != self.frame:
|
||||
send_button = self.make_spam_button(CC, CS)
|
||||
if send_button > 0:
|
||||
can_sends.append(hyundaican.create_clu11_button(self.packer, self.frame, CS.clu11, send_button, self.CP))
|
||||
|
||||
# 20 Hz LFA MFA message
|
||||
if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value:
|
||||
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled, self.lfa_icon))
|
||||
|
||||
# 5 Hz ACC options
|
||||
if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl:
|
||||
can_sends.extend(hyundaican.create_acc_opt(self.packer, self.CP, self.ESCC))
|
||||
|
||||
# 2 Hz front radar options
|
||||
if self.frame % 50 == 0 and self.CP.openpilotLongitudinalControl and not self.ESCC.enabled:
|
||||
can_sends.append(hyundaican.create_frt_radar_opt(self.packer))
|
||||
|
||||
return can_sends
|
||||
|
||||
def create_canfd_msgs(self, apply_steer_req, apply_torque, set_speed_in_units, accel, stopping, hud_control, CS, CC):
|
||||
can_sends = []
|
||||
|
||||
lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING
|
||||
lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl
|
||||
|
||||
# steering control
|
||||
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, self.lkas_icon))
|
||||
|
||||
# prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU
|
||||
if self.frame % 5 == 0 and lka_steering:
|
||||
can_sends.append(hyundaicanfd.create_suppress_lfa(self.packer, self.CAN, CS.lfa_block_msg,
|
||||
self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT))
|
||||
|
||||
# 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, self.lfa_icon))
|
||||
|
||||
# blinkers
|
||||
if lka_steering and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
|
||||
can_sends.extend(hyundaicanfd.create_spas_messages(self.packer, self.CAN, CC.leftBlinker, CC.rightBlinker))
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if lka_steering:
|
||||
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
||||
else:
|
||||
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame))
|
||||
if self.frame % 2 == 0:
|
||||
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, self.lead_data, CS.main_cruise_enabled, self.tuning))
|
||||
self.accel_last = accel
|
||||
else:
|
||||
# button presses
|
||||
|
||||
# carrot.. 왜 alt_cruise_button는 값이 리스트일까?, 그리고 왜? 빈데이터가 들어오는것일까?
|
||||
if CS.cruise_buttons_msg is not None and self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
|
||||
try:
|
||||
cruise_buttons_msg_values = {key: value[0] for key, value in CS.cruise_buttons_msg.items()}
|
||||
except: # IndexError:
|
||||
#print("IndexError....")
|
||||
cruise_buttons_msg_values = None
|
||||
self.cruise_buttons_msg_cnt += 1
|
||||
if cruise_buttons_msg_values is not None:
|
||||
self.cruise_buttons_msg_values = cruise_buttons_msg_values
|
||||
self.cruise_buttons_msg_cnt = 0
|
||||
|
||||
if (self.frame - self.last_button_frame) * DT_CTRL > 0.25:
|
||||
# cruise cancel
|
||||
if CC.cruiseControl.cancel:
|
||||
if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
|
||||
can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
|
||||
self.last_button_frame = self.frame
|
||||
else:
|
||||
for _ in range(20):
|
||||
can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, CS.buttons_counter + 1, Buttons.CANCEL))
|
||||
if (self.frame - self.last_button_frame) * DT_CTRL > 0.1:
|
||||
print("cruiseControl.cancel222222")
|
||||
if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
|
||||
#can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.scc_control))
|
||||
if self.cruise_buttons_msg_values is not None:
|
||||
can_sends.append(hyundaicanfd.alt_cruise_buttons(self.packer, self.CP, self.CAN, Buttons.CANCEL, self.cruise_buttons_msg_values, self.cruise_buttons_msg_cnt))
|
||||
|
||||
else:
|
||||
for _ in range(20):
|
||||
can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.CANCEL))
|
||||
self.last_button_frame = self.frame
|
||||
|
||||
# cruise standstill resume
|
||||
elif CC.cruiseControl.resume:
|
||||
elif False: #CC.cruiseControl.resume:
|
||||
if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
|
||||
# TODO: resume for alt button cars
|
||||
pass
|
||||
else:
|
||||
for _ in range(20):
|
||||
can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, CS.buttons_counter + 1, Buttons.RES_ACCEL))
|
||||
can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.RES_ACCEL))
|
||||
self.last_button_frame = self.frame
|
||||
|
||||
## button 스패밍을 안했을때...
|
||||
if self.last_button_frame != self.frame:
|
||||
dat = self.canfd_speed_control_pcm(CC, CS, self.cruise_buttons_msg_values)
|
||||
if dat is not None:
|
||||
for _ in range(self.button_spam3):
|
||||
can_sends.append(dat)
|
||||
self.cruise_buttons_msg_cnt += 1
|
||||
|
||||
return can_sends
|
||||
|
||||
def canfd_toggle_adas(self, CC, CS):
|
||||
trigger_min = -200
|
||||
trigger_start = 6
|
||||
self.MainMode_ACC_trigger = max(trigger_min, self.MainMode_ACC_trigger - 1)
|
||||
self.LFA_trigger = max(trigger_min, self.LFA_trigger - 1)
|
||||
if self.MainMode_ACC_trigger == trigger_min and self.LFA_trigger == trigger_min:
|
||||
if CC.enabled and not CS.MainMode_ACC and CS.out.vEgo > 3.:
|
||||
self.MainMode_ACC_trigger = trigger_start
|
||||
elif CC.latActive and CS.LFA_ICON == 0:
|
||||
self.LFA_trigger = trigger_start
|
||||
|
||||
def canfd_speed_control_pcm(self, CC, CS, cruise_buttons_msg_values):
|
||||
|
||||
alt_buttons = True if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS else False
|
||||
|
||||
if alt_buttons and cruise_buttons_msg_values is None:
|
||||
return None
|
||||
|
||||
send_button = self.make_spam_button(CC, CS)
|
||||
if send_button > 0:
|
||||
if alt_buttons:
|
||||
return hyundaicanfd.alt_cruise_buttons(self.packer, self.CP, self.CAN, send_button, cruise_buttons_msg_values, self.cruise_buttons_msg_cnt)
|
||||
else:
|
||||
return hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, CS.buttons_counter+1, send_button)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def make_spam_button(self, CC, CS):
|
||||
hud_control = CC.hudControl
|
||||
set_speed_in_units = hud_control.setSpeed * (CV.MS_TO_KPH if CS.is_metric else CV.MS_TO_MPH)
|
||||
target = int(set_speed_in_units+0.5)
|
||||
current = int(CS.out.cruiseState.speed * (CV.MS_TO_KPH if CS.is_metric else CV.MS_TO_MPH) + 0.5)
|
||||
v_ego_kph = CS.out.vEgo * CV.MS_TO_KPH
|
||||
|
||||
send_button = 0
|
||||
activate_cruise = False
|
||||
|
||||
if CC.enabled:
|
||||
if not CS.out.cruiseState.enabled:
|
||||
if (hud_control.leadVisible or v_ego_kph > 10.0) and self.activateCruise == 0:
|
||||
send_button = Buttons.RES_ACCEL
|
||||
self.activateCruise = 1
|
||||
activate_cruise = True
|
||||
elif CC.cruiseControl.resume:
|
||||
send_button = Buttons.RES_ACCEL
|
||||
elif target < current and current>= 31 and self.speed_from_pcm != 1:
|
||||
send_button = Buttons.SET_DECEL
|
||||
elif target > current and current < 160 and self.speed_from_pcm != 1:
|
||||
send_button = Buttons.RES_ACCEL
|
||||
elif CS.out.activateCruise: #CC.cruiseControl.activate:
|
||||
if (hud_control.leadVisible or v_ego_kph > 10.0) and self.activateCruise == 0:
|
||||
self.activateCruise = 1
|
||||
send_button = Buttons.RES_ACCEL
|
||||
activate_cruise = True
|
||||
|
||||
if CS.out.brakePressed or CS.out.gasPressed:
|
||||
self.activateCruise = 0
|
||||
|
||||
if send_button == 0:
|
||||
self.button_spamming_count = 0
|
||||
self.prev_clu_speed = current
|
||||
return 0
|
||||
|
||||
speed_diff = self.prev_clu_speed - current
|
||||
spamming_max = self.button_spam1
|
||||
if CS.cruise_buttons[-1] != Buttons.NONE:
|
||||
self.last_button_frame = self.frame
|
||||
self.button_wait = self.button_spam2
|
||||
self.button_spamming_count = 0
|
||||
elif abs(self.button_spamming_count) >= spamming_max or abs(speed_diff) > 0:
|
||||
self.last_button_frame = self.frame
|
||||
self.button_wait = self.button_spam2 if abs(self.button_spamming_count) >= spamming_max else 7
|
||||
self.button_spamming_count = 0
|
||||
|
||||
self.prev_clu_speed = current
|
||||
send_button_allowed = (self.frame - self.last_button_frame) > self.button_wait
|
||||
#CC.debugTextCC = "{} speed_diff={:.1f},{:.0f}/{:.0f}, button={}, button_wait={}, count={}".format(
|
||||
# send_button_allowed, speed_diff, target, current, send_button, self.button_wait, self.button_spamming_count)
|
||||
|
||||
if send_button_allowed or activate_cruise or (CC.cruiseControl.resume and self.frame % 2 == 0):
|
||||
self.button_spamming_count = self.button_spamming_count + 1 if send_button == Buttons.RES_ACCEL else self.button_spamming_count - 1
|
||||
return send_button
|
||||
else:
|
||||
self.button_spamming_count = 0
|
||||
return 0
|
||||
|
||||
from openpilot.common.filter_simple import MyMovingAverage
|
||||
class HyundaiJerk:
|
||||
def __init__(self):
|
||||
self.params = Params()
|
||||
self.jerk = 0.0
|
||||
self.jerk_u = self.jerk_l = 0.0
|
||||
self.cb_upper = self.cb_lower = 0.0
|
||||
self.jerk_u_min = 0.5
|
||||
self.carrot_cruise = 1
|
||||
self.carrot_cruise_accel = 0.0
|
||||
|
||||
def check_carrot_cruise(self, CC, CS, hud_control, stopping, accel, a_target):
|
||||
carrot_cruise_decel = self.params.get_float("CarrotCruiseDecel")
|
||||
carrot_cruise_atc_decel = self.params.get_float("CarrotCruiseAtcDecel")
|
||||
if carrot_cruise_atc_decel >= 0 and 0 < hud_control.atcDistance < 500:
|
||||
carrot_cruise_decel = max(carrot_cruise_decel, carrot_cruise_atc_decel)
|
||||
self.carrot_cruise = 0
|
||||
if CS.out.carrotCruise > 0 and not CC.cruiseControl.override:
|
||||
if CS.softHoldActive == 0 and not stopping:
|
||||
if CS.out.vEgo > 10/3.6:
|
||||
if carrot_cruise_decel < 0:
|
||||
if (a_target > -0.1 or accel > -0.1):
|
||||
self.carrot_cruise = 1
|
||||
self.carrot_cruise_accel = 0.0
|
||||
else:
|
||||
self.carrot_cruise = 2
|
||||
carrot_cruise = min(accel, -carrot_cruise_decel * 0.01)
|
||||
self.carrot_cruise_accel = max(carrot_cruise, self.carrot_cruise_accel - 1.0 * DT_CTRL) # 점진적으로 줄임.
|
||||
if self.carrot_cruise == 0:
|
||||
self.carrot_cruise_accel = CS.out.aEgo
|
||||
|
||||
def make_jerk(self, CP, CS, accel, actuators, hud_control):
|
||||
if actuators.longControlState == LongCtrlState.stopping:
|
||||
self.jerk = self.jerk_u_min / 2 - CS.out.aEgo
|
||||
else:
|
||||
jerk = actuators.jerk if actuators.longControlState == LongCtrlState.pid else 0.0
|
||||
#a_error = actuators.aTarget - CS.out.aEgo
|
||||
self.jerk = jerk# + a_error
|
||||
|
||||
jerk_max_l = 5.0
|
||||
jerk_max_u = jerk_max_l
|
||||
if actuators.longControlState == LongCtrlState.off:
|
||||
self.jerk_u = jerk_max_u
|
||||
self.jerk_l = jerk_max_l
|
||||
self.cb_upper = self.cb_lower = 0.0
|
||||
else:
|
||||
if CP.flags & HyundaiFlags.CANFD:
|
||||
# Keep deceleration authority after the MPC jerk settles to zero. Stock SCC raises the
|
||||
# lower jerk limit with the raw acceleration request instead of relying on jerk alone.
|
||||
jerk_l_base = 1.2
|
||||
jerk_l_raw = np.clip(jerk_l_base + 2.0 * max(0.0, -accel - 2.8), jerk_l_base, jerk_max_l)
|
||||
jerk_l_mpc = np.clip(-self.jerk * 4.0, jerk_l_base, jerk_max_l)
|
||||
|
||||
self.jerk_u = min(max(self.jerk_u_min, self.jerk * 2.0), jerk_max_u)
|
||||
self.jerk_l = max(jerk_l_raw, jerk_l_mpc)
|
||||
self.cb_upper = self.cb_lower = 0.0
|
||||
else:
|
||||
self.jerk_u = min(max(self.jerk_u_min, self.jerk * 2.0), jerk_max_u)
|
||||
self.jerk_l = min(max(1.0, -self.jerk * 4.0), jerk_max_l)
|
||||
self.cb_upper = np.clip(0.9 + accel * 0.2, 0, 1.2)
|
||||
self.cb_lower = np.clip(0.8 + accel * 0.2, 0, 1.2)
|
||||
|
||||
@@ -1,47 +1,83 @@
|
||||
from collections import deque
|
||||
import copy
|
||||
import math
|
||||
import numpy as np
|
||||
import ast
|
||||
|
||||
from iqdbc.can import CANDefine, CANParser
|
||||
from iqdbc.car import Bus, create_button_events, structs
|
||||
from iqdbc.car import Bus, create_button_events, structs, DT_CTRL
|
||||
from iqdbc.car.common.conversions import Conversions as CV
|
||||
from iqdbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags, CAR, DBC, Buttons, CarControllerParams
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags, CAR, DBC, Buttons, CarControllerParams, CAMERA_SCC_CAR, HyundaiExtFlags, \
|
||||
EV_MODE_ACTIVE_VALUES, EV_MODE_STATUS_ADDR, EV_MODE_STATUS_DLC, EV_MODE_STATUS_MSG, \
|
||||
EV_MODE_STATUS_SIGNAL
|
||||
from iqdbc.car.interfaces import CarStateBase
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.carstate_ext import CarStateExt
|
||||
from iqdbc.iqpilot.car.hyundai.escc import EsccCarStateBase
|
||||
from iqdbc.iqpilot.car.hyundai.aol import AolCarState
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ
|
||||
from openpilot.common.params import Params
|
||||
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
|
||||
PREV_BUTTON_SAMPLES = 8
|
||||
CLUSTER_SAMPLE_RATE = 20 # frames
|
||||
STANDSTILL_THRESHOLD = 12 * 0.03125
|
||||
STANDSTILL_THRESHOLD = 12 * 0.03125 * CV.KPH_TO_MS
|
||||
|
||||
# Cancel button can sometimes be ACC pause/resume button, main button can also enable on some cars
|
||||
ENABLE_BUTTONS = (Buttons.RES_ACCEL, Buttons.SET_DECEL, Buttons.CANCEL)
|
||||
BUTTONS_DICT = {Buttons.RES_ACCEL: ButtonType.accelCruise, Buttons.SET_DECEL: ButtonType.decelCruise,
|
||||
Buttons.GAP_DIST: ButtonType.gapAdjustCruise, Buttons.CANCEL: ButtonType.cancel}
|
||||
Buttons.GAP_DIST: ButtonType.gapAdjustCruise, Buttons.CANCEL: ButtonType.cancel, Buttons.LFA_BUTTON: ButtonType.lfaButton}
|
||||
|
||||
GearShifter = structs.CarState.GearShifter
|
||||
|
||||
READY_COUNT_OK = 200
|
||||
TRAILER_DISCONNECT_GRACE_FRAMES = int(5.0 / DT_CTRL)
|
||||
EV_MODE_STATUS_TIMEOUT_NS = 500_000_000
|
||||
|
||||
|
||||
class CarState(CarStateBase, EsccCarStateBase, AolCarState, CarStateExt):
|
||||
def __init__(self, CP, CP_IQ):
|
||||
CarStateBase.__init__(self, CP, CP_IQ)
|
||||
EsccCarStateBase.__init__(self)
|
||||
AolCarState.__init__(self, CP, CP_IQ)
|
||||
CarStateExt.__init__(self, CP, CP_IQ)
|
||||
def _get_ev_mode_state(cp: CANParser) -> tuple[bool, bool]:
|
||||
timestamps = cp.ts_nanos.get(EV_MODE_STATUS_MSG)
|
||||
if timestamps is None:
|
||||
return False, False
|
||||
|
||||
timestamp = timestamps.get(EV_MODE_STATUS_SIGNAL, 0)
|
||||
dat = cp.dat.get(EV_MODE_STATUS_ADDR, b"")
|
||||
# The update timestamp advances even when the whole ECAN bus is silent.
|
||||
# last_nonempty_nanos would leave the final decoded state valid forever.
|
||||
age = cp._last_update_nanos - timestamp
|
||||
valid = timestamp > 0 and len(dat) == EV_MODE_STATUS_DLC and not cp.bus_timeout and 0 <= age <= EV_MODE_STATUS_TIMEOUT_NS
|
||||
active = valid and int(cp.vl[EV_MODE_STATUS_MSG][EV_MODE_STATUS_SIGNAL]) in EV_MODE_ACTIVE_VALUES
|
||||
return active, valid
|
||||
|
||||
|
||||
NUMERIC_TO_TZ = {
|
||||
840: "America/New_York", # 미국 (US) → 동부 시간대
|
||||
124: "America/Toronto", # 캐나다 (CA) → 동부 시간대
|
||||
250: "Europe/Paris", # 프랑스 (FR)
|
||||
276: "Europe/Berlin", # 독일 (DE)
|
||||
826: "Europe/London", # 영국 (GB)
|
||||
392: "Asia/Tokyo", # 일본 (JP)
|
||||
156: "Asia/Shanghai", # 중국 (CN)
|
||||
410: "Asia/Seoul", # 한국 (KR)
|
||||
36: "Australia/Sydney", # 호주 (AU)
|
||||
356: "Asia/Kolkata", # 인도 (IN)
|
||||
}
|
||||
|
||||
class CarState(CarStateBase):
|
||||
def __init__(self, CP, CP_IQ=None):
|
||||
super().__init__(CP, CP_IQ or structs.IQCarParams())
|
||||
can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt])
|
||||
|
||||
self.cruise_buttons: deque = deque([Buttons.NONE] * PREV_BUTTON_SAMPLES, maxlen=PREV_BUTTON_SAMPLES)
|
||||
self.main_buttons: deque = deque([Buttons.NONE] * PREV_BUTTON_SAMPLES, maxlen=PREV_BUTTON_SAMPLES)
|
||||
self.lda_button = 0
|
||||
|
||||
self.gear_msg_canfd = "ACCELERATOR" if CP.flags & HyundaiFlags.EV else \
|
||||
self.gear_msg_canfd = "GEAR" if CP.extFlags & HyundaiExtFlags.CANFD_GEARS_69 else \
|
||||
"ACCELERATOR" if CP.flags & HyundaiFlags.EV else \
|
||||
"GEAR_ALT" if CP.flags & HyundaiFlags.CANFD_ALT_GEARS else \
|
||||
"GEAR_ALT_2" if CP.flags & HyundaiFlags.CANFD_ALT_GEARS_2 else \
|
||||
"GEAR_SHIFTER"
|
||||
|
||||
self.use_accelerator = self.gear_msg_canfd == "ACCELERATOR"
|
||||
if CP.flags & HyundaiFlags.CANFD:
|
||||
self.shifter_values = can_define.dv[self.gear_msg_canfd]["GEAR"]
|
||||
elif CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV):
|
||||
@@ -63,31 +99,210 @@ class CarState(CarStateBase, EsccCarStateBase, AolCarState, CarStateExt):
|
||||
self.is_metric = False
|
||||
self.buttons_counter = 0
|
||||
|
||||
self.cruise_info = {}
|
||||
# for generic CAN parsing
|
||||
self.fca11 = None
|
||||
self.scc11 = None
|
||||
self.scc12 = None
|
||||
self.scc13 = None
|
||||
self.scc14 = None
|
||||
self.lkas11 = None
|
||||
self.clu11 = None
|
||||
|
||||
# for CANFD parsing
|
||||
self.scc_control = None
|
||||
self.lfa = None
|
||||
self.lfa_alt = None
|
||||
self.lfahda_cluster = None
|
||||
self.adrv_0x161 = None
|
||||
self.adrv_0x200 = None
|
||||
self.adrv_0x1ea = None
|
||||
self.adrv_0x160 = None
|
||||
self.ccnc_0x162 = None
|
||||
self.hda_info_4a3 = None
|
||||
self.tcs = None
|
||||
self.mdps = None
|
||||
self.steer_touch_2af = None
|
||||
self.cruise_buttons_msg = None
|
||||
self.cam_0x362 = None
|
||||
self.cam_0x2a4 = None
|
||||
self.manual_speed_limit_assist = None
|
||||
self.accelerator = None
|
||||
self.blinkers = None
|
||||
self.blinkers_alt = None
|
||||
self.doors_seatbelts = None
|
||||
self.cruise_buttons_alt2 = None
|
||||
|
||||
# On some cars, CLU15->CF_Clu_VehicleSpeed can oscillate faster than the dash updates. Sample at 5 Hz
|
||||
self.cluster_speed = 0
|
||||
self.cluster_speed_counter = CLUSTER_SAMPLE_RATE
|
||||
|
||||
self.params = CarControllerParams(CP)
|
||||
self.op_params = Params()
|
||||
|
||||
self.main_enabled = True if self.op_params.get_int("AutoEngage") == 2 else False
|
||||
self.gear_shifter = GearShifter.drive # Gear_init for Nexo ?? unknown 21.02.23.LSW
|
||||
|
||||
self.totalDistance = 0.0
|
||||
self.speedLimitDistance = 0
|
||||
self.pcmCruiseGap = 0
|
||||
|
||||
self.cruise_buttons_alt = True if self.CP.carFingerprint in (CAR.HYUNDAI_CASPER, CAR.HYUNDAI_CASPER_EV) else False
|
||||
self.MainMode_ACC = False
|
||||
self.ACCMode = 0
|
||||
self.LFA_ICON = 0
|
||||
self.paddle_button_prev = 0
|
||||
|
||||
self.lf_distance = 0
|
||||
self.rf_distance = 0
|
||||
self.lr_distance = 0
|
||||
self.rr_distance = 0
|
||||
#self.lf_lateral = 0
|
||||
#self.rf_lateral = 0
|
||||
|
||||
fingerprints_str = Params().get("FingerPrints")
|
||||
try:
|
||||
fingerprints = ast.literal_eval(fingerprints_str) if fingerprints_str else {i: {} for i in range(8)}
|
||||
except (SyntaxError, ValueError):
|
||||
fingerprints = {i: {} for i in range(8)}
|
||||
#print("fingerprints =", fingerprints)
|
||||
ecu_disabled = False
|
||||
if self.CP.openpilotLongitudinalControl and not (self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC):
|
||||
ecu_disabled = True
|
||||
|
||||
|
||||
self.HAS_LFA_BUTTON = True if 913 in fingerprints[0] else False
|
||||
self.CRUISE_BUTTON_ALT = True if 1007 in fingerprints[0] else False
|
||||
|
||||
cam_bus = CanBus(CP).CAM
|
||||
pt_bus = CanBus(CP).ECAN
|
||||
alt_bus = CanBus(CP).ACAN
|
||||
self.GEAR = True if 69 in fingerprints[pt_bus] else False
|
||||
self.GEAR_ALT = True if 64 in fingerprints[pt_bus] else False
|
||||
self.TPMS = True if 0x3a0 in fingerprints[pt_bus] else False
|
||||
self.LOCAL_TIME = True if 1264 in fingerprints[pt_bus] else False
|
||||
|
||||
self.cp_bsm = None
|
||||
self.time_zone = "UTC"
|
||||
|
||||
self.cp = None
|
||||
self.cp_cam = None
|
||||
self.cp_alt = None
|
||||
self.controls_ready_count = 0
|
||||
|
||||
# trailer detection
|
||||
self.trailer_connected = False
|
||||
self.trailer_timeout_cnt = 0
|
||||
self.trailer_connected_prev = False
|
||||
self.trailer_status = None
|
||||
|
||||
def monitor_fingerprint(self, can_parsers, canfd):
|
||||
if self.controls_ready_count <= READY_COUNT_OK:
|
||||
if Params().get_bool("ControlsReady"):
|
||||
self.controls_ready_count += 1
|
||||
|
||||
self.cp = can_parsers[Bus.pt]
|
||||
self.cp_cam = can_parsers[Bus.cam]
|
||||
self.cp_alt = can_parsers[Bus.alt] if Bus.alt in can_parsers else None
|
||||
|
||||
def add_if_seen(parser, name, ignore_counter = False):
|
||||
msg = parser.dbc.name_to_msg.get(name)
|
||||
if not msg:
|
||||
print(f"{name} not in DBC")
|
||||
return
|
||||
if msg.address not in parser.seen_addresses:
|
||||
return
|
||||
if msg.address in parser.addresses:
|
||||
return
|
||||
parser._add_message(name, ignore_counter = ignore_counter) # ← 이름으로 등록
|
||||
|
||||
def add_and_cache(parser, name: str, attr: str, ignore_counter: bool = False):
|
||||
add_if_seen(parser, name, ignore_counter)
|
||||
if name in parser.vl: # 등록 성공했을 때만
|
||||
setattr(self, attr, parser.vl[name])
|
||||
return True
|
||||
return False
|
||||
|
||||
if self.controls_ready_count == 50:
|
||||
self.cp.controls_ready = self.cp_cam.controls_ready = True
|
||||
if self.cp_alt is not None:
|
||||
self.cp_alt.controls_ready = True
|
||||
elif self.controls_ready_count == 100:
|
||||
self.cp.enable_capture = self.cp_cam.enable_capture = False
|
||||
if self.cp_alt is not None:
|
||||
self.cp_alt.enable_capture = False
|
||||
elif self.controls_ready_count == 101:
|
||||
print("cp_cam.seen_addresses =", self.cp_cam.seen_addresses)
|
||||
elif self.controls_ready_count == 102:
|
||||
print("cp.seen_addresses =", self.cp.seen_addresses)
|
||||
elif self.controls_ready_count == 103:
|
||||
if self.cp_alt is not None:
|
||||
print("cp_alt.seen_addresses =", self.cp_alt.seen_addresses)
|
||||
else:
|
||||
print("cp_alt.seen_addresses = None")
|
||||
if not canfd:
|
||||
if self.controls_ready_count == 104:
|
||||
if not add_and_cache(self.cp_cam, "FCA11", "fca11"):
|
||||
add_and_cache(self.cp, "FCA11", "fca11")
|
||||
add_and_cache(self.cp_cam, "LKAS11", "lkas11")
|
||||
add_and_cache(self.cp, "CLU11", "clu11")
|
||||
elif self.controls_ready_count == 105:
|
||||
cp_cruise = self.cp_cam if self.CP.flags & HyundaiFlags.CAMERA_SCC else self.cp
|
||||
scc_messages_expected = not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC
|
||||
if scc_messages_expected:
|
||||
add_and_cache(cp_cruise, "SCC11", "scc11")
|
||||
add_and_cache(cp_cruise, "SCC12", "scc12")
|
||||
add_and_cache(cp_cruise, "SCC13", "scc13")
|
||||
add_and_cache(cp_cruise, "SCC14", "scc14")
|
||||
else: # canfd
|
||||
if self.controls_ready_count == 120:
|
||||
cp_cruise = self.cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else self.cp
|
||||
add_and_cache(cp_cruise, "SCC_CONTROL", "scc_control")
|
||||
elif self.controls_ready_count == 121:
|
||||
add_and_cache(self.cp, "TCS", "tcs")
|
||||
add_and_cache(self.cp, "MDPS", "mdps")
|
||||
add_and_cache(self.cp_cam, "LFA", "lfa")
|
||||
add_and_cache(self.cp_cam, "LFA_ALT", "lfa_alt")
|
||||
add_and_cache(self.cp_cam, "LFAHDA_CLUSTER", "lfahda_cluster")
|
||||
elif self.controls_ready_count == 122:
|
||||
add_and_cache(self.cp_cam, "ADRV_0x161", "adrv_0x161")
|
||||
add_and_cache(self.cp_cam, "ADRV_0x200", "adrv_0x200")
|
||||
add_and_cache(self.cp_cam, "ADRV_0x1ea", "adrv_0x1ea")
|
||||
add_and_cache(self.cp_cam, "ADRV_0x160", "adrv_0x160")
|
||||
add_and_cache(self.cp_cam, "CCNC_0x162", "ccnc_0x162")
|
||||
elif self.controls_ready_count == 123:
|
||||
add_and_cache(self.cp, "HDA_INFO_4A3", "hda_info_4a3")
|
||||
add_and_cache(self.cp, "STEER_TOUCH_2AF", "steer_touch_2af")
|
||||
elif self.controls_ready_count == 124:
|
||||
add_and_cache(self.cp, self.cruise_btns_msg_canfd, "cruise_buttons_msg")
|
||||
if not add_and_cache(self.cp_cam, "CAM_0x362", "cam_0x362") and self.cp_alt is not None:
|
||||
add_and_cache(self.cp_alt, "CAM_0x362", "cam_0x362")
|
||||
if not add_and_cache(self.cp_alt, "CAM_0x2a4", "cam_0x2a4") and self.cp_cam is not None:
|
||||
add_and_cache(self.cp_cam, "CAM_0x2a4", "cam_0x2a4")
|
||||
elif self.controls_ready_count == 125:
|
||||
add_and_cache(self.cp, "MANUAL_SPEED_LIMIT_ASSIST", "manual_speed_limit_assist", ignore_counter = True)
|
||||
if self.gear_msg_canfd == "ACCELERATOR":
|
||||
add_and_cache(self.cp, "ACCELERATOR", "accelerator", ignore_counter = True)
|
||||
add_and_cache(self.cp, "BLINKERS", "blinkers")
|
||||
add_and_cache(self.cp, "BLINKERS_ALT", "blinkers_alt")
|
||||
add_and_cache(self.cp, "DOORS_SEATBELTS", "doors_seatbelts")
|
||||
elif self.controls_ready_count == 126:
|
||||
add_and_cache(self.cp, "CRUISE_BUTTONS_ALT2", "cruise_buttons_alt2", ignore_counter = True)
|
||||
add_and_cache(self.cp, "TRAILER_STATUS", "trailer_status", ignore_counter = True)
|
||||
|
||||
|
||||
|
||||
self.steer_fault_counter = 0
|
||||
|
||||
def recent_button_interaction(self) -> bool:
|
||||
# On some newer model years, the CANCEL button acts as a pause/resume button based on the PCM state
|
||||
# To avoid re-engaging when openpilot cancels, check user engagement intention via buttons
|
||||
# Main button also can trigger an engagement on these cars
|
||||
return any(btn in ENABLE_BUTTONS for btn in self.cruise_buttons) or any(self.main_buttons)
|
||||
|
||||
def update(self, can_parsers) -> tuple[structs.CarState, structs.IQCarState]:
|
||||
self.monitor_fingerprint(can_parsers, self.CP.flags & HyundaiFlags.CANFD)
|
||||
cp = can_parsers[Bus.pt]
|
||||
cp_cam = can_parsers[Bus.cam]
|
||||
cp_alt = can_parsers[Bus.alt] if Bus.alt in can_parsers else None
|
||||
|
||||
if self.CP.flags & HyundaiFlags.CANFD:
|
||||
return self.update_canfd(can_parsers)
|
||||
return self.update_canfd(can_parsers), self.out_iq
|
||||
|
||||
ret = structs.CarState()
|
||||
ret_iq = structs.IQCarState()
|
||||
cp_cruise = cp_cam if self.CP.flags & HyundaiFlags.CAMERA_SCC else cp
|
||||
self.is_metric = cp.vl["CLU11"]["CF_Clu_SPEED_UNIT"] == 0
|
||||
speed_conv = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS
|
||||
@@ -97,13 +312,18 @@ class CarState(CarStateBase, EsccCarStateBase, AolCarState, CarStateExt):
|
||||
|
||||
ret.seatbeltUnlatched = cp.vl["CGW1"]["CF_Gway_DrvSeatBeltSw"] == 0
|
||||
|
||||
self.parse_wheel_speeds(ret,
|
||||
if cp.ts_nanos["EMS21"]["SCR_UREA_LEVEL"] > 0:
|
||||
ret.ureaGauge = float(np.clip(cp.vl["EMS21"]["SCR_UREA_LEVEL"] / 100.0, 0.0, 1.0))
|
||||
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_FL"],
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_FR"],
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_RL"],
|
||||
cp.vl["WHL_SPD11"]["WHL_SPD_RR"],
|
||||
)
|
||||
ret.standstill = cp.vl["WHL_SPD11"]["WHL_SPD_FL"] <= STANDSTILL_THRESHOLD and cp.vl["WHL_SPD11"]["WHL_SPD_RR"] <= STANDSTILL_THRESHOLD
|
||||
ret.vEgoRaw = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
ret.standstill = ret.wheelSpeeds.fl <= STANDSTILL_THRESHOLD and ret.wheelSpeeds.rr <= STANDSTILL_THRESHOLD
|
||||
|
||||
self.cluster_speed_counter += 1
|
||||
if self.cluster_speed_counter > CLUSTER_SAMPLE_RATE:
|
||||
@@ -116,73 +336,109 @@ class CarState(CarStateBase, EsccCarStateBase, AolCarState, CarStateExt):
|
||||
if not self.is_metric and self.CP.carFingerprint not in (CAR.KIA_SORENTO,):
|
||||
self.cluster_speed = math.floor(self.cluster_speed * CV.KPH_TO_MPH + CV.KPH_TO_MPH)
|
||||
|
||||
ret.vEgoCluster = self.cluster_speed * speed_conv
|
||||
#ret.vEgoCluster = self.cluster_speed * speed_conv
|
||||
|
||||
ret.steeringAngleDeg = cp.vl["SAS11"]["SAS_Angle"]
|
||||
ret.steeringRateDeg = cp.vl["SAS11"]["SAS_Speed"]
|
||||
ret.yawRate = cp.vl["ESP12"]["YAW_RATE"]
|
||||
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(
|
||||
50, cp.vl["CGW1"]["CF_Gway_TurnSigLh"], cp.vl["CGW1"]["CF_Gway_TurnSigRh"])
|
||||
ret.steeringTorque = cp.vl["MDPS12"]["CR_Mdps_StrColTq"]
|
||||
ret.steeringTorqueEps = cp.vl["MDPS12"]["CR_Mdps_OutTq"]
|
||||
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
|
||||
steer_fault_raw = cp.vl["MDPS12"]["CF_Mdps_ToiUnavail"] != 0 or cp.vl["MDPS12"]["CF_Mdps_ToiFlt"] != 0
|
||||
self.steer_fault_counter = self.steer_fault_counter + 1 if steer_fault_raw else 0
|
||||
ret.steerFaultTemporary = self.steer_fault_counter > 5
|
||||
ret.steerFaultTemporary = cp.vl["MDPS12"]["CF_Mdps_ToiUnavail"] != 0 or cp.vl["MDPS12"]["CF_Mdps_ToiFlt"] != 0
|
||||
|
||||
# cruise state
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
# These are not used for engage/disengage since openpilot keeps track of state using the buttons
|
||||
ret.cruiseState.available = cp.vl["TCS13"]["ACCEnable"] == 0
|
||||
ret.cruiseState.available = self.main_enabled and self.controls_ready_count >= READY_COUNT_OK #cp.vl["TCS13"]["ACCEnable"] == 0
|
||||
ret.cruiseState.enabled = cp.vl["TCS13"]["ACC_REQ"] == 1
|
||||
ret.cruiseState.standstill = False
|
||||
ret.cruiseState.nonAdaptive = False
|
||||
elif not self.CP_IQ.flags & HyundaiFlagsIQ.NON_SCC:
|
||||
ret.cruiseState.available = cp_cruise.vl["SCC11"]["MainMode_ACC"] == 1
|
||||
elif not self.CP.flags & HyundaiFlags.CC_ONLY_CAR:
|
||||
self.main_enabled = ret.cruiseState.available = cp_cruise.vl["SCC11"]["MainMode_ACC"] == 1
|
||||
ret.cruiseState.enabled = cp_cruise.vl["SCC12"]["ACCMode"] != 0
|
||||
ret.cruiseState.standstill = cp_cruise.vl["SCC11"]["SCCInfoDisplay"] == 4.
|
||||
ret.cruiseState.nonAdaptive = cp_cruise.vl["SCC11"]["SCCInfoDisplay"] == 2. # Shows 'Cruise Control' on dash
|
||||
ret.cruiseState.speed = cp_cruise.vl["SCC11"]["VSetDis"] * speed_conv
|
||||
|
||||
ret.pcmCruiseGap = cp_cruise.vl["SCC11"]["TauGapSet"]
|
||||
|
||||
# TODO: Find brake pressure
|
||||
ret.brake = 0
|
||||
ret.brakePressed = cp.vl["TCS13"]["DriverOverride"] == 2 # 2 includes regen braking by user on HEV/EV
|
||||
ret.brakeHoldActive = cp.vl["TCS15"]["AVH_LAMP"] == 2 # 0 OFF, 1 ERROR, 2 ACTIVE, 3 READY
|
||||
ret.parkingBrake = cp.vl["TCS13"]["PBRAKE_ACT"] == 1
|
||||
ret.espDisabled = cp.vl["TCS11"]["TCS_PAS"] == 1
|
||||
ret.espActive = cp.vl["TCS11"]["ABS_ACT"] == 1
|
||||
ret.accFaulted = cp.vl["TCS13"]["ACCEnable"] != 0 # 0 ACC CONTROL ENABLED, 1-3 ACC CONTROL DISABLED
|
||||
if not self.CP.flags & HyundaiFlags.CC_ONLY_CAR:
|
||||
ret.brakePressed = cp.vl["TCS13"]["DriverOverride"] == 2 # 2 includes regen braking by user on HEV/EV
|
||||
ret.brakeHoldActive = cp.vl["TCS15"]["AVH_LAMP"] == 2 # 0 OFF, 1 ERROR, 2 ACTIVE, 3 READY
|
||||
ret.parkingBrake = cp.vl["TCS13"]["PBRAKE_ACT"] == 1
|
||||
ret.espDisabled = cp.vl["TCS11"]["TCS_PAS"] == 1
|
||||
ret.espActive = cp.vl["TCS11"]["ABS_ACT"] == 1
|
||||
ret.accFaulted = cp.vl["TCS13"]["ACCEnable"] != 0 # 0 ACC CONTROL ENABLED, 1-3 ACC CONTROL DISABLED
|
||||
ret.brakeLights = bool(cp.vl["TCS13"]["BrakeLight"] or ret.brakePressed)
|
||||
|
||||
if self.CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV | HyundaiFlags.FCEV):
|
||||
if self.CP.flags & HyundaiFlags.FCEV:
|
||||
ret.gasPressed = cp.vl["FCEV_ACCELERATOR"]["ACCELERATOR_PEDAL"] > 0
|
||||
ret.gas = cp.vl["FCEV_ACCELERATOR"]["ACCELERATOR_PEDAL"] / 254.
|
||||
elif self.CP.flags & HyundaiFlags.HYBRID:
|
||||
ret.gasPressed = cp.vl["E_EMS11"]["CR_Vcu_AccPedDep_Pos"] > 0
|
||||
ret.gas = cp.vl["E_EMS11"]["CR_Vcu_AccPedDep_Pos"] / 254.
|
||||
else:
|
||||
ret.gasPressed = cp.vl["E_EMS11"]["Accel_Pedal_Pos"] > 0
|
||||
ret.gas = cp.vl["E_EMS11"]["Accel_Pedal_Pos"] / 254.
|
||||
ret.gasPressed = ret.gas > 0
|
||||
else:
|
||||
ret.gas = cp.vl["EMS12"]["PV_AV_CAN"] / 100.
|
||||
ret.gasPressed = bool(cp.vl["EMS16"]["CF_Ems_AclAct"])
|
||||
|
||||
# Gear Selection via Cluster - For those Kia/Hyundai which are not fully discovered, we can use the Cluster Indicator for Gear Selection,
|
||||
# as this seems to be standard over all cars, but is not the preferred method.
|
||||
if self.CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV):
|
||||
gear = cp.vl["ELECT_GEAR"]["Elect_Gear_Shifter"]
|
||||
ret.gearStep = cp.vl["ELECT_GEAR"]["Elect_Gear_Step"]
|
||||
if self.CP.carFingerprint == CAR.HYUNDAI_CASPER_EV:
|
||||
ret.gearStep = 0
|
||||
elif self.CP.flags & HyundaiFlags.FCEV:
|
||||
gear = cp.vl["EMS20"]["HYDROGEN_GEAR_SHIFTER"]
|
||||
elif self.CP.flags & HyundaiFlags.CLUSTER_GEARS:
|
||||
gear = cp.vl["CLU15"]["CF_Clu_Gear"]
|
||||
if self.CP.carFingerprint == CAR.KIA_K7:
|
||||
ret.gearStep = cp.vl["LVR11"]["CF_Lvr_GearInf"]
|
||||
elif self.CP.flags & HyundaiFlags.TCU_GEARS:
|
||||
gear = cp.vl["TCU12"]["CUR_GR"]
|
||||
else:
|
||||
gear = cp.vl["LVR12"]["CF_Lvr_Gear"]
|
||||
ret.gearStep = cp.vl["LVR11"]["CF_Lvr_GearInf"]
|
||||
|
||||
ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear))
|
||||
if not self.CP.carFingerprint in (CAR.HYUNDAI_NEXO):
|
||||
ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear))
|
||||
else:
|
||||
gear = cp.vl["ELECT_GEAR"]["Elect_Gear_Shifter"]
|
||||
gear_disp = cp.vl["ELECT_GEAR"]
|
||||
|
||||
if (not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC) and not self.CP_IQ.flags & HyundaiFlagsIQ.NON_SCC:
|
||||
gear_shifter = GearShifter.unknown
|
||||
|
||||
if gear == 1546: # Thank you for Neokii # fix PolorBear 22.06.05
|
||||
gear_shifter = GearShifter.drive
|
||||
elif gear == 2314:
|
||||
gear_shifter = GearShifter.neutral
|
||||
elif gear == 2569:
|
||||
gear_shifter = GearShifter.park
|
||||
elif gear == 2566:
|
||||
gear_shifter = GearShifter.reverse
|
||||
|
||||
if gear_shifter != GearShifter.unknown and self.gear_shifter != gear_shifter:
|
||||
self.gear_shifter = gear_shifter
|
||||
|
||||
ret.gearShifter = self.gear_shifter
|
||||
|
||||
if not self.CP.flags & HyundaiFlags.CC_ONLY_CAR and (not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC):
|
||||
aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12"
|
||||
aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct"
|
||||
aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0
|
||||
scc_warning = cp_cruise.vl["SCC12"]["TakeOverReq"] == 1 # sometimes only SCC system shows an FCW
|
||||
aeb_braking = cp_cruise.vl[aeb_src]["CF_VSM_DecCmdAct"] != 0 or cp_cruise.vl[aeb_src][aeb_sig] != 0
|
||||
if self.CP.carFingerprint == CAR.HYUNDAI_CASPER_EV and aeb_src == "FCA11":
|
||||
fca_fault = cp_cruise.vl["FCA11"]["FCA_Failinfo"] != 0 or cp_cruise.vl["FCA11"]["FCA_Status"] == 3
|
||||
if fca_fault:
|
||||
aeb_warning = False
|
||||
aeb_braking = False
|
||||
ret.stockFcw = (aeb_warning or scc_warning) and not aeb_braking
|
||||
ret.stockAeb = aeb_warning and aeb_braking
|
||||
|
||||
@@ -190,157 +446,393 @@ class CarState(CarStateBase, EsccCarStateBase, AolCarState, CarStateExt):
|
||||
ret.leftBlindspot = cp.vl["LCA11"]["CF_Lca_IndLeft"] != 0
|
||||
ret.rightBlindspot = cp.vl["LCA11"]["CF_Lca_IndRight"] != 0
|
||||
|
||||
# save the entire LKAS11 and CLU11
|
||||
self.lkas11 = copy.copy(cp_cam.vl["LKAS11"])
|
||||
self.clu11 = copy.copy(cp.vl["CLU11"])
|
||||
self.steer_state = cp.vl["MDPS12"]["CF_Mdps_ToiActive"] # 0 NOT ACTIVE, 1 ACTIVE
|
||||
prev_cruise_buttons = self.cruise_buttons[-1]
|
||||
#self.cruise_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwState"])
|
||||
#carrot {{
|
||||
#if self.CRUISE_BUTTON_ALT and cp.vl["CRUISE_BUTTON_ALT"]["SET_ME_1"] == 1:
|
||||
# self.cruise_buttons_alt = True
|
||||
|
||||
cruise_button = [Buttons.NONE]
|
||||
if self.cruise_buttons_alt:
|
||||
lfa_button = cp.vl["CRUISE_BUTTON_LFA"]["CruiseSwLfa"]
|
||||
cruise_button = [Buttons.LFA_BUTTON] if lfa_button > 0 else [cp.vl["CRUISE_BUTTON_ALT"]["CruiseSwState"]]
|
||||
elif self.HAS_LFA_BUTTON and cp.vl["BCM_PO_11"]["LFA_Pressed"] == 1: # for K5
|
||||
cruise_button = [Buttons.LFA_BUTTON]
|
||||
else:
|
||||
cruise_button = cp.vl_all["CLU11"]["CF_Clu_CruiseSwState"]
|
||||
self.cruise_buttons.extend(cruise_button)
|
||||
# }} carrot
|
||||
prev_main_buttons = self.main_buttons[-1]
|
||||
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:
|
||||
self.lda_button = cp.vl["BCM_PO_11"]["LDA_BTN"]
|
||||
#self.cruise_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwState"])
|
||||
if self.cruise_buttons_alt:
|
||||
self.main_buttons.extend(cp.vl_all["CRUISE_BUTTON_ALT"]["CruiseSwMain"])
|
||||
else:
|
||||
self.main_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwMain"])
|
||||
self.mdps12 = copy.copy(cp.vl["MDPS12"])
|
||||
|
||||
ret.buttonEvents = [*create_button_events(self.cruise_buttons[-1], prev_cruise_buttons, BUTTONS_DICT),
|
||||
*create_button_events(self.main_buttons[-1], prev_main_buttons, {1: ButtonType.mainCruise}),
|
||||
*create_button_events(self.lda_button, prev_lda_button, {1: ButtonType.lkas})]
|
||||
*create_button_events(self.main_buttons[-1], prev_main_buttons, {1: ButtonType.mainCruise})]
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
ret.cruiseState.available = self.get_main_cruise(ret)
|
||||
|
||||
CarStateExt.update(self, ret, ret_iq, can_parsers, speed_conv)
|
||||
if not self.CP.flags & HyundaiFlags.CC_ONLY_CAR:
|
||||
tpms_unit = cp.vl["TPMS11"]["UNIT"] * 0.725 if int(cp.vl["TPMS11"]["UNIT"]) > 0 else 1.
|
||||
ret.tpms.fl = tpms_unit * cp.vl["TPMS11"]["PRESSURE_FL"]
|
||||
ret.tpms.fr = tpms_unit * cp.vl["TPMS11"]["PRESSURE_FR"]
|
||||
ret.tpms.rl = tpms_unit * cp.vl["TPMS11"]["PRESSURE_RL"]
|
||||
ret.tpms.rr = tpms_unit * cp.vl["TPMS11"]["PRESSURE_RR"]
|
||||
|
||||
ret.blockPcmEnable = not self.recent_button_interaction()
|
||||
cluSpeed = cp.vl["CLU11"]["CF_Clu_Vanz"]
|
||||
decimal = cp.vl["CLU11"]["CF_Clu_VanzDecimal"]
|
||||
if 0. < decimal < 0.5:
|
||||
cluSpeed += decimal
|
||||
|
||||
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
|
||||
if ret.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
|
||||
self.low_speed_alert = True
|
||||
if ret.vEgo > (self.CP.minSteerSpeed + 4.):
|
||||
self.low_speed_alert = False
|
||||
ret.lowSpeedAlert = self.low_speed_alert
|
||||
ret.vEgoCluster = cluSpeed * speed_conv
|
||||
vEgoClu, aEgoClu = self.update_clu_speed_kf(ret.vEgoCluster)
|
||||
ret.vCluRatio = (ret.vEgo / vEgoClu) if (vEgoClu > 3. and ret.vEgo > 3.) else 1.0
|
||||
|
||||
return ret, ret_iq
|
||||
if self.CP.extFlags & HyundaiExtFlags.NAVI_CLUSTER.value:
|
||||
speedLimit = cp.vl["Navi_HU"]["SpeedLim_Nav_Clu"]
|
||||
speedLimitCam = cp.vl["Navi_HU"]["SpeedLim_Nav_Cam"]
|
||||
ret.speedLimit = speedLimit if speedLimit < 255 and speedLimitCam == 1 else 0
|
||||
speed_limit_cam = speedLimitCam == 1
|
||||
else:
|
||||
ret.speedLimit = 0
|
||||
ret.speedLimitDistance = 0
|
||||
speed_limit_cam = False
|
||||
|
||||
def update_canfd(self, can_parsers) -> tuple[structs.CarState, structs.IQCarState]:
|
||||
self.update_speed_limit(ret, speed_limit_cam)
|
||||
|
||||
if prev_main_buttons == 0 and self.main_buttons[-1] != 0:
|
||||
self.main_enabled = not self.main_enabled
|
||||
|
||||
return ret, self.out_iq
|
||||
|
||||
def update_speed_limit(self, ret, speed_limit_cam):
|
||||
self.totalDistance += ret.vEgo * DT_CTRL
|
||||
if ret.speedLimit > 0 and not ret.gasPressed and speed_limit_cam:
|
||||
if self.speedLimitDistance <= self.totalDistance:
|
||||
self.speedLimitDistance = self.totalDistance + ret.speedLimit * 6
|
||||
self.speedLimitDistance = max(self.totalDistance + 1, self.speedLimitDistance)
|
||||
else:
|
||||
self.speedLimitDistance = self.totalDistance
|
||||
ret.speedLimitDistance = self.speedLimitDistance - self.totalDistance
|
||||
|
||||
def update_canfd(self, can_parsers) -> structs.CarState:
|
||||
cp = can_parsers[Bus.pt]
|
||||
cp_cam = can_parsers[Bus.cam]
|
||||
cp_alt = can_parsers[Bus.alt] if Bus.alt in can_parsers else None
|
||||
|
||||
ret = structs.CarState()
|
||||
ret_iq = structs.IQCarState()
|
||||
|
||||
if self.CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230:
|
||||
ret.evModeActive, ret.evModeValid = _get_ev_mode_state(cp)
|
||||
|
||||
self.is_metric = cp.vl["CRUISE_BUTTONS_ALT"]["DISTANCE_UNIT"] != 1
|
||||
speed_factor = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS
|
||||
|
||||
if self.CP.flags & (HyundaiFlags.EV | HyundaiFlags.HYBRID):
|
||||
ret.gasPressed = cp.vl[self.accelerator_msg_canfd]["ACCELERATOR_PEDAL"] > 1e-5
|
||||
offset = 255. if self.CP.flags & HyundaiFlags.EV else 1023.
|
||||
ret.gas = cp.vl[self.accelerator_msg_canfd]["ACCELERATOR_PEDAL"] / offset if not self.use_accelerator else 0 if self.accelerator is None else self.accelerator["ACCELERATOR_PEDAL"] / offset
|
||||
ret.gasPressed = ret.gas > 1e-5
|
||||
else:
|
||||
ret.gasPressed = bool(cp.vl[self.accelerator_msg_canfd]["ACCELERATOR_PEDAL_PRESSED"])
|
||||
ret.gasPressed = bool(cp.vl[self.accelerator_msg_canfd]["ACCELERATOR_PEDAL_PRESSED"]) if not self.use_accelerator else False if self.accelerator is None else bool(self.accelerator["ACCELERATOR_PEDAL_PRESSED"])
|
||||
|
||||
ret.brakePressed = cp.vl["TCS"]["DriverBraking"] == 1
|
||||
#print(cp.vl["TCS"], cp.vl_all["TCS"]["DriverBraking"][-10:])
|
||||
|
||||
ret.doorOpen = cp.vl["DOORS_SEATBELTS"]["DRIVER_DOOR"] == 1
|
||||
ret.seatbeltUnlatched = cp.vl["DOORS_SEATBELTS"]["DRIVER_SEATBELT"] == 0
|
||||
if self.doors_seatbelts is not None:
|
||||
ret.doorOpen = self.doors_seatbelts["DRIVER_DOOR"] == 1
|
||||
ret.seatbeltUnlatched = self.doors_seatbelts["DRIVER_SEATBELT"] == 0
|
||||
|
||||
gear = cp.vl[self.gear_msg_canfd]["GEAR"]
|
||||
gear = cp.vl[self.gear_msg_canfd]["GEAR"] if not self.use_accelerator else 0 if self.accelerator is None else self.accelerator["GEAR"]
|
||||
ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear))
|
||||
|
||||
if self.TPMS:
|
||||
tpms_unit = cp.vl["TPMS"]["UNIT"] * 0.725 if int(cp.vl["TPMS"]["UNIT"]) > 0 else 1.
|
||||
ret.tpms.fl = tpms_unit * cp.vl["TPMS"]["PRESSURE_FL"]
|
||||
ret.tpms.fr = tpms_unit * cp.vl["TPMS"]["PRESSURE_FR"]
|
||||
ret.tpms.rl = tpms_unit * cp.vl["TPMS"]["PRESSURE_RL"]
|
||||
ret.tpms.rr = tpms_unit * cp.vl["TPMS"]["PRESSURE_RR"]
|
||||
|
||||
# TODO: figure out positions
|
||||
self.parse_wheel_speeds(ret,
|
||||
cp.vl["WHEEL_SPEEDS"]["WHL_SpdFLVal"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHL_SpdFRVal"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHL_SpdRLVal"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHL_SpdRRVal"],
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_1"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_2"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_3"],
|
||||
cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_4"],
|
||||
)
|
||||
ret.standstill = cp.vl["WHEEL_SPEEDS"]["WHL_SpdFLVal"] <= STANDSTILL_THRESHOLD and cp.vl["WHEEL_SPEEDS"]["WHL_SpdFRVal"] <= STANDSTILL_THRESHOLD and \
|
||||
cp.vl["WHEEL_SPEEDS"]["WHL_SpdRLVal"] <= STANDSTILL_THRESHOLD and cp.vl["WHEEL_SPEEDS"]["WHL_SpdRRVal"] <= STANDSTILL_THRESHOLD
|
||||
ret.vEgoRaw = (ret.wheelSpeeds.fl + ret.wheelSpeeds.fr + ret.wheelSpeeds.rl + ret.wheelSpeeds.rr) / 4.
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
ret.standstill = ret.wheelSpeeds.fl <= STANDSTILL_THRESHOLD and ret.wheelSpeeds.rr <= STANDSTILL_THRESHOLD
|
||||
|
||||
ret.brakeLights = ret.brakePressed or cp.vl["TCS"]["BrakeLight"] == 1 or ret.aEgo < -0.5
|
||||
|
||||
ret.steeringRateDeg = cp.vl["STEERING_SENSORS"]["STEERING_RATE"]
|
||||
ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEERING_ANGLE"]
|
||||
|
||||
# steering angle deg값이 이상함. mdps값이 더 신뢰가 가는듯.. torque steering 차량도 확인해야함.
|
||||
#ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEERING_ANGLE"] * -1
|
||||
#ret.steeringAngleDeg = cp.vl["MDPS"]["STEERING_ANGLE"] * -1
|
||||
if self.CP.flags & HyundaiFlags.ANGLE_CONTROL:
|
||||
ret.steeringAngleDeg = cp.vl["MDPS"]["STEERING_ANGLE_2"] * -1
|
||||
else:
|
||||
ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEERING_ANGLE"] * -1
|
||||
|
||||
trailer_signal = self.trailer_status is not None and self.trailer_status["TRAILER_CONNECTED"] != 0
|
||||
if trailer_signal:
|
||||
# Rising edge is immediate so trailer-specific behavior is preserved.
|
||||
self.trailer_timeout_cnt = 0
|
||||
self.trailer_connected = True
|
||||
elif self.trailer_connected:
|
||||
# During ignition-off, the trailer bit can clear before the cluster shuts down.
|
||||
# Keep suppression active through that transient, while still detecting a real
|
||||
# disconnect after 5 seconds at the 100 Hz CarState update rate.
|
||||
self.trailer_timeout_cnt += 1
|
||||
if self.trailer_timeout_cnt > TRAILER_DISCONNECT_GRACE_FRAMES:
|
||||
self.trailer_connected = False
|
||||
else:
|
||||
self.trailer_timeout_cnt = 0
|
||||
|
||||
ret.trailerConnected = self.trailer_connected
|
||||
|
||||
if self.trailer_connected != self.trailer_connected_prev:
|
||||
print(f"[TRAILER_DEBUG] connected={self.trailer_connected} timeout={self.trailer_timeout_cnt}")
|
||||
self.trailer_connected_prev = self.trailer_connected
|
||||
|
||||
ret.steeringTorque = cp.vl["MDPS"]["STEERING_COL_TORQUE"]
|
||||
ret.steeringTorqueEps = cp.vl["MDPS"]["STEERING_OUT_TORQUE"]
|
||||
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
|
||||
steer_fault_raw = cp.vl["MDPS"]["LKA_FAULT"] != 0
|
||||
self.steer_fault_counter = self.steer_fault_counter + 1 if steer_fault_raw else 0
|
||||
ret.steerFaultTemporary = self.steer_fault_counter > 5
|
||||
ret.steerFaultTemporary = cp.vl["MDPS"]["LKA_FAULT"] != 0 or cp.vl["MDPS"]["LFA2_FAULT"] != 0
|
||||
#ret.steerFaultTemporary = False
|
||||
|
||||
blinkers_info = self.blinkers if self.blinkers is not None else self.blinkers_alt if self.blinkers_alt is not None else None
|
||||
if blinkers_info is not None:
|
||||
left_blinker_lamp = blinkers_info["LEFT_LAMP"] or blinkers_info["LEFT_LAMP_ALT"]
|
||||
right_blinker_lamp = blinkers_info["RIGHT_LAMP"] or blinkers_info["RIGHT_LAMP_ALT"]
|
||||
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, left_blinker_lamp, right_blinker_lamp)
|
||||
|
||||
# TODO: alt signal usage may be described by cp.vl['BLINKERS']['USE_ALT_LAMP']
|
||||
left_blinker_sig, right_blinker_sig = "LEFT_LAMP", "RIGHT_LAMP"
|
||||
if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN:
|
||||
left_blinker_sig, right_blinker_sig = "LEFT_LAMP_ALT", "RIGHT_LAMP_ALT"
|
||||
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig],
|
||||
cp.vl["BLINKERS"][right_blinker_sig])
|
||||
if self.CP.enableBsm:
|
||||
ret.leftBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FL_INDICATOR"] != 0
|
||||
ret.rightBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FR_INDICATOR"] != 0
|
||||
if self.cp_bsm is None:
|
||||
if 442 in cp.seen_addresses:
|
||||
self.cp_bsm = cp
|
||||
print("######## BSM in ECAN")
|
||||
elif 442 in cp_cam.seen_addresses:
|
||||
self.cp_bsm = cp_cam
|
||||
print("######## BSM in CAM")
|
||||
else:
|
||||
bsm_info = self.cp_bsm.vl["BLINDSPOTS_REAR_CORNERS"]
|
||||
ret.leftBlindspot = (bsm_info["FL_INDICATOR"] + bsm_info["INDICATOR_LEFT_TWO"] + bsm_info["INDICATOR_LEFT_FOUR"]) > 0
|
||||
ret.rightBlindspot = (bsm_info["FR_INDICATOR"] + bsm_info["INDICATOR_RIGHT_TWO"] + bsm_info["INDICATOR_RIGHT_FOUR"]) > 0
|
||||
|
||||
# cruise state
|
||||
if self.cruise_buttons_alt2 is not None:
|
||||
cruise_button = self.cruise_buttons_alt2["CRUISE_BUTTONS"]
|
||||
else:
|
||||
cruise_button = cp.vl[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"]
|
||||
if cruise_button in [Buttons.RES_ACCEL, Buttons.SET_DECEL] and self.CP.openpilotLongitudinalControl:
|
||||
self.main_enabled = True
|
||||
# CAN FD cars enable on main button press, set available if no TCS faults preventing engagement
|
||||
ret.cruiseState.available = cp.vl["TCS"]["ACCEnable"] == 0
|
||||
ret.cruiseState.available = self.main_enabled and self.controls_ready_count >= READY_COUNT_OK #cp.vl["TCS"]["ACCEnable"] == 0
|
||||
if self.CP.flags & HyundaiFlags.CAMERA_SCC.value:
|
||||
self.MainMode_ACC = cp_cam.vl["SCC_CONTROL"]["MainMode_ACC"] == 1
|
||||
self.ACCMode = cp_cam.vl["SCC_CONTROL"]["ACCMode"]
|
||||
self.LFA_ICON = cp_cam.vl["LFAHDA_CLUSTER"]["HDA_LFA_SymSta"]
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
# These are not used for engage/disengage since openpilot keeps track of state using the buttons
|
||||
ret.cruiseState.enabled = cp.vl["TCS"]["ACC_REQ"] == 1
|
||||
ret.cruiseState.standstill = False
|
||||
if self.MainMode_ACC or self.main_enabled:
|
||||
self.main_enabled = True
|
||||
else:
|
||||
cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp
|
||||
ret.cruiseState.enabled = cp_cruise_info.vl["SCC_CONTROL"]["ACCMode"] in (1, 2)
|
||||
ret.cruiseState.standstill = cp_cruise_info.vl["SCC_CONTROL"]["CRUISE_STANDSTILL"] == 1
|
||||
if cp_cruise_info.vl["SCC_CONTROL"]["MainMode_ACC"] == 1: # carrot
|
||||
ret.cruiseState.available = self.main_enabled = True
|
||||
ret.pcmCruiseGap = int(np.clip(cp_cruise_info.vl["SCC_CONTROL"]["DISTANCE_SETTING"], 1, 4))
|
||||
ret.cruiseState.standstill = cp_cruise_info.vl["SCC_CONTROL"]["InfoDisplay"] >= 4
|
||||
ret.cruiseState.speed = cp_cruise_info.vl["SCC_CONTROL"]["VSetDis"] * speed_factor
|
||||
self.cruise_info = copy.copy(cp_cruise_info.vl["SCC_CONTROL"])
|
||||
ret.brakeHoldActive = cp.vl["ESP_STATUS"]["AUTO_HOLD"] == 1 and cp_cruise_info.vl["SCC_CONTROL"]["ACCMode"] not in (1, 2)
|
||||
|
||||
speed_limit_cam = False
|
||||
corner = False
|
||||
corner_infos = [info for info in (self.adrv_0x1ea, self.ccnc_0x162) if info is not None]
|
||||
if corner_infos:
|
||||
def corner_max(signal):
|
||||
return max(info[signal] for info in corner_infos)
|
||||
|
||||
ret.leftLongDist = self.lf_distance = corner_max("LF_DETECT_DISTANCE")
|
||||
ret.rightLongDist = self.rf_distance = corner_max("RF_DETECT_DISTANCE")
|
||||
self.lr_distance = corner_max("LR_DETECT_DISTANCE")
|
||||
self.rr_distance = corner_max("RR_DETECT_DISTANCE")
|
||||
ret.leftLatDist = corner_max("LF_DETECT_LATERAL")
|
||||
ret.rightLatDist = corner_max("RF_DETECT_LATERAL")
|
||||
ret.leftRearLongDist = self.lr_distance
|
||||
ret.rightRearLongDist = self.rr_distance
|
||||
ret.leftRearLatDist = corner_max("LR_DETECT_LATERAL")
|
||||
ret.rightRearLatDist = corner_max("RR_DETECT_LATERAL")
|
||||
corner = True
|
||||
if corner:
|
||||
raw_corner_radar_enabled = (
|
||||
self.op_params.get_int("EnableCornerRadar") > 0 and
|
||||
bool(self.CP.extFlags & (HyundaiExtFlags.CORNER_RADAR_OBJECTS_235.value |
|
||||
HyundaiExtFlags.CORNER_RADAR_OBJECTS_180.value))
|
||||
)
|
||||
left_front_block = (not raw_corner_radar_enabled) and 0 < ret.leftLongDist < 7.0
|
||||
right_front_block = (not raw_corner_radar_enabled) and 0 < ret.rightLongDist < 7.0
|
||||
rear_block_dist = 5.0 if raw_corner_radar_enabled else 7.0
|
||||
left_rear_block = 0 < self.lr_distance < rear_block_dist
|
||||
right_rear_block = 0 < self.rr_distance < rear_block_dist
|
||||
left_block = left_front_block or left_rear_block
|
||||
right_block = right_front_block or right_rear_block
|
||||
if left_block:
|
||||
ret.leftBlindspot = True
|
||||
if right_block:
|
||||
ret.rightBlindspot = True
|
||||
|
||||
if self.hda_info_4a3 is not None:
|
||||
speedLimit = self.hda_info_4a3["SPEED_LIMIT"]
|
||||
if not self.is_metric:
|
||||
speedLimit *= CV.MPH_TO_KPH
|
||||
ret.speedLimit = speedLimit if speedLimit < 255 else 0
|
||||
if int(self.hda_info_4a3["MapSource"]) == 2:
|
||||
speed_limit_cam = True
|
||||
|
||||
if self.time_zone == "UTC":
|
||||
country_code = int(self.hda_info_4a3["CountryCode"])
|
||||
self.time_zone = ZoneInfo(NUMERIC_TO_TZ.get(country_code, "UTC"))
|
||||
|
||||
ret.gearStep = cp.vl["GEAR"]["GEAR_STEP"] if self.GEAR else 0
|
||||
if 1 <= ret.gearStep <= 8 and ret.gearShifter == GearShifter.unknown:
|
||||
ret.gearShifter = GearShifter.drive
|
||||
ret.gearStep = cp.vl["GEAR_ALT"]["GEAR_STEP"] if self.GEAR_ALT else ret.gearStep
|
||||
|
||||
lane_info = self.cam_0x2a4 if self.cam_0x2a4 is not None else self.cam_0x362
|
||||
|
||||
if lane_info is not None:
|
||||
left_lane_prob = lane_info["LEFT_LANE_PROB"]
|
||||
right_lane_prob = lane_info["RIGHT_LANE_PROB"]
|
||||
left_lane_type = lane_info["LEFT_LANE_TYPE"] # 0: dashed, 1: solid, 2: undecided, 3: road edge, 4: DLM Inner Solid, 5: DLM InnerDashed, 6:DLM Inner Undecided, 7: Botts Dots, 8: Barrier
|
||||
right_lane_type = lane_info["RIGHT_LANE_TYPE"]
|
||||
left_lane_color = lane_info["LEFT_LANE_COLOR"] # 0: none, 1: white, 2: yellow, 3: blue
|
||||
right_lane_color = lane_info["RIGHT_LANE_COLOR"]
|
||||
left_lane_info = left_lane_color * 10 + left_lane_type
|
||||
right_lane_info = right_lane_color * 10 + right_lane_type
|
||||
ret.leftLaneLine = left_lane_info
|
||||
ret.rightLaneLine = right_lane_info
|
||||
|
||||
# Manual Speed Limit Assist is a feature that replaces non-adaptive cruise control on EV CAN FD platforms.
|
||||
# It limits the vehicle speed, overridable by pressing the accelerator past a certain point.
|
||||
# The car will brake, but does not respect positive acceleration commands in this mode
|
||||
# TODO: find this message on ICE & HYBRID cars + cruise control signals (if exists)
|
||||
if self.CP.flags & HyundaiFlags.EV:
|
||||
ret.cruiseState.nonAdaptive = cp.vl["MANUAL_SPEED_LIMIT_ASSIST"]["MSLA_ENABLED"] == 1
|
||||
if self.manual_speed_limit_assist is not None:
|
||||
#ret.cruiseState.nonAdaptive = cp.vl["MANUAL_SPEED_LIMIT_ASSIST"]["MSLA_ENABLED"] == 1
|
||||
ret.cruiseState.nonAdaptive = self.manual_speed_limit_assist["MSLA_ENABLED"] == 1
|
||||
|
||||
if self.LOCAL_TIME and self.time_zone != "UTC":
|
||||
lt = cp.vl["LOCAL_TIME"]
|
||||
y, m, d, H, M, S = int(lt["YEAR"]) + 2000, int(lt["MONTH"]), int(lt["DATE"]), int(lt["HOURS"]), int(lt["MINUTES"]), int(lt["SECONDS"])
|
||||
try:
|
||||
dt_local = datetime(y, m, d, H, M, S, tzinfo=self.time_zone)
|
||||
ret.datetime = int(dt_local.timestamp() * 1000)
|
||||
except:
|
||||
#print(f"Error parsing local time: {y}-{m}-{d} {H}:{M}:{S} in {self.time_zone}")
|
||||
pass
|
||||
|
||||
prev_cruise_buttons = self.cruise_buttons[-1]
|
||||
#self.cruise_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"])
|
||||
#carrot {{
|
||||
|
||||
if self.cruise_buttons_alt2 is not None:
|
||||
if int(self.cruise_buttons_alt2.get("LFA_BTN", 0)) == 1:
|
||||
cruise_button = [Buttons.LFA_BUTTON]
|
||||
else:
|
||||
v = int(self.cruise_buttons_alt2.get("CRUISE_BUTTONS", 0))
|
||||
cruise_button = [v if v < 5 else Buttons.NONE]
|
||||
elif cp.vl[self.cruise_btns_msg_canfd]["LFA_BTN"]:
|
||||
cruise_button = [Buttons.LFA_BUTTON]
|
||||
else:
|
||||
cruise_button = cp.vl_all[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"]
|
||||
|
||||
self.cruise_buttons.extend(cruise_button)
|
||||
# }} carrot
|
||||
|
||||
|
||||
#if self.cruise_btns_msg_canfd in cp.vl:
|
||||
# self.cruise_buttons_msg = copy.copy(cp.vl[self.cruise_btns_msg_canfd])
|
||||
"""
|
||||
if self.cruise_btns_msg_canfd in cp.vl: #carrot
|
||||
if not cp.vl[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"]:
|
||||
pass
|
||||
#print("empty cruise btns...")
|
||||
else:
|
||||
self.cruise_buttons_msg = copy.copy(cp.vl[self.cruise_btns_msg_canfd])
|
||||
"""
|
||||
prev_main_buttons = self.main_buttons[-1]
|
||||
prev_lda_button = self.lda_button
|
||||
self.cruise_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"])
|
||||
self.main_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["ADAPTIVE_CRUISE_MAIN_BTN"])
|
||||
self.lda_button = cp.vl[self.cruise_btns_msg_canfd]["LDA_BTN"]
|
||||
#self.cruise_buttons.extend(cp.vl_all[self.cruise_btns_msg_canfd]["CRUISE_BUTTONS"])
|
||||
if self.cruise_buttons_alt2 is not None:
|
||||
self.main_buttons.extend([1 if int(self.cruise_buttons_alt2.get("CRUISE_BUTTONS", 0)) == 8 else 0])
|
||||
else:
|
||||
adaptive_main = cp.vl_all[self.cruise_btns_msg_canfd]["ADAPTIVE_CRUISE_MAIN_BTN"]
|
||||
normal_main = cp.vl_all[self.cruise_btns_msg_canfd]["NORMAL_CRUISE_MAIN_BTN"]
|
||||
self.main_buttons.extend(int(adaptive or normal) for adaptive, normal in zip(adaptive_main, normal_main, strict=True))
|
||||
if self.main_buttons[-1] != prev_main_buttons and not self.main_buttons[-1]: # and self.CP.openpilotLongitudinalControl: #carrot
|
||||
self.main_enabled = not self.main_enabled
|
||||
print("main_enabled = {}".format(self.main_enabled))
|
||||
self.buttons_counter = cp.vl[self.cruise_btns_msg_canfd]["COUNTER"]
|
||||
ret.accFaulted = cp.vl["TCS"]["ACCEnable"] != 0 # 0 ACC CONTROL ENABLED, 1-3 ACC CONTROL DISABLED
|
||||
|
||||
if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING:
|
||||
self.lfa_block_msg = copy.copy(cp_cam.vl["CAM_0x362"] if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT
|
||||
else cp_cam.vl["CAM_0x2a4"])
|
||||
speed_conv = CV.KPH_TO_MS # if self.is_metric else CV.MPH_TO_MS
|
||||
cluSpeed = cp.vl["CRUISE_BUTTONS_ALT"]["CLU_SPEED"]
|
||||
ret.vEgoCluster = cluSpeed * speed_conv # MPH단위에서도 KPH로 나오는듯..
|
||||
vEgoClu, aEgoClu = self.update_clu_speed_kf(ret.vEgoCluster)
|
||||
ret.vCluRatio = (ret.vEgo / vEgoClu) if (vEgoClu > 3. and ret.vEgo > 3.) else 1.0
|
||||
|
||||
AolCarState.update_aol_canfd(self, ret, can_parsers)
|
||||
self.update_speed_limit(ret, speed_limit_cam)
|
||||
|
||||
paddle_button = self.paddle_button_prev
|
||||
if self.cruise_btns_msg_canfd == "CRUISE_BUTTONS":
|
||||
paddle_button = 1 if cp.vl["CRUISE_BUTTONS"]["LEFT_PADDLE"] == 1 else 2 if cp.vl["CRUISE_BUTTONS"]["RIGHT_PADDLE"] == 1 else 0
|
||||
elif self.gear_msg_canfd == "GEAR":
|
||||
paddle_button = 1 if cp.vl["GEAR"]["LEFT_PADDLE"] == 1 else 2 if cp.vl["GEAR"]["RIGHT_PADDLE"] == 1 else 0
|
||||
|
||||
ret.buttonEvents = [*create_button_events(self.cruise_buttons[-1], prev_cruise_buttons, BUTTONS_DICT),
|
||||
*create_button_events(self.main_buttons[-1], prev_main_buttons, {1: ButtonType.mainCruise}),
|
||||
*create_button_events(self.lda_button, prev_lda_button, {1: ButtonType.lkas})]
|
||||
*create_button_events(paddle_button, self.paddle_button_prev, {1: ButtonType.paddleLeft, 2: ButtonType.paddleRight}),
|
||||
*create_button_events(self.main_buttons[-1], prev_main_buttons, {1: ButtonType.mainCruise})]
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
ret.cruiseState.available = self.get_main_cruise(ret)
|
||||
self.paddle_button_prev = paddle_button
|
||||
|
||||
CarStateExt.update_canfd_ext(self, ret, ret_iq, can_parsers, speed_factor)
|
||||
return ret
|
||||
|
||||
ret.blockPcmEnable = not self.recent_button_interaction()
|
||||
|
||||
return ret, ret_iq
|
||||
|
||||
def get_can_parsers_canfd(self, CP):
|
||||
def get_can_parsers_canfd(self, CP, CP_IQ=None):
|
||||
msgs = []
|
||||
if not (CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS):
|
||||
# TODO: this can be removed once we add dynamic support to vl_all
|
||||
msgs += [
|
||||
# this message is 50Hz but the ECU frequently stops transmitting for ~0.5s
|
||||
("CRUISE_BUTTONS", 1)
|
||||
("CRUISE_BUTTONS", 50)
|
||||
]
|
||||
|
||||
CAN = CanBus(CP)
|
||||
pt_parser = CANParser(DBC[CP.carFingerprint][Bus.pt], msgs, CAN.ECAN)
|
||||
if CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230:
|
||||
# Display-only while the signal is fleet-validated: checksum and freshness
|
||||
# gate the value without making a counter/alive fault disable controls.
|
||||
pt_parser._add_message(EV_MODE_STATUS_MSG, math.nan, ignore_counter=True)
|
||||
|
||||
return {
|
||||
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], msgs, CanBus(CP).ECAN),
|
||||
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).CAM),
|
||||
Bus.pt: pt_parser,
|
||||
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CAN.CAM),
|
||||
Bus.alt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CAN.ACAN),
|
||||
}
|
||||
|
||||
def get_can_parsers(self, CP, CP_IQ):
|
||||
def get_can_parsers(self, CP, CP_IQ=None):
|
||||
if CP.flags & HyundaiFlags.CANFD:
|
||||
return self.get_can_parsers_canfd(CP)
|
||||
|
||||
return {
|
||||
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0),
|
||||
# EMS21 carries SCR_UREA_LEVEL on diesel platforms. NaN frequency makes
|
||||
# it optional, so gasoline/EV platforms do not fail CAN validity.
|
||||
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [("EMS21", math.nan)], 0),
|
||||
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2),
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
""" AUTO-FORMATTED USING iqdbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE."""
|
||||
from iqdbc.car.structs import CarParams
|
||||
from iqdbc.car.hyundai.values import CAR
|
||||
|
||||
from iqdbc.iqpilot.car.fingerprints_ext import merge_fw_versions
|
||||
from iqdbc.iqpilot.car.hyundai.fingerprints_ext import FW_VERSIONS_EXT
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
# The existence of SCC or RDR in the fwdRadar FW usually determines the radar's function,
|
||||
@@ -12,6 +8,14 @@ Ecu = CarParams.Ecu
|
||||
|
||||
|
||||
FW_VERSIONS = {
|
||||
CAR.HYUNDAI_AZERA_7TH_GEN: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00GN7_ RDR ----- 1.00 1.03 99110-N1000 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00GN7 MFC AT KOR LHD 1.00 1.03 99211-N1000 230322',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_AZERA_6TH_GEN: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00IG__ SCC F-CU- 1.00 1.00 99110-G8100 ',
|
||||
@@ -21,7 +25,6 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00IG MFC AT MES LHD 1.00 1.04 99211-G8100 200511',
|
||||
b'\xf1\x00IG MFC AT MES LHD 1.00 1.05 99211-G8100 210409',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_AZERA_HEV_6TH_GEN: {
|
||||
@@ -55,20 +58,13 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00AE MDPS C 1.00 1.03 56310/G2300 4AEHC103',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.03 56310G2300\x00 4AEHC103',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.04 56310G2550\x00 4AEHC104',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.05 56310/G2500 4AEHC105',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.05 56310/G2501 4AEHC105',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2301 4AEHC107',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2501 4AEHC107',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2551 4AEHC107',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00AEH MFC AT EUR LHD 1.00 1.00 95740-G2400 180222',
|
||||
b'\xf1\x00AEH MFC AT EUR LHD 1.00 1.00 95740-G7200 160418',
|
||||
b'\xf1\x00AEH MFC AT EUR RHD 1.00 1.00 95740-G2200 161014',
|
||||
b'\xf1\x00AEH MFC AT EUR RHD 1.00 1.00 95740-G2400 180222',
|
||||
b'\xf1\x00AEH MFC AT USA LHD 1.00 1.00 95740-G2300 170703',
|
||||
b'\xf1\x00AEH MFC AT USA LHD 1.00 1.00 95740-G2400 180222',
|
||||
],
|
||||
},
|
||||
@@ -78,13 +74,11 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2100 ',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2201 4AEHC107',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2501 4AEHC107',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2551 4AEHC107',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00AEP MFC AT AUS RHD 1.00 1.00 95740-G2400 180222',
|
||||
b'\xf1\x00AEP MFC AT EUR LHD 1.00 1.00 95740-G2400 180222',
|
||||
b'\xf1\x00AEP MFC AT USA LHD 1.00 1.00 95740-G2400 180222',
|
||||
],
|
||||
},
|
||||
@@ -154,12 +148,10 @@ FW_VERSIONS = {
|
||||
CAR.HYUNDAI_IONIQ_HEV_2022: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00AEhe SCC F-CUP 1.00 1.00 99110-G2600 ',
|
||||
b'\xf1\x00AEhe SCC F-CUP 1.00 1.02 99110-G2100 ',
|
||||
b'\xf1\x00AEhe SCC FHCUP 1.00 1.00 99110-G2600 ',
|
||||
b'\xf1\x00AEhe SCC FHCUP 1.00 1.02 99110-G2100 ',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00AE MDPS C 1.00 1.01 56310-XX000 4APHC101',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.01 56310/G2510 4APHC101',
|
||||
b'\xf1\x00AE MDPS C 1.00 1.01 56310G2510\x00 4APHC101',
|
||||
],
|
||||
@@ -173,7 +165,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00DN8_ SCC F-CU- 1.00 1.00 99110-L0000 ',
|
||||
b'\xf1\x00DN8_ SCC F-CUP 1.00 1.00 99110-L0000 ',
|
||||
b'\xf1\x00DN8_ SCC F-CUP 1.00 1.02 99110-L1000 ',
|
||||
b'\xf1\x00DN8_ SCC FHCU- 1.00 1.00 99110-L0000 ',
|
||||
b'\xf1\x00DN8_ SCC FHCUP 1.00 1.00 99110-L0000 ',
|
||||
b'\xf1\x00DN8_ SCC FHCUP 1.00 1.01 99110-L1000 ',
|
||||
b'\xf1\x00DN8_ SCC FHCUP 1.00 1.02 99110-L1000 ',
|
||||
@@ -232,6 +223,15 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00LFF LKAS AT USA LHD 1.01 1.02 95740-C1000 E52',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_SONATA_2024: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ',
|
||||
],
|
||||
(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',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_TUCSON: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00TL__ FCA F-CUP 1.00 1.01 99110-D3500 ',
|
||||
@@ -293,7 +293,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00TM ESC \x04 101 \x08\x04 58910-S2GA0',
|
||||
b'\xf1\x00TM ESC \x04 102!\x04\x05 58910-S2GA0',
|
||||
b'\xf1\x00TM ESC \x04 103"\x07\x08 58910-S2GA0',
|
||||
b'\xf1\x00TM ESC \x1b 102 \x08\x08 58910-S1DA0',
|
||||
b'\xf1\x00TM ESC \x1e 102 \x08\x08 58910-S1DA0',
|
||||
b'\xf1\x00TM ESC 103!\x030 58910-S1MA0',
|
||||
],
|
||||
@@ -301,7 +300,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00TM MDPS C 1.00 1.01 56310-S1AB0 4TSDC101',
|
||||
b'\xf1\x00TM MDPS C 1.00 1.01 56310-S1EB0 4TSDC101',
|
||||
b'\xf1\x00TM MDPS C 1.00 1.02 56370-S2AA0 0B19',
|
||||
b'\xf1\x00TM MDPS R 1.00 1.05 57700-S1500 4TSDP105',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00TM MFC AT EUR LHD 1.00 1.03 99211-S1500 210224',
|
||||
@@ -367,7 +365,6 @@ FW_VERSIONS = {
|
||||
},
|
||||
CAR.KIA_STINGER: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00CK__ SCC FHCUP 1.00 1.02 96400-J5000 ',
|
||||
b'\xf1\x00CK__ SCC F_CUP 1.00 1.01 96400-J5000 ',
|
||||
b'\xf1\x00CK__ SCC F_CUP 1.00 1.01 96400-J5100 ',
|
||||
b'\xf1\x00CK__ SCC F_CUP 1.00 1.02 96400-J5100 ',
|
||||
@@ -383,7 +380,6 @@ FW_VERSIONS = {
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00CK MFC AT EUR LHD 1.00 1.03 95740-J5000 170822',
|
||||
b'\xf1\x00CK MFC AT KOR LHD 1.00 1.04 95740-J5000 180504',
|
||||
b'\xf1\x00CK MFC AT USA LHD 1.00 1.03 95740-J5000 170822',
|
||||
b'\xf1\x00CK MFC AT USA LHD 1.00 1.04 95740-J5000 180504',
|
||||
],
|
||||
@@ -400,7 +396,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5320 4C2VL503',
|
||||
b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5380 4C2VR503',
|
||||
b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5520 4C4VL503',
|
||||
b'\xf1\x00CK MDPS R 1.00 5.04 57700-J5320 4C2VL504',
|
||||
b'\xf1\x00CK MDPS R 1.00 5.04 57700-J5520 4C4VL504',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
@@ -442,7 +437,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00LX ESC \x0b 104 \x10\x13 58910-S8330',
|
||||
b'\xf1\x00LX ESC \x0b 104 \x10\x16 58910-S8360',
|
||||
b'\xf1\x00ON ESC \x01 101\x19\t\x08 58910-S9360',
|
||||
b'\xf1\x00ON ESC \x01 103$\x04\x08 58910-S9360',
|
||||
b'\xf1\x00ON ESC \x0b 100\x18\x12\x18 58910-S9360',
|
||||
b'\xf1\x00ON ESC \x0b 101\x19\t\x05 58910-S9320',
|
||||
b'\xf1\x00ON ESC \x0b 101\x19\t\x08 58910-S9360',
|
||||
@@ -648,6 +642,14 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.04 99210-L2000 210527',
|
||||
],
|
||||
},
|
||||
CAR.KIA_K5_DL3_24_HEV: { # (DL3)
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.02 99210-L2500 230911'
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00DL3_ RDR ----- 1.00 1.01 99110-L2500 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_KONA_EV: {
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00OS IEB \x01 212 \x11\x13 58520-K4000',
|
||||
@@ -703,7 +705,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.02 56310-K4271 4OEPC102',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.02 56310/K4271 4OEPC102',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.02 56310/K4970 4OEPC102',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.02 56310/K4971 4OEPC102',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.02 56310K4260\x00 4OEPC102',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.02 56310K4261\x00 4OEPC102',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.02 56310K4971\x00 4OEPC102',
|
||||
@@ -720,6 +721,14 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00SX2EMFC AT KOR LHD 1.00 1.00 99211-BF000 230410',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_KONA_HEV_2ND_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
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-BE500 ',
|
||||
],
|
||||
},
|
||||
CAR.KIA_NIRO_EV: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00DEev SCC F-CUP 1.00 1.00 99110-Q4000 ',
|
||||
@@ -737,14 +746,11 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00DE MDPS C 1.00 1.04 56310Q4100\x00 4DEEC104',
|
||||
b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4000\x00 4DEEC105',
|
||||
b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4100\x00 4DEEC105',
|
||||
b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4150\x00 4DEEC105',
|
||||
b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4200\x00 4DEEC105',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00DEE MFC AT EUR LHD 1.00 1.00 99211-Q4000 191211',
|
||||
b'\xf1\x00DEE MFC AT EUR LHD 1.00 1.00 99211-Q4100 200706',
|
||||
b'\xf1\x00DEE MFC AT EUR LHD 1.00 1.03 95740-Q4000 180821',
|
||||
b'\xf1\x00DEE MFC AT EUR RHD 1.00 1.00 99211-Q4000 191211',
|
||||
b'\xf1\x00DEE MFC AT KOR LHD 1.00 1.02 95740-Q4000 180705',
|
||||
b'\xf1\x00DEE MFC AT KOR LHD 1.00 1.03 95740-Q4000 180821',
|
||||
b'\xf1\x00DEE MFC AT USA LHD 1.00 1.00 99211-Q4000 191211',
|
||||
@@ -756,13 +762,9 @@ FW_VERSIONS = {
|
||||
CAR.KIA_NIRO_EV_2ND_GEN: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00SG2_ RDR ----- 1.00 1.01 99110-AT000 ',
|
||||
b'\xf1\x00SG__ RDR ----- 1.00 1.00 99110-AT200 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00SG2EMFC AT EUR LHD 1.00 1.00 99211-AT200 240315',
|
||||
b'\xf1\x00SG2EMFC AT EUR LHD 1.01 1.09 99211-AT000 220801',
|
||||
b'\xf1\x00SG2EMFC AT USA LHD 1.00 1.00 99211-AT100 230216',
|
||||
b'\xf1\x00SG2EMFC AT USA LHD 1.00 1.00 99211-AT200 240401',
|
||||
b'\xf1\x00SG2EMFC AT USA LHD 1.01 1.09 99211-AT000 220801',
|
||||
],
|
||||
},
|
||||
@@ -866,11 +868,9 @@ FW_VERSIONS = {
|
||||
CAR.KIA_OPTIMA_H_G4_FL: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00JFhe SCC FHCUP 1.00 1.01 99110-A8500 ',
|
||||
b'\xf1\x00JFhe SCC FHCUP 1.00 1.03 99110-A8500 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00JFH MFC AT KOR LHD 1.00 1.01 95895-A8200 180323',
|
||||
b'\xf1\x00JFH MFC AT KOR LHD 1.00 1.04 95895-A8200 181217',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_ELANTRA: {
|
||||
@@ -930,7 +930,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.06 99210-AA000 220111',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.07 99210-AA000 220426',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.08 99210-AA000 220728',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.09 99210-AA000 221108',
|
||||
],
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00CN ESC \t 101 \x10\x03 58910-AB800',
|
||||
@@ -998,7 +997,6 @@ FW_VERSIONS = {
|
||||
},
|
||||
CAR.KIA_SORENTO: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00UMP LKAS AT AUS RHD 1.00 1.00 96400-C6550 S30',
|
||||
b'\xf1\x00UMP LKAS AT KOR LHD 1.00 1.00 95740-C5550 S30',
|
||||
b'\xf1\x00UMP LKAS AT USA LHD 1.00 1.00 95740-C6550 d00',
|
||||
b'\xf1\x00UMP LKAS AT USA LHD 1.01 1.01 95740-C6550 d01',
|
||||
@@ -1032,6 +1030,14 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.06 99210-CV000 220328',
|
||||
],
|
||||
},
|
||||
CAR.KIA_EV6_PE: { # (CV1)
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
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',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_IONIQ_5: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NE1_ RDR ----- 1.00 1.00 99110-GI000 ',
|
||||
@@ -1042,7 +1048,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.00 99211-GI100 230915',
|
||||
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.01 99211-GI010 211007',
|
||||
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.01 99211-GI100 240110',
|
||||
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.02 99211-GI010 211206',
|
||||
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.03 99211-GI010 220401',
|
||||
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.06 99211-GI000 210813',
|
||||
b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.06 99211-GI010 230110',
|
||||
@@ -1056,13 +1061,29 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.00 99211-GI020 230719',
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.00 99211-GI100 230915',
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.01 99211-GI010 211007',
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.01 99211-GI100 240110',
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.02 99211-GI010 211206',
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.03 99211-GI010 220401',
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.05 99211-GI010 220614',
|
||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_IONIQ_5_PE: { # (NE1)
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NE__ RDR ----- 1.00 1.00 99110-GI500 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NE MFC AT KOR LHD 1.00 1.02 99211-GI500 240221',
|
||||
],
|
||||
},
|
||||
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 USA LHD 1.00 1.04 99211-NI000 231219',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_IONIQ_6: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ',
|
||||
@@ -1076,9 +1097,16 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00CE MFC AT USA LHD 1.00 1.06 99211-KL000 230915',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_IONIQ_9: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00MEev RDR ----- 1.00 1.00 99110-GO000 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00ME MFC AT KOR LHD 1.00 1.00 99211-GO000 241007',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_TUCSON_4TH_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N9220 14K',
|
||||
b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N9260 14Y',
|
||||
b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.01 99211-N9100 14A',
|
||||
b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 1.00 99211-N9220 14K',
|
||||
@@ -1090,14 +1118,12 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9260 14Y',
|
||||
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N9100 14A',
|
||||
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N9240 14T',
|
||||
b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 1.00 99211-N9240 14Q',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NX4__ 1.00 1.00 99110-N9100 ',
|
||||
b'\xf1\x00NX4__ 1.00 1.01 99110-N9000 ',
|
||||
b'\xf1\x00NX4__ 1.00 1.02 99110-N9000 ',
|
||||
b'\xf1\x00NX4__ 1.01 1.00 99110-N9100 ',
|
||||
b'\xf1\x00NX4__ 1.01 1.02 99110-N9000 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN: {
|
||||
@@ -1115,13 +1141,11 @@ FW_VERSIONS = {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00NQ5 FR_CMR AT AUS RHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT EUR LHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT GEN LHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT GEN LHD 1.00 1.00 99211-P1060 665',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1030 662',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1040 663',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1060 665',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1070 690',
|
||||
b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.01 99211-P1060 680',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00NQ5__ 1.00 1.02 99110-P1000 ',
|
||||
@@ -1134,14 +1158,11 @@ FW_VERSIONS = {
|
||||
CAR.GENESIS_GV70_1ST_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00JK1 MFC AT CAN LHD 1.00 1.02 99211-IY000 230627',
|
||||
b'\xf1\x00JK1 MFC AT CAN LHD 1.00 1.04 99211-AR100 210204',
|
||||
b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.01 99211-AR200 220125',
|
||||
b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.01 99211-AR300 220125',
|
||||
b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.02 99211-IY000 230627',
|
||||
b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.04 99211-AR000 210204',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00JK1_ SCC ----- 1.00 1.02 99110-AR100 ',
|
||||
b'\xf1\x00JK1_ SCC FHCUP 1.00 1.00 99110-AR200 ',
|
||||
b'\xf1\x00JK1_ SCC FHCUP 1.00 1.00 99110-AR300 ',
|
||||
b'\xf1\x00JK1_ SCC FHCUP 1.00 1.00 99110-IY000 ',
|
||||
@@ -1158,6 +1179,24 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00JKev SCC ----- 1.00 1.01 99110-DS000 ',
|
||||
],
|
||||
},
|
||||
|
||||
CAR.HYUNDAI_NEXO_1ST_GEN: {
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00FE IEB \x01 312 \x11\x13 58520-M5000',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00FE MFC AT KOR LHD 1.00 1.00 99211-M5100 201218',
|
||||
b'\xf1\x00FE MFC AT KOR LHD 1.00 1.02 99211-M5100 220405',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00FE MDPS C 1.00 1.05 56340-M5000 9903',
|
||||
b'\xf1\x00FE MDPS C 1.00 1.06 56340-M5000 1625',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00FE__ SCC FHCUP 1.00 1.05 99110-M5000 ',
|
||||
],
|
||||
},
|
||||
|
||||
CAR.GENESIS_GV60_EV_1ST_GEN: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00JW1 MFC AT AUS RHD 1.00 1.03 99211-CU100 221118',
|
||||
@@ -1189,7 +1228,6 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00MQ4HMFC AT KOR LHD 1.00 1.12 99210-P2000 230331',
|
||||
b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.10 99210-P2000 210406',
|
||||
b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.11 99210-P2000 211217',
|
||||
b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.12 99210-P2000 230331',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00MQhe SCC FHCUP 1.00 1.04 99110-P4000 ',
|
||||
@@ -1250,40 +1288,15 @@ FW_VERSIONS = {
|
||||
b'\xf1\x00US4_ RDR ----- 1.00 1.00 99110-CG000 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_NEXO_1ST_GEN: {
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00FE IEB \x01 312 \x11\x13 58520-M5000',
|
||||
CAR.KIA_EV9: { # (MV)
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00MV__ RDR ----- 1.00 1.02 99110-DO700 ',
|
||||
b'\xf1\x00MV__ RDR ----- 1.00 1.02 99110-DO000 '
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00FE MFC AT KOR LHD 1.00 1.00 99211-M5100 201218',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00FE MDPS C 1.00 1.05 56340-M5000 9903',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00FE__ SCC FHCUP 1.00 1.05 99110-M5000 ',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_KONA_2022: {
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00OSP LKA AT CND LHD 1.00 1.04 99211-J9200 904',
|
||||
b'\xf1\x00OSP LKA AT USA LHD 1.00 1.04 99211-J9200 904',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.04 56310/J9290 4OPCC104',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.04 56310/J9291 4OPCC104',
|
||||
b'\xf1\x00OSP MDPS C 1.00 1.04 56310J9291\x00 4OPCC104',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00YB__ FCA ----- 1.00 1.01 99110-J9000 \x00\x00\x00',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x00HT6WA280BLHT6VA650A1COS4N20NS1\x00\x00\x00\x00\x00\x00\x15\xf5\x87~',
|
||||
b'\xf1\x00T01960BL T01E60A1 DOS2T16X4XE60NS4N\x90\xe6\xcb',
|
||||
b'\xf1\x00T01G00BL T01I00A1 DOS2T16X2XI00NS0\x8c`\xff\xe7',
|
||||
b'\xf1\x00T01G00BL T01I00A1 DOS2T16X4XI00NS0\x99L\xeeq',
|
||||
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',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
FW_VERSIONS = merge_fw_versions(FW_VERSIONS, FW_VERSIONS_EXT)
|
||||
|
||||
@@ -1,21 +1,33 @@
|
||||
import copy
|
||||
import crcmod
|
||||
from iqdbc.car.hyundai.values import CAR, HyundaiFlags
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.escc import EnhancedSmartCruiseControl
|
||||
from iqdbc.iqpilot.car.hyundai.lead_data_ext import CanLeadData
|
||||
|
||||
hyundai_checksum = crcmod.mkCrcFun(0x11D, initCrc=0xFD, rev=False, xorOut=0xdf)
|
||||
|
||||
def suppress_casper_ev_fca11_fault(values):
|
||||
# CASPER EV can report transient FCA faults during camera-SCC handoff.
|
||||
# Keep the copied FCA11 frame non-faulting without changing other cars.
|
||||
fca_fault = values["FCA_Failinfo"] != 0 or values["FCA_Status"] == 3
|
||||
values["FCA_Failinfo"] = 0
|
||||
|
||||
def _use_stock_scc_surrogates(CP) -> bool:
|
||||
return CP.carFingerprint == CAR.HYUNDAI_PALISADE
|
||||
if fca_fault:
|
||||
values["FCA_Status"] = 2
|
||||
values["CF_VSM_Prefill"] = 0
|
||||
values["CF_VSM_HBACmd"] = 0
|
||||
values["CF_VSM_Warn"] = 0
|
||||
values["CF_VSM_BeltCmd"] = 0
|
||||
values["CR_VSM_DecCmd"] = 0
|
||||
values["FCA_CmdAct"] = 0
|
||||
values["FCA_StopReq"] = 0
|
||||
values["CF_VSM_DecCmdAct"] = 0
|
||||
|
||||
return values
|
||||
|
||||
def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
torque_fault, lkas11, sys_warning, sys_state, enabled,
|
||||
left_lane, right_lane,
|
||||
left_lane_depart, right_lane_depart,
|
||||
lkas_icon):
|
||||
left_lane_depart, right_lane_depart, is_ldws_car):
|
||||
|
||||
values = {s: lkas11[s] for s in [
|
||||
"CF_Lkas_LdwsActivemode",
|
||||
"CF_Lkas_LdwsSysState",
|
||||
@@ -34,7 +46,7 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
"CF_Lkas_LdwsOpt_USM",
|
||||
]}
|
||||
values["CF_Lkas_LdwsSysState"] = sys_state
|
||||
values["CF_Lkas_SysWarning"] = 3 if sys_warning else 0
|
||||
values["CF_Lkas_SysWarning"] = 0 # 3 if sys_warning else 0
|
||||
values["CF_Lkas_LdwsLHWarning"] = left_lane_depart
|
||||
values["CF_Lkas_LdwsRHWarning"] = right_lane_depart
|
||||
values["CR_Lkas_StrToqReq"] = apply_torque
|
||||
@@ -42,16 +54,10 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
values["CF_Lkas_ToiFlt"] = torque_fault # seems to allow actuation on CR_Lkas_StrToqReq
|
||||
values["CF_Lkas_MsgCount"] = frame % 0x10
|
||||
|
||||
if CP.carFingerprint in (CAR.HYUNDAI_SONATA, CAR.HYUNDAI_PALISADE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_NIRO_PHEV_2022, CAR.HYUNDAI_SANTA_FE,
|
||||
CAR.HYUNDAI_IONIQ_EV_2020, CAR.HYUNDAI_IONIQ_PHEV, CAR.KIA_SELTOS, CAR.HYUNDAI_ELANTRA_2021, CAR.GENESIS_G70_2020,
|
||||
CAR.HYUNDAI_ELANTRA_HEV_2021, CAR.HYUNDAI_SONATA_HYBRID, CAR.HYUNDAI_KONA_EV, CAR.HYUNDAI_KONA_HEV, CAR.HYUNDAI_KONA_EV_2022,
|
||||
CAR.HYUNDAI_SANTA_FE_2022, CAR.KIA_K5_2021, CAR.HYUNDAI_IONIQ_HEV_2022, CAR.HYUNDAI_SANTA_FE_HEV_2022,
|
||||
CAR.HYUNDAI_SANTA_FE_PHEV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_CEED,
|
||||
CAR.HYUNDAI_AZERA_6TH_GEN, CAR.HYUNDAI_AZERA_HEV_6TH_GEN, CAR.HYUNDAI_CUSTIN_1ST_GEN, CAR.HYUNDAI_KONA_2022,
|
||||
CAR.KIA_CEED_PHEV_2022_NON_SCC, CAR.HYUNDAI_KONA_EV_NON_SCC, CAR.HYUNDAI_ELANTRA_2022_NON_SCC,
|
||||
CAR.GENESIS_G70_2021_NON_SCC, CAR.KIA_SELTOS_2023_NON_SCC, CAR.HYUNDAI_BAYON_1ST_GEN_NON_SCC):
|
||||
|
||||
if CP.flags & HyundaiFlags.SEND_LFA.value or CP.carFingerprint in (CAR.HYUNDAI_SANTA_FE):
|
||||
values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1)
|
||||
values["CF_Lkas_LdwsOpt_USM"] = 2
|
||||
values["CF_Lkas_LdwsOpt_USM"] = 0 if CP.carFingerprint in (CAR.KIA_RAY_EV) else 2
|
||||
|
||||
# FcwOpt_USM 5 = Orange blinking car + lanes
|
||||
# FcwOpt_USM 4 = Orange car + lanes
|
||||
@@ -59,16 +65,16 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
# FcwOpt_USM 2 = Green car + lanes
|
||||
# FcwOpt_USM 1 = White car + lanes
|
||||
# FcwOpt_USM 0 = No car + lanes
|
||||
values["CF_Lkas_FcwOpt_USM"] = lkas_icon
|
||||
values["CF_Lkas_FcwOpt_USM"] = 2 if enabled else 1
|
||||
|
||||
# SysWarning 4 = keep hands on wheel
|
||||
# SysWarning 5 = keep hands on wheel (red)
|
||||
# SysWarning 6 = keep hands on wheel (red) + beep
|
||||
# Note: the warning is hidden while the blinkers are on
|
||||
values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0
|
||||
values["CF_Lkas_SysWarning"] = 0 #4 if sys_warning else 0
|
||||
|
||||
# Likely cars lacking the ability to show individual lane lines in the dash
|
||||
elif CP.carFingerprint in (CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.HYUNDAI_KONA_NON_SCC):
|
||||
elif CP.carFingerprint in (CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL):
|
||||
# SysWarning 4 = keep hands on wheel + beep
|
||||
values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0
|
||||
|
||||
@@ -76,7 +82,7 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
# SysState 1-2 = white car + lanes
|
||||
# SysState 3 = green car + lanes, green steering wheel
|
||||
# SysState 4 = green car + lanes
|
||||
values["CF_Lkas_LdwsSysState"] = lkas_icon
|
||||
values["CF_Lkas_LdwsSysState"] = 3 if enabled else 1
|
||||
values["CF_Lkas_LdwsOpt_USM"] = 2 # non-2 changes above SysState definition
|
||||
|
||||
# these have no effect
|
||||
@@ -88,6 +94,11 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
|
||||
# Genesis and Optima fault when forwarding while engaged
|
||||
values["CF_Lkas_LdwsActivemode"] = 2
|
||||
|
||||
if is_ldws_car:
|
||||
values["CF_Lkas_LdwsOpt_USM"] = 3
|
||||
|
||||
values["CF_Lkas_Chksum"] = 0
|
||||
|
||||
dat = packer.make_can_msg("LKAS11", 0, values)[1]
|
||||
|
||||
if CP.flags & HyundaiFlags.CHECKSUM_CRC8:
|
||||
@@ -128,152 +139,265 @@ def create_clu11(packer, frame, clu11, button, CP):
|
||||
return packer.make_can_msg("CLU11", bus, values)
|
||||
|
||||
|
||||
def create_lfahda_mfc(packer, enabled, lfa_icon):
|
||||
def create_lfahda_mfc(packer, CC, blinking_signal):
|
||||
activeCarrot = CC.hudControl.activeCarrot
|
||||
values = {
|
||||
"LFA_Icon_State": lfa_icon,
|
||||
"LFA_Icon_State": 2 if CC.latActive else 1 if CC.enabled else 0,
|
||||
#"HDA_Active": 1 if activeCarrot >= 2 else 0,
|
||||
#"HDA_Icon_State": 2 if activeCarrot == 3 and blinking_signal else 2 if activeCarrot >= 2 else 0,
|
||||
"HDA_Icon_State": 0 if activeCarrot == 3 and blinking_signal else 2 if activeCarrot >= 1 else 0,
|
||||
"HDA_VSetReq": 0, #set_speed_in_units if activeCarrot >= 2 else 0,
|
||||
"HDA_USM" : 2,
|
||||
"HDA_Icon_Wheel" : 1 if CC.latActive else 0,
|
||||
#"HDA_Chime" : 1 if CC.latActive else 0, # comment for K9 chime,
|
||||
}
|
||||
return packer.make_can_msg("LFAHDA_MFC", 0, values)
|
||||
|
||||
def create_acc_commands_scc(packer, enabled, accel, jerk, idx, hud_control, set_speed, stopping, long_override, suppress_casper_ev_fca, CS, soft_hold_mode):
|
||||
from iqdbc.car.hyundai.carcontroller import HyundaiJerk
|
||||
cruise_available = CS.out.cruiseState.available
|
||||
if CS.paddle_button_prev > 0:
|
||||
cruise_available = False
|
||||
soft_hold_active = CS.softHoldActive
|
||||
soft_hold_info = soft_hold_active > 1 and enabled
|
||||
#soft_hold_mode = 2 ## some cars can't enable while braking
|
||||
long_enabled = enabled or (soft_hold_active > 0 and soft_hold_mode == 2)
|
||||
stop_req = 1 if stopping or (soft_hold_active > 0 and soft_hold_mode == 2) else 0
|
||||
d = hud_control.leadDistance
|
||||
objGap = 0 if d == 0 else 2 if d < 25 else 3 if d < 40 else 4 if d < 70 else 5
|
||||
objGap2 = 0 if objGap == 0 else 2 if hud_control.leadRelSpeed < -0.2 else 1
|
||||
|
||||
if long_enabled:
|
||||
if jerk.carrot_cruise == 1:
|
||||
long_enabled = False
|
||||
accel = -0.5
|
||||
elif jerk.carrot_cruise == 2:
|
||||
accel = jerk.carrot_cruise_accel
|
||||
|
||||
if long_enabled:
|
||||
scc12_acc_mode = 2 if long_override else 1
|
||||
scc14_acc_mode = 2 if long_override else 1
|
||||
if CS.out.brakeHoldActive:
|
||||
scc12_acc_mode = 0
|
||||
scc14_acc_mode = 4
|
||||
elif CS.out.brakePressed:
|
||||
scc12_acc_mode = 1
|
||||
scc14_acc_mode = 1
|
||||
else:
|
||||
scc12_acc_mode = 0
|
||||
scc14_acc_mode = 4
|
||||
|
||||
warning_front = False
|
||||
|
||||
def create_acc_commands(packer, enabled, accel, upper_jerk, idx, lead_data: CanLeadData,
|
||||
hud_control, set_speed, stopping, long_override, use_fca, CP,
|
||||
main_cruise_enabled, tuning, ESCC: EnhancedSmartCruiseControl | None = None):
|
||||
commands = []
|
||||
if CS.scc11 is not None:
|
||||
values = copy.copy(CS.scc11)
|
||||
values["MainMode_ACC"] = 1 if cruise_available else 0
|
||||
values["TauGapSet"] = hud_control.leadDistanceBars
|
||||
values["VSetDis"] = set_speed if enabled else 0
|
||||
values["AliveCounterACC"] = idx % 0x10
|
||||
values["SCCInfoDisplay"] = 3 if warning_front else 4 if soft_hold_info else 0 if enabled else 0 #2: 크루즈 선택, 3: 전방상황주의, 4: 출발준비
|
||||
values["ObjValid"] = 1 if hud_control.leadVisible else 0
|
||||
values["ACC_ObjStatus"] = 1 if hud_control.leadVisible else 0
|
||||
values["ACC_ObjLatPos"] = 0
|
||||
values["ACC_ObjRelSpd"] = hud_control.leadRelSpeed
|
||||
values["ACC_ObjDist"] = int(hud_control.leadDistance)
|
||||
values["DriverAlertDisplay"] = 0
|
||||
commands.append(packer.make_can_msg("SCC11", 0, values))
|
||||
|
||||
def get_scc11_values():
|
||||
values = {
|
||||
"MainMode_ACC": 1 if main_cruise_enabled else 0,
|
||||
"TauGapSet": hud_control.leadDistanceBars,
|
||||
"VSetDis": set_speed if enabled else 0,
|
||||
"AliveCounterACC": idx % 0x10,
|
||||
"ObjValid": int(lead_data.lead_visible), # close lead makes controls tighter
|
||||
"ACC_ObjStatus": int(lead_data.lead_visible), # close lead makes controls tighter
|
||||
"ACC_ObjLatPos": 0,
|
||||
"ACC_ObjRelSpd": lead_data.lead_rel_speed,
|
||||
"ACC_ObjDist": int(lead_data.lead_distance), # close lead makes controls tighter
|
||||
}
|
||||
if _use_stock_scc_surrogates(CP):
|
||||
values["ObjValid"] = 1
|
||||
values["ACC_ObjStatus"] = 1
|
||||
values["ACC_ObjDist"] = 1
|
||||
return values
|
||||
if CS.scc12 is not None:
|
||||
values = copy.copy(CS.scc12)
|
||||
values["ACCMode"] = scc12_acc_mode #2 if enabled and long_override else 1 if long_enabled else 0
|
||||
values["StopReq"] = stop_req
|
||||
values["aReqRaw"] = accel
|
||||
values["aReqValue"] = accel
|
||||
values["ACCFailInfo"] = 0
|
||||
|
||||
def get_scc12_values():
|
||||
scc12_values = {
|
||||
"ACCMode": 2 if enabled and long_override else 1 if enabled else 0,
|
||||
"StopReq": 1 if tuning.stopping else 0,
|
||||
"aReqRaw": tuning.desired_accel,
|
||||
"aReqValue": tuning.actual_accel, # stock ramps up and down respecting jerk limit until it reaches aReqRaw
|
||||
"CR_VSM_Alive": idx % 0xF,
|
||||
}
|
||||
#values["DESIRED_DIST"] = CS.out.vEgo * 1.0 + 4.0 # TF: 1.0 + STOPDISTANCE 4.0 m로 가정함.
|
||||
|
||||
# show AEB disabled indicator on dash with SCC12 if not sending FCA messages.
|
||||
# these signals also prevent a TCS fault on non-FCA cars with alpha longitudinal
|
||||
if not use_fca:
|
||||
scc12_values["CF_VSM_ConfMode"] = 1
|
||||
scc12_values["AEB_Status"] = 1 # AEB disabled
|
||||
|
||||
# Since we have ESCC available, we can update SCC12 with ESCC values.
|
||||
if ESCC and ESCC.enabled:
|
||||
ESCC.update_scc12(scc12_values)
|
||||
|
||||
return scc12_values
|
||||
|
||||
def calculate_scc12_checksum(values):
|
||||
values["CR_VSM_ChkSum"] = 0
|
||||
values["CR_VSM_Alive"] = idx % 0xF
|
||||
scc12_dat = packer.make_can_msg("SCC12", 0, values)[1]
|
||||
values["CR_VSM_ChkSum"] = 0x10 - sum(sum(divmod(i, 16)) for i in scc12_dat) % 0x10
|
||||
return values
|
||||
|
||||
def get_scc14_values():
|
||||
values = {
|
||||
"ComfortBandUpper": tuning.comfort_band_upper, # stock usually is 0 but sometimes uses higher values
|
||||
"ComfortBandLower": tuning.comfort_band_lower, # stock usually is 0 but sometimes uses higher values
|
||||
"JerkUpperLimit": tuning.jerk_upper, # stock usually is 1.0 but sometimes uses higher values
|
||||
"JerkLowerLimit": tuning.jerk_lower, # stock usually is 0.5 but sometimes uses higher values
|
||||
"ACCMode": 2 if enabled and long_override else 1 if enabled else 4, # stock will always be 4 instead of 0 after first disengage
|
||||
"ObjGap": lead_data.object_gap, # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead
|
||||
}
|
||||
if not _use_stock_scc_surrogates(CP):
|
||||
values["ObjDistStat"] = lead_data.object_rel_gap
|
||||
return values
|
||||
commands.append(packer.make_can_msg("SCC12", 0, values))
|
||||
|
||||
def get_fca11_values():
|
||||
return {
|
||||
if CS.scc14 is not None:
|
||||
values = copy.copy(CS.scc14)
|
||||
values["ComfortBandUpper"] = jerk.cb_upper
|
||||
values["ComfortBandLower"] = jerk.cb_lower
|
||||
values["JerkUpperLimit"] = jerk.jerk_u
|
||||
values["JerkLowerLimit"] = jerk.jerk_l if long_enabled else 0 # for KONA test
|
||||
values["ACCMode"] = scc14_acc_mode #2 if enabled and long_override else 1 if long_enabled else 4 # stock will always be 4 instead of 0 after first disengage
|
||||
values["ObjGap"] = objGap #2 if hud_control.leadVisible else 0 # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead
|
||||
values["ObjDistStat"] = objGap2
|
||||
commands.append(packer.make_can_msg("SCC14", 0, values))
|
||||
|
||||
if CS.fca11 is not None and suppress_casper_ev_fca: # CASPER_EV의 경우 FCA11에서 fail이 간헐적 발생함.. 그냥막자.. 원인불명..
|
||||
values = suppress_casper_ev_fca11_fault(copy.copy(CS.fca11))
|
||||
fca11_dat = packer.make_can_msg("FCA11", 0, values)[1]
|
||||
values["CR_FCA_ChkSum"] = hyundai_checksum(fca11_dat[:7])
|
||||
commands.append(packer.make_can_msg("FCA11", 0, values))
|
||||
# Only send FCA11 on cars where it exists on the bus
|
||||
if False: #use_fca:
|
||||
# note that some vehicles most likely have an alternate checksum/counter definition
|
||||
# https://github.com/commaai/iqdbc/commit/9ddcdb22c4929baf310295e832668e6e7fcfa602
|
||||
fca11_values = {
|
||||
"CR_FCA_Alive": idx % 0xF,
|
||||
"PAINT1_Status": 1,
|
||||
"FCA_DrvSetStatus": 1,
|
||||
"FCA_Status": 1,
|
||||
"FCA_Status": 1, # AEB disabled
|
||||
}
|
||||
|
||||
def calculate_fca11_checksum(values):
|
||||
fca11_dat = packer.make_can_msg("FCA11", 0, values)[1]
|
||||
values["CR_FCA_ChkSum"] = hyundai_checksum(fca11_dat[:7])
|
||||
return values
|
||||
|
||||
scc11_values = get_scc11_values()
|
||||
commands.append(packer.make_can_msg("SCC11", 0, scc11_values))
|
||||
|
||||
scc12_values = get_scc12_values()
|
||||
scc12_values = calculate_scc12_checksum(scc12_values)
|
||||
commands.append(packer.make_can_msg("SCC12", 0, scc12_values))
|
||||
|
||||
scc14_values = get_scc14_values()
|
||||
commands.append(packer.make_can_msg("SCC14", 0, scc14_values))
|
||||
|
||||
# Only send FCA11 on cars where it exists on the bus
|
||||
# On Camera SCC cars, FCA11 is not disabled, so we forward stock FCA11 back to the car forward hooks
|
||||
# If we don't use ESCC since ESCC does not block FCA11 from stock radar
|
||||
if use_fca and not ((CP.flags & HyundaiFlags.CAMERA_SCC) or (ESCC and ESCC.enabled)):
|
||||
# note that some vehicles most likely have an alternate checksum/counter definition
|
||||
# https://github.com/commaai/iqdbc/commit/9ddcdb22c4929baf310295e832668e6e7fcfa602
|
||||
fca11_values = get_fca11_values()
|
||||
fca11_values = calculate_fca11_checksum(fca11_values)
|
||||
fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[1]
|
||||
fca11_values["CR_FCA_ChkSum"] = hyundai_checksum(fca11_dat[:7])
|
||||
commands.append(packer.make_can_msg("FCA11", 0, fca11_values))
|
||||
|
||||
return commands
|
||||
|
||||
def create_acc_opt_copy(CS, packer):
|
||||
values = copy.copy(CS.scc13)
|
||||
if values["NEW_SIGNAL_1"] == 255:
|
||||
values["NEW_SIGNAL_1"] = 218
|
||||
values["NEW_SIGNAL_2"] = 0
|
||||
return packer.make_can_msg("SCC13", 0, CS.scc13)
|
||||
|
||||
def create_acc_opt(packer, CP, ESCC: EnhancedSmartCruiseControl | None = None):
|
||||
"""
|
||||
Creates SCC13 and FCA12. If ESCC is enabled, it will only create SCC13 since ESCC does not block FCA12.
|
||||
:param packer:
|
||||
:param ESCC:
|
||||
:return:
|
||||
"""
|
||||
def create_acc_commands(packer, enabled, accel, jerk, idx, hud_control, set_speed, stopping, long_override, use_fca, CP, CS, soft_hold_mode):
|
||||
from iqdbc.car.hyundai.carcontroller import HyundaiJerk
|
||||
cruise_available = CS.out.cruiseState.available
|
||||
soft_hold_active = CS.softHoldActive
|
||||
soft_hold_info = soft_hold_active > 1 and enabled
|
||||
#soft_hold_mode = 2 ## some cars can't enable while braking
|
||||
long_enabled = enabled or (soft_hold_active > 0 and soft_hold_mode == 2)
|
||||
stop_req = 1 if stopping or (soft_hold_active > 0 and soft_hold_mode == 2) else 0
|
||||
d = hud_control.leadDistance
|
||||
objGap = 0 if d == 0 else 2 if d < 25 else 3 if d < 40 else 4 if d < 70 else 5
|
||||
objGap2 = 0 if objGap == 0 else 2 if hud_control.leadRelSpeed < -0.2 else 1
|
||||
|
||||
def get_scc13_values():
|
||||
return {
|
||||
"SCCDrvModeRValue": 2,
|
||||
"SCC_Equip": 1,
|
||||
"Lead_Veh_Dep_Alert_USM": 2,
|
||||
}
|
||||
if long_enabled:
|
||||
scc12_acc_mode = 2 if long_override else 1
|
||||
scc14_acc_mode = 2 if long_override else 1
|
||||
if CS.out.brakeHoldActive:
|
||||
scc12_acc_mode = 0
|
||||
scc14_acc_mode = 4
|
||||
elif CS.out.brakePressed:
|
||||
scc12_acc_mode = 1
|
||||
scc14_acc_mode = 1
|
||||
else:
|
||||
scc12_acc_mode = 0
|
||||
scc14_acc_mode = 4
|
||||
|
||||
def get_fca12_values():
|
||||
return {
|
||||
"FCA_DrvSetState": 2,
|
||||
"FCA_USM": 1, # AEB disabled
|
||||
}
|
||||
warning_front = False
|
||||
|
||||
commands = []
|
||||
|
||||
scc13_values = get_scc13_values()
|
||||
commands.append(packer.make_can_msg("SCC13", 0, scc13_values))
|
||||
scc11_values = {
|
||||
"MainMode_ACC": 1 if cruise_available else 0,
|
||||
"TauGapSet": hud_control.leadDistanceBars,
|
||||
"VSetDis": set_speed if enabled else 0,
|
||||
"AliveCounterACC": idx % 0x10,
|
||||
"SCCInfoDisplay": 3 if warning_front else 4 if soft_hold_info else 0 if enabled else 0,
|
||||
"ObjValid": 1 if hud_control.leadVisible else 0, # close lead makes controls tighter
|
||||
"ACC_ObjStatus": 1 if hud_control.leadVisible else 0, # close lead makes controls tighter
|
||||
"ACC_ObjLatPos": 0,
|
||||
"ACC_ObjRelSpd": hud_control.leadRelSpeed,
|
||||
"ACC_ObjDist": int(hud_control.leadDistance), # close lead makes controls tighter
|
||||
"DriverAlertDisplay": 0,
|
||||
}
|
||||
commands.append(packer.make_can_msg("SCC11", 0, scc11_values))
|
||||
|
||||
# If ESCC is available and enabled, we skip FCA12, since ESCC does not block FCA12
|
||||
if ESCC and ESCC.enabled:
|
||||
return commands
|
||||
scc12_values = {
|
||||
"ACCMode": scc12_acc_mode,
|
||||
"StopReq": stop_req,
|
||||
"aReqRaw": 0 if stop_req > 0 else accel,
|
||||
"aReqValue": accel, # stock ramps up and down respecting jerk limit until it reaches aReqRaw
|
||||
#"DESIRED_DIST": CS.out.vEgo * 1.0 + 4.0,
|
||||
"CR_VSM_Alive": idx % 0xF,
|
||||
}
|
||||
|
||||
# show AEB disabled indicator on dash with SCC12 if not sending FCA messages.
|
||||
# these signals also prevent a TCS fault on non-FCA cars with alpha longitudinal
|
||||
if not use_fca:
|
||||
scc12_values["CF_VSM_ConfMode"] = 1
|
||||
scc12_values["AEB_Status"] = 1 # AEB disabled
|
||||
|
||||
scc12_dat = packer.make_can_msg("SCC12", 0, scc12_values)[1]
|
||||
scc12_values["CR_VSM_ChkSum"] = 0x10 - sum(sum(divmod(i, 16)) for i in scc12_dat) % 0x10
|
||||
|
||||
commands.append(packer.make_can_msg("SCC12", 0, scc12_values))
|
||||
|
||||
scc14_values = {
|
||||
"ComfortBandUpper": jerk.cb_upper, # stock usually is 0 but sometimes uses higher values
|
||||
"ComfortBandLower": jerk.cb_lower, # stock usually is 0 but sometimes uses higher values
|
||||
"JerkUpperLimit": jerk.jerk_u, # stock usually is 1.0 but sometimes uses higher values
|
||||
"JerkLowerLimit": jerk.jerk_l, # stock usually is 0.5 but sometimes uses higher values
|
||||
"ACCMode": scc14_acc_mode, # if enabled and long_override else 1 if enabled else 4, # stock will always be 4 instead of 0 after first disengage
|
||||
"ObjGap": objGap, #2 if hud_control.leadVisible else 0, # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead
|
||||
"ObjDistStat": objGap2,
|
||||
}
|
||||
commands.append(packer.make_can_msg("SCC14", 0, scc14_values))
|
||||
|
||||
# Only send FCA11 on cars where it exists on the bus
|
||||
# On Camera SCC cars, FCA11 is not disabled, so we forward stock FCA11 back to the car forward hooks
|
||||
if use_fca and not (CP.flags & HyundaiFlags.CAMERA_SCC):
|
||||
# note that some vehicles most likely have an alternate checksum/counter definition
|
||||
# https://github.com/commaai/iqdbc/commit/9ddcdb22c4929baf310295e832668e6e7fcfa602
|
||||
fca11_values = {
|
||||
"CR_FCA_Alive": idx % 0xF,
|
||||
"PAINT1_Status": 1,
|
||||
"FCA_DrvSetStatus": 1,
|
||||
"FCA_Status": 1, # AEB disabled
|
||||
}
|
||||
fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[1]
|
||||
fca11_values["CR_FCA_ChkSum"] = hyundai_checksum(fca11_dat[:7])
|
||||
commands.append(packer.make_can_msg("FCA11", 0, fca11_values))
|
||||
|
||||
return commands
|
||||
|
||||
def create_acc_opt(packer, CP):
|
||||
commands = []
|
||||
|
||||
scc13_values = {
|
||||
"SCCDrvModeRValue": 2,
|
||||
"SCC_Equip": 1,
|
||||
"Lead_Veh_Dep_Alert_USM": 2,
|
||||
}
|
||||
commands.append(packer.make_can_msg("SCC13", 0, scc13_values))
|
||||
|
||||
# TODO: this needs to be detected and conditionally sent on unsupported long cars
|
||||
# On Camera SCC cars, FCA12 is not disabled, so we forward stock FCA12 back to the car forward hooks
|
||||
if not (CP.flags & HyundaiFlags.CAMERA_SCC):
|
||||
fca12_values = get_fca12_values()
|
||||
fca12_values = {
|
||||
"FCA_DrvSetState": 2,
|
||||
"FCA_USM": 1, # AEB disabled
|
||||
}
|
||||
commands.append(packer.make_can_msg("FCA12", 0, fca12_values))
|
||||
|
||||
return commands
|
||||
|
||||
|
||||
def create_frt_radar_opt(packer):
|
||||
frt_radar11_values = {
|
||||
"CF_FCA_Equip_Front_Radar": 1,
|
||||
}
|
||||
return packer.make_can_msg("FRT_RADAR11", 0, frt_radar11_values)
|
||||
|
||||
def create_clu11_button(packer, frame, clu11, button, CP):
|
||||
values = clu11.copy()
|
||||
values["CF_Clu_CruiseSwState"] = button
|
||||
#values["CF_Clu_AliveCnt1"] = frame % 0x10
|
||||
values["CF_Clu_AliveCnt1"] = (values["CF_Clu_AliveCnt1"] + 1) % 0x10
|
||||
# send buttons to camera on camera-scc based cars
|
||||
bus = 2 if CP.flags & HyundaiFlags.CAMERA_SCC else 0
|
||||
return packer.make_can_msg("CLU11", bus, values)
|
||||
|
||||
def create_mdps12(packer, frame, mdps12):
|
||||
values = mdps12
|
||||
values["CF_Mdps_ToiActive"] = 0
|
||||
values["CF_Mdps_ToiUnavail"] = 1
|
||||
values["CF_Mdps_MsgCount2"] = frame % 0x100
|
||||
values["CF_Mdps_Chksum2"] = 0
|
||||
|
||||
dat = packer.make_can_msg("MDPS12", 2, values)[1]
|
||||
checksum = sum(dat) % 256
|
||||
values["CF_Mdps_Chksum2"] = checksum
|
||||
|
||||
return packer.make_can_msg("MDPS12", 2, values)
|
||||
|
||||
@@ -2,22 +2,42 @@ import copy
|
||||
import numpy as np
|
||||
from iqdbc.car import CanBusBase
|
||||
from iqdbc.car.crc import CRC16_XMODEM
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags
|
||||
from iqdbc.iqpilot.car.hyundai.lead_data_ext import CanFdLeadData
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags, HyundaiExtFlags
|
||||
from openpilot.common.params import Params
|
||||
from iqdbc.car.common.conversions import Conversions as CV
|
||||
from cereal import log
|
||||
|
||||
LaneChangeState = log.LaneChangeState
|
||||
LaneChangeDirection = log.LaneChangeDirection
|
||||
TurnDirection = log.Desire
|
||||
|
||||
|
||||
def hyundai_crc8(data: bytes) -> int:
|
||||
poly = 0x2F
|
||||
crc = 0xFF
|
||||
|
||||
for byte in data:
|
||||
crc ^= byte
|
||||
for _ in range(8):
|
||||
if crc & 0x80:
|
||||
crc = ((crc << 1) ^ poly) & 0xFF
|
||||
else:
|
||||
crc = (crc << 1) & 0xFF
|
||||
|
||||
return crc ^ 0xFF
|
||||
|
||||
class CanBus(CanBusBase):
|
||||
def __init__(self, CP, fingerprint=None, lka_steering=None) -> None:
|
||||
super().__init__(CP, fingerprint)
|
||||
|
||||
if lka_steering is None:
|
||||
lka_steering = CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value if CP is not None else False
|
||||
lka_steering = CP.flags & HyundaiFlags.CANFD_HDA2.value if CP is not None else False
|
||||
|
||||
# On the CAN-FD platforms, the LKAS camera is on both A-CAN and E-CAN. LKA steering cars
|
||||
# have a different harness than the LFA steering variants in order to split
|
||||
# a different bus, since the steering is done by different ECUs.
|
||||
self._a, self._e = 1, 0
|
||||
if lka_steering:
|
||||
if lka_steering and Params().get_int("HyundaiCameraSCC") == 0: #배선개조는 무조건 Bus0가 ECAN임.
|
||||
self._a, self._e = 0, 1
|
||||
|
||||
self._a += self.offset
|
||||
@@ -36,50 +56,190 @@ class CanBus(CanBusBase):
|
||||
def CAM(self):
|
||||
return self._cam
|
||||
|
||||
# CAN LIST (CAM) - 롱컨개조시... ADAS + CAM
|
||||
# 160: ADRV_0x160
|
||||
# 1da: ADRV_0x1da
|
||||
# 1ea: ADRV_0x1ea
|
||||
# 200: ADRV_0x200
|
||||
# 345: ADRV_0x345
|
||||
# 1fa: CLUSTER_SPEED_LIMIT
|
||||
# 12a: LFA
|
||||
# 1e0: LFAHDA_CLUSTER
|
||||
# 11a:
|
||||
# 1b5:
|
||||
# 1a0: SCC_CONTROL
|
||||
|
||||
def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque, lkas_icon):
|
||||
common_values = {
|
||||
"LKA_MODE": 2,
|
||||
"LKA_ICON": lkas_icon,
|
||||
"TORQUE_REQUEST": apply_torque,
|
||||
"LKA_ASSIST": 0,
|
||||
"STEER_REQ": 1 if lat_active else 0,
|
||||
"STEER_MODE": 0,
|
||||
"HAS_LANE_SAFETY": 0, # hide LKAS settings
|
||||
"NEW_SIGNAL_2": 0,
|
||||
"DAMP_FACTOR": 100, # can potentially tuned for better perf [3, 200]
|
||||
}
|
||||
# CAN LIST (ACAN)
|
||||
# 160: ADRV_0x160
|
||||
# 51: ADRV_0x51
|
||||
# 180: CAM_0x180
|
||||
# ...
|
||||
# 185: CAM_0x185
|
||||
# 1b6: CAM_0x1b6
|
||||
# ...
|
||||
# 1b9: CAM_0x1b9
|
||||
# 1fb: CAM_0x1fb
|
||||
# 2a2 - 2a4
|
||||
# 2bb - 2be
|
||||
# LKAS
|
||||
# 201 - 2a0
|
||||
|
||||
lkas_values = copy.copy(common_values)
|
||||
lkas_values["LKA_AVAILABLE"] = 0
|
||||
|
||||
lfa_values = copy.copy(common_values)
|
||||
lfa_values["NEW_SIGNAL_1"] = 0
|
||||
|
||||
def create_steering_messages_camera_scc(frame, packer, CP, CAN, CC, lat_active, apply_steer, CS, apply_angle, max_torque, angle_control):
|
||||
|
||||
emergency_steering = False
|
||||
if CS.adrv_0x161 is not None:
|
||||
values = CS.adrv_0x161
|
||||
emergency_steering = values["ALERTS_1"] in [11, 12, 13, 14, 15, 21, 22, 23, 24, 25, 26]
|
||||
|
||||
|
||||
ret = []
|
||||
if CP.flags & HyundaiFlags.CANFD_LKA_STEERING:
|
||||
lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT else "LKAS"
|
||||
if CP.openpilotLongitudinalControl:
|
||||
ret.append(packer.make_can_msg("LFA", CAN.ECAN, lfa_values))
|
||||
ret.append(packer.make_can_msg(lkas_msg, CAN.ACAN, lkas_values))
|
||||
else:
|
||||
ret.append(packer.make_can_msg("LFA", CAN.ECAN, lfa_values))
|
||||
if CS.mdps is not None:
|
||||
values = copy.copy(CS.mdps)
|
||||
#rx_counter = values.pop("COUNTER", None)
|
||||
if angle_control:
|
||||
if CS.lfa_alt is not None:
|
||||
values["LFA2_ACTIVE"] = CS.lfa_alt["LKAS_ANGLE_ACTIVE"]
|
||||
else:
|
||||
if CS.lfa is not None:
|
||||
values["LKA_ACTIVE"] = 1 if CS.lfa["STEER_REQ"] == 1 else 0
|
||||
|
||||
if frame % 1000 < 40:
|
||||
values["STEERING_COL_TORQUE"] += 220
|
||||
#ret.append(packer.make_can_msg("MDPS", CAN.CAM, values, rx_counter = rx_counter))
|
||||
ret.append(packer.make_can_msg("MDPS", CAN.CAM, values))
|
||||
|
||||
if frame % 10 == 0:
|
||||
if CS.steer_touch_2af is not None:
|
||||
values = copy.copy(CS.steer_touch_2af)
|
||||
if frame % 1000 < 40:
|
||||
values["TOUCH_DETECT"] = 3
|
||||
values["TOUCH1"] = 50
|
||||
values["TOUCH2"] = 50
|
||||
values["CHECKSUM_"] = 0
|
||||
dat = packer.make_can_msg("STEER_TOUCH_2AF", 0, values)[1]
|
||||
values["CHECKSUM_"] = hyundai_crc8(dat[1:8])
|
||||
|
||||
ret.append(packer.make_can_msg("STEER_TOUCH_2AF", CAN.CAM, values))
|
||||
|
||||
if angle_control:
|
||||
if CS.lfa_alt is not None:
|
||||
values = copy.copy(CS.lfa_alt)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
if emergency_steering:
|
||||
pass
|
||||
else:
|
||||
#values = {} #CS.lfa_alt
|
||||
values["LKAS_ANGLE_ACTIVE"] = 2 if CC.latActive else 1
|
||||
values["LKAS_ANGLE_CMD"] = -apply_angle
|
||||
values["LKAS_ANGLE_MAX_TORQUE"] = max_torque if CC.latActive else 0
|
||||
ret.append(packer.make_can_msg("LFA_ALT", CAN.ECAN, values, rx_counter = rx_counter))
|
||||
|
||||
if CS.lfa is not None:
|
||||
values = copy.copy(CS.lfa)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
if not emergency_steering:
|
||||
values["LKA_MODE"] = 0
|
||||
values["LKA_ICON"] = 2 if CC.latActive else 1
|
||||
values["TORQUE_REQUEST"] = -1024 # apply_steer,
|
||||
values["VALUE63"] = 0 # LKA_ASSIST
|
||||
values["STEER_REQ"] = 0 # 1 if lat_active else 0,
|
||||
values["HAS_LANE_SAFETY"] = 0 # hide LKAS settings
|
||||
values["LKA_ACTIVE"] = 3 if CC.latActive else 0 # this changes sometimes, 3 seems to indicate engaged
|
||||
values["VALUE64"] = 0 #STEER_MODE, NEW_SIGNAL_2
|
||||
values["LKAS_ANGLE_CMD"] = -25.6 #-apply_angle,
|
||||
values["LKAS_ANGLE_ACTIVE"] = 0 #2 if lat_active else 1,
|
||||
values["LKAS_ANGLE_MAX_TORQUE"] = 0 #max_torque if lat_active else 0,
|
||||
values["NEW_SIGNAL_1"] = 10
|
||||
ret.append(packer.make_can_msg("LFA", CAN.ECAN, values, rx_counter = rx_counter))
|
||||
|
||||
elif CS.lfa is not None:
|
||||
values = {}
|
||||
values["LKA_MODE"] = 2
|
||||
values["LKA_ICON"] = 2 if lat_active else 1
|
||||
values["TORQUE_REQUEST"] = apply_steer
|
||||
values["STEER_REQ"] = 1 if lat_active else 0
|
||||
values["VALUE64"] = 0 # STEER_MODE, NEW_SIGNAL_2
|
||||
values["HAS_LANE_SAFETY"] = 0
|
||||
values["LKA_ACTIVE"] = 0 # NEW_SIGNAL_1
|
||||
|
||||
values["DampingGain"] = 0 if lat_active else 100
|
||||
#values["VALUE63"] = 0
|
||||
|
||||
#values["VALUE82_SET256"] = 0
|
||||
|
||||
ret.append(packer.make_can_msg("LFA", CAN.ECAN, values))
|
||||
|
||||
return ret
|
||||
|
||||
def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_steer, apply_angle, max_torque, angle_control):
|
||||
|
||||
def create_suppress_lfa(packer, CAN, lfa_block_msg, lka_steering_alt):
|
||||
suppress_msg = "CAM_0x362" if lka_steering_alt else "CAM_0x2a4"
|
||||
msg_bytes = 32 if lka_steering_alt else 24
|
||||
ret = []
|
||||
if angle_control:
|
||||
values = {
|
||||
"LKA_MODE": 0,
|
||||
"LKA_ICON": 2 if enabled else 1,
|
||||
"TORQUE_REQUEST": 0, # apply_steer,
|
||||
"VALUE63": 0, # LKA_ASSIST
|
||||
"STEER_REQ": 0, # 1 if lat_active else 0,
|
||||
"HAS_LANE_SAFETY": 0, # hide LKAS settings
|
||||
"LKA_ACTIVE": 3 if lat_active else 0, # this changes sometimes, 3 seems to indicate engaged
|
||||
"VALUE64": 0, #STEER_MODE, NEW_SIGNAL_2
|
||||
"LKAS_ANGLE_CMD": -apply_angle,
|
||||
"LKAS_ANGLE_ACTIVE": 2 if lat_active else 1,
|
||||
"LKAS_ANGLE_MAX_TORQUE": max_torque if lat_active else 0,
|
||||
|
||||
values = {f"BYTE{i}": lfa_block_msg[f"BYTE{i}"] for i in range(3, msg_bytes) if i != 7}
|
||||
# test for EV6PE
|
||||
"NEW_SIGNAL_1": 10, #2,
|
||||
"DampingGain": 9,
|
||||
"VALUE231": 146,
|
||||
"VALUE239": 1,
|
||||
"VALUE247": 255,
|
||||
"VALUE255": 255,
|
||||
}
|
||||
else:
|
||||
values = {
|
||||
"LKA_MODE": 2,
|
||||
"LKA_ICON": 2 if enabled else 1,
|
||||
"TORQUE_REQUEST": apply_steer,
|
||||
"DampingGain": 100, #3 if enabled else 100,
|
||||
"STEER_REQ": 1 if lat_active else 0,
|
||||
#"STEER_MODE": 0,
|
||||
"HAS_LANE_SAFETY": 0, # hide LKAS settings
|
||||
"VALUE63": 0,
|
||||
"VALUE64": 100,
|
||||
}
|
||||
|
||||
if CP.flags & HyundaiFlags.CANFD_HDA2:
|
||||
lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_HDA2_ALT_STEERING else "LKAS"
|
||||
if CP.openpilotLongitudinalControl:
|
||||
ret.append(packer.make_can_msg("LFA", CAN.ECAN, values))
|
||||
if not (CP.flags & HyundaiFlags.CAMERA_SCC.value):
|
||||
ret.append(packer.make_can_msg(lkas_msg, CAN.ACAN, values))
|
||||
else:
|
||||
ret.append(packer.make_can_msg("LFA", CAN.ECAN, values))
|
||||
|
||||
return ret
|
||||
|
||||
def create_suppress_lfa(packer, CAN, CS):
|
||||
if CS.cam_0x362 is not None:
|
||||
suppress_msg = "CAM_0x362"
|
||||
lfa_block_msg = CS.cam_0x362
|
||||
elif CS.cam_0x2a4 is not None:
|
||||
suppress_msg = "CAM_0x2a4"
|
||||
lfa_block_msg = CS.cam_0x2a4
|
||||
else:
|
||||
return []
|
||||
|
||||
#values = {f"BYTE{i}": lfa_block_msg[f"BYTE{i}"] for i in range(3, msg_bytes) if i != 7}
|
||||
values = copy.copy(lfa_block_msg)
|
||||
values["COUNTER"] = lfa_block_msg["COUNTER"]
|
||||
values["SET_ME_0"] = 0
|
||||
values["SET_ME_0_2"] = 0
|
||||
values["LEFT_LANE_LINE"] = 0
|
||||
values["RIGHT_LANE_LINE"] = 0
|
||||
return packer.make_can_msg(suppress_msg, CAN.ACAN, values)
|
||||
|
||||
return [packer.make_can_msg(suppress_msg, CAN.ACAN, values)]
|
||||
|
||||
def create_buttons(packer, CP, CAN, cnt, btn):
|
||||
values = {
|
||||
@@ -88,14 +248,12 @@ def create_buttons(packer, CP, CAN, cnt, btn):
|
||||
"CRUISE_BUTTONS": btn,
|
||||
}
|
||||
|
||||
bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_LKA_STEERING else CAN.CAM
|
||||
#bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_HDA2 else CAN.CAM
|
||||
bus = CAN.ECAN
|
||||
return packer.make_can_msg("CRUISE_BUTTONS", bus, values)
|
||||
|
||||
|
||||
def create_acc_cancel(packer, CP, CAN, cruise_info_copy):
|
||||
# CAN FD camera-based SCC requires additional signals to be preserved
|
||||
# verbatim from the previous SCC_CONTROL frame to avoid checksum or
|
||||
# state validation faults. Classic CAN SCC only validates a subset.
|
||||
# TODO: why do we copy different values here?
|
||||
if CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value:
|
||||
values = {s: cruise_info_copy[s] for s in [
|
||||
"COUNTER",
|
||||
@@ -124,49 +282,169 @@ def create_acc_cancel(packer, CP, CAN, cruise_info_copy):
|
||||
})
|
||||
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
|
||||
|
||||
|
||||
def create_lfahda_cluster(packer, CAN, enabled, lfa_icon):
|
||||
values = {
|
||||
"HDA_ICON": 1 if enabled else 0,
|
||||
"LFA_ICON": lfa_icon,
|
||||
}
|
||||
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
|
||||
def create_lfahda_cluster(packer, CS, CAN, long_active, lat_active):
|
||||
|
||||
|
||||
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control,
|
||||
lead_data: CanFdLeadData, main_cruise_enabled, tuning):
|
||||
if CS.lfahda_cluster is not None:
|
||||
values = copy.copy(CS.lfahda_cluster)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
else:
|
||||
return []
|
||||
values = {}
|
||||
rx_counter = None
|
||||
values["LFA_OptUsmSta"] = 2
|
||||
values["HDA_OptUsmSta"] = 2
|
||||
values["HDA_CntrlModSta"] = 2 if long_active else 0
|
||||
values["HDA_LFA_SymSta"] = 2 if lat_active else 0
|
||||
return [packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values, rx_counter=rx_counter)]
|
||||
|
||||
def create_lfa_icon_non_camera_scc(packer, CS, CAN, CC):
|
||||
ret = []
|
||||
if CS.adrv_0x161 is not None:
|
||||
values = copy.copy(CS.adrv_0x161)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
|
||||
lat_active = CC.latActive
|
||||
lat_enabled = CS.out.latEnabled
|
||||
|
||||
values["LFA_ICON"] = 2 if lat_active else 1 if lat_enabled else 0
|
||||
values["LKA_ICON"] = 4 if lat_active else 3 if lat_enabled else 0
|
||||
|
||||
if values["ALERTS_2"] in [1, 2, 5, 6, 10, 21, 22]:
|
||||
values["ALERTS_2"] = 0
|
||||
values["DAW_ICON"] = 0
|
||||
|
||||
if values["ALERTS_1"] == 0:
|
||||
values["SOUNDS_1"] = 0
|
||||
values["SOUNDS_2"] = 0
|
||||
values["SOUNDS_4"] = 0
|
||||
|
||||
if values["ALERTS_3"] in [3, 4, 11, 12, 13, 14, 17, 19, 26, 7, 8, 9, 10]:
|
||||
values["ALERTS_3"] = 0
|
||||
values["SOUNDS_3"] = 0
|
||||
|
||||
if values["ALERTS_5"] in [1, 2, 3, 4, 5]:
|
||||
values["ALERTS_5"] = 0
|
||||
|
||||
ret.append(packer.make_can_msg("ADRV_0x161", CAN.ECAN, values, rx_counter=rx_counter))
|
||||
return ret
|
||||
|
||||
def create_acc_control_scc2(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control, hyundai_jerk, CS):
|
||||
|
||||
if CS.scc_control is None:
|
||||
return None
|
||||
enabled = (enabled or CS.softHoldActive > 0) and CS.paddle_button_prev == 0
|
||||
|
||||
acc_mode = 0 if not enabled else (2 if gas_override else 1)
|
||||
|
||||
if hyundai_jerk.carrot_cruise == 1:
|
||||
acc_mode = 4 if enabled else 0
|
||||
enabled = False
|
||||
accel = accel_last = 0.5
|
||||
|
||||
elif hyundai_jerk.carrot_cruise == 2:
|
||||
accel = accel_last = hyundai_jerk.carrot_cruise_accel
|
||||
|
||||
jerk_u = hyundai_jerk.jerk_u
|
||||
jerk_l = hyundai_jerk.jerk_l
|
||||
jerk = 5
|
||||
jn = jerk / 50
|
||||
if not enabled or gas_override:
|
||||
a_val, a_raw = 0, 0
|
||||
else:
|
||||
a_raw = accel # noqa: F841
|
||||
a_val = np.clip(accel, accel_last - jn, accel_last + jn) # noqa: F841
|
||||
a_raw = accel
|
||||
a_val = accel #np.clip(accel, accel_last - jn, accel_last + jn)
|
||||
|
||||
values = copy.copy(CS.scc_control)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
values["ACCMode"] = acc_mode
|
||||
values["MainMode_ACC"] = 1
|
||||
values["StopReq"] = 1 if stopping or CS.softHoldActive > 0 else 0 # 1: Stop control is required, 2: Not used, 3: Error Indicator
|
||||
values["aReqValue"] = a_val
|
||||
values["aReqRaw"] = a_raw
|
||||
values["VSetDis"] = set_speed
|
||||
#values["JerkLowerLimit"] = jerk if enabled else 1
|
||||
#values["JerkUpperLimit"] = 3.0
|
||||
values["JerkLowerLimit"] = jerk_l if enabled else 1
|
||||
values["JerkUpperLimit"] = 2.0 if stopping or CS.softHoldActive else jerk_u
|
||||
values["DISTANCE_SETTING"] = hud_control.leadDistanceBars # + 5
|
||||
#values["DISTANCE_SETTING"] = hud_control.leadDistanceBars + 5
|
||||
|
||||
#values["ACC_ObjDist"] = 1
|
||||
#values["ObjValid"] = 0
|
||||
#values["OBJ_STATUS"] = 2
|
||||
#values["NSCCOper"] = 1 if enabled else 0 # 0: off, 1: Ready, 2: Act, 3: Error Indicator
|
||||
#values["NSCCOnOff"] = 2 # 0: Default, 1: Off, 2: On, 3: Invalid
|
||||
#values["SET_ME_3"] = 0x3 # objRelsped와 충돌
|
||||
#values["ACC_ObjLatPos"] = - hud_control.leadDPath
|
||||
values["DriveMode"] = 0 # 0: Default, 1: Comfort Mode, 2:Normal mode, 3:Dynamic mode, reserved
|
||||
|
||||
hud_lead_info = 0
|
||||
if hud_control.leadVisible:
|
||||
hud_lead_info = 1 if values["ACC_ObjRelSpd"] > 0 else 2
|
||||
values["HUD_LEAD_INFO"] = hud_lead_info #1: in-path object detected(uncontrollable), 2: controllable long, 3: controllable long & lat, ... reserved
|
||||
|
||||
values["DriverAlert"] = 0 # 1: SCC Disengaged, 2: No SCC Engage condition, 3: SCC Disenganed when the vehicle stops
|
||||
|
||||
values["TARGET_DISTANCE"] = CS.out.vEgo * 1.0 + 4.0
|
||||
|
||||
soft_hold_info = 1 if CS.softHoldActive > 1 and enabled else 0
|
||||
|
||||
# 이거안하면 정지중 뒤로 밀리는 현상 발생하는듯.. (신호정지중에 뒤로 밀리는 경험함.. 시험해봐야)
|
||||
if values["InfoDisplay"] != 5: #5: Front Car Departure Notice
|
||||
values["InfoDisplay"] = 4 if stopping and CS.out.aEgo > -0.3 else 0 # 1: SCC Mode, 2: Convention Cruise Mode, 3: Object disappered at low speed, 4: Available to resume acceleration control, 5: Front vehicle departure notice, 6: Reserved, 7: Invalid
|
||||
|
||||
values["TakeOverReq"] = 0 # 1: Takeover request, 2: Not used, 3: Error indicator , 이것이 켜지면 가속을 안하는듯함.
|
||||
#values["NEW_SIGNAL_4"] = 9 if hud_control.leadVisible else 0
|
||||
# AccelLimitBandUpper, Lower
|
||||
values["SysFailState"] = 0 # 1: Performance degredation, 2: system temporairy unavailble, 3: SCC Service required , 눈이 묻어 레이더오류시... 2가 됨. 이때 가속을 안함...
|
||||
|
||||
values["AccelLimitBandUpper"] = 0.0 # 이값이 1.26일때 가속을 안하는 증상이 보임..
|
||||
values["AccelLimitBandLower"] = 0.0
|
||||
|
||||
values["ZEROS_7"] = 1
|
||||
|
||||
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
|
||||
|
||||
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control, jerk_u, jerk_l, CS):
|
||||
|
||||
enabled = enabled or CS.softHoldActive > 0
|
||||
jerk = 5
|
||||
jn = jerk / 50
|
||||
if not enabled or gas_override:
|
||||
a_val, a_raw = 0, 0
|
||||
else:
|
||||
a_raw = accel
|
||||
a_val = np.clip(accel, accel_last - jn, accel_last + jn)
|
||||
|
||||
values = {
|
||||
"ACCMode": 0 if not enabled else (2 if gas_override else 1),
|
||||
"MainMode_ACC": 1 if main_cruise_enabled else 0,
|
||||
"StopReq": 1 if tuning.stopping else 0,
|
||||
"aReqValue": tuning.actual_accel,
|
||||
"aReqRaw": tuning.actual_accel,
|
||||
"MainMode_ACC": 1,
|
||||
"StopReq": 1 if stopping or CS.softHoldActive > 0 else 0,
|
||||
"aReqValue": a_val,
|
||||
"aReqRaw": a_raw,
|
||||
"VSetDis": set_speed,
|
||||
"JerkLowerLimit": tuning.jerk_lower,
|
||||
"JerkUpperLimit": tuning.jerk_upper,
|
||||
#"JerkLowerLimit": jerk if enabled else 1,
|
||||
#"JerkUpperLimit": 3.0,
|
||||
"JerkLowerLimit": jerk_l if enabled else 1,
|
||||
"JerkUpperLimit": jerk_u,
|
||||
|
||||
"ACC_ObjDist": int(lead_data.lead_distance),
|
||||
"ACC_ObjRelSpd": lead_data.lead_rel_speed,
|
||||
"ObjValid": int(not lead_data.lead_visible),
|
||||
"SCC_ObjSta": 0 if not (enabled and lead_data.lead_visible) else (1 if gas_override else 2),
|
||||
"SET_ME_2": 0x4,
|
||||
"SET_ME_3": 0x3,
|
||||
"SET_ME_TMP_64": 0x64,
|
||||
"DISTANCE_SETTING": hud_control.leadDistanceBars,
|
||||
"ACC_ObjDist": 1,
|
||||
#"ObjValid": 0,
|
||||
#"OBJ_STATUS": 2,
|
||||
"NSCCOper": 0,
|
||||
"NSCCOnOff": 2,
|
||||
"DriveMode": 0,
|
||||
#"SET_ME_3": 0x3,
|
||||
"ACC_ObjLatPos": 0x64,
|
||||
"DISTANCE_SETTING": hud_control.leadDistanceBars, # + 5,
|
||||
"InfoDisplay": 4 if stopping and CS.out.cruiseState.standstill else 0,
|
||||
}
|
||||
|
||||
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
|
||||
|
||||
|
||||
def create_spas_messages(packer, CAN, left_blink, right_blink):
|
||||
def create_spas_messages(packer, CAN, frame, left_blink, right_blink):
|
||||
ret = []
|
||||
|
||||
values = {
|
||||
@@ -186,8 +464,10 @@ def create_spas_messages(packer, CAN, left_blink, right_blink):
|
||||
return ret
|
||||
|
||||
|
||||
def create_fca_warning_light(packer, CAN, frame):
|
||||
def create_fca_warning_light(CP, packer, CAN, frame):
|
||||
ret = []
|
||||
if CP.flags & HyundaiFlags.CAMERA_SCC.value:
|
||||
return ret
|
||||
|
||||
if frame % 2 == 0:
|
||||
values = {
|
||||
@@ -196,53 +476,100 @@ def create_fca_warning_light(packer, CAN, frame):
|
||||
'SET_ME_FF': 0xff,
|
||||
'SET_ME_FC': 0xfc,
|
||||
'SET_ME_9': 0x9,
|
||||
#'DATA102': 1,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x160", CAN.ECAN, values))
|
||||
return ret
|
||||
|
||||
def create_tcs_messages(packer, CAN, CS):
|
||||
ret = []
|
||||
if CS.tcs is not None:
|
||||
values = copy.copy(CS.tcs)
|
||||
#rx_counter = values.pop("COUNTER", None)
|
||||
values["DriverBraking"] = 0
|
||||
values["NEW_SIGNAL_20"] = 0
|
||||
values["NEW_SIGNAL_11"] = 0
|
||||
values["DriverBrakingLowSens"] = 0
|
||||
#values["NEW_SIGNAL_1"] = 0 # accel과 관련.. 옆두부 꺼지는것과 관련? 확인필요
|
||||
#values["ACC_REQ"] = 1 # 옆두부 꺼지는것과 관련? 확인필요.. 항상 켜지게함..
|
||||
values["NEW_SIGNAL_1"] = 0 if values["ACC_REQ"] == 1 else 1 # 옆두부..
|
||||
#ret.append(packer.make_can_msg("TCS", CAN.CAM, values, rx_counter = rx_counter))
|
||||
ret.append(packer.make_can_msg("TCS", CAN.CAM, values))
|
||||
return ret
|
||||
|
||||
def create_adrv_messages(packer, CAN, frame):
|
||||
def forward_button_message(packer, CAN, frame, CS, cruise_button, MainMode_ACC_trigger, LFA_trigger):
|
||||
ret = []
|
||||
if frame % 2 == 0:
|
||||
if CS.cruise_buttons_msg is not None:
|
||||
values = copy.copy(CS.cruise_buttons_msg)
|
||||
# A held MAIN is reported on this bit and switches some clusters to LIMIT mode.
|
||||
values["NORMAL_CRUISE_MAIN_BTN"] = 0
|
||||
#rx_counter = values.pop("COUNTER", None)
|
||||
cruise_button_driver = values["CRUISE_BUTTONS"]
|
||||
if cruise_button_driver == 0:
|
||||
values["CRUISE_BUTTONS"] = cruise_button
|
||||
if MainMode_ACC_trigger > 0:
|
||||
#values["ADAPTIVE_CRUISE_MAIN_BTN"] = 1
|
||||
pass
|
||||
elif LFA_trigger > 0:
|
||||
values["LFA_BTN"] = 1
|
||||
|
||||
#ret.append(packer.make_can_msg(CS.cruise_btns_msg_canfd, CAN.CAM, values, rx_counter = rx_counter))
|
||||
ret.append(packer.make_can_msg(CS.cruise_btns_msg_canfd, CAN.CAM, values))
|
||||
return ret
|
||||
|
||||
def create_adrv_messages(CP, packer, CAN, frame):
|
||||
# messages needed to car happy after disabling
|
||||
# the ADAS Driving ECU to do longitudinal control
|
||||
|
||||
ret = []
|
||||
|
||||
values = {
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x51", CAN.ACAN, values))
|
||||
if not CP.flags & HyundaiFlags.CAMERA_SCC.value:
|
||||
values = {}
|
||||
|
||||
ret.extend(create_fca_warning_light(packer, CAN, frame))
|
||||
ret.extend(create_fca_warning_light(CP, packer, CAN, frame))
|
||||
if frame % 5 == 0:
|
||||
values = {
|
||||
#'HDA_MODE1': 0x8,
|
||||
'HDA_MODE2': 0x1,
|
||||
#'SET_ME_1C': 0x1c,
|
||||
'SET_ME_FF': 0xff,
|
||||
#'SET_ME_TMP_F': 0xf,
|
||||
#'SET_ME_TMP_F_2': 0xf,
|
||||
#'DATA26': 1, #1
|
||||
#'DATA32': 5, #5
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x1ea", CAN.ECAN, values))
|
||||
|
||||
if frame % 5 == 0:
|
||||
values = {
|
||||
'SET_ME_1C': 0x1c,
|
||||
'SET_ME_FF': 0xff,
|
||||
'SET_ME_TMP_F': 0xf,
|
||||
'SET_ME_TMP_F_2': 0xf,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x1ea", CAN.ECAN, values))
|
||||
values = {
|
||||
'SET_ME_E1': 0xe1,
|
||||
#'SET_ME_3A': 0x3a,
|
||||
'TauGapSet' : 1,
|
||||
'NEW_SIGNAL_2': 3,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x200", CAN.ECAN, values))
|
||||
|
||||
values = {
|
||||
'SET_ME_E1': 0xe1,
|
||||
'SET_ME_3A': 0x3a,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x200", CAN.ECAN, values))
|
||||
if frame % 20 == 0:
|
||||
values = {
|
||||
'SET_ME_15': 0x15,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x345", CAN.ECAN, values))
|
||||
|
||||
if frame % 20 == 0:
|
||||
values = {
|
||||
'SET_ME_15': 0x15,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x345", CAN.ECAN, values))
|
||||
|
||||
if frame % 100 == 0:
|
||||
values = {
|
||||
'SET_ME_22': 0x22,
|
||||
'SET_ME_41': 0x41,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x1da", CAN.ECAN, values))
|
||||
if frame % 100 == 0:
|
||||
values = {
|
||||
'SET_ME_22': 0x22,
|
||||
'SET_ME_41': 0x41,
|
||||
}
|
||||
ret.append(packer.make_can_msg("ADRV_0x1da", CAN.ECAN, values))
|
||||
|
||||
return ret
|
||||
|
||||
## carrot
|
||||
def alt_cruise_buttons(packer, CP, CAN, buttons, cruise_btns_msg, cnt):
|
||||
cruise_btns_msg["CRUISE_BUTTONS"] = buttons
|
||||
cruise_btns_msg["COUNTER"] = (cruise_btns_msg["COUNTER"] + 1 + cnt) % 256
|
||||
bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_HDA2 else CAN.CAM
|
||||
return packer.make_can_msg("CRUISE_BUTTONS_ALT", bus, cruise_btns_msg)
|
||||
|
||||
def hkg_can_fd_checksum(address: int, sig, d: bytearray) -> int:
|
||||
crc = 0
|
||||
@@ -259,3 +586,348 @@ def hkg_can_fd_checksum(address: int, sig, d: bytearray) -> int:
|
||||
elif len(d) == 32:
|
||||
crc ^= 0x9F5B
|
||||
return crc
|
||||
|
||||
|
||||
|
||||
|
||||
def _clip_int(x, lo, hi):
|
||||
return lo if x < lo else hi if x > hi else int(x)
|
||||
|
||||
def _get_desire_and_lane_changing(md):
|
||||
desire = 0
|
||||
lane_changing = 0
|
||||
if md is not None:
|
||||
desire = md.meta.desire.raw
|
||||
ds = md.meta.desireState
|
||||
if len(ds) > 4:
|
||||
if ds[1] > 0.9: lane_changing = 1
|
||||
if ds[2] > 0.9: lane_changing = 2
|
||||
if ds[3] > 0.9: lane_changing = 3
|
||||
if ds[4] > 0.9: lane_changing = 4
|
||||
return desire, lane_changing
|
||||
|
||||
def _apply_lane_desire(values, desire):
|
||||
#values['LANE_CHANGING'] = 0
|
||||
|
||||
if desire == 1: # 좌회전
|
||||
values['LANE_CHANGING'] = 1
|
||||
values["LANELINE_CURVATURE"] = 15
|
||||
values["LANELINE_CURVATURE_DIRECTION"] = 0
|
||||
|
||||
elif desire == 2: # 우회전
|
||||
values['LANE_CHANGING'] = 2
|
||||
values["LANELINE_CURVATURE"] = 15
|
||||
values["LANELINE_CURVATURE_DIRECTION"] = 1
|
||||
|
||||
elif desire == 3: # 좌차선변경
|
||||
values['LANE_CHANGING'] = 3
|
||||
|
||||
elif desire == 4: # 우차선변경
|
||||
values['LANE_CHANGING'] = 4
|
||||
|
||||
def _apply_radar_blink(values, radar_pairs, frame, *,
|
||||
disp_dist=30.0, min_dist=14.0,
|
||||
max_interval=100, t=1.0):
|
||||
"""
|
||||
거리 > min_dist 일 때만 깜빡임.
|
||||
거리 멀수록 interval 커짐(느리게).
|
||||
"""
|
||||
for det_key, dist_key in radar_pairs:
|
||||
dist = values[dist_key]
|
||||
if dist <= min_dist:
|
||||
continue
|
||||
|
||||
d = min(dist, disp_dist)
|
||||
interval = int((1 + (max_interval - 1) * (d / disp_dist)) * t)
|
||||
interval = _clip_int(interval, 1, max_interval)
|
||||
|
||||
blink = (frame // interval) & 1
|
||||
values[det_key] = 2 - blink
|
||||
values[dist_key] = min_dist
|
||||
|
||||
def _suppress_trailer_mode_warning(values, CS):
|
||||
# Logs from IONIQ 9 show ALERTS_5=6 is the periodic
|
||||
# "driver assistance limited in trailer mode" popup.
|
||||
if CS.trailer_connected and values.get("ALERTS_5") == 6:
|
||||
values["ALERTS_5"] = 0
|
||||
|
||||
def _make_ccnc_values(values, CS, lat_active, frame, hud_control,
|
||||
lane_line=True, corner_radar=True,
|
||||
desire=0,
|
||||
blink_pairs=None,
|
||||
blink_t=1.0):
|
||||
if lane_line:
|
||||
curvature = round(CS.out.steeringAngleDeg / 3)
|
||||
mag = min(abs(curvature), 15)
|
||||
curv = mag + (-1 if curvature < 0 else 0)
|
||||
direction = 1 if curvature < 0 else 0
|
||||
values["LANELINE_CURVATURE"] = curv if lat_active else 0
|
||||
values["LANELINE_CURVATURE_DIRECTION"] = direction if lat_active else 0
|
||||
if desire:
|
||||
_apply_lane_desire(values, desire)
|
||||
|
||||
if corner_radar:
|
||||
radar_all = [
|
||||
('LF_DETECT', 'LF_DETECT_DISTANCE'),
|
||||
('RF_DETECT', 'RF_DETECT_DISTANCE'),
|
||||
('LR_DETECT', 'LR_DETECT_DISTANCE'),
|
||||
('RR_DETECT', 'RR_DETECT_DISTANCE'),
|
||||
]
|
||||
for det_key, dist_key in radar_all:
|
||||
if values[det_key] >= 4 and values[dist_key] != 0:
|
||||
values[det_key] = 1
|
||||
|
||||
if blink_pairs:
|
||||
_apply_radar_blink(values, blink_pairs, frame, t=blink_t)
|
||||
|
||||
def create_ccnc_messages(CP, packer, CAN, frame, CC, CS, hud_control,
|
||||
disp_angle, left_lane_warning, right_lane_warning,
|
||||
enable_corner_radar, stopping, canfd_debug):
|
||||
ret = []
|
||||
|
||||
md = CS.modelV2
|
||||
if not hasattr(create_ccnc_messages, '_lane_line_check') or frame % 100 == 0:
|
||||
create_ccnc_messages._lane_line_check = Params().get_int("LaneLineCheck")
|
||||
lane_line_check = create_ccnc_messages._lane_line_check
|
||||
desire, lane_changing = _get_desire_and_lane_changing(md)
|
||||
|
||||
if CP.flags & HyundaiFlags.CAMERA_SCC.value:
|
||||
HDA_CntrlModSta = 0
|
||||
HDA_LFA_SymSta = 0
|
||||
if CS.lfahda_cluster is not None:
|
||||
HDA_CntrlModSta = CS.lfahda_cluster["HDA_CntrlModSta"]
|
||||
HDA_LFA_SymSta = CS.lfahda_cluster["HDA_LFA_SymSta"]
|
||||
|
||||
if frame % 2 == 0:
|
||||
#if CS.adrv_0x160 is not None:
|
||||
# values = copy.copy(CS.adrv_0x160)
|
||||
# ret.append(packer.make_can_msg("ADRV_0x160", CAN.ECAN, values))
|
||||
|
||||
if CS.cruise_buttons_msg is not None:
|
||||
values = copy.copy(CS.cruise_buttons_msg)
|
||||
# Keep the physical long press on ECAN for CarState, but don't forward it to CAM.
|
||||
values["NORMAL_CRUISE_MAIN_BTN"] = 0
|
||||
|
||||
if HDA_LFA_SymSta == 0 and 0 < frame % 200 < 12:
|
||||
values["LFA_BTN"] = 1
|
||||
|
||||
if CC.enabled:
|
||||
if not CS.MainMode_ACC:
|
||||
if 10 < frame % 200 <= 16 and CS.out.vEgo > 3.:
|
||||
values["ADAPTIVE_CRUISE_MAIN_BTN"] = 1
|
||||
elif CS.ACCMode in [0, 4]:
|
||||
if 10 < frame % 200 <= 16 and CS.out.vEgo > 3.:
|
||||
values["CRUISE_BUTTONS"] = 2
|
||||
elif CS.scc_control is not None and CS.scc_control["InfoDisplay"] == 4:
|
||||
if 10 < frame % 30 <= 16 and not stopping:
|
||||
values["CRUISE_BUTTONS"] = 2
|
||||
else:
|
||||
if CS.adrv_0x1ea is not None and CS.adrv_0x1ea["HDA_MODE2"] == 0: # if corner radar is disabled, send main btn
|
||||
if 10 < frame % 1000 <= 16 and CS.out.vEgo > 3:
|
||||
values["ADAPTIVE_CRUISE_MAIN_BTN"] = 1
|
||||
|
||||
ret.append(packer.make_can_msg(CS.cruise_btns_msg_canfd, CAN.CAM, values))
|
||||
|
||||
# --- 0x161/0x200/0x1ea/0x162 (frame%5) ---
|
||||
if frame % 5 == 0:
|
||||
lat_active = CC.latActive
|
||||
|
||||
if CS.adrv_0x161 is not None:
|
||||
main_enabled = CS.out.cruiseState.available
|
||||
cruise_enabled = CC.enabled
|
||||
lat_enabled = CS.out.latEnabled
|
||||
nav_active = hud_control.activeCarrot > 1
|
||||
|
||||
# hdpuse carrot
|
||||
hdp_use = int(Params().get("HDPuse"))
|
||||
hdp_active = False
|
||||
if hdp_use == 1:
|
||||
hdp_active = cruise_enabled and nav_active
|
||||
elif hdp_use == 2:
|
||||
hdp_active = cruise_enabled
|
||||
# hdpuse carrot
|
||||
|
||||
values = copy.copy(CS.adrv_0x161)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
values["SETSPEED"] = (6 if hdp_active else 3 if cruise_enabled else 1) if main_enabled else 0
|
||||
values["SETSPEED_HUD"] = (5 if hdp_active else 3 if cruise_enabled else 1) if main_enabled else 0
|
||||
|
||||
set_speed_in_units = hud_control.setSpeed * (CV.MS_TO_KPH if CS.is_metric else CV.MS_TO_MPH)
|
||||
values["vSetDis"] = int(set_speed_in_units + 0.5)
|
||||
|
||||
values["DISTANCE"] = 4 if hdp_active else hud_control.leadDistanceBars
|
||||
values["DISTANCE_LEAD"] = 2 if cruise_enabled and hud_control.leadVisible else 1 if main_enabled and hud_control.leadVisible else 0
|
||||
values["DISTANCE_CAR"] = 3 if hdp_active else 2 if cruise_enabled else 1 if main_enabled else 0
|
||||
values["DISTANCE_SPACING"] = 5 if hdp_active else 1 if cruise_enabled else 0
|
||||
|
||||
values["TARGET"] = 1 if hud_control.leadVisible and cruise_enabled else 0
|
||||
values["TARGET_DISTANCE"] = int(hud_control.leadDistance)
|
||||
|
||||
values["BACKGROUND"] = 6 if CS.paddle_button_prev > 0 else 1 if cruise_enabled else 3 if lat_active else 7
|
||||
values["CENTERLINE"] = 1 if HDA_CntrlModSta > 0 else 0
|
||||
values["CAR_CIRCLE"] = 2 if hdp_active else 1 if cruise_enabled else 0
|
||||
|
||||
values["NAV_ICON"] = 2 if nav_active and cruise_enabled else 1 if main_enabled and nav_active else 0
|
||||
values["HDA_ICON"] = 5 if hdp_active else 2 if cruise_enabled else 1 if main_enabled else 0
|
||||
values["LFA_ICON"] = 5 if hdp_active else 2 if lat_active else 1 if lat_enabled else 0
|
||||
values["LKA_ICON"] = 4 if lat_active else 3 if lat_enabled else 0
|
||||
values["FCA_ALT_ICON"] = 0
|
||||
|
||||
if values["ALERTS_2"] in [1, 2, 5, 6, 10, 21, 22]:
|
||||
values["ALERTS_2"] = 0
|
||||
values["DAW_ICON"] = 0
|
||||
|
||||
if values["ALERTS_1"] == 0: # alerts가 있으면 사운드도 같이 나옴
|
||||
values["SOUNDS_1"] = 0
|
||||
values["SOUNDS_2"] = 0
|
||||
values["SOUNDS_4"] = 0
|
||||
|
||||
if values["ALERTS_3"] in [3, 4, 11, 12, 13, 14, 17, 19, 20, 26, 27, 28, 7, 8, 9, 10]: # hide gap distance msg.(11,12,13,14), lanechange(19,20,27, 28)
|
||||
values["ALERTS_3"] = 0
|
||||
values["SOUNDS_3"] = 0
|
||||
|
||||
if values["ALERTS_5"] in [1, 2, 3, 4, 5]:
|
||||
values["ALERTS_5"] = 0
|
||||
|
||||
if values["ALERTS_5"] in [11] and CS.softHoldActive == 0:
|
||||
values["ALERTS_5"] = 0
|
||||
|
||||
# curvature 표시(0x161쪽 기존 로직 유지)
|
||||
_suppress_trailer_mode_warning(values, CS)
|
||||
|
||||
curvature = round(CS.out.steeringAngleDeg / 3)
|
||||
values["LANELINE_CURVATURE"] = (min(abs(curvature), 15) + (-1 if curvature < 0 else 0)) if lat_active else 0
|
||||
values["LANELINE_CURVATURE_DIRECTION"] = 1 if curvature < 0 and lat_active else 0
|
||||
|
||||
trailer_lane_change_blocked = CS.trailer_connected
|
||||
if trailer_lane_change_blocked:
|
||||
values["LANELINE_LEFT"] = 2 if hud_control.leftLaneVisible else 0
|
||||
values["LANELINE_RIGHT"] = 2 if hud_control.rightLaneVisible else 0
|
||||
else:
|
||||
lane_color = 6 if md is not None and md.meta.laneChangeAvailableLeft else 2
|
||||
if lane_line_check >= 1:
|
||||
lane_line_warn_left = CS.out.leftLaneLine % 10 not in (0, 5)
|
||||
else:
|
||||
lane_line_warn_left = CS.out.leftLaneLine // 10 == 2
|
||||
lane_color = 4 if lane_line_warn_left or CS.out.leftBlindspot else lane_color
|
||||
if hud_control.leftLaneDepart:
|
||||
values["LANELINE_LEFT"] = 4 if (frame // 50) % 2 == 0 else 1
|
||||
else:
|
||||
values["LANELINE_LEFT"] = lane_color if hud_control.leftLaneVisible else 0
|
||||
|
||||
lane_color = 6 if md is not None and md.meta.laneChangeAvailableRight else 2
|
||||
if lane_line_check >= 1:
|
||||
lane_line_warn_right = CS.out.rightLaneLine % 10 not in (0, 5)
|
||||
else:
|
||||
lane_line_warn_right = CS.out.rightLaneLine // 10 == 2
|
||||
lane_color = 4 if lane_line_warn_right or CS.out.rightBlindspot else lane_color
|
||||
if hud_control.rightLaneDepart:
|
||||
values["LANELINE_RIGHT"] = 4 if (frame // 50) % 2 == 0 else 1
|
||||
else:
|
||||
values["LANELINE_RIGHT"] = lane_color if hud_control.rightLaneVisible else 0
|
||||
|
||||
values["LCA_LEFT_ARROW"] = 2 if CS.out.leftBlinker else 0
|
||||
values["LCA_RIGHT_ARROW"] = 2 if CS.out.rightBlinker else 0
|
||||
|
||||
if trailer_lane_change_blocked:
|
||||
values["LCA_LEFT_ICON"] = 1 if lat_active else 0
|
||||
values["LCA_RIGHT_ICON"] = 1 if lat_active else 0
|
||||
else:
|
||||
values["LCA_LEFT_ICON"] = (1 if CS.out.leftBlindspot else 2) if lat_active else 0
|
||||
values["LCA_RIGHT_ICON"] = (1 if CS.out.rightBlindspot else 2) if lat_active else 0
|
||||
|
||||
values["LANE_LEFT"] = 0 if trailer_lane_change_blocked else 1 if desire in (1, 3) else 0
|
||||
values["LANE_RIGHT"] = 0 if trailer_lane_change_blocked else 1 if desire in (2, 4) else 0
|
||||
|
||||
ret.append(packer.make_can_msg("ADRV_0x161", CAN.ECAN, values, rx_counter = rx_counter))
|
||||
|
||||
if CS.adrv_0x200 is not None:
|
||||
values = copy.copy(CS.adrv_0x200)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
values["TauGapSet"] = hud_control.leadDistanceBars
|
||||
ret.append(packer.make_can_msg("ADRV_0x200", CAN.ECAN, values, rx_counter = rx_counter))
|
||||
|
||||
if CS.adrv_0x1ea is not None:
|
||||
values = copy.copy(CS.adrv_0x1ea)
|
||||
rx_counter = values.pop("COUNTER", None)
|
||||
# blinker hold
|
||||
values['LEFT_BLINK_HOLD'] = 1 if lane_changing == 3 else 0
|
||||
values['RIGHT_BLINK_HOLD'] = 1 if lane_changing == 4 else 0
|
||||
|
||||
_make_ccnc_values(
|
||||
values, CS, lat_active, frame, hud_control,
|
||||
lane_line=True,
|
||||
corner_radar=True,
|
||||
desire=desire,
|
||||
# 기존대로 LR/RR만 깜빡임
|
||||
blink_pairs=[('LR_DETECT', 'LR_DETECT_DISTANCE'),
|
||||
('RR_DETECT', 'RR_DETECT_DISTANCE')],
|
||||
blink_t=1.0
|
||||
)
|
||||
|
||||
ret.append(packer.make_can_msg("ADRV_0x1ea", CAN.ECAN, values, rx_counter = rx_counter))
|
||||
|
||||
if CS.ccnc_0x162 is not None:
|
||||
values = copy.copy(CS.ccnc_0x162)
|
||||
|
||||
if hud_control.leadDistance > 0:
|
||||
values["FF_DISTANCE"] = hud_control.leadDistance
|
||||
ff_type = 3 if hud_control.leadRadar == 1 else 13
|
||||
values["FF_DETECT"] = ff_type if hud_control.leadRelSpeed > -0.1 else ff_type + 1
|
||||
|
||||
_make_ccnc_values(
|
||||
values, CS, lat_active, frame, hud_control,
|
||||
lane_line=False,
|
||||
corner_radar=True,
|
||||
desire=0,
|
||||
# 필요하면 162도 깜빡임 적용(원래 코드처럼 LR/RR만)
|
||||
blink_pairs=[('LR_DETECT', 'LR_DETECT_DISTANCE'),
|
||||
('RR_DETECT', 'RR_DETECT_DISTANCE')],
|
||||
blink_t=1.0
|
||||
)
|
||||
|
||||
if (left_lane_warning and not CS.out.leftBlinker) or (right_lane_warning and not CS.out.rightBlinker):
|
||||
values["VIBRATE"] = 1
|
||||
|
||||
if canfd_debug > 0:
|
||||
values["FAULT_LSS"] = 0
|
||||
values["FAULT_DAS"] = 0
|
||||
|
||||
ret.append(packer.make_can_msg("CCNC_0x162", CAN.ECAN, values))
|
||||
|
||||
# --- NEW_MSG_4B9 (corner radar keep-alive?) ---
|
||||
if enable_corner_radar > 0:
|
||||
if HDA_CntrlModSta == 0:
|
||||
if frame % 500 in [10, 20, 30]:
|
||||
values = {
|
||||
'BYTE_1': 0,
|
||||
'BYTE_2': 0,
|
||||
'BYTE_3': 0x80,
|
||||
'BYTE_4': 0x8A,
|
||||
'BYTE_5': 0x32,
|
||||
'BYTE_6': 0x30,
|
||||
'BYTE_7': 0x01,
|
||||
'BYTE_8': 0x00,
|
||||
}
|
||||
ret.append(packer.make_can_msg("NEW_MSG_4B9", CAN.CAM, values))
|
||||
elif frame % 500 in [40, 50, 60]:
|
||||
values = {
|
||||
'BYTE_1': 0xff,
|
||||
'BYTE_2': 0xff,
|
||||
'BYTE_3': 0xff,
|
||||
'BYTE_4': 0xff,
|
||||
'BYTE_5': 0xff,
|
||||
'BYTE_6': 0xff,
|
||||
'BYTE_7': 0xff,
|
||||
'BYTE_8': 0xff,
|
||||
}
|
||||
ret.append(packer.make_can_msg("NEW_MSG_4B9", CAN.CAM, values))
|
||||
|
||||
if False: # canfd_debug > 1 and frame % 20 == 0:
|
||||
if CS.hda_info_4a3 is not None:
|
||||
values = copy.copy(CS.hda_info_4a3)
|
||||
values["LinkClass"] = 1
|
||||
values["SPEED_LIMIT"] = 100
|
||||
ret.append(packer.make_can_msg("HDA_INFO_4A3", CAN.CAM, values))
|
||||
|
||||
return ret
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from iqdbc.car import Bus, get_safety_config, structs, uds
|
||||
from iqdbc.car import Bus, get_safety_config, structs
|
||||
from iqdbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags, CAR, DBC, \
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags, CAR, DBC, CANFD_RADAR_SCC_CAR, \
|
||||
CANFD_UNSUPPORTED_LONGITUDINAL_CAR, \
|
||||
UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags
|
||||
UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags, HyundaiExtFlags, \
|
||||
CANFD_HYBRID_STATUS_ADDR, CANFD_HYBRID_STATUS_DLC, \
|
||||
EV_MODE_STATUS_ADDR, EV_MODE_STATUS_DLC
|
||||
from iqdbc.car.hyundai.radar_interface import RADAR_START_ADDR
|
||||
from iqdbc.car.interfaces import CarInterfaceBase
|
||||
from iqdbc.car.disable_ecu import disable_ecu
|
||||
@@ -10,9 +12,7 @@ from iqdbc.car.hyundai.carcontroller import CarController
|
||||
from iqdbc.car.hyundai.carstate import CarState
|
||||
from iqdbc.car.hyundai.radar_interface import RadarInterface
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.escc import ESCC_MSG
|
||||
from iqdbc.iqpilot.car.hyundai.longitudinal.helpers import get_longitudinal_tune
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ, HyundaiSafetyFlagsIQ
|
||||
from openpilot.common.params import Params
|
||||
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
Ecu = structs.CarParams.Ecu
|
||||
@@ -20,67 +20,125 @@ Ecu = structs.CarParams.Ecu
|
||||
# Cancel button can sometimes be ACC pause/resume button, main button can also enable on some cars
|
||||
ENABLE_BUTTONS = (ButtonType.accelCruise, ButtonType.decelCruise, ButtonType.cancel, ButtonType.mainCruise)
|
||||
|
||||
SteerControlType = structs.CarParams.SteerControlType
|
||||
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
CarState = CarState
|
||||
CarController = CarController
|
||||
RadarInterface = RadarInterface
|
||||
|
||||
DRIVABLE_GEARS = (structs.CarState.GearShifter.sport, structs.CarState.GearShifter.manumatic)
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
|
||||
params = Params()
|
||||
camera_scc = params.get_int("HyundaiCameraSCC")
|
||||
if camera_scc > 0:
|
||||
ret.flags |= HyundaiFlags.CAMERA_SCC.value
|
||||
print("$$$CAMERA_SCC toggled...")
|
||||
|
||||
ret.brand = "hyundai"
|
||||
|
||||
# "LKA steering" if LKAS or LKAS_ALT messages are seen coming from the camera.
|
||||
# Generally means our LKAS message is forwarded to another ECU (commonly ADAS ECU)
|
||||
# that finally retransmits our steering command in LFA or LFA_ALT to the MDPS.
|
||||
# "LFA steering" if camera directly sends LFA to the MDPS
|
||||
cam_can = CanBus(None, fingerprint).CAM
|
||||
lka_steering = 0x50 in fingerprint[cam_can] or 0x110 in fingerprint[cam_can]
|
||||
CAN = CanBus(None, fingerprint, lka_steering)
|
||||
if candidate == CAR.KIA_SORENTO:
|
||||
ret.extFlags |= HyundaiExtFlags.RADAR_GROUP4.value
|
||||
|
||||
cam_can = CanBus(None, fingerprint).CAM if camera_scc == 0 else 1
|
||||
hda2 = False #0x50 in fingerprint[cam_can] or 0x110 in fingerprint[cam_can]
|
||||
hda2 = hda2 or params.get_int("CanfdHDA2") > 0
|
||||
CAN = CanBus(None, fingerprint, hda2)
|
||||
|
||||
if ret.flags & HyundaiFlags.CANFD:
|
||||
# Shared configuration for CAN-FD cars
|
||||
ret.alphaLongitudinalAvailable = candidate not in CANFD_UNSUPPORTED_LONGITUDINAL_CAR
|
||||
if lka_steering and Ecu.adas not in [fw.ecu for fw in car_fw]:
|
||||
# this needs to be figured out for cars without an ADAS ECU
|
||||
ret.alphaLongitudinalAvailable = False
|
||||
ret.alphaLongitudinalAvailable = True #candidate not in (CANFD_UNSUPPORTED_LONGITUDINAL_CAR | CANFD_RADAR_SCC_CAR)
|
||||
#ret.enableBsm = 0x1e5 in fingerprint[CAN.ECAN]
|
||||
ret.enableBsm = 0x1ba in fingerprint[CAN.ECAN] # BLINDSPOTS_REAR_CORNERS 0x1ba(442)
|
||||
|
||||
ret.enableBsm = 0x1e5 in fingerprint[CAN.ECAN]
|
||||
|
||||
# Check if the car is hybrid. Only HEV/PHEV cars have 0xFA on E-CAN.
|
||||
if 0xFA in fingerprint[CAN.ECAN]:
|
||||
if 0x105 in fingerprint[CAN.ECAN]:
|
||||
ret.flags |= HyundaiFlags.HYBRID.value
|
||||
|
||||
if lka_steering:
|
||||
# detect LKA steering
|
||||
ret.flags |= HyundaiFlags.CANFD_LKA_STEERING.value
|
||||
if 0x110 in fingerprint[CAN.CAM]:
|
||||
ret.flags |= HyundaiFlags.CANFD_LKA_STEERING_ALT.value
|
||||
# Keep drivetrain/safety classification unchanged: this capability is display-only and requires both exact ECAN frames.
|
||||
has_ev_mode_status = fingerprint[CAN.ECAN].get(CANFD_HYBRID_STATUS_ADDR) == CANFD_HYBRID_STATUS_DLC and \
|
||||
fingerprint[CAN.ECAN].get(EV_MODE_STATUS_ADDR) == EV_MODE_STATUS_DLC
|
||||
if has_ev_mode_status:
|
||||
ret.extFlags |= HyundaiExtFlags.EV_MODE_STATUS_230.value
|
||||
|
||||
if 203 in fingerprint[CAN.CAM]: # LFA_ALT
|
||||
print("##### Anglecontrol detected (LFA_ALT)")
|
||||
ret.flags |= HyundaiFlags.ANGLE_CONTROL.value
|
||||
|
||||
print("ACAN=", fingerprint[CAN.ACAN])
|
||||
|
||||
if 0x210 in fingerprint[CAN.ACAN]:
|
||||
print("##### Radar Group 1 detected (0x210)")
|
||||
ret.extFlags |= HyundaiExtFlags.RADAR_GROUP1.value
|
||||
elif 0x400 in fingerprint[CAN.ACAN] and 0x41D in fingerprint[CAN.ACAN]:
|
||||
print("##### Radar Group 3 detected (0x400-0x41D)")
|
||||
ret.extFlags |= HyundaiExtFlags.RADAR_GROUP3.value
|
||||
if all(fingerprint[CAN.ACAN].get(addr) == 32 for addr in range(0x235, 0x249)):
|
||||
ret.extFlags |= HyundaiExtFlags.CORNER_RADAR_OBJECTS_235.value
|
||||
print("##### Corner radar objects 0x235 group detected")
|
||||
if all(fingerprint[CAN.ACAN].get(addr) == 32 for addr in range(0x180, 0x185)):
|
||||
ret.extFlags |= HyundaiExtFlags.CORNER_RADAR_OBJECTS_180.value
|
||||
print("##### Corner radar objects 0x180 group detected")
|
||||
if all(fingerprint[CAN.ACAN].get(addr) == 32 for addr in tuple(range(0x430, 0x438)) + tuple(range(0x440, 0x448))):
|
||||
ret.extFlags |= HyundaiExtFlags.CORNER_RADAR_OBJECTS_430.value
|
||||
print("##### Corner radar objects 0x430/0x440 group detected")
|
||||
|
||||
# detect HDA2 with ADAS Driving ECU
|
||||
if hda2:
|
||||
print("$$$CANFD HDA2")
|
||||
ret.flags |= HyundaiFlags.CANFD_HDA2.value
|
||||
if camera_scc > 0:
|
||||
if 0x110 in fingerprint[CAN.ACAN]:
|
||||
ret.flags |= HyundaiFlags.CANFD_HDA2_ALT_STEERING.value
|
||||
print("$$$CANFD ALT_STEERING1")
|
||||
else:
|
||||
if 0x110 in fingerprint[CAN.CAM]: # 0x110(272): LKAS_ALT
|
||||
ret.flags |= HyundaiFlags.CANFD_HDA2_ALT_STEERING.value
|
||||
print("$$$CANFD ALT_STEERING1")
|
||||
## carrot_todo: sorento:
|
||||
if 0x2a4 not in fingerprint[CAN.CAM]: # 0x2a4(676): CAM_0x2a4
|
||||
ret.flags |= HyundaiFlags.CANFD_HDA2_ALT_STEERING.value
|
||||
print("$$$CANFD ALT_STEERING2")
|
||||
|
||||
## carrot: canival 4th, no 0x1cf
|
||||
if 0x1cf not in fingerprint[CAN.ECAN]: # 0x1cf(463): CRUISE_BUTTONS
|
||||
ret.flags |= HyundaiFlags.CANFD_ALT_BUTTONS.value
|
||||
print("$$$CANFD ALT_BUTTONS")
|
||||
else:
|
||||
# no LKA steering
|
||||
# non-HDA2
|
||||
print("$$$CANFD non HDA2")
|
||||
if 0x1cf not in fingerprint[CAN.ECAN]:
|
||||
ret.flags |= HyundaiFlags.CANFD_ALT_BUTTONS.value
|
||||
if not ret.flags & HyundaiFlags.RADAR_SCC:
|
||||
ret.flags |= HyundaiFlags.CANFD_CAMERA_SCC.value
|
||||
|
||||
# Some LKA steering cars have alternative messages for gear checks
|
||||
print("$$$CANFD ALT_BUTTONS")
|
||||
#if not ret.flags & HyundaiFlags.RADAR_SCC:
|
||||
# ret.flags |= HyundaiFlags.CANFD_CAMERA_SCC.value
|
||||
# print("$$$CANFD CAMERA_SCC")
|
||||
# Some HDA2 cars have alternative messages for gear checks
|
||||
# ICE cars do not have 0x130; GEARS message on 0x40 or 0x70 instead
|
||||
if 0x130 not in fingerprint[CAN.ECAN]:
|
||||
if 0x40 not in fingerprint[CAN.ECAN]:
|
||||
ret.flags |= HyundaiFlags.CANFD_ALT_GEARS_2.value
|
||||
else:
|
||||
ret.flags |= HyundaiFlags.CANFD_ALT_GEARS.value
|
||||
if 0x40 in fingerprint[CAN.ECAN]: # 0x40(64): GEAR_ALT
|
||||
ret.flags |= HyundaiFlags.CANFD_ALT_GEARS.value
|
||||
print("$$$CANFD ALT_GEARS")
|
||||
elif 69 in fingerprint[CAN.ECAN]: # Special case
|
||||
ret.extFlags |= HyundaiExtFlags.CANFD_GEARS_69.value
|
||||
print("$$$CANFD GEARS_69")
|
||||
elif 112 in fingerprint[CAN.ECAN]: # carrot: eGV70
|
||||
ret.flags |= HyundaiFlags.CANFD_ALT_GEARS_2.value
|
||||
print("$$$CANFD ALT_GEARS_2")
|
||||
elif 0x130 in fingerprint[CAN.ECAN]: # 0x130(304): GEAR_SHIFTER
|
||||
print("$$$CANFD GEAR_SHIFTER present")
|
||||
else:
|
||||
ret.extFlags |= HyundaiExtFlags.CANFD_GEARS_NONE.value
|
||||
print("$$$CANFD GEARS_NONE")
|
||||
|
||||
cfgs = [get_safety_config(structs.CarParams.SafetyModel.hyundaiCanfd), ]
|
||||
if CAN.ECAN >= 4:
|
||||
cfgs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput))
|
||||
ret.safetyConfigs = cfgs
|
||||
|
||||
if ret.flags & HyundaiFlags.CANFD_LKA_STEERING:
|
||||
if ret.flags & HyundaiFlags.CANFD_HDA2:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEERING.value
|
||||
if ret.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT:
|
||||
if ret.flags & HyundaiFlags.CANFD_HDA2_ALT_STEERING:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT.value
|
||||
if ret.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value
|
||||
@@ -89,53 +147,93 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
else:
|
||||
# Shared configuration for non CAN-FD cars
|
||||
ret.alphaLongitudinalAvailable = candidate not in UNSUPPORTED_LONGITUDINAL_CAR
|
||||
ret.alphaLongitudinalAvailable = True #candidate not in (UNSUPPORTED_LONGITUDINAL_CAR | CAMERA_SCC_CAR)
|
||||
ret.enableBsm = 0x58b in fingerprint[0]
|
||||
print(f"$$$ enableBsm = {ret.enableBsm}")
|
||||
|
||||
# Send LFA message on cars with HDA
|
||||
if 0x485 in fingerprint[2]:
|
||||
ret.flags |= HyundaiFlags.SEND_LFA.value
|
||||
print("$$$SEND_LFA")
|
||||
|
||||
# These cars use the FCA11 message for the AEB and FCW signals, all others use SCC12
|
||||
if 0x38d in fingerprint[0] or 0x38d in fingerprint[2]:
|
||||
ret.flags |= HyundaiFlags.USE_FCA.value
|
||||
print("$$$USE_FCA")
|
||||
|
||||
if ret.flags & HyundaiFlags.LEGACY:
|
||||
# these cars require a special panda safety mode due to missing counters and checksums in the messages
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hyundaiLegacy)]
|
||||
print("$$$Legacy Safety Model")
|
||||
else:
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hyundai, 0)]
|
||||
|
||||
if ret.flags & HyundaiFlags.CAMERA_SCC:
|
||||
ret.safetyConfigs[0].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value
|
||||
|
||||
# These cars have the LFA button on the steering wheel
|
||||
if 0x391 in fingerprint[0]:
|
||||
ret.flags |= HyundaiFlags.HAS_LDA_BUTTON.value
|
||||
print("$$$CAMERA_SCC")
|
||||
|
||||
# Common lateral control setup
|
||||
|
||||
ret.centerToFront = ret.wheelbase * 0.4
|
||||
ret.steerActuatorDelay = 0.1
|
||||
ret.steerLimitTimer = 0.4
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
if ret.flags & HyundaiFlags.ANGLE_CONTROL:
|
||||
ret.steerControlType = SteerControlType.angle
|
||||
else:
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
if ret.flags & HyundaiFlags.ALT_LIMITS:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.ALT_LIMITS.value
|
||||
|
||||
if ret.flags & HyundaiFlags.ALT_LIMITS_2:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.ALT_LIMITS_2.value
|
||||
|
||||
# see https://github.com/commaai/iqdbc/pull/1137/
|
||||
ret.dashcamOnly = True
|
||||
|
||||
# Common longitudinal control setup
|
||||
|
||||
ret.radarUnavailable = RADAR_START_ADDR not in fingerprint[1] or Bus.radar not in DBC[ret.carFingerprint]
|
||||
ret.openpilotLongitudinalControl = alpha_long and ret.alphaLongitudinalAvailable
|
||||
|
||||
# carrot, if camera_scc enabled, enable openpilotLongitudinalControl
|
||||
enable_radar_tracks = params.get_int("EnableRadarTracks")
|
||||
if ret.flags & HyundaiFlags.CAMERA_SCC.value or enable_radar_tracks > 0 or enable_radar_tracks == -2:
|
||||
ret.radarUnavailable = False
|
||||
ret.openpilotLongitudinalControl = True if camera_scc < 3 else False
|
||||
print(f"$$$OenpilotLongitudinalControl = True, CAMERA_SCC({ret.flags & HyundaiFlags.CAMERA_SCC.value}) or RadarTracks{enable_radar_tracks}")
|
||||
else:
|
||||
print(f"$$$OenpilotLongitudinalControl = {alpha_long}")
|
||||
|
||||
#ret.radarUnavailable = False # TODO: canfd... carrot, hyundai cars have radar
|
||||
|
||||
ret.radarTimeStep = 0.05 #if params.get_int("EnableRadarTracks") > 0 else 0.02
|
||||
|
||||
ret.pcmCruise = not ret.openpilotLongitudinalControl
|
||||
ret.startingState = False # True # carrot
|
||||
ret.vEgoStarting = 0.1
|
||||
ret.startAccel = 1.0
|
||||
ret.longitudinalActuatorDelay = 0.5
|
||||
|
||||
ret.longitudinalTuning.kpBP = [0.]
|
||||
ret.longitudinalTuning.kpV = [1.]
|
||||
ret.longitudinalTuning.kf = 1.0
|
||||
|
||||
# *** feature detection ***
|
||||
if ret.flags & HyundaiFlags.CANFD:
|
||||
print(f"$$$$$ CanFD ECAN = {CAN.ECAN}")
|
||||
if 0x1fa in fingerprint[CAN.ECAN]:
|
||||
ret.extFlags |= HyundaiExtFlags.NAVI_CLUSTER.value
|
||||
print("$$$$ NaviCluster = True")
|
||||
else:
|
||||
print("$$$$ NaviCluster = False")
|
||||
|
||||
else:
|
||||
if 1348 in fingerprint[0]:
|
||||
ret.extFlags |= HyundaiExtFlags.NAVI_CLUSTER.value
|
||||
print("$$$$ NaviCluster = True")
|
||||
if 1157 in fingerprint[0] or 1157 in fingerprint[2]:
|
||||
ret.extFlags |= HyundaiExtFlags.HAS_LFAHDA.value
|
||||
print("$$$$ HasLFAHDA")
|
||||
if 1007 in fingerprint[0]:
|
||||
print("#### cruiseButtonAlt")
|
||||
|
||||
print(f"$$$$ enableBsm = {ret.enableBsm}")
|
||||
|
||||
if ret.openpilotLongitudinalControl:
|
||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.LONG.value
|
||||
if ret.flags & HyundaiFlags.HYBRID:
|
||||
@@ -152,95 +250,56 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# Dashcam cars are missing a test route, or otherwise need validation
|
||||
# TODO: Optima Hybrid 2017 uses a different SCC12 checksum
|
||||
if candidate in (CAR.KIA_OPTIMA_H,):
|
||||
ret.dashcamOnly = True
|
||||
#ret.dashcamOnly = candidate in {CAR.KIA_OPTIMA_H, }
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def _get_params_iq(stock_cp: structs.CarParams, ret: structs.IQCarParams, candidate, fingerprint: dict[int, dict[int, int]],
|
||||
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release_iq: bool, docs: bool) -> structs.IQCarParams:
|
||||
# identical logic used in _get_params
|
||||
# "LKA steering" if LKAS or LKAS_ALT messages are seen coming from the camera.
|
||||
# Generally means our LKAS message is forwarded to another ECU (commonly ADAS ECU)
|
||||
# that finally retransmits our steering command in LFA or LFA_ALT to the MDPS.
|
||||
# "LFA steering" if camera directly sends LFA to the MDPS
|
||||
cam_can = CanBus(None, fingerprint).CAM
|
||||
lka_steering = 0x50 in fingerprint[cam_can] or 0x110 in fingerprint[cam_can]
|
||||
CAN = CanBus(None, fingerprint, lka_steering)
|
||||
def init(CP, can_recv, can_send):
|
||||
|
||||
if not stock_cp.flags & HyundaiFlags.CANFD:
|
||||
# TODO-IQ: add route with ESCC message for process replay
|
||||
if ESCC_MSG in fingerprint[0]:
|
||||
ret.flags |= HyundaiFlagsIQ.ENHANCED_SCC.value
|
||||
Params().put_int('LongitudinalPersonalityMax', 4)
|
||||
|
||||
if ret.flags & HyundaiFlagsIQ.ENHANCED_SCC:
|
||||
ret.iqSafetyFlags |= HyundaiSafetyFlagsIQ.ESCC
|
||||
stock_cp.radarUnavailable = False
|
||||
|
||||
if stock_cp.flags & HyundaiFlags.HAS_LDA_BUTTON:
|
||||
ret.iqSafetyFlags |= HyundaiSafetyFlagsIQ.HAS_LDA_BUTTON
|
||||
|
||||
if stock_cp.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC):
|
||||
stock_cp.radarUnavailable = False
|
||||
|
||||
if stock_cp.flags & HyundaiFlags.ALT_LIMITS_2:
|
||||
stock_cp.dashcamOnly = False
|
||||
|
||||
if ret.flags & HyundaiFlagsIQ.NON_SCC:
|
||||
stock_cp.alphaLongitudinalAvailable = False
|
||||
stock_cp.openpilotLongitudinalControl = False
|
||||
stock_cp.pcmCruise = True
|
||||
ret.iqSafetyFlags |= HyundaiSafetyFlagsIQ.NON_SCC
|
||||
|
||||
# untested non-SCC platforms, need user validations
|
||||
if stock_cp.carFingerprint in (CAR.HYUNDAI_BAYON_1ST_GEN_NON_SCC, CAR.KIA_FORTE_2021_NON_SCC,
|
||||
CAR.KIA_SELTOS_2023_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC):
|
||||
stock_cp.dashcamOnly = True
|
||||
|
||||
if stock_cp.flags & HyundaiFlags.CANFD:
|
||||
if 0x1fa in fingerprint[CAN.ECAN]:
|
||||
ret.flags |= HyundaiFlagsIQ.SPEED_LIMIT_AVAILABLE.value
|
||||
else:
|
||||
# Detect smartMDPS, which bypasses EPS low-speed lockout, allowing iqpilot to send steering commands down to 0
|
||||
if 0x2AA in fingerprint[0]:
|
||||
stock_cp.minSteerSpeed = 0.0
|
||||
stock_cp.flags &= ~HyundaiFlags.MIN_STEER_32_MPH.value
|
||||
|
||||
if 0x544 in fingerprint[0]:
|
||||
ret.flags |= HyundaiFlagsIQ.SPEED_LIMIT_AVAILABLE.value
|
||||
|
||||
if 0x53E in fingerprint[2]:
|
||||
ret.flags |= HyundaiFlagsIQ.HAS_LKAS12.value
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def _get_longitudinal_tuning_iq(stock_cp: structs.CarParams, ret: structs.IQCarParams) -> structs.IQCarParams:
|
||||
if ret.flags & (HyundaiFlagsIQ.LONG_TUNING_DYNAMIC | HyundaiFlagsIQ.LONG_TUNING_PREDICTIVE):
|
||||
get_longitudinal_tune(stock_cp)
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def init(CP, CP_IQ, can_recv, can_send, communication_control=None):
|
||||
# 0x80 silences response
|
||||
if communication_control is None:
|
||||
communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.DISABLE_RX_DISABLE_TX, uds.MESSAGE_TYPE.NORMAL])
|
||||
|
||||
if CP.openpilotLongitudinalControl and not ((CP.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC)) or
|
||||
(CP_IQ.flags & HyundaiFlagsIQ.ENHANCED_SCC)):
|
||||
addr, bus = 0x7d0, CanBus(CP).ECAN if CP.flags & HyundaiFlags.CANFD else 0
|
||||
if CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value:
|
||||
if CP.openpilotLongitudinalControl and not (CP.flags & HyundaiFlags.CANFD_CAMERA_SCC):
|
||||
addr, bus = 0x7d0, 0
|
||||
if CP.flags & HyundaiFlags.CANFD_HDA2.value:
|
||||
addr, bus = 0x730, CanBus(CP).ECAN
|
||||
disable_ecu(can_recv, can_send, bus=bus, addr=addr, com_cont_req=communication_control)
|
||||
disable_ecu(can_recv, can_send, bus=bus, addr=addr, com_cont_req=b'\x28\x83\x01')
|
||||
|
||||
params = Params()
|
||||
if params.get_int("EnableRadarTracks") > 0 and not CP.flags & HyundaiFlags.CANFD:
|
||||
result = enable_radar_tracks(CP, can_recv, can_send)
|
||||
params.put_bool("EnableRadarTracksResult", result)
|
||||
|
||||
# for blinkers
|
||||
if CP.flags & HyundaiFlags.ENABLE_BLINKERS:
|
||||
disable_ecu(can_recv, can_send, bus=CanBus(CP).ECAN, addr=0x7B1, com_cont_req=communication_control)
|
||||
disable_ecu(can_recv, can_send, bus=CanBus(CP).ECAN, addr=0x7B1, com_cont_req=b'\x28\x83\x01')
|
||||
|
||||
@staticmethod
|
||||
def deinit(CP, can_recv, can_send):
|
||||
communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX, uds.MESSAGE_TYPE.NORMAL])
|
||||
CarInterface.init(CP, can_recv, can_send, communication_control)
|
||||
def enable_radar_tracks(CP, logcan, sendcan):
|
||||
from iqdbc.car.isotp_parallel_query import IsoTpParallelQuery
|
||||
print("################ Try To Enable Radar Tracks ####################")
|
||||
|
||||
ret = False
|
||||
sccBus = 2 if CP.flags & HyundaiFlags.CAMERA_SCC.value else 0
|
||||
rdr_fw = None
|
||||
rdr_fw_address = 0x7d0 #
|
||||
try:
|
||||
try:
|
||||
query = IsoTpParallelQuery(sendcan, logcan, sccBus, [rdr_fw_address], [b'\x10\x07'], [b'\x50\x07'])
|
||||
for addr, dat in query.get_data(0.1).items(): # pylint: disable=unused-variable
|
||||
print("ecu write data by id ...")
|
||||
new_config = b"\x00\x00\x00\x01\x00\x01"
|
||||
#new_config = b"\x00\x00\x00\x00\x00\x01"
|
||||
dataId = b'\x01\x42'
|
||||
WRITE_DAT_REQUEST = b'\x2e'
|
||||
WRITE_DAT_RESPONSE = b'\x68'
|
||||
query = IsoTpParallelQuery(sendcan, logcan, sccBus, [rdr_fw_address], [WRITE_DAT_REQUEST+dataId+new_config], [WRITE_DAT_RESPONSE])
|
||||
result = query.get_data(0)
|
||||
print("result=", result)
|
||||
ret = True
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"Failed : {e}")
|
||||
except Exception as e:
|
||||
print("############## Failed to enable tracks" + str(e))
|
||||
print("################ END Try to enable radar tracks")
|
||||
return ret
|
||||
|
||||
@@ -1,86 +1,885 @@
|
||||
import math
|
||||
import os
|
||||
from collections import deque
|
||||
|
||||
from iqdbc import DBC_PATH
|
||||
from iqdbc.can import CANParser
|
||||
from iqdbc.car import Bus, structs
|
||||
from iqdbc.car.interfaces import RadarInterfaceBase
|
||||
from iqdbc.car.hyundai.values import DBC
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.radar_interface_ext import RadarInterfaceExt
|
||||
from iqdbc.car.hyundai.values import DBC, HyundaiFlags, HyundaiExtFlags
|
||||
from openpilot.common.params import Params
|
||||
from iqdbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from openpilot.common.filter_simple import MyMovingAverage
|
||||
|
||||
SCC_TID = 0
|
||||
RADAR_START_ADDR = 0x500
|
||||
RADAR_MSG_COUNT = 32
|
||||
RADAR_MSG_COUNT4 = 8
|
||||
RADAR_GROUP4_MAX_LONG_DIST = 325.0
|
||||
RADAR_GROUP4_MAX_YREL = 6.0
|
||||
RADAR_START_ADDR_CANFD1 = 0x210
|
||||
RADAR_MSG_COUNT1 = 16
|
||||
RADAR_START_ADDR_CANFD2 = 0x3A5 # Group 2, Group 1: 0x210 2개씩?어???단 보류.
|
||||
RADAR_MSG_COUNT2 = 32
|
||||
RADAR_START_ADDR_CANFD3 = 0x400
|
||||
RADAR_MSG_COUNT3 = 30
|
||||
CORNER_OBJECT_235_START_ADDR = 0x235
|
||||
CORNER_OBJECT_235_MSG_COUNT = 20
|
||||
CORNER_OBJECT_235_TRACK_ID_OFFSET = 200
|
||||
CORNER_OBJECT_235_DBC = 'hyundai_canfd_corner_radar_235_generated'
|
||||
CORNER_OBJECT_180_START_ADDR = 0x180
|
||||
CORNER_OBJECT_180_MSG_COUNT = 5
|
||||
CORNER_OBJECT_180_SLOTS_PER_MSG = 2
|
||||
CORNER_OBJECT_180_TRACK_ID_OFFSET = 240
|
||||
CORNER_OBJECT_180_DBC = 'hyundai_canfd_corner_radar_180_generated'
|
||||
CORNER_OBJECT_430_LEFT_START_ADDR = 0x430
|
||||
CORNER_OBJECT_430_RIGHT_START_ADDR = 0x440
|
||||
CORNER_OBJECT_430_MSG_COUNT_PER_SIDE = 8
|
||||
CORNER_OBJECT_430_SLOTS_PER_MSG = 7
|
||||
CORNER_OBJECT_430_TRACK_ID_OFFSET = 300
|
||||
CORNER_OBJECT_430_DBC = 'hyundai_canfd_corner_radar_430_generated'
|
||||
CORNER_OBJECT_430_EMPTY_RAW_VALUES = (0x010d1f40, 0x00010d1f)
|
||||
CORNER_OBJECT_430_DEFAULT_DISTANCE_RAW_MIN = 2520 # 126.0 m
|
||||
CORNER_OBJECT_430_DEFAULT_DISTANCE_RAW_MAX = 2600 # 130.0 m
|
||||
CORNER_OBJECT_430_MAX_DREL = 120.0
|
||||
CORNER_OBJECT_430_MAX_TRACKS_PER_SIDE = 4
|
||||
CORNER_OBJECT_430_DT = 0.05
|
||||
CORNER_OBJECT_430_MAX_DREL_DELTA = 1.5
|
||||
CORNER_OBJECT_430_CANDIDATE_META_BYTE_3 = (2,)
|
||||
CORNER_OBJECT_430_CANDIDATE_EXCLUDED_SLOTS = (1,)
|
||||
CORNER_OBJECT_430_CANDIDATE_RAW_DELTA = 200
|
||||
CORNER_OBJECT_430_STRONG_META_BYTE_2 = (10,)
|
||||
CORNER_OBJECT_430_WEAK_META_BYTE_2 = (5, 6, 7, 8, 9)
|
||||
CORNER_OBJECT_430_STRONG_MIN_SUPPORT = 2
|
||||
CORNER_OBJECT_430_WEAK_MIN_SUPPORT = 3
|
||||
CORNER_OBJECT_430_CLUSTER_RAW_GAP = 200
|
||||
CORNER_OBJECT_430_TRACK_MATCH_MAX_DREL_DELTA = 3.0
|
||||
CORNER_OBJECT_430_MAX_ABS_VREL = 20.0
|
||||
CORNER_OBJECT_430_MAX_ABS_YVREL = 3.0
|
||||
CORNER_OBJECT_430_VREL_ALPHA = 0.35
|
||||
CORNER_OBJECT_430_YVREL_ALPHA = 0.35
|
||||
CORNER_OBJECT_430_LATERAL_CELL_MSG_WEIGHT = 0.35
|
||||
CORNER_OBJECT_430_LATERAL_CELL_SLOT_WEIGHT = 0.65
|
||||
CORNER_OBJECT_430_YREL_OFFSET = 5.8
|
||||
CORNER_OBJECT_430_YREL_SCALE = 1.1
|
||||
CORNER_OBJECT_430_RIGHT_CELL_MIRROR = 7.0
|
||||
CORNER_OBJECT_430_MIN_ABS_YREL = 0.8
|
||||
CORNER_OBJECT_430_MAX_ABS_YREL = 4.2
|
||||
CORNER_OBJECT_430_HISTORY_SIZE = 8
|
||||
CORNER_OBJECT_430_MIN_HISTORY = 5
|
||||
CORNER_OBJECT_430_MIN_INWARD_YREL_DELTA = 0.35
|
||||
CORNER_OBJECT_430_MIN_RECENT_INWARD_YREL_DELTA = 0.05
|
||||
CORNER_OBJECT_430_MIN_INWARD_RATIO = 0.65
|
||||
CORNER_OBJECT_430_INWARD_CENTER_ABS_YREL = 1.55
|
||||
CORNER_OBJECT_430_INWARD_KEEP_YVREL_ABS_YREL = 2.2
|
||||
CORNER_OBJECT_430_EARLY_INWARD_NONCENTER_FRAMES = 2
|
||||
CORNER_OBJECT_430_SIDE_KEEP_ABS_YREL = 2.0
|
||||
CORNER_OBJECT_STABLE_TRACK_ID_START = 1000
|
||||
CORNER_SIDE_OBJECT_MAX_DREL = 0.2
|
||||
CORNER_SIDE_OBJECT_MIN_ABS_YREL = 1.4
|
||||
CORNER_SIDE_OBJECT_MAX_ABS_YREL = 4.5
|
||||
|
||||
# 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]:
|
||||
class CornerObjectTrackIdManager:
|
||||
def __init__(self):
|
||||
self.next_track_id = CORNER_OBJECT_STABLE_TRACK_ID_START
|
||||
self.objects: dict[tuple[str, int], tuple[int, int]] = {}
|
||||
|
||||
def get_track_id(self, source: str, object_id: int, age: int) -> int:
|
||||
key = (source, object_id)
|
||||
previous = self.objects.get(key)
|
||||
if previous is None or age < previous[1]:
|
||||
track_id = self.next_track_id
|
||||
self.next_track_id += 1
|
||||
else:
|
||||
track_id = previous[0]
|
||||
self.objects[key] = (track_id, age)
|
||||
return track_id
|
||||
|
||||
def clear_source(self, source: str):
|
||||
self.objects = {key: value for key, value in self.objects.items() if key[0] != source}
|
||||
|
||||
|
||||
def corner_object_position_valid(d_rel: float, y_rel: float) -> bool:
|
||||
normal_object = 0.2 < d_rel < 180.0
|
||||
clipped_side_object = (
|
||||
0.0 <= d_rel <= CORNER_SIDE_OBJECT_MAX_DREL and
|
||||
CORNER_SIDE_OBJECT_MIN_ABS_YREL <= abs(y_rel) <= CORNER_SIDE_OBJECT_MAX_ABS_YREL
|
||||
)
|
||||
return (normal_object or clipped_side_object) and abs(y_rel) < 40.0
|
||||
|
||||
|
||||
def get_radar_can_parser(CP, radar_tracks, msg_start_addr, msg_count, radar_group4=False):
|
||||
if not radar_tracks:
|
||||
return None
|
||||
#if Bus.radar not in DBC[CP.carFingerprint]:
|
||||
# return None
|
||||
print("RadarInterface: RadarTracks...")
|
||||
|
||||
if CP.flags & HyundaiFlags.CANFD:
|
||||
CAN = CanBus(CP)
|
||||
messages = [(f"RADAR_TRACK_{addr:x}", 20) for addr in range(msg_start_addr, msg_start_addr + msg_count)]
|
||||
return CANParser('hyundai_canfd_radar_generated', messages, CAN.ACAN)
|
||||
else:
|
||||
messages = [(f"RADAR_TRACK_{addr:x}", 20) for addr in range(msg_start_addr, msg_start_addr + msg_count)]
|
||||
#return CANParser(DBC[CP.carFingerprint][Bus.radar], messages, 1)
|
||||
dbc_name = 'hyundai_kia_denso_front_radar_generated' if radar_group4 else 'hyundai_kia_mando_front_radar_generated'
|
||||
return CANParser(dbc_name, messages, 1)
|
||||
|
||||
def get_corner_object_can_parser(CP, enabled):
|
||||
if not enabled or not (CP.flags & HyundaiFlags.CANFD):
|
||||
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)
|
||||
dbc_path = os.path.join(DBC_PATH, f"{CORNER_OBJECT_235_DBC}.dbc")
|
||||
if not os.path.exists(dbc_path):
|
||||
print(f"RadarInterface: missing {CORNER_OBJECT_235_DBC}.dbc, 0x235 corner radar disabled")
|
||||
return None
|
||||
|
||||
CAN = CanBus(CP)
|
||||
messages = [(f"CORNER_RADAR_235_OBJECTS_{addr:x}", 33) for addr in range(CORNER_OBJECT_235_START_ADDR, CORNER_OBJECT_235_START_ADDR + CORNER_OBJECT_235_MSG_COUNT)]
|
||||
return CANParser(CORNER_OBJECT_235_DBC, messages, CAN.ACAN)
|
||||
|
||||
class RadarInterface(RadarInterfaceBase, RadarInterfaceExt):
|
||||
def __init__(self, CP, CP_IQ):
|
||||
RadarInterfaceBase.__init__(self, CP, CP_IQ)
|
||||
RadarInterfaceExt.__init__(self, CP, CP_IQ)
|
||||
self.updated_messages = set()
|
||||
self.trigger_msg = RADAR_START_ADDR + RADAR_MSG_COUNT - 1
|
||||
def get_corner_object_180_can_parser(CP, enabled):
|
||||
if not enabled or not (CP.flags & HyundaiFlags.CANFD):
|
||||
return None
|
||||
|
||||
dbc_path = os.path.join(DBC_PATH, f"{CORNER_OBJECT_180_DBC}.dbc")
|
||||
if not os.path.exists(dbc_path):
|
||||
print(f"RadarInterface: missing {CORNER_OBJECT_180_DBC}.dbc, 0x180 corner radar disabled")
|
||||
return None
|
||||
|
||||
CAN = CanBus(CP)
|
||||
messages = [(f"CORNER_RADAR_180_OBJECTS_{addr:x}", 33) for addr in range(CORNER_OBJECT_180_START_ADDR, CORNER_OBJECT_180_START_ADDR + CORNER_OBJECT_180_MSG_COUNT)]
|
||||
return CANParser(CORNER_OBJECT_180_DBC, messages, CAN.ACAN)
|
||||
|
||||
def get_corner_object_430_can_parser(CP, enabled):
|
||||
if not enabled or not (CP.flags & HyundaiFlags.CANFD):
|
||||
return None
|
||||
|
||||
dbc_path = os.path.join(DBC_PATH, f"{CORNER_OBJECT_430_DBC}.dbc")
|
||||
if not os.path.exists(dbc_path):
|
||||
print(f"RadarInterface: missing {CORNER_OBJECT_430_DBC}.dbc, 0x430/0x440 corner radar disabled")
|
||||
return None
|
||||
|
||||
CAN = CanBus(CP)
|
||||
messages = [(f"CORNER_RADAR_430_OBJECTS_{addr:x}", 33) for addr in range(CORNER_OBJECT_430_LEFT_START_ADDR, CORNER_OBJECT_430_LEFT_START_ADDR + CORNER_OBJECT_430_MSG_COUNT_PER_SIDE)]
|
||||
messages += [(f"CORNER_RADAR_430_OBJECTS_{addr:x}", 33) for addr in range(CORNER_OBJECT_430_RIGHT_START_ADDR, CORNER_OBJECT_430_RIGHT_START_ADDR + CORNER_OBJECT_430_MSG_COUNT_PER_SIDE)]
|
||||
return CANParser(CORNER_OBJECT_430_DBC, messages, CAN.ACAN)
|
||||
|
||||
def get_radar_can_parser_scc(CP):
|
||||
CAN = CanBus(CP)
|
||||
if CP.flags & HyundaiFlags.CANFD:
|
||||
messages = [("SCC_CONTROL", 50)]
|
||||
bus = CAN.ECAN
|
||||
else:
|
||||
messages = [("SCC11", 50)]
|
||||
bus = CAN.ECAN
|
||||
|
||||
print("$$$$$$$$ ECAN = ", CAN.ECAN)
|
||||
bus = CAN.CAM if CP.flags & HyundaiFlags.CAMERA_SCC else bus
|
||||
return CANParser(DBC[CP.carFingerprint][Bus.pt], messages, bus)
|
||||
|
||||
class RadarInterface(RadarInterfaceBase):
|
||||
def __init__(self, CP, CP_IQ=None):
|
||||
super().__init__(CP, CP_IQ or structs.IQCarParams())
|
||||
self.v_ego = 0.0
|
||||
|
||||
self.canfd = True if CP.flags & HyundaiFlags.CANFD else False
|
||||
self.radar_group1 = False
|
||||
self.radar_group3 = False
|
||||
self.radar_group4 = not self.canfd and bool(CP.extFlags & HyundaiExtFlags.RADAR_GROUP4.value)
|
||||
if self.canfd:
|
||||
if CP.extFlags & HyundaiExtFlags.RADAR_GROUP1.value:
|
||||
self.radar_start_addr = RADAR_START_ADDR_CANFD1
|
||||
self.radar_msg_count = RADAR_MSG_COUNT1
|
||||
self.radar_group1 = True
|
||||
elif CP.extFlags & HyundaiExtFlags.RADAR_GROUP3.value:
|
||||
self.radar_start_addr = RADAR_START_ADDR_CANFD3
|
||||
self.radar_msg_count = RADAR_MSG_COUNT3
|
||||
self.radar_group3 = True
|
||||
else:
|
||||
self.radar_start_addr = RADAR_START_ADDR_CANFD2
|
||||
self.radar_msg_count = RADAR_MSG_COUNT2
|
||||
else:
|
||||
self.radar_start_addr = RADAR_START_ADDR
|
||||
self.radar_msg_count = RADAR_MSG_COUNT4 if self.radar_group4 else RADAR_MSG_COUNT
|
||||
|
||||
self.params = Params()
|
||||
self.radar_tracks = self.params.get_int("EnableRadarTracks") >= 1
|
||||
self.corner_object_tracks = bool(CP.extFlags & HyundaiExtFlags.CORNER_RADAR_OBJECTS_235.value) and self.params.get_int("EnableCornerRadar") > 0
|
||||
self.corner_object_180_tracks = bool(CP.extFlags & HyundaiExtFlags.CORNER_RADAR_OBJECTS_180.value) and self.params.get_int("EnableCornerRadar") > 0
|
||||
self.corner_object_430_tracks = bool(CP.extFlags & HyundaiExtFlags.CORNER_RADAR_OBJECTS_430.value) and self.params.get_int("EnableCornerRadar") > 0
|
||||
self.updated_tracks = set()
|
||||
self.updated_scc = set()
|
||||
self.updated_corner_objects = set()
|
||||
self.updated_corner_objects_180 = set()
|
||||
self.updated_corner_objects_430 = set()
|
||||
self.corner_object_missed_updates = 0
|
||||
self.corner_object_180_missed_updates = 0
|
||||
self.corner_object_430_missed_updates = 0
|
||||
self.corner_object_track_ids = CornerObjectTrackIdManager()
|
||||
self.rcp_tracks = get_radar_can_parser(CP, self.radar_tracks, self.radar_start_addr, self.radar_msg_count, self.radar_group4)
|
||||
self.rcp_corner_objects = get_corner_object_can_parser(CP, self.corner_object_tracks)
|
||||
self.rcp_corner_objects_180 = get_corner_object_180_can_parser(CP, self.corner_object_180_tracks)
|
||||
self.rcp_corner_objects_430 = get_corner_object_430_can_parser(CP, self.corner_object_430_tracks)
|
||||
# Enabling raw radar tracks on legacy CAN disables the stock SCC11 stream on
|
||||
# some Hyundai/Kia platforms. Camera-SCC cars may still use SCC11.
|
||||
use_scc_parser = not (self.radar_tracks and not self.canfd and not (CP.flags & HyundaiFlags.CAMERA_SCC))
|
||||
self.rcp_scc = get_radar_can_parser_scc(CP) if use_scc_parser else None
|
||||
self.trigger_msg_scc = 416 if self.canfd else 0x420
|
||||
|
||||
self.trigger_msg_tracks = self.radar_start_addr + self.radar_msg_count - 1
|
||||
self.trigger_msg_corner_objects = CORNER_OBJECT_235_START_ADDR + CORNER_OBJECT_235_MSG_COUNT - 1
|
||||
self.trigger_msg_corner_objects_180 = CORNER_OBJECT_180_START_ADDR + CORNER_OBJECT_180_MSG_COUNT - 1
|
||||
self.trigger_msg_corner_objects_430 = CORNER_OBJECT_430_RIGHT_START_ADDR + CORNER_OBJECT_430_MSG_COUNT_PER_SIDE - 1
|
||||
self.track_id = 0
|
||||
|
||||
self.radar_off_can = CP.radarUnavailable
|
||||
self.rcp = get_radar_can_parser(CP)
|
||||
self.corner_objects_available = self.rcp_corner_objects is not None or self.rcp_corner_objects_180 is not None or self.rcp_corner_objects_430 is not None
|
||||
self.radar_off_can = CP.radarUnavailable and not self.corner_objects_available
|
||||
print(
|
||||
"RadarInterface: "
|
||||
f"radarUnavailable={CP.radarUnavailable} radarTracks={self.radar_tracks} "
|
||||
f"group4={self.radar_group4} "
|
||||
f"corner235={self.rcp_corner_objects is not None} corner180={self.rcp_corner_objects_180 is not None} "
|
||||
f"corner430={self.rcp_corner_objects_430 is not None} "
|
||||
f"radarOffCan={self.radar_off_can}"
|
||||
)
|
||||
|
||||
self.vRel_last = 0
|
||||
self.dRel_last = 0
|
||||
self.corner_object_430_prev_d_rel = {}
|
||||
self.corner_object_430_prev_v_rel = {}
|
||||
self.corner_object_430_prev_y_rel = {}
|
||||
self.corner_object_430_prev_yv_rel = {}
|
||||
self.corner_object_430_prev_code = {}
|
||||
self.corner_object_430_history = {}
|
||||
self.corner_object_430_noncenter_inward_frames = {}
|
||||
|
||||
# Initialize pts
|
||||
if self.rcp_tracks is not None:
|
||||
total_tracks = self.radar_msg_count * (2 if self.radar_group1 else 1)
|
||||
for track_id in range(total_tracks):
|
||||
t_id = track_id + 32
|
||||
self.pts[t_id] = structs.RadarData.RadarPoint()
|
||||
self.pts[t_id].measured = False
|
||||
self.pts[t_id].trackId = t_id
|
||||
|
||||
if self.rcp_scc is not None:
|
||||
self.pts[SCC_TID] = structs.RadarData.RadarPoint()
|
||||
self.pts[SCC_TID].trackId = SCC_TID
|
||||
self.pts[SCC_TID].radarSource = "scc"
|
||||
if self.rcp_corner_objects is not None:
|
||||
for slot in range(CORNER_OBJECT_235_MSG_COUNT):
|
||||
t_id = CORNER_OBJECT_235_TRACK_ID_OFFSET + slot
|
||||
self.pts[t_id] = structs.RadarData.RadarPoint()
|
||||
self.pts[t_id].measured = False
|
||||
self.pts[t_id].trackId = t_id
|
||||
self.pts[t_id].radarSource = "corner235"
|
||||
if self.rcp_corner_objects_180 is not None:
|
||||
for slot in range(CORNER_OBJECT_180_MSG_COUNT * CORNER_OBJECT_180_SLOTS_PER_MSG):
|
||||
t_id = CORNER_OBJECT_180_TRACK_ID_OFFSET + slot
|
||||
self.pts[t_id] = structs.RadarData.RadarPoint()
|
||||
self.pts[t_id].measured = False
|
||||
self.pts[t_id].trackId = t_id
|
||||
self.pts[t_id].radarSource = "corner180"
|
||||
if self.rcp_corner_objects_430 is not None:
|
||||
for slot in range(CORNER_OBJECT_430_MSG_COUNT_PER_SIDE * 2 * CORNER_OBJECT_430_SLOTS_PER_MSG):
|
||||
t_id = CORNER_OBJECT_430_TRACK_ID_OFFSET + slot
|
||||
self.pts[t_id] = structs.RadarData.RadarPoint()
|
||||
self.pts[t_id].measured = False
|
||||
self.pts[t_id].trackId = t_id
|
||||
|
||||
self.frame = 0
|
||||
|
||||
if self.rcp is None:
|
||||
self.initialize_radar_ext(self.trigger_msg)
|
||||
|
||||
def update(self, can_strings):
|
||||
if self.radar_off_can or (self.rcp is None):
|
||||
self.frame += 1
|
||||
if self.radar_off_can or (self.rcp_tracks is None and self.rcp_scc is None and self.rcp_corner_objects is None and self.rcp_corner_objects_180 is None and self.rcp_corner_objects_430 is None):
|
||||
return super().update(None)
|
||||
|
||||
vls = self.rcp.update(can_strings)
|
||||
self.updated_messages.update(vls)
|
||||
if self.rcp_scc is not None:
|
||||
vls_s = self.rcp_scc.update(can_strings)
|
||||
self.updated_scc.update(vls_s)
|
||||
|
||||
if self.trigger_msg not in self.updated_messages:
|
||||
track_ready = False
|
||||
if self.radar_tracks and self.rcp_tracks is not None:
|
||||
vls_t = self.rcp_tracks.update(can_strings)
|
||||
self.updated_tracks.update(vls_t)
|
||||
track_ready = self.trigger_msg_tracks in self.updated_tracks
|
||||
|
||||
corner_ready = False
|
||||
if self.rcp_corner_objects is not None:
|
||||
vls_c = self.rcp_corner_objects.update(can_strings)
|
||||
self.updated_corner_objects.update(vls_c)
|
||||
corner_ready = self.trigger_msg_corner_objects in self.updated_corner_objects
|
||||
|
||||
corner_180_ready = False
|
||||
if self.rcp_corner_objects_180 is not None:
|
||||
vls_180 = self.rcp_corner_objects_180.update(can_strings)
|
||||
self.updated_corner_objects_180.update(vls_180)
|
||||
corner_180_ready = self.trigger_msg_corner_objects_180 in self.updated_corner_objects_180
|
||||
|
||||
corner_430_ready = False
|
||||
if self.rcp_corner_objects_430 is not None:
|
||||
vls_430 = self.rcp_corner_objects_430.update(can_strings)
|
||||
self.updated_corner_objects_430.update(vls_430)
|
||||
corner_430_ready = self.trigger_msg_corner_objects_430 in self.updated_corner_objects_430
|
||||
|
||||
scc_ready = not self.radar_tracks and self.frame % 5 == 0 and self.rcp_scc is not None
|
||||
|
||||
if track_ready:
|
||||
self._update(self.updated_tracks)
|
||||
self.updated_tracks.clear()
|
||||
|
||||
if corner_ready:
|
||||
self._update_corner_objects(self.updated_corner_objects)
|
||||
self.corner_object_missed_updates = 0
|
||||
self.updated_corner_objects.clear()
|
||||
|
||||
if corner_180_ready:
|
||||
self._update_corner_objects_180(self.updated_corner_objects_180)
|
||||
self.corner_object_180_missed_updates = 0
|
||||
self.updated_corner_objects_180.clear()
|
||||
|
||||
if corner_430_ready:
|
||||
self._update_corner_objects_430(self.updated_corner_objects_430)
|
||||
self.corner_object_430_missed_updates = 0
|
||||
self.updated_corner_objects_430.clear()
|
||||
|
||||
# Corner radar runs at its own cadence. Do not let corner-only frames publish
|
||||
# RadarData, since liveTracks uses a fixed radarTimeStep for aLead/jLead.
|
||||
publish_ready = track_ready or scc_ready
|
||||
if not publish_ready:
|
||||
return None
|
||||
|
||||
rr = self._update(self.updated_messages)
|
||||
self.updated_messages.clear()
|
||||
if self.rcp_scc is not None:
|
||||
self._update_scc(self.updated_scc)
|
||||
if self.rcp_corner_objects is not None:
|
||||
if self.updated_corner_objects:
|
||||
self._update_corner_objects(self.updated_corner_objects)
|
||||
self.corner_object_missed_updates = 0
|
||||
else:
|
||||
self.corner_object_missed_updates += 1
|
||||
if self.corner_object_missed_updates > 10:
|
||||
self._clear_corner_objects()
|
||||
if self.rcp_corner_objects_180 is not None:
|
||||
if self.updated_corner_objects_180:
|
||||
self._update_corner_objects_180(self.updated_corner_objects_180)
|
||||
self.corner_object_180_missed_updates = 0
|
||||
else:
|
||||
self.corner_object_180_missed_updates += 1
|
||||
if self.corner_object_180_missed_updates > 10:
|
||||
self._clear_corner_objects_180()
|
||||
if self.rcp_corner_objects_430 is not None:
|
||||
if self.updated_corner_objects_430:
|
||||
self._update_corner_objects_430(self.updated_corner_objects_430)
|
||||
self.corner_object_430_missed_updates = 0
|
||||
else:
|
||||
self.corner_object_430_missed_updates += 1
|
||||
if self.corner_object_430_missed_updates > 10:
|
||||
self._clear_corner_objects_430()
|
||||
self.updated_scc.clear()
|
||||
self.updated_corner_objects.clear()
|
||||
self.updated_corner_objects_180.clear()
|
||||
self.updated_corner_objects_430.clear()
|
||||
|
||||
return rr
|
||||
ret = structs.RadarData()
|
||||
if ((self.rcp_tracks is not None and self.radar_tracks and not self.rcp_tracks.can_valid) or
|
||||
(self.rcp_scc is not None and not self.corner_objects_available and not self.rcp_scc.can_valid) or
|
||||
(self.rcp_corner_objects is not None and not self.rcp_corner_objects.can_valid) or
|
||||
(self.rcp_corner_objects_180 is not None and not self.rcp_corner_objects_180.can_valid) or
|
||||
(self.rcp_corner_objects_430 is not None and not self.rcp_corner_objects_430.can_valid)):
|
||||
ret.errors.canError = True
|
||||
ret.points = [point for point in self.pts.values() if point.measured]
|
||||
return ret
|
||||
|
||||
def _update(self, updated_messages):
|
||||
ret = structs.RadarData()
|
||||
if self.rcp is None:
|
||||
return ret
|
||||
|
||||
if not self.rcp.can_valid:
|
||||
ret.errors.canError = True
|
||||
t_id = 32
|
||||
for addr in range(self.radar_start_addr, self.radar_start_addr + self.radar_msg_count):
|
||||
|
||||
if self.use_radar_interface_ext:
|
||||
return self.update_ext(ret)
|
||||
|
||||
for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT):
|
||||
msg = self.rcp.vl[f"RADAR_TRACK_{addr:x}"]
|
||||
|
||||
if addr not in self.pts:
|
||||
self.pts[addr] = structs.RadarData.RadarPoint()
|
||||
self.pts[addr].trackId = self.track_id
|
||||
self.track_id += 1
|
||||
|
||||
valid = msg['STATE'] in (3, 4)
|
||||
if valid:
|
||||
azimuth = math.radians(msg['AZIMUTH'])
|
||||
self.pts[addr].measured = True
|
||||
self.pts[addr].dRel = math.cos(azimuth) * msg['LONG_DIST']
|
||||
self.pts[addr].yRel = 0.5 * -math.sin(azimuth) * msg['LONG_DIST']
|
||||
self.pts[addr].vRel = msg['REL_SPEED']
|
||||
self.pts[addr].aRel = msg['REL_ACCEL']
|
||||
self.pts[addr].yvRel = float('nan')
|
||||
msg = self.rcp_tracks.vl[f"RADAR_TRACK_{addr:x}"]
|
||||
|
||||
if self.radar_group1:
|
||||
valid = msg['VALID_CNT1'] > 10
|
||||
elif self.radar_group3:
|
||||
# Group 3 marks an empty object slot with LONG_DIST raw 0x7ff (204.7 m).
|
||||
valid = msg['LONG_DIST'] < 204.7
|
||||
elif self.canfd:
|
||||
valid = msg['VALID_CNT'] > 10
|
||||
elif self.radar_group4:
|
||||
# EN: DNMWR006 exposes eight stable tracked-object slots at 0x500-0x507.
|
||||
# Messages from 0x508 onward are distance-sorted raw detections without
|
||||
# stable IDs, so they are excluded. OBJECT_STATE 3 is a confirmed track;
|
||||
# empty slots use LONG_DIST raw 0xfff8 (409.55 m). Driving logs reached
|
||||
# 317.80 m, so 325 m preserves every observed confirmed track while
|
||||
# retaining margin from the empty-slot sentinel. Keep the +/-6 m
|
||||
# ego/adjacent-lane envelope to suppress farther roadside reflections.
|
||||
# KO: DNMWR006의 안정적인 추적 객체 슬롯은 0x500~0x507의 8개임.
|
||||
# 0x508 이후 메시지는 고정 ID가 없는 거리순 raw detection이므로 제외함.
|
||||
# OBJECT_STATE 3은 확정 추적 객체이며, 빈 슬롯은 LONG_DIST raw
|
||||
# 0xfff8(409.55m)을 사용함. 주행 로그의 최대값은 317.80m였으므로
|
||||
# 325m 상한으로 관측된 확정 트랙을 모두 보존하면서 빈 슬롯 값과 충분한
|
||||
# 여유를 확보함. 원거리 도로변 반사를 줄이기 위해 좌우 6m 범위를 유지함.
|
||||
valid = (msg['OBJECT_STATE'] == 3 and 0.2 < msg['LONG_DIST'] < RADAR_GROUP4_MAX_LONG_DIST and
|
||||
abs(msg['LAT_DIST']) <= RADAR_GROUP4_MAX_YREL)
|
||||
else:
|
||||
del self.pts[addr]
|
||||
valid = msg['STATE'] in (3, 4)
|
||||
|
||||
ret.points = list(self.pts.values())
|
||||
return ret
|
||||
self.pts[t_id].measured = bool(valid)
|
||||
if not valid:
|
||||
self.pts[t_id].dRel = 0
|
||||
self.pts[t_id].yRel = 0
|
||||
self.pts[t_id].vRel = 0
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0
|
||||
elif self.radar_group1:
|
||||
self.pts[t_id].dRel = msg['LONG_DIST1']
|
||||
self.pts[t_id].yRel = msg['LAT_DIST1']
|
||||
self.pts[t_id].vRel = msg['REL_SPEED1']
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = msg['REL_ACCEL1']
|
||||
self.pts[t_id].yvRel = msg['LAT_SPEED1']
|
||||
elif self.canfd:
|
||||
if self.radar_group3:
|
||||
# Group 3 reports the object's center. Convert it to the rear surface to match SCC/vision dRel.
|
||||
self.pts[t_id].dRel = max(0.0, msg['LONG_DIST'] - msg['OBJECT_LENGTH'] * 0.5 - 0.1)
|
||||
else:
|
||||
self.pts[t_id].dRel = msg['LONG_DIST']
|
||||
self.pts[t_id].yRel = msg['LAT_DIST']
|
||||
self.pts[t_id].vRel = msg['REL_SPEED']
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = float('nan') if self.radar_group3 else msg['REL_ACCEL']
|
||||
self.pts[t_id].yvRel = 0.0 if self.radar_group3 else msg['LAT_SPEED']
|
||||
elif self.radar_group4:
|
||||
self.pts[t_id].dRel = msg['LONG_DIST']
|
||||
self.pts[t_id].yRel = -msg['LAT_DIST']
|
||||
self.pts[t_id].vRel = msg['REL_SPEED']
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0.0
|
||||
else:
|
||||
azimuth = math.radians(msg['AZIMUTH'])
|
||||
self.pts[t_id].dRel = math.cos(azimuth) * msg['LONG_DIST']
|
||||
self.pts[t_id].yRel = 0.5 * -math.sin(azimuth) * msg['LONG_DIST']
|
||||
self.pts[t_id].vRel = msg['REL_SPEED']
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = msg['REL_ACCEL']
|
||||
self.pts[t_id].yvRel = 0.0
|
||||
|
||||
t_id += 1
|
||||
# radar group1? ?나??msg??2개의 ?이?? ?어?음.
|
||||
if self.radar_group1:
|
||||
for addr in range(self.radar_start_addr, self.radar_start_addr + self.radar_msg_count):
|
||||
msg = self.rcp_tracks.vl[f"RADAR_TRACK_{addr:x}"]
|
||||
|
||||
valid = msg['VALID_CNT2'] > 10
|
||||
self.pts[t_id].measured = bool(valid)
|
||||
if not valid:
|
||||
self.pts[t_id].dRel = 0
|
||||
self.pts[t_id].yRel = 0
|
||||
self.pts[t_id].vRel = 0
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0
|
||||
else:
|
||||
self.pts[t_id].dRel = msg['LONG_DIST2']
|
||||
self.pts[t_id].yRel = msg['LAT_DIST2']
|
||||
self.pts[t_id].vRel = msg['REL_SPEED2']
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = msg['REL_ACCEL2']
|
||||
self.pts[t_id].yvRel = msg['LAT_SPEED2']
|
||||
|
||||
t_id += 1
|
||||
|
||||
def _update_corner_objects(self, updated_messages):
|
||||
if self.rcp_corner_objects is None:
|
||||
return
|
||||
|
||||
if not updated_messages:
|
||||
self._clear_corner_objects()
|
||||
return
|
||||
|
||||
candidates = []
|
||||
for slot, addr in enumerate(range(CORNER_OBJECT_235_START_ADDR, CORNER_OBJECT_235_START_ADDR + CORNER_OBJECT_235_MSG_COUNT)):
|
||||
t_id = CORNER_OBJECT_235_TRACK_ID_OFFSET + slot
|
||||
msg = self.rcp_corner_objects.vl[f"CORNER_RADAR_235_OBJECTS_{addr:x}"]
|
||||
|
||||
d_rel = msg["OBJ_REL_POS_X"]
|
||||
y_rel = msg["OBJ_REL_POS_Y"]
|
||||
v_rel = msg["OBJ_REL_VEL_X"]
|
||||
yv_rel = msg["OBJ_REL_VEL_Y"]
|
||||
a_rel = msg["OBJ_REL_ACCEL_X"]
|
||||
# Side objects are clipped to x=0 by the corner radar. Quality, identity,
|
||||
# and lateral motion still describe a real object, so keep them for
|
||||
# corner-confirmed front-radar association in radard.
|
||||
valid = msg["OBJ_QUAL_LEVEL"] > 0 and corner_object_position_valid(d_rel, y_rel) and v_rel > -99.0
|
||||
|
||||
if not valid:
|
||||
continue
|
||||
candidates.append((t_id, int(msg["OBJ_OBJECT_ID"]), int(msg["OBJ_AGE"]), int(msg["OBJ_QUAL_LEVEL"]),
|
||||
d_rel, y_rel, v_rel, yv_rel, a_rel))
|
||||
|
||||
self._apply_corner_objects("corner235", candidates,
|
||||
range(CORNER_OBJECT_235_TRACK_ID_OFFSET,
|
||||
CORNER_OBJECT_235_TRACK_ID_OFFSET + CORNER_OBJECT_235_MSG_COUNT))
|
||||
|
||||
def _update_corner_objects_180(self, updated_messages):
|
||||
if self.rcp_corner_objects_180 is None:
|
||||
return
|
||||
|
||||
if not updated_messages:
|
||||
self._clear_corner_objects_180()
|
||||
return
|
||||
|
||||
candidates = []
|
||||
for msg_index, addr in enumerate(range(CORNER_OBJECT_180_START_ADDR, CORNER_OBJECT_180_START_ADDR + CORNER_OBJECT_180_MSG_COUNT)):
|
||||
msg = self.rcp_corner_objects_180.vl[f"CORNER_RADAR_180_OBJECTS_{addr:x}"]
|
||||
for slot_index in range(CORNER_OBJECT_180_SLOTS_PER_MSG):
|
||||
t_id = CORNER_OBJECT_180_TRACK_ID_OFFSET + msg_index * CORNER_OBJECT_180_SLOTS_PER_MSG + slot_index
|
||||
prefix = f"SLOT{slot_index + 1}_"
|
||||
d_rel = msg[f"{prefix}REL_POS_X"]
|
||||
y_rel = msg[f"{prefix}REL_POS_Y"]
|
||||
v_rel = msg[f"{prefix}REL_VEL_X"]
|
||||
yv_rel = msg[f"{prefix}REL_VEL_Y"]
|
||||
a_rel = msg[f"{prefix}REL_ACCEL_X"]
|
||||
valid = msg[f"{prefix}QUAL_LEVEL"] > 0 and corner_object_position_valid(d_rel, y_rel) and v_rel > -99.0
|
||||
|
||||
if not valid:
|
||||
continue
|
||||
candidates.append((t_id, int(msg[f"{prefix}OBJECT_ID"]), int(msg[f"{prefix}AGE"]), int(msg[f"{prefix}QUAL_LEVEL"]),
|
||||
d_rel, y_rel, v_rel, yv_rel, a_rel))
|
||||
|
||||
self._apply_corner_objects("corner180", candidates,
|
||||
range(CORNER_OBJECT_180_TRACK_ID_OFFSET,
|
||||
CORNER_OBJECT_180_TRACK_ID_OFFSET + CORNER_OBJECT_180_MSG_COUNT * CORNER_OBJECT_180_SLOTS_PER_MSG))
|
||||
|
||||
def _apply_corner_objects(self, source, candidates, slot_ids):
|
||||
for t_id in slot_ids:
|
||||
self._clear_point(t_id)
|
||||
|
||||
# The same object can occupy two CAN slots for one cycle during a slot handoff.
|
||||
# Publish only the newest/highest-quality copy so trackId stays unique.
|
||||
objects = {}
|
||||
for candidate in candidates:
|
||||
object_id = candidate[1]
|
||||
previous = objects.get(object_id)
|
||||
if previous is None or (candidate[2], candidate[3]) > (previous[2], previous[3]):
|
||||
objects[object_id] = candidate
|
||||
|
||||
for t_id, object_id, age, _, d_rel, y_rel, v_rel, yv_rel, a_rel in objects.values():
|
||||
point = self.pts[t_id]
|
||||
point.measured = True
|
||||
point.trackId = self.corner_object_track_ids.get_track_id(source, object_id, age)
|
||||
point.radarSource = source
|
||||
point.dRel = d_rel
|
||||
point.yRel = y_rel
|
||||
point.vRel = v_rel
|
||||
point.vLead = v_rel + self.v_ego
|
||||
point.aRel = a_rel
|
||||
point.yvRel = yv_rel
|
||||
|
||||
|
||||
def _update_corner_objects_430(self, updated_messages):
|
||||
if self.rcp_corner_objects_430 is None:
|
||||
return
|
||||
|
||||
if not updated_messages:
|
||||
self._clear_corner_objects_430()
|
||||
return
|
||||
|
||||
bank_defs = (
|
||||
(CORNER_OBJECT_430_LEFT_START_ADDR, 1.0, 0),
|
||||
(CORNER_OBJECT_430_RIGHT_START_ADDR, -1.0, CORNER_OBJECT_430_MSG_COUNT_PER_SIDE * CORNER_OBJECT_430_SLOTS_PER_MSG),
|
||||
)
|
||||
for start_addr, side_sign, track_base in bank_defs:
|
||||
bins = []
|
||||
for msg_index, addr in enumerate(range(start_addr, start_addr + CORNER_OBJECT_430_MSG_COUNT_PER_SIDE)):
|
||||
msg = self.rcp_corner_objects_430.vl[f"CORNER_RADAR_430_OBJECTS_{addr:x}"]
|
||||
for slot_index in range(CORNER_OBJECT_430_SLOTS_PER_MSG):
|
||||
prefix = f"SLOT{slot_index + 1}_"
|
||||
distance_raw = int(msg[f"{prefix}DISTANCE_RAW"])
|
||||
raw = (
|
||||
distance_raw |
|
||||
(int(msg[f"{prefix}META_13_15"]) << 13) |
|
||||
(int(msg[f"{prefix}META_BYTE_2"]) << 16) |
|
||||
(int(msg[f"{prefix}META_BYTE_3"]) << 24)
|
||||
)
|
||||
code = (
|
||||
int(msg[f"{prefix}META_13_15"]),
|
||||
int(msg[f"{prefix}META_BYTE_2"]),
|
||||
int(msg[f"{prefix}META_BYTE_3"]),
|
||||
)
|
||||
d_rel = distance_raw * 0.05
|
||||
default_distance = CORNER_OBJECT_430_DEFAULT_DISTANCE_RAW_MIN <= distance_raw <= CORNER_OBJECT_430_DEFAULT_DISTANCE_RAW_MAX
|
||||
base_valid = (
|
||||
raw not in CORNER_OBJECT_430_EMPTY_RAW_VALUES and
|
||||
distance_raw not in (0, 8000, 8191) and
|
||||
not default_distance and
|
||||
0.2 < d_rel < CORNER_OBJECT_430_MAX_DREL
|
||||
)
|
||||
candidate_valid = (
|
||||
base_valid and
|
||||
slot_index + 1 not in CORNER_OBJECT_430_CANDIDATE_EXCLUDED_SLOTS and
|
||||
code[2] in CORNER_OBJECT_430_CANDIDATE_META_BYTE_3 and
|
||||
code[1] in CORNER_OBJECT_430_STRONG_META_BYTE_2 + CORNER_OBJECT_430_WEAK_META_BYTE_2
|
||||
)
|
||||
bins.append({
|
||||
"msg_index": msg_index,
|
||||
"slot_index": slot_index,
|
||||
"distance_raw": distance_raw,
|
||||
"d_rel": d_rel,
|
||||
"code": code,
|
||||
"candidate_valid": candidate_valid,
|
||||
})
|
||||
|
||||
supported_bins = []
|
||||
candidates = [b for b in bins if b["candidate_valid"]]
|
||||
for b in candidates:
|
||||
support = 1
|
||||
for other in candidates:
|
||||
if other is b:
|
||||
continue
|
||||
if abs(other["msg_index"] - b["msg_index"]) > 1:
|
||||
continue
|
||||
if abs(other["slot_index"] - b["slot_index"]) > 2:
|
||||
continue
|
||||
if abs(other["distance_raw"] - b["distance_raw"]) > CORNER_OBJECT_430_CANDIDATE_RAW_DELTA:
|
||||
continue
|
||||
support += 1
|
||||
min_support = (CORNER_OBJECT_430_STRONG_MIN_SUPPORT if b["code"][1] in CORNER_OBJECT_430_STRONG_META_BYTE_2
|
||||
else CORNER_OBJECT_430_WEAK_MIN_SUPPORT)
|
||||
if support >= min_support:
|
||||
supported_bins.append({**b, "support": support})
|
||||
|
||||
clusters = []
|
||||
for b in sorted(supported_bins, key=lambda item: item["distance_raw"]):
|
||||
if not clusters or b["distance_raw"] - clusters[-1][-1]["distance_raw"] > CORNER_OBJECT_430_CLUSTER_RAW_GAP:
|
||||
clusters.append([b])
|
||||
else:
|
||||
clusters[-1].append(b)
|
||||
clusters = sorted(clusters, key=lambda cluster: sum(b["distance_raw"] for b in cluster) / len(cluster))[:CORNER_OBJECT_430_MAX_TRACKS_PER_SIDE]
|
||||
|
||||
cluster_objects = []
|
||||
for cluster in clusters:
|
||||
msg_index = sum(b["msg_index"] for b in cluster) / len(cluster)
|
||||
slot = sum(b["slot_index"] + 1 for b in cluster) / len(cluster)
|
||||
lateral_cell = (CORNER_OBJECT_430_LATERAL_CELL_MSG_WEIGHT * msg_index +
|
||||
CORNER_OBJECT_430_LATERAL_CELL_SLOT_WEIGHT * slot)
|
||||
mapped_cell = lateral_cell if side_sign > 0.0 else CORNER_OBJECT_430_RIGHT_CELL_MIRROR - lateral_cell
|
||||
y_abs = max(CORNER_OBJECT_430_MIN_ABS_YREL,
|
||||
min(CORNER_OBJECT_430_MAX_ABS_YREL,
|
||||
CORNER_OBJECT_430_YREL_OFFSET - CORNER_OBJECT_430_YREL_SCALE * mapped_cell))
|
||||
cluster_objects.append({
|
||||
"d_rel": sum(b["d_rel"] for b in cluster) / len(cluster),
|
||||
"y_rel": side_sign * y_abs,
|
||||
"code": max((b["code"] for b in cluster), key=lambda code: sum(1 for item in cluster if item["code"] == code)),
|
||||
})
|
||||
|
||||
active_t_ids = set()
|
||||
side_track_ids = [
|
||||
CORNER_OBJECT_430_TRACK_ID_OFFSET + track_base + slot
|
||||
for slot in range(CORNER_OBJECT_430_MAX_TRACKS_PER_SIDE)
|
||||
]
|
||||
unmatched_track_ids = {t_id for t_id in side_track_ids if t_id in self.corner_object_430_prev_d_rel}
|
||||
unused_track_ids = [t_id for t_id in side_track_ids if t_id not in unmatched_track_ids]
|
||||
|
||||
for cluster in cluster_objects:
|
||||
d_rel = cluster["d_rel"]
|
||||
code = cluster["code"]
|
||||
matched_t_id = None
|
||||
if unmatched_track_ids:
|
||||
nearest_t_id = min(unmatched_track_ids, key=lambda t_id: abs(d_rel - self.corner_object_430_prev_d_rel[t_id]))
|
||||
if abs(d_rel - self.corner_object_430_prev_d_rel[nearest_t_id]) <= CORNER_OBJECT_430_TRACK_MATCH_MAX_DREL_DELTA:
|
||||
matched_t_id = nearest_t_id
|
||||
unmatched_track_ids.remove(matched_t_id)
|
||||
if matched_t_id is None and unused_track_ids:
|
||||
matched_t_id = unused_track_ids.pop(0)
|
||||
if matched_t_id is None:
|
||||
continue
|
||||
|
||||
t_id = matched_t_id
|
||||
active_t_ids.add(t_id)
|
||||
prev_d_rel = self.corner_object_430_prev_d_rel.get(t_id)
|
||||
prev_code = self.corner_object_430_prev_code.get(t_id)
|
||||
self.corner_object_430_prev_d_rel[t_id] = d_rel
|
||||
self.corner_object_430_prev_y_rel[t_id] = cluster["y_rel"]
|
||||
self.corner_object_430_prev_code[t_id] = code
|
||||
reset_track = prev_d_rel is None or code != prev_code or abs(d_rel - prev_d_rel) > CORNER_OBJECT_430_MAX_DREL_DELTA
|
||||
if reset_track:
|
||||
self.corner_object_430_prev_v_rel.pop(t_id, None)
|
||||
self.corner_object_430_prev_yv_rel.pop(t_id, None)
|
||||
self.corner_object_430_history.pop(t_id, None)
|
||||
self.corner_object_430_noncenter_inward_frames.pop(t_id, None)
|
||||
|
||||
history = self.corner_object_430_history.setdefault(t_id, deque(maxlen=CORNER_OBJECT_430_HISTORY_SIZE))
|
||||
history.append((d_rel, cluster["y_rel"]))
|
||||
if len(history) < CORNER_OBJECT_430_MIN_HISTORY:
|
||||
self._clear_point(t_id)
|
||||
continue
|
||||
|
||||
window_dt = CORNER_OBJECT_430_DT * (len(history) - 1)
|
||||
first_d_rel, first_y_rel = history[0]
|
||||
hist_v_rel = (d_rel - first_d_rel) / window_dt
|
||||
if abs(hist_v_rel) > CORNER_OBJECT_430_MAX_ABS_VREL:
|
||||
self.corner_object_430_prev_v_rel.pop(t_id, None)
|
||||
self.corner_object_430_prev_yv_rel.pop(t_id, None)
|
||||
self.corner_object_430_history.pop(t_id, None)
|
||||
self.corner_object_430_noncenter_inward_frames.pop(t_id, None)
|
||||
self._clear_point(t_id)
|
||||
continue
|
||||
prev_v_rel = self.corner_object_430_prev_v_rel.get(t_id, hist_v_rel)
|
||||
v_rel = (1.0 - CORNER_OBJECT_430_VREL_ALPHA) * prev_v_rel + CORNER_OBJECT_430_VREL_ALPHA * hist_v_rel
|
||||
self.corner_object_430_prev_v_rel[t_id] = v_rel
|
||||
|
||||
inward_steps = 0
|
||||
usable_steps = 0
|
||||
prev_abs_y = abs(history[0][1])
|
||||
for _, y_rel in list(history)[1:]:
|
||||
abs_y = abs(y_rel)
|
||||
delta = prev_abs_y - abs_y
|
||||
if abs(delta) > 1e-3:
|
||||
usable_steps += 1
|
||||
if delta > 0.0:
|
||||
inward_steps += 1
|
||||
prev_abs_y = abs_y
|
||||
net_inward_y = abs(first_y_rel) - abs(cluster["y_rel"])
|
||||
inward_ratio = inward_steps / usable_steps if usable_steps > 0 else 0.0
|
||||
hist_yv_rel = (cluster["y_rel"] - first_y_rel) / window_dt
|
||||
recent_inward_y = abs(history[-3][1]) - abs(cluster["y_rel"]) if len(history) >= 3 else net_inward_y
|
||||
if (net_inward_y < CORNER_OBJECT_430_MIN_INWARD_YREL_DELTA or
|
||||
recent_inward_y < CORNER_OBJECT_430_MIN_RECENT_INWARD_YREL_DELTA or
|
||||
inward_ratio < CORNER_OBJECT_430_MIN_INWARD_RATIO or
|
||||
abs(hist_yv_rel) > CORNER_OBJECT_430_MAX_ABS_YVREL):
|
||||
hist_yv_rel = 0.0
|
||||
inward_motion_candidate = hist_yv_rel != 0.0 and abs(cluster["y_rel"]) <= CORNER_OBJECT_430_INWARD_KEEP_YVREL_ABS_YREL
|
||||
inward_center_candidate = inward_motion_candidate and abs(cluster["y_rel"]) <= CORNER_OBJECT_430_INWARD_CENTER_ABS_YREL
|
||||
y_rel = cluster["y_rel"]
|
||||
if inward_motion_candidate:
|
||||
if inward_center_candidate:
|
||||
self.corner_object_430_noncenter_inward_frames[t_id] = 0
|
||||
prev_yv_rel = self.corner_object_430_prev_yv_rel.get(t_id, hist_yv_rel)
|
||||
yv_rel = (1.0 - CORNER_OBJECT_430_YVREL_ALPHA) * prev_yv_rel + CORNER_OBJECT_430_YVREL_ALPHA * hist_yv_rel
|
||||
else:
|
||||
noncenter_frames = self.corner_object_430_noncenter_inward_frames.get(t_id, 0) + 1
|
||||
self.corner_object_430_noncenter_inward_frames[t_id] = noncenter_frames
|
||||
if noncenter_frames <= CORNER_OBJECT_430_EARLY_INWARD_NONCENTER_FRAMES:
|
||||
prev_yv_rel = self.corner_object_430_prev_yv_rel.get(t_id, hist_yv_rel)
|
||||
yv_rel = (1.0 - CORNER_OBJECT_430_YVREL_ALPHA) * prev_yv_rel + CORNER_OBJECT_430_YVREL_ALPHA * hist_yv_rel
|
||||
else:
|
||||
yv_rel = 0.0
|
||||
if not inward_center_candidate and abs(y_rel) < CORNER_OBJECT_430_SIDE_KEEP_ABS_YREL:
|
||||
y_rel = math.copysign(CORNER_OBJECT_430_SIDE_KEEP_ABS_YREL, y_rel)
|
||||
else:
|
||||
hist_yv_rel = 0.0
|
||||
yv_rel = 0.0
|
||||
self.corner_object_430_noncenter_inward_frames[t_id] = 0
|
||||
if abs(y_rel) < CORNER_OBJECT_430_SIDE_KEEP_ABS_YREL:
|
||||
y_rel = math.copysign(CORNER_OBJECT_430_SIDE_KEEP_ABS_YREL, y_rel)
|
||||
self.corner_object_430_prev_yv_rel[t_id] = yv_rel
|
||||
|
||||
self.pts[t_id].measured = True
|
||||
self.pts[t_id].trackId = t_id
|
||||
self.pts[t_id].dRel = d_rel
|
||||
self.pts[t_id].yRel = y_rel
|
||||
self.pts[t_id].vRel = v_rel
|
||||
self.pts[t_id].vLead = v_rel + self.v_ego
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = yv_rel
|
||||
|
||||
side_track_count = CORNER_OBJECT_430_MSG_COUNT_PER_SIDE * CORNER_OBJECT_430_SLOTS_PER_MSG
|
||||
for slot in range(side_track_count):
|
||||
t_id = CORNER_OBJECT_430_TRACK_ID_OFFSET + track_base + slot
|
||||
if t_id in active_t_ids:
|
||||
continue
|
||||
self.corner_object_430_prev_d_rel.pop(t_id, None)
|
||||
self.corner_object_430_prev_v_rel.pop(t_id, None)
|
||||
self.corner_object_430_prev_y_rel.pop(t_id, None)
|
||||
self.corner_object_430_prev_yv_rel.pop(t_id, None)
|
||||
self.corner_object_430_prev_code.pop(t_id, None)
|
||||
self.corner_object_430_history.pop(t_id, None)
|
||||
self.corner_object_430_noncenter_inward_frames.pop(t_id, None)
|
||||
self._clear_point(t_id)
|
||||
|
||||
|
||||
def _clear_point(self, t_id):
|
||||
self.pts[t_id].measured = False
|
||||
self.pts[t_id].dRel = 0
|
||||
self.pts[t_id].yRel = 0
|
||||
self.pts[t_id].vRel = 0
|
||||
self.pts[t_id].vLead = self.v_ego
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0
|
||||
|
||||
def _clear_corner_objects(self):
|
||||
for slot in range(CORNER_OBJECT_235_MSG_COUNT):
|
||||
self._clear_point(CORNER_OBJECT_235_TRACK_ID_OFFSET + slot)
|
||||
self.corner_object_track_ids.clear_source("corner235")
|
||||
|
||||
def _clear_corner_objects_180(self):
|
||||
for slot in range(CORNER_OBJECT_180_MSG_COUNT * CORNER_OBJECT_180_SLOTS_PER_MSG):
|
||||
self._clear_point(CORNER_OBJECT_180_TRACK_ID_OFFSET + slot)
|
||||
self.corner_object_track_ids.clear_source("corner180")
|
||||
|
||||
def _clear_corner_objects_430(self):
|
||||
self.corner_object_430_prev_d_rel.clear()
|
||||
self.corner_object_430_prev_v_rel.clear()
|
||||
self.corner_object_430_prev_y_rel.clear()
|
||||
self.corner_object_430_prev_yv_rel.clear()
|
||||
self.corner_object_430_prev_code.clear()
|
||||
self.corner_object_430_history.clear()
|
||||
self.corner_object_430_noncenter_inward_frames.clear()
|
||||
for slot in range(CORNER_OBJECT_430_MSG_COUNT_PER_SIDE * 2 * CORNER_OBJECT_430_SLOTS_PER_MSG):
|
||||
self._clear_point(CORNER_OBJECT_430_TRACK_ID_OFFSET + slot)
|
||||
|
||||
def _update_scc(self, updated_messages):
|
||||
cpt = self.rcp_scc.vl
|
||||
t_id = SCC_TID
|
||||
if self.canfd:
|
||||
dRel = cpt["SCC_CONTROL"]['ACC_ObjDist']
|
||||
vRel = cpt["SCC_CONTROL"]['ACC_ObjRelSpd']
|
||||
new_pts = abs(dRel - self.dRel_last) > 3 or abs(vRel - self.vRel_last) > 1
|
||||
vLead = vRel + self.v_ego
|
||||
valid = 0 < dRel < 150 and not new_pts #cpt["SCC_CONTROL"]['OBJ_STATUS'] and dRel < 150
|
||||
self.pts[t_id].measured = bool(valid)
|
||||
if not valid:
|
||||
self.pts[t_id].dRel = 0
|
||||
self.pts[t_id].yRel = 0
|
||||
self.pts[t_id].vRel = 0
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0
|
||||
else:
|
||||
self.pts[t_id].dRel = dRel
|
||||
self.pts[t_id].yRel = 0
|
||||
self.pts[t_id].vRel = vRel
|
||||
self.pts[t_id].vLead = vLead
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0 #float('nan')
|
||||
else:
|
||||
dRel = cpt["SCC11"]['ACC_ObjDist']
|
||||
vRel = cpt["SCC11"]['ACC_ObjRelSpd']
|
||||
new_pts = abs(dRel - self.dRel_last) > 3 or abs(vRel - self.vRel_last) > 1
|
||||
vLead = vRel + self.v_ego
|
||||
valid = cpt["SCC11"]['ACC_ObjStatus'] and dRel < 150 and not new_pts
|
||||
self.pts[t_id].measured = bool(valid)
|
||||
if not valid:
|
||||
self.pts[t_id].dRel = 0
|
||||
self.pts[t_id].yRel = 0
|
||||
self.pts[t_id].vRel = 0
|
||||
self.pts[t_id].vLead = self.pts[t_id].vRel + self.v_ego
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0
|
||||
else:
|
||||
self.pts[t_id].dRel = dRel
|
||||
self.pts[t_id].yRel = -cpt["SCC11"]['ACC_ObjLatPos'] # in car frame's y axis, left is negative
|
||||
self.pts[t_id].vRel = vRel
|
||||
self.pts[t_id].vLead = vLead
|
||||
self.pts[t_id].aRel = float('nan')
|
||||
self.pts[t_id].yvRel = 0 #float('nan')
|
||||
|
||||
self.dRel_last = dRel
|
||||
self.vRel_last = vRel
|
||||
|
||||
0
iqdbc_repo/iqdbc/car/hyundai/tests/print_platform_codes.py
Executable file → Normal file
0
iqdbc_repo/iqdbc/car/hyundai/tests/print_platform_codes.py
Executable file → Normal file
194
iqdbc_repo/iqdbc/car/hyundai/tests/test_ev_mode.py
Normal file
194
iqdbc_repo/iqdbc/car/hyundai/tests/test_ev_mode.py
Normal file
@@ -0,0 +1,194 @@
|
||||
import math
|
||||
|
||||
import pytest
|
||||
|
||||
from iqdbc.can import CANPacker, CANParser
|
||||
from iqdbc.car import Bus, gen_empty_fingerprint, structs
|
||||
from iqdbc.car.hyundai.carstate import CarState, EV_MODE_STATUS_TIMEOUT_NS, _get_ev_mode_state
|
||||
from iqdbc.car.hyundai.interface import CarInterface
|
||||
from iqdbc.car.hyundai.values import CANFD_HYBRID_STATUS_ADDR, CANFD_HYBRID_STATUS_DLC, CAR, DBC, EV_MODE_ACTIVE_VALUES, \
|
||||
EV_MODE_STATUS_ADDR, EV_MODE_STATUS_DLC, EV_MODE_STATUS_MSG, EV_MODE_STATUS_SIGNAL, \
|
||||
HyundaiExtFlags, HyundaiFlags
|
||||
from openpilot.common.params import Params
|
||||
|
||||
|
||||
def get_params(candidate, *, hybrid=True, hybrid_bus=0, hybrid_status=None, hybrid_status_bus=0,
|
||||
hybrid_status_dlc=CANFD_HYBRID_STATUS_DLC, status_bus=0, status_dlc=EV_MODE_STATUS_DLC):
|
||||
Params().put_int("HyundaiCameraSCC", 1)
|
||||
Params().put_int("CanfdHDA2", 1)
|
||||
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if hybrid:
|
||||
fingerprint[hybrid_bus][0x105] = 32
|
||||
if hybrid_status is None:
|
||||
hybrid_status = hybrid
|
||||
if hybrid_status:
|
||||
fingerprint[hybrid_status_bus][CANFD_HYBRID_STATUS_ADDR] = hybrid_status_dlc
|
||||
if status_bus is not None:
|
||||
fingerprint[status_bus][EV_MODE_STATUS_ADDR] = status_dlc
|
||||
return CarInterface.get_params(candidate, fingerprint, [], False, False, False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("candidate", "hybrid", "status_bus", "status_dlc", "expected"), (
|
||||
(CAR.HYUNDAI_SANTAFE_MX5_HEV, True, 0, 32, True),
|
||||
(CAR.HYUNDAI_SANTAFE_MX5_HEV, False, 0, 32, False),
|
||||
(CAR.HYUNDAI_SANTAFE_MX5_HEV, True, None, 32, False),
|
||||
(CAR.HYUNDAI_SANTAFE_MX5_HEV, True, 1, 32, False),
|
||||
(CAR.HYUNDAI_SANTAFE_MX5_HEV, True, 0, 16, False),
|
||||
(CAR.KIA_SORENTO_4TH_GEN, False, None, 32, False),
|
||||
# Shared ICE/HEV/PHEV candidates rely on the observed ECAN capability frames, not their model name.
|
||||
(CAR.HYUNDAI_TUCSON_4TH_GEN, True, 0, 32, True),
|
||||
(CAR.HYUNDAI_TUCSON_4TH_GEN, False, 0, 32, False),
|
||||
(CAR.KIA_SORENTO_HEV_4TH_GEN, True, 0, 32, True),
|
||||
(CAR.HYUNDAI_KONA_HEV_2ND_GEN, True, 0, 32, True),
|
||||
(CAR.HYUNDAI_KONA_HEV_2ND_GEN, False, 0, 32, False),
|
||||
(CAR.HYUNDAI_ELANTRA_HEV_2021, True, 0, 32, False),
|
||||
))
|
||||
def test_ev_mode_capability(candidate, hybrid, status_bus, status_dlc, expected):
|
||||
CP = get_params(candidate, hybrid=hybrid, status_bus=status_bus, status_dlc=status_dlc)
|
||||
assert bool(CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("hybrid_status_bus", "hybrid_status_dlc"), (
|
||||
(1, CANFD_HYBRID_STATUS_DLC),
|
||||
(0, 16),
|
||||
))
|
||||
def test_ev_mode_capability_requires_ecan_hybrid_status_dlc32(hybrid_status_bus, hybrid_status_dlc):
|
||||
CP = get_params(CAR.HYUNDAI_SANTAFE_MX5_HEV, hybrid_status_bus=hybrid_status_bus,
|
||||
hybrid_status_dlc=hybrid_status_dlc)
|
||||
|
||||
assert not bool(CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230)
|
||||
|
||||
|
||||
def test_0x105_and_ev_status_without_0xfa_do_not_enable_ev_mode():
|
||||
CP = get_params(CAR.HYUNDAI_TUCSON_4TH_GEN, hybrid=True, hybrid_status=False)
|
||||
|
||||
assert bool(CP.flags & HyundaiFlags.HYBRID)
|
||||
assert not bool(CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230)
|
||||
|
||||
|
||||
def test_ev_mode_display_capability_does_not_change_hybrid_safety_classification():
|
||||
CP = get_params(CAR.HYUNDAI_TUCSON_4TH_GEN, hybrid=False, hybrid_status=True)
|
||||
|
||||
assert not bool(CP.flags & HyundaiFlags.HYBRID)
|
||||
assert bool(CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230)
|
||||
|
||||
|
||||
def test_ev_mode_capability_uses_the_detected_ecan_offset():
|
||||
CP = get_params(CAR.KIA_SORENTO_HEV_4TH_GEN, hybrid_bus=4, hybrid_status_bus=4, status_bus=4)
|
||||
|
||||
assert bool(CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230)
|
||||
|
||||
|
||||
def test_ev_mode_parser_registration_is_capability_gated():
|
||||
supported = get_params(CAR.HYUNDAI_SANTAFE_MX5_HEV)
|
||||
unsupported = get_params(CAR.KIA_SORENTO_4TH_GEN, hybrid=False, status_bus=1, status_dlc=16)
|
||||
|
||||
supported_parser = CarState.get_can_parsers_canfd(None, supported)[Bus.pt]
|
||||
unsupported_parser = CarState.get_can_parsers_canfd(None, unsupported)[Bus.pt]
|
||||
|
||||
assert EV_MODE_STATUS_ADDR in supported_parser.addresses
|
||||
assert supported_parser.message_states[EV_MODE_STATUS_ADDR].ignore_alive
|
||||
assert supported_parser.message_states[EV_MODE_STATUS_ADDR].ignore_counter
|
||||
assert EV_MODE_STATUS_ADDR not in unsupported_parser.addresses
|
||||
|
||||
|
||||
def test_sorento_ice_corner_radar_status_does_not_enable_ev_mode():
|
||||
Params().put_int("HyundaiCameraSCC", 1)
|
||||
Params().put_int("CanfdHDA2", 1)
|
||||
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[1][0x230] = 16 # Actual Sorento ICE ACAN corner-radar status frame.
|
||||
CP = CarInterface.get_params(CAR.KIA_SORENTO_4TH_GEN, fingerprint, [], False, False, False)
|
||||
parser = CarState.get_can_parsers_canfd(None, CP)[Bus.pt]
|
||||
|
||||
assert not bool(CP.extFlags & HyundaiExtFlags.EV_MODE_STATUS_230)
|
||||
assert EV_MODE_STATUS_ADDR not in parser.addresses
|
||||
|
||||
|
||||
def test_ev_mode_state_requires_a_fresh_dlc32_frame():
|
||||
CP = get_params(CAR.HYUNDAI_SANTAFE_MX5_HEV)
|
||||
parser = CarState.get_can_parsers_canfd(None, CP)[Bus.pt]
|
||||
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
|
||||
|
||||
assert _get_ev_mode_state(parser) == (False, False)
|
||||
|
||||
timestamp = 1_000_000_000
|
||||
wrong_bus_short_status = (EV_MODE_STATUS_ADDR, b"\x00" * 16, 1)
|
||||
parser.update([timestamp, [wrong_bus_short_status]])
|
||||
assert _get_ev_mode_state(parser) == (False, False)
|
||||
|
||||
ev_active = packer.make_can_msg(EV_MODE_STATUS_MSG, parser.bus, {"COUNTER": 1, EV_MODE_STATUS_SIGNAL: 6})
|
||||
parser.update([timestamp + 100_000_000, [ev_active]])
|
||||
assert _get_ev_mode_state(parser) == (True, True)
|
||||
|
||||
ev_inactive = packer.make_can_msg(EV_MODE_STATUS_MSG, parser.bus, {"COUNTER": 2, EV_MODE_STATUS_SIGNAL: 3})
|
||||
parser.update([timestamp + 200_000_000, [ev_inactive]])
|
||||
assert _get_ev_mode_state(parser) == (False, True)
|
||||
|
||||
parser.dat[EV_MODE_STATUS_ADDR] = b"\x00" * 16
|
||||
assert _get_ev_mode_state(parser) == (False, False)
|
||||
|
||||
parser.dat[EV_MODE_STATUS_ADDR] = ev_inactive[1]
|
||||
parser.update([timestamp + 200_000_000 + EV_MODE_STATUS_TIMEOUT_NS + 1, []])
|
||||
assert not parser.bus_timeout
|
||||
assert _get_ev_mode_state(parser) == (False, False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", range(16))
|
||||
def test_ev_mode_enum_mapping(mode):
|
||||
CP = get_params(CAR.HYUNDAI_SANTAFE_MX5_HEV)
|
||||
parser = CarState.get_can_parsers_canfd(None, CP)[Bus.pt]
|
||||
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
|
||||
msg = packer.make_can_msg(EV_MODE_STATUS_MSG, parser.bus, {"COUNTER": mode, EV_MODE_STATUS_SIGNAL: mode})
|
||||
|
||||
parser.update([1_000_000_000, [msg]])
|
||||
|
||||
assert int(parser.vl[EV_MODE_STATUS_MSG][EV_MODE_STATUS_SIGNAL]) == mode
|
||||
assert _get_ev_mode_state(parser) == (mode in EV_MODE_ACTIVE_VALUES, True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("payload", "expected_mode", "expected_active"), (
|
||||
("758139048402000000000000000000000000d3009805001c24000000c05dc80f", 1, True),
|
||||
("4d466f048402000000000000000000000000bf007408001c24000000c05dc80f", 2, True),
|
||||
("32206e048402000000000000000000000000c9007418001c24000000c05dc80f", 6, True),
|
||||
# Route 455 mode 3 was a false positive with the old single-bit 0x230 interpretation.
|
||||
("4f935e0484020000000000000000000000004400640d001c10000000c05dc40f", 3, False),
|
||||
("066558048402000000000000000000000000c4003020001c24000000c05dc80f", 8, False),
|
||||
("059683048402000000000000000000000000a1008425001c24000000c05dc80f", 9, False),
|
||||
("011305048402000000000000000000000000d600a829001c24000000c05dc80f", 10, False),
|
||||
))
|
||||
def test_ev_mode_dbc_decodes_real_mx5_frames(payload, expected_mode, expected_active):
|
||||
parser = CANParser("hyundai_canfd_generated", [(EV_MODE_STATUS_MSG, math.nan)], 0)
|
||||
updated = parser.update([1_000_000_000, [(EV_MODE_STATUS_ADDR, bytes.fromhex(payload), 0)]])
|
||||
|
||||
assert updated == {EV_MODE_STATUS_ADDR}
|
||||
assert int(parser.vl[EV_MODE_STATUS_MSG][EV_MODE_STATUS_SIGNAL]) == expected_mode
|
||||
assert _get_ev_mode_state(parser) == (expected_active, True)
|
||||
|
||||
|
||||
def test_ev_mode_rejects_checksum_corruption():
|
||||
CP = get_params(CAR.HYUNDAI_SANTAFE_MX5_HEV)
|
||||
parser = CarState.get_can_parsers_canfd(None, CP)[Bus.pt]
|
||||
payload = bytearray.fromhex("32206e048402000000000000000000000000c9007418001c24000000c05dc80f")
|
||||
payload[-1] ^= 1
|
||||
|
||||
parser.update([1_000_000_000, [(EV_MODE_STATUS_ADDR, bytes(payload), parser.bus)]])
|
||||
|
||||
assert EV_MODE_STATUS_ADDR not in parser.dat
|
||||
assert _get_ev_mode_state(parser) == (False, False)
|
||||
|
||||
|
||||
def test_ev_mode_fields_default_invalid():
|
||||
state = structs.CarState()
|
||||
assert not state.evModeActive
|
||||
assert not state.evModeValid
|
||||
|
||||
|
||||
def test_ev_mode_parser_is_optional_for_can_validity():
|
||||
CP = get_params(CAR.HYUNDAI_SANTAFE_MX5_HEV)
|
||||
parser = CarState.get_can_parsers_canfd(None, CP)[Bus.pt]
|
||||
state = parser.message_states[EV_MODE_STATUS_ADDR]
|
||||
|
||||
assert state.ignore_alive
|
||||
assert state.ignore_counter
|
||||
@@ -6,13 +6,11 @@ from iqdbc.car import gen_empty_fingerprint
|
||||
from iqdbc.car.structs import CarParams
|
||||
from iqdbc.car.fw_versions import build_fw_dict
|
||||
from iqdbc.car.hyundai.interface import CarInterface
|
||||
from iqdbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from iqdbc.car.hyundai.radar_interface import RADAR_START_ADDR
|
||||
from iqdbc.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, \
|
||||
HyundaiFlags, get_platform_codes, HyundaiSafetyFlags, \
|
||||
NON_SCC_CAR
|
||||
from iqdbc.car.hyundai.values import CANFD_CAR, CAN_GEARS, CAR, CHECKSUM, DATE_FW_ECUS, \
|
||||
HYBRID_CAR, EV_CAR, FW_QUERY_CONFIG, LEGACY_SAFETY_MODE_CAR, \
|
||||
PLATFORM_CODE_ECUS, HYUNDAI_VERSION_REQUEST_LONG, \
|
||||
HyundaiFlags, get_platform_codes, HyundaiSafetyFlags
|
||||
from iqdbc.car.hyundai.fingerprints import FW_VERSIONS
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
@@ -45,16 +43,8 @@ CANFD_EXPECTED_ECUS = {Ecu.fwdCamera, Ecu.fwdRadar}
|
||||
|
||||
|
||||
class TestHyundaiFingerprint:
|
||||
def test_feature_detection(self):
|
||||
# LKA steering
|
||||
for lka_steering in (True, False):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if lka_steering:
|
||||
cam_can = CanBus(None, fingerprint).CAM
|
||||
fingerprint[cam_can] = [0x50, 0x110] # LKA steering messages
|
||||
CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False)
|
||||
assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEERING) == lka_steering
|
||||
|
||||
def test_feature_detection(self, monkeypatch, tmp_path):
|
||||
monkeypatch.setenv("PARAMS_ROOT", str(tmp_path))
|
||||
# radar available
|
||||
for radar in (True, False):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
@@ -74,19 +64,20 @@ class TestHyundaiFingerprint:
|
||||
# Test no EV/HEV in any gear lists (should all use ELECT_GEAR)
|
||||
assert set.union(*CAN_GEARS.values()) & (HYBRID_CAR | EV_CAR) == set()
|
||||
|
||||
# Test CAN FD car not in CAN feature lists
|
||||
can_specific_feature_list = set.union(*CAN_GEARS.values(), *CHECKSUM.values(), LEGACY_SAFETY_MODE_CAR, UNSUPPORTED_LONGITUDINAL_CAR, CAMERA_SCC_CAR)
|
||||
# Test CAN FD cars are not classified with classic-CAN-only parsing or safety modes.
|
||||
can_specific_feature_list = set.union(*CAN_GEARS.values(), *CHECKSUM.values(), LEGACY_SAFETY_MODE_CAR)
|
||||
for car_model in CANFD_CAR:
|
||||
assert car_model not in can_specific_feature_list, "CAN FD car unexpectedly found in a CAN feature list"
|
||||
|
||||
def test_hybrid_ev_sets(self):
|
||||
assert HYBRID_CAR & EV_CAR == set(), "Shared cars between hybrid and EV"
|
||||
assert CANFD_CAR & HYBRID_CAR == set(), "Hard coding CAN FD cars as hybrid is no longer supported"
|
||||
assert HYBRID_CAR <= set(CAR)
|
||||
assert EV_CAR <= set(CAR)
|
||||
|
||||
def test_canfd_ecu_whitelist(self):
|
||||
# Asserts only expected Ecus can exist in database for CAN-FD cars
|
||||
for car_model in CANFD_CAR:
|
||||
ecus = {fw[0] for fw in FW_VERSIONS[car_model].keys()}
|
||||
ecus = {fw[0] for fw in FW_VERSIONS.get(car_model, {}).keys()}
|
||||
ecus_not_in_whitelist = ecus - CANFD_EXPECTED_ECUS
|
||||
ecu_strings = ", ".join([f"Ecu.{ecu}" for ecu in ecus_not_in_whitelist])
|
||||
assert len(ecus_not_in_whitelist) == 0, \
|
||||
@@ -158,8 +149,6 @@ class TestHyundaiFingerprint:
|
||||
continue
|
||||
if platform_code_ecu == Ecu.eps and car_model in no_eps_platforms:
|
||||
continue
|
||||
if car_model in NON_SCC_CAR:
|
||||
continue
|
||||
assert platform_code_ecu in [e[0] for e in ecus]
|
||||
|
||||
def test_fw_format(self, subtests):
|
||||
@@ -174,9 +163,6 @@ class TestHyundaiFingerprint:
|
||||
if ecu[0] not in PLATFORM_CODE_ECUS:
|
||||
continue
|
||||
|
||||
if car_model in NON_SCC_CAR:
|
||||
continue
|
||||
|
||||
codes = set()
|
||||
for fw in fws:
|
||||
result = get_platform_codes([fw])
|
||||
@@ -225,15 +211,6 @@ class TestHyundaiFingerprint:
|
||||
(b"ON-S9100", b"190405"), (b"ON-S9100", b"190720")}
|
||||
|
||||
def test_fuzzy_excluded_platforms(self):
|
||||
# Asserts a list of platforms that will not fuzzy fingerprint with platform codes due to them being shared.
|
||||
# This list can be shrunk as we combine platforms and detect features
|
||||
excluded_platforms = {
|
||||
CAR.GENESIS_G70, # shared platform code, part number, and date
|
||||
CAR.GENESIS_G70_2020,
|
||||
}
|
||||
excluded_platforms |= CANFD_CAR - EV_CAR - CANFD_FUZZY_WHITELIST # shared platform codes
|
||||
excluded_platforms |= NO_DATES_PLATFORMS # date codes are required to match
|
||||
|
||||
platforms_with_shared_codes = set()
|
||||
for platform, fw_by_addr in FW_VERSIONS.items():
|
||||
car_fw = []
|
||||
@@ -243,9 +220,6 @@ class TestHyundaiFingerprint:
|
||||
car_fw.append(CarParams.CarFw(ecu=ecu_name, fwVersion=fw, address=addr,
|
||||
subAddress=0 if sub_addr is None else sub_addr))
|
||||
|
||||
if platform in NON_SCC_CAR:
|
||||
continue
|
||||
|
||||
CP = CarParams(carFw=car_fw)
|
||||
matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(build_fw_dict(CP.carFw), CP.carVin, FW_VERSIONS)
|
||||
if len(matches) == 1:
|
||||
@@ -253,4 +227,6 @@ class TestHyundaiFingerprint:
|
||||
else:
|
||||
platforms_with_shared_codes.add(platform)
|
||||
|
||||
assert platforms_with_shared_codes == excluded_platforms
|
||||
# A unique fuzzy match must always resolve back to the platform that supplied the firmware.
|
||||
# Ambiguity is expected for shared platform codes and for platforms without parseable dates.
|
||||
assert {CAR.GENESIS_G70, CAR.GENESIS_G70_2020} <= platforms_with_shared_codes
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
from iqdbc.can import CANParser, CANPacker
|
||||
from iqdbc.car import Bus
|
||||
from iqdbc.car.hyundai import hyundaican
|
||||
from iqdbc.car.hyundai.values import CAR, DBC
|
||||
|
||||
|
||||
class DummyHudControl:
|
||||
leadDistanceBars = 3
|
||||
leadVisible = True
|
||||
|
||||
|
||||
class DummyLeadData:
|
||||
lead_visible = False
|
||||
lead_rel_speed = -7
|
||||
lead_distance = 42
|
||||
object_gap = 5
|
||||
object_rel_gap = 2
|
||||
|
||||
|
||||
class DummyTuning:
|
||||
comfort_band_upper = 0.2
|
||||
comfort_band_lower = 0.3
|
||||
jerk_upper = 1.7
|
||||
jerk_lower = 1.2
|
||||
desired_accel = 0.4
|
||||
actual_accel = 0.3
|
||||
stopping = False
|
||||
|
||||
|
||||
class DummyCP:
|
||||
carFingerprint = CAR.HYUNDAI_PALISADE
|
||||
flags = 0
|
||||
|
||||
|
||||
def _decode(msg_name: str, addr: int, dat: bytes):
|
||||
cp = CANParser(DBC[CAR.HYUNDAI_PALISADE][Bus.pt], [(msg_name, 0)], 0)
|
||||
cp.update([(0, [(addr, dat, 0)])])
|
||||
return cp.vl[msg_name]
|
||||
|
||||
|
||||
def test_palisade_uses_stock_scc_surrogates():
|
||||
packer = CANPacker(DBC[CAR.HYUNDAI_PALISADE][Bus.pt])
|
||||
cp = DummyCP()
|
||||
hud = DummyHudControl()
|
||||
tuning = DummyTuning()
|
||||
lead = DummyLeadData()
|
||||
|
||||
scc11 = hyundaican.create_acc_commands(
|
||||
packer, True, 0.5, 3.0, 1, lead, hud, 72, False, False, True, cp, False, tuning
|
||||
)[0]
|
||||
scc14 = hyundaican.create_acc_commands(
|
||||
packer, True, 0.5, 3.0, 1, lead, hud, 72, False, False, True, cp, False, tuning
|
||||
)[2]
|
||||
|
||||
scc11_vals = _decode("SCC11", scc11[0], scc11[1])
|
||||
assert scc11_vals["ObjValid"] == 1
|
||||
assert scc11_vals["ACC_ObjStatus"] == 1
|
||||
assert scc11_vals["ACC_ObjDist"] == 1
|
||||
|
||||
scc14_vals = _decode("SCC14", scc14[0], scc14[1])
|
||||
assert "ObjDistStat" not in scc14_vals or scc14_vals["ObjDistStat"] == 0
|
||||
41
iqdbc_repo/iqdbc/car/hyundai/tests/test_integration.py
Normal file
41
iqdbc_repo/iqdbc/car/hyundai/tests/test_integration.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import pytest
|
||||
|
||||
from iqdbc.car import gen_empty_fingerprint, structs
|
||||
from iqdbc.car.hyundai.interface import CarInterface
|
||||
from iqdbc.car.hyundai.values import CAR
|
||||
|
||||
|
||||
@pytest.mark.parametrize("candidate", list(CAR), ids=lambda candidate: candidate.value)
|
||||
@pytest.mark.parametrize("alpha_long", (False, True), ids=("stock_long", "openpilot_long"))
|
||||
def test_all_platform_state_controller_and_radar(candidate, alpha_long, monkeypatch, tmp_path):
|
||||
"""Every declared HKG platform must initialize and execute one complete interface cycle."""
|
||||
monkeypatch.setenv("PARAMS_ROOT", str(tmp_path / candidate.value))
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
|
||||
cp = CarInterface.get_params(candidate, fingerprint, [], alpha_long, False, False)
|
||||
cp_iq = CarInterface.get_params_iq(cp, candidate, fingerprint, [], alpha_long, False, False)
|
||||
interface = CarInterface(cp, cp_iq)
|
||||
|
||||
state, state_iq = interface.update([])
|
||||
actuators, can_sends = interface.apply(structs.CarControl().as_reader(), structs.IQCarControl())
|
||||
radar = interface.RadarInterface(cp, cp_iq)
|
||||
radar_result = radar.update([])
|
||||
|
||||
assert state.vEgo == 0.0
|
||||
assert state_iq is not None
|
||||
assert actuators is not None
|
||||
assert isinstance(can_sends, list)
|
||||
assert radar_result is None
|
||||
|
||||
|
||||
def test_parameter_defaults_do_not_require_persisted_fingerprint(monkeypatch, tmp_path):
|
||||
"""A clean installation must not crash when carrotpilot-specific Params have not been written yet."""
|
||||
monkeypatch.setenv("PARAMS_ROOT", str(tmp_path))
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
|
||||
cp = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False)
|
||||
cp_iq = CarInterface.get_params_iq(cp, CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False)
|
||||
interface = CarInterface(cp, cp_iq)
|
||||
|
||||
state, _ = interface.update([])
|
||||
assert state.vEgo == 0.0
|
||||
326
iqdbc_repo/iqdbc/car/hyundai/tests/test_radar.py
Normal file
326
iqdbc_repo/iqdbc/car/hyundai/tests/test_radar.py
Normal file
@@ -0,0 +1,326 @@
|
||||
import math
|
||||
|
||||
import pytest
|
||||
|
||||
from iqdbc.can import CANParser
|
||||
from iqdbc.car import Bus, structs
|
||||
import iqdbc.car.hyundai.hyundaicanfd as hyundaicanfd
|
||||
import iqdbc.car.hyundai.radar_interface as radar_interface_module
|
||||
from iqdbc.car.hyundai.radar_interface import (
|
||||
CORNER_OBJECT_STABLE_TRACK_ID_START,
|
||||
RADAR_MSG_COUNT3,
|
||||
RADAR_MSG_COUNT4,
|
||||
RADAR_START_ADDR_CANFD3,
|
||||
CornerObjectTrackIdManager,
|
||||
RadarInterface,
|
||||
corner_object_position_valid,
|
||||
)
|
||||
from iqdbc.car.hyundai.values import CAR, HyundaiExtFlags, HyundaiFlags
|
||||
|
||||
|
||||
class TestDensoRadar:
|
||||
@staticmethod
|
||||
def parse(addr, dat):
|
||||
name = f"RADAR_TRACK_{addr:x}"
|
||||
parser = CANParser("hyundai_kia_denso_front_radar_generated", [(name, 20)], 1)
|
||||
parser.update([0, [(addr, bytes.fromhex(dat), 1)]])
|
||||
return parser.vl[name]
|
||||
|
||||
def test_active_track_signals(self):
|
||||
# Person walking toward the parked car, left of the camera center.
|
||||
track = self.parse(0x503, "bc047efcc1fe8b00")
|
||||
|
||||
assert track["LONG_DIST"] == pytest.approx(7.1875)
|
||||
assert track["LAT_DIST"] == pytest.approx(-1.625)
|
||||
assert track["REL_SPEED"] == pytest.approx(-0.734375)
|
||||
assert track["OBJECT_STATE"] == 3
|
||||
|
||||
def test_empty_track(self):
|
||||
track = self.parse(0x507, "53fff80000000081")
|
||||
|
||||
assert track["LONG_DIST"] == pytest.approx(409.55)
|
||||
assert track["LAT_DIST"] == 0
|
||||
assert track["REL_SPEED"] == 0
|
||||
assert track["OBJECT_STATE"] == 0
|
||||
|
||||
def test_long_range_lateral_distance(self):
|
||||
# Real driving sample: treating the signed field as -12 degrees would put
|
||||
# this target about 34 m sideways at 161 m. It is instead -3.0 m lateral.
|
||||
track = self.parse(0x506, "b664eafa00cd230b")
|
||||
|
||||
assert track["LONG_DIST"] == pytest.approx(161.4625)
|
||||
assert track["LAT_DIST"] == pytest.approx(-3.0)
|
||||
assert track["OBJECT_STATE"] == 3
|
||||
|
||||
def test_parser_selection_and_point_conversion(self, monkeypatch):
|
||||
class FakeParams:
|
||||
def get_int(self, key):
|
||||
return 1 if key == "EnableRadarTracks" else 0
|
||||
|
||||
monkeypatch.setattr(radar_interface_module, "Params", FakeParams)
|
||||
cp = structs.CarParams()
|
||||
cp.carFingerprint = CAR.KIA_SORENTO
|
||||
cp.flags = 0
|
||||
cp.extFlags = HyundaiExtFlags.RADAR_GROUP4.value
|
||||
cp.radarUnavailable = False
|
||||
cp.safetyConfigs = [structs.CarParams.SafetyConfig()]
|
||||
|
||||
radar_interface = RadarInterface(cp)
|
||||
|
||||
assert radar_interface.radar_group4
|
||||
assert RADAR_MSG_COUNT4 == 8
|
||||
assert radar_interface.radar_msg_count == RADAR_MSG_COUNT4
|
||||
assert radar_interface.trigger_msg_tracks == 0x507
|
||||
|
||||
active_dat = bytes.fromhex("bc047efcc1fe8b00")
|
||||
empty_dat = bytes.fromhex("bcfff80000000081")
|
||||
packets = [(addr, active_dat if addr == 0x503 else empty_dat, 1) for addr in range(0x500, 0x508)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
point = next(point for point in radar_data.points if point.trackId == 35)
|
||||
|
||||
assert point.measured
|
||||
assert point.dRel == pytest.approx(7.1875)
|
||||
assert point.yRel == pytest.approx(1.625)
|
||||
assert point.vRel == pytest.approx(-0.734375)
|
||||
assert math.isnan(point.aRel)
|
||||
|
||||
# EN: Confirm that the long-range sample survives the filter and converts
|
||||
# radar-left-negative to openpilot-left-positive coordinates.
|
||||
# KO: 장거리 샘플의 필터 통과와 레이더 좌측 음수 좌표가 openpilot 좌측
|
||||
# 양수 좌표로 변환되는지 확인함.
|
||||
long_range_dat = bytes.fromhex("b664eafa00cd230b")
|
||||
packets = [(addr, long_range_dat if addr == 0x506 else empty_dat, 1) for addr in range(0x500, 0x508)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
point = next(point for point in radar_data.points if point.trackId == 38)
|
||||
|
||||
assert point.dRel == pytest.approx(161.4625)
|
||||
assert point.yRel == pytest.approx(3.0)
|
||||
|
||||
# EN: A state-0 raw detection must not enter a stable tracked-object slot.
|
||||
# KO: 상태 0인 raw detection이 안정적인 추적 객체 슬롯에 들어오지 않음을 확인함.
|
||||
raw_detection = bytes.fromhex("d702f4fc200000e4")
|
||||
packets = [(addr, raw_detection if addr == 0x503 else empty_dat, 1) for addr in range(0x500, 0x508)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
assert not radar_data.points
|
||||
|
||||
# EN: A real confirmed track beyond the former 205 m limit remains valid.
|
||||
# KO: 기존 205m 상한을 넘는 실제 확정 트랙도 유효하게 유지됨.
|
||||
confirmed_213m_track = bytes.fromhex("35854c0780f163e0")
|
||||
packets = [(addr, confirmed_213m_track if addr == 0x503 else empty_dat, 1) for addr in range(0x500, 0x508)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
point = next(point for point in radar_data.points if point.trackId == 35)
|
||||
assert point.dRel == pytest.approx(213.275)
|
||||
assert point.yRel == pytest.approx(-3.75)
|
||||
|
||||
# EN: The 325 m boundary is rejected, leaving ample separation from the
|
||||
# 409.55 m empty-slot sentinel.
|
||||
# KO: 325m 경계값을 제외해 409.55m 빈 슬롯 값과 충분한 간격을 확보함.
|
||||
boundary_track = bytes.fromhex("bccb200000000300")
|
||||
packets = [(addr, boundary_track if addr == 0x503 else empty_dat, 1) for addr in range(0x500, 0x508)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
assert not radar_data.points
|
||||
|
||||
# EN: The wider profile keeps a real stable track at 4.875 m, covering more
|
||||
# of the outer adjacent lane than the conservative 4.5 m profile.
|
||||
# KO: 넓어진 필터에서 4.875m의 실제 안정 트랙을 유지해 보수적인 4.5m
|
||||
# 설정보다 바깥쪽 인접 차선을 더 넓게 포함함.
|
||||
outer_lane_track = bytes.fromhex("d80b66f640000300")
|
||||
packets = [(addr, outer_lane_track if addr == 0x503 else empty_dat, 1) for addr in range(0x500, 0x508)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
point = next(point for point in radar_data.points if point.trackId == 35)
|
||||
assert point.yRel == pytest.approx(4.875)
|
||||
|
||||
# EN: Tracks beyond the widened envelope are rejected as roadside clutter;
|
||||
# this payload differs only in lateral distance (-7.0 m).
|
||||
# KO: 넓어진 범위를 벗어난 트랙은 도로변 잡음으로 제외함. 이 payload는
|
||||
# 횡방향 거리(-7.0m)만 다름.
|
||||
far_side_reflection = bytes.fromhex("d80b66f200000300")
|
||||
packets = [(addr, far_side_reflection if addr == 0x503 else empty_dat, 1) for addr in range(0x500, 0x508)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
assert not radar_data.points
|
||||
|
||||
|
||||
class TestRadarGroup3:
|
||||
@staticmethod
|
||||
def parse(addr, dat):
|
||||
name = f"RADAR_TRACK_{addr:x}"
|
||||
parser = CANParser("hyundai_canfd_radar_generated", [(name, 20)], 1)
|
||||
parser.update([0, [(addr, bytes.fromhex(dat), 1)]])
|
||||
return parser.vl[name]
|
||||
|
||||
def test_group3_active_track(self):
|
||||
track = self.parse(0x406, "e1043b0f02590e692a227e16f80fe00f28fcc753a20a0000")
|
||||
|
||||
assert track["OBJECT_LENGTH"] == pytest.approx(4.4)
|
||||
assert track["LONG_DIST"] == pytest.approx(55.4)
|
||||
assert track["LAT_DIST"] == pytest.approx(-3.0)
|
||||
assert track["REL_SPEED"] == pytest.approx(4.4)
|
||||
|
||||
def test_group3_empty_track(self):
|
||||
track = self.parse(0x407, "c03d3b0000000000ff0700000000000000d0020000000000")
|
||||
|
||||
assert track["OBJECT_LENGTH"] == 0
|
||||
assert track["LONG_DIST"] == pytest.approx(204.7)
|
||||
assert track["LAT_DIST"] == 0
|
||||
assert track["REL_SPEED"] == 0
|
||||
|
||||
def test_group3_parser_selection(self, monkeypatch):
|
||||
class FakeParams:
|
||||
def get_int(self, key):
|
||||
return 1 if key == "EnableRadarTracks" else 0
|
||||
|
||||
monkeypatch.setattr(radar_interface_module, "Params", FakeParams)
|
||||
monkeypatch.setattr(hyundaicanfd, "Params", FakeParams)
|
||||
cp = structs.CarParams()
|
||||
cp.carFingerprint = next(car for car, dbc in radar_interface_module.DBC.items() if "hyundai_canfd" in dbc[Bus.pt])
|
||||
cp.flags = HyundaiFlags.CANFD.value
|
||||
cp.extFlags = HyundaiExtFlags.RADAR_GROUP3.value
|
||||
cp.radarUnavailable = False
|
||||
cp.safetyConfigs = [structs.CarParams.SafetyConfig()]
|
||||
|
||||
radar_interface = RadarInterface(cp)
|
||||
|
||||
assert radar_interface.radar_group3
|
||||
assert radar_interface.radar_start_addr == RADAR_START_ADDR_CANFD3
|
||||
assert radar_interface.radar_msg_count == RADAR_MSG_COUNT3
|
||||
assert radar_interface.trigger_msg_tracks == 0x41D
|
||||
|
||||
active_dat = bytes.fromhex("e1043b0f02590e692a227e16f80fe00f28fcc753a20a0000")
|
||||
empty_dat = bytes.fromhex("c03d3b0000000000ff0700000000000000d0020000000000")
|
||||
packets = [(addr, active_dat if addr == 0x406 else empty_dat, 1) for addr in range(0x400, 0x41E)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
point = next(point for point in radar_data.points if point.trackId == 38)
|
||||
|
||||
assert point.measured
|
||||
assert point.dRel == pytest.approx(53.1)
|
||||
assert point.yRel == pytest.approx(-3.0)
|
||||
assert point.vRel == pytest.approx(4.4)
|
||||
|
||||
|
||||
class TestCornerRadarObjectIdentity:
|
||||
@staticmethod
|
||||
def set_bits(data, start, size, value):
|
||||
for offset in range(size):
|
||||
bit = start + offset
|
||||
data[bit // 8] |= ((value >> offset) & 1) << (bit % 8)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"dbc,msg_name,addr,age_signal,id_signal,age_start,id_start",
|
||||
(
|
||||
("hyundai_canfd_corner_radar_180_generated", "CORNER_RADAR_180_OBJECTS_180", 0x180,
|
||||
"SLOT1_AGE", "SLOT1_OBJECT_ID", 32, 44),
|
||||
("hyundai_canfd_corner_radar_235_generated", "CORNER_RADAR_235_OBJECTS_235", 0x235,
|
||||
"OBJ_AGE", "OBJ_OBJECT_ID", 32, 44),
|
||||
),
|
||||
)
|
||||
def test_object_identity_signals(self, dbc, msg_name, addr, age_signal, id_signal, age_start, id_start):
|
||||
data = bytearray(32)
|
||||
self.set_bits(data, age_start, 8, 23)
|
||||
self.set_bits(data, id_start, 7, 46)
|
||||
parser = CANParser(dbc, [(msg_name, 33)], 1)
|
||||
parser.update([0, [(addr, bytes(data), 1)]])
|
||||
|
||||
assert parser.vl[msg_name][age_signal] == 23
|
||||
assert parser.vl[msg_name][id_signal] == 46
|
||||
|
||||
def test_track_id_survives_slot_move_and_resets_with_age(self):
|
||||
manager = CornerObjectTrackIdManager()
|
||||
first_id = manager.get_track_id("corner180", object_id=108, age=240)
|
||||
|
||||
assert first_id == CORNER_OBJECT_STABLE_TRACK_ID_START
|
||||
assert manager.get_track_id("corner180", object_id=108, age=241) == first_id
|
||||
assert manager.get_track_id("corner235", object_id=108, age=241) != first_id
|
||||
assert manager.get_track_id("corner180", object_id=108, age=2) != first_id
|
||||
|
||||
def test_clipped_side_object_position_is_valid(self):
|
||||
assert corner_object_position_valid(0.0, 2.8)
|
||||
assert corner_object_position_valid(25.0, 0.2)
|
||||
assert not corner_object_position_valid(0.0, 0.0)
|
||||
assert not corner_object_position_valid(0.0, 5.0)
|
||||
|
||||
|
||||
class TestCornerRadar430CandidateFilter:
|
||||
@staticmethod
|
||||
def slot_word(distance_raw, meta13=0, b2=10, b3=2):
|
||||
return distance_raw | (meta13 << 13) | (b2 << 16) | (b3 << 24)
|
||||
|
||||
@classmethod
|
||||
def message(cls, slots):
|
||||
words = [0x010d1f40] * 7
|
||||
for slot, word in slots.items():
|
||||
words[slot - 1] = word
|
||||
|
||||
dat = bytearray(32)
|
||||
for idx, word in enumerate(words):
|
||||
dat[4 + idx * 4:8 + idx * 4] = int(word).to_bytes(4, "little")
|
||||
return bytes(dat)
|
||||
|
||||
@staticmethod
|
||||
def build_interface(monkeypatch):
|
||||
class FakeParams:
|
||||
def get_int(self, key):
|
||||
return 1 if key == "EnableCornerRadar" else 0
|
||||
|
||||
monkeypatch.setattr(radar_interface_module, "Params", FakeParams)
|
||||
monkeypatch.setattr(hyundaicanfd, "Params", FakeParams)
|
||||
cp = structs.CarParams()
|
||||
cp.carFingerprint = next(car for car, dbc in radar_interface_module.DBC.items() if "hyundai_canfd" in dbc[Bus.pt])
|
||||
cp.flags = HyundaiFlags.CANFD.value
|
||||
cp.extFlags = HyundaiExtFlags.CORNER_RADAR_OBJECTS_430.value
|
||||
cp.radarUnavailable = True
|
||||
cp.safetyConfigs = [structs.CarParams.SafetyConfig()]
|
||||
return RadarInterface(cp)
|
||||
|
||||
@staticmethod
|
||||
def update_frames(radar_interface, packets, frames=5):
|
||||
radar_data = None
|
||||
for _ in range(frames):
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
return radar_data
|
||||
|
||||
def test_430_promotes_supported_neighbor_bins(self, monkeypatch):
|
||||
radar_interface = self.build_interface(monkeypatch)
|
||||
empty = self.message({})
|
||||
supported_bins = self.message({
|
||||
6: self.slot_word(1000),
|
||||
7: self.slot_word(1004),
|
||||
})
|
||||
packets = [(addr, supported_bins if addr == 0x436 else empty, 1) for addr in range(0x430, 0x438)]
|
||||
packets += [(addr, empty, 1) for addr in range(0x440, 0x448)]
|
||||
|
||||
radar_data = self.update_frames(radar_interface, packets)
|
||||
points = {point.trackId: point for point in radar_data.points}
|
||||
|
||||
assert points[300].measured
|
||||
assert points[300].dRel == pytest.approx(50.1)
|
||||
assert points[300].yRel == pytest.approx(2.0)
|
||||
assert points[300].yvRel == 0.0
|
||||
|
||||
def test_430_expires_noncenter_inward_yvrel(self, monkeypatch):
|
||||
radar_interface = self.build_interface(monkeypatch)
|
||||
empty = self.message({})
|
||||
frame_defs = (
|
||||
(0x431, 4, 5),
|
||||
(0x433, 3, 4),
|
||||
(0x435, 2, 3),
|
||||
(0x430, 5, 6),
|
||||
(0x432, 4, 5),
|
||||
(0x434, 3, 4),
|
||||
(0x436, 2, 3),
|
||||
)
|
||||
|
||||
radar_data = None
|
||||
for addr, first_slot, second_slot in frame_defs:
|
||||
msg = self.message({
|
||||
first_slot: self.slot_word(1000),
|
||||
second_slot: self.slot_word(1004),
|
||||
})
|
||||
packets = [(a, msg if a == addr else empty, 1) for a in range(0x430, 0x438)]
|
||||
packets += [(a, empty, 1) for a in range(0x440, 0x448)]
|
||||
radar_data = radar_interface.update([0, packets])
|
||||
radar_data = self.update_frames(radar_interface, packets, frames=3)
|
||||
points = {point.trackId: point for point in radar_data.points}
|
||||
|
||||
assert points[300].measured
|
||||
assert points[300].yRel == pytest.approx(2.0)
|
||||
assert points[300].yvRel == 0.0
|
||||
@@ -1,21 +1,37 @@
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from enum import IntFlag
|
||||
from enum import Enum, IntFlag
|
||||
|
||||
from iqdbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, uds
|
||||
from iqdbc.car.lateral import AngleSteeringLimits
|
||||
from iqdbc.car.common.conversions import Conversions as CV
|
||||
from iqdbc.car.structs import CarParams
|
||||
from iqdbc.car.docs_definitions import CarHarness, CarDocs, CarParts, SupportType
|
||||
from iqdbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column
|
||||
from iqdbc.car.fw_query_definitions import FwQueryConfig, Request, p16
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
|
||||
class CarControllerParams:
|
||||
ACCEL_MIN = -3.5 # m/s
|
||||
ACCEL_MAX = 2.0 # m/s
|
||||
ACCEL_MIN = -4.0 # m/s
|
||||
ACCEL_MAX = 2.5 # m/s
|
||||
ANGLE_LIMITS: AngleSteeringLimits = AngleSteeringLimits(
|
||||
# LKAS angle command is unlimited, but LFA is limited to 176.7 deg (but does not fault if requesting above)
|
||||
175, # deg
|
||||
# stock comma's
|
||||
#([0, 9, 16, 25], [1.4, 0.6, 0.4, 0.1]),
|
||||
#([0, 9, 16, 25], [1.4, 0.7, 0.5, 0.1]),
|
||||
([0, 9, 16, 25], [1.8, 1.6, 1.3, 0.8]),
|
||||
([0, 9, 16, 25], [2.4, 2.0, 1.6, 1.0]),
|
||||
#([0, 9, 16, 25], [1.6, 1.0, 0.6, 0.15]),
|
||||
#([0, 9, 16, 25], [2.0, 1.2, 0.8, 0.28]),
|
||||
)
|
||||
# Stock LFA system is seen sending 250 max, but for LKAS events it's 175 max.
|
||||
# 250 can at least achieve 4 m/s^2, 80 corresponds to ~2.5 m/s^2
|
||||
ANGLE_MAX_TORQUE = 200 # The maximum amount of torque that will be allowed
|
||||
ANGLE_MIN_TORQUE = 25 # equivalent to ~0.8 m/s^2 of torque (based on ANGLE_MAX_TORQUE) when overriding
|
||||
ANGLE_TORQUE_UP_RATE = 8 #2 # Indicates how fast the torque ramps up after user intervention.
|
||||
ANGLE_TORQUE_DOWN_RATE = 12 #4 Indicates how fast the torque ramps down during user intervention (handing off).
|
||||
|
||||
def __init__(self, CP):
|
||||
self.STEER_DELTA_UP = 3
|
||||
@@ -41,20 +57,17 @@ class CarControllerParams:
|
||||
CAR.KIA_OPTIMA_H, CAR.KIA_OPTIMA_H_G4_FL, CAR.KIA_SORENTO):
|
||||
self.STEER_MAX = 255
|
||||
|
||||
elif CP.carFingerprint in (CAR.HYUNDAI_SANTA_FE_PHEV_2022):
|
||||
self.STEER_MAX = 409
|
||||
# these cars have significantly more torque than most HKG; limit to 70% of max
|
||||
elif CP.flags & HyundaiFlags.ALT_LIMITS:
|
||||
self.STEER_MAX = 270
|
||||
self.STEER_DELTA_UP = 2
|
||||
self.STEER_DELTA_DOWN = 3
|
||||
|
||||
elif CP.flags & HyundaiFlags.ALT_LIMITS_2:
|
||||
self.STEER_MAX = 170
|
||||
self.STEER_MAX = 384
|
||||
self.STEER_DELTA_UP = 2
|
||||
self.STEER_DELTA_DOWN = 3
|
||||
|
||||
# Default for most HKG
|
||||
else:
|
||||
self.STEER_MAX = 384
|
||||
self.STEER_MAX = 409
|
||||
|
||||
|
||||
class HyundaiSafetyFlags(IntFlag):
|
||||
@@ -72,12 +85,7 @@ class HyundaiSafetyFlags(IntFlag):
|
||||
|
||||
class HyundaiFlags(IntFlag):
|
||||
# Dynamic Flags
|
||||
|
||||
# Default assumption: all cars use LFA (ADAS) steering from the camera.
|
||||
# CANFD_LKA_STEERING/CANFD_LKA_STEERING_ALT cars typically have both LKA (camera) and LFA (ADAS) steering messages,
|
||||
# with LKA commands forwarded to the ADAS DRV ECU.
|
||||
# Most HDA2 trims are assumed to be equipped with the ADAS DRV ECU, though some variants may not be equipped with one.
|
||||
CANFD_LKA_STEERING = 1
|
||||
CANFD_HDA2 = 1
|
||||
CANFD_ALT_BUTTONS = 2
|
||||
CANFD_ALT_GEARS = 2 ** 2
|
||||
CANFD_CAMERA_SCC = 2 ** 3
|
||||
@@ -87,7 +95,7 @@ class HyundaiFlags(IntFlag):
|
||||
CANFD_ALT_GEARS_2 = 2 ** 6
|
||||
SEND_LFA = 2 ** 7
|
||||
USE_FCA = 2 ** 8
|
||||
CANFD_LKA_STEERING_ALT = 2 ** 9
|
||||
CANFD_HDA2_ALT_STEERING = 2 ** 9
|
||||
|
||||
# these cars use a different gas signal
|
||||
HYBRID = 2 ** 10
|
||||
@@ -103,7 +111,7 @@ class HyundaiFlags(IntFlag):
|
||||
# The radar does SCC on these cars when HDA I, rather than the camera
|
||||
RADAR_SCC = 2 ** 14
|
||||
# The camera does SCC on these cars, rather than the radar
|
||||
CAMERA_SCC = 2 ** 15
|
||||
CAMERA_SCC = CANFD_CAMERA_SCC #2 ** 15
|
||||
CHECKSUM_CRC8 = 2 ** 16
|
||||
CHECKSUM_6B = 2 ** 17
|
||||
|
||||
@@ -122,23 +130,41 @@ class HyundaiFlags(IntFlag):
|
||||
|
||||
MIN_STEER_32_MPH = 2 ** 23
|
||||
|
||||
HAS_LDA_BUTTON = 2 ** 24
|
||||
ANGLE_CONTROL = 2 ** 24
|
||||
|
||||
FCEV = 2 ** 25
|
||||
|
||||
ALT_LIMITS_2 = 2 ** 26
|
||||
|
||||
CC_ONLY_CAR = 2 ** 31
|
||||
|
||||
class HyundaiExtFlags(IntFlag):
|
||||
NAVI_CLUSTER = 2 ** 2
|
||||
HAS_LFAHDA = 2 ** 4
|
||||
CANFD_GEARS_NONE = 2 ** 6
|
||||
RADAR_GROUP1 = 2 ** 7 # 0x210 radar group 1, 0x3A5 radar group 2
|
||||
CANFD_GEARS_69 = 2 ** 10
|
||||
RADAR_GROUP3 = 2 ** 11 # 0x400-0x41D radar object group
|
||||
CORNER_RADAR_OBJECTS_235 = 2 ** 12 # 0x230 status + 0x235-0x248 raw corner radar objects
|
||||
CORNER_RADAR_OBJECTS_180 = 2 ** 13 # 0x180-0x184 bus 1 two-slot raw corner/front radar objects
|
||||
CORNER_RADAR_OBJECTS_430 = 2 ** 14 # 0x430-0x437 left + 0x440-0x447 right IONIQ 9 corner radar bins
|
||||
RADAR_GROUP4 = 2 ** 15 # 0x500-0x507 Denso DNMWR006 stable radar tracks
|
||||
EV_MODE_STATUS_230 = 2 ** 16 # ECAN 0x230/DLC32 exposes the hybrid power-flow mode used for the EV indicator
|
||||
|
||||
class Footnote(Enum):
|
||||
CANFD = CarFootnote(
|
||||
"Requires a <a href=\"https://comma.ai/shop/can-fd-panda-kit\" target=\"_blank\">CAN FD panda kit</a> if not using " +
|
||||
"comma 3X for this <a href=\"https://en.wikipedia.org/wiki/CAN_FD\" target=\"_blank\">CAN FD car</a>.",
|
||||
Column.MODEL)
|
||||
|
||||
|
||||
@dataclass
|
||||
class HyundaiCarDocs(CarDocs):
|
||||
package: str = "Smart Cruise Control (SCC)"
|
||||
|
||||
|
||||
@dataclass
|
||||
class HyundaiNonSccCarDocs(CarDocs):
|
||||
package: str = "No Smart Cruise Control (Non-SCC)"
|
||||
support_type: SupportType = SupportType.COMMUNITY
|
||||
support_link: str = "community"
|
||||
def init_make(self, CP: CarParams):
|
||||
if CP.flags & HyundaiFlags.CANFD:
|
||||
self.footnotes.insert(0, Footnote.CANFD)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -153,20 +179,9 @@ class HyundaiPlatformConfig(PlatformConfig):
|
||||
self.specs = self.specs.override(minSteerSpeed=32 * CV.MPH_TO_MS)
|
||||
|
||||
|
||||
@dataclass
|
||||
class HyundaiNonSccPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: "hyundai_kia_generic"})
|
||||
|
||||
def init(self):
|
||||
self.iq_flags |= HyundaiFlagsIQ.NON_SCC
|
||||
|
||||
if self.flags & HyundaiFlags.MIN_STEER_32_MPH:
|
||||
self.specs = self.specs.override(minSteerSpeed=32 * CV.MPH_TO_MS)
|
||||
|
||||
|
||||
@dataclass
|
||||
class HyundaiCanFDPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: "hyundai_canfd_generated"})
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: "hyundai_canfd_generated", Bus.radar: 'hyundai_canfd_radar_generated'})
|
||||
|
||||
def init(self):
|
||||
self.flags |= HyundaiFlags.CANFD
|
||||
@@ -174,6 +189,10 @@ class HyundaiCanFDPlatformConfig(PlatformConfig):
|
||||
|
||||
class CAR(Platforms):
|
||||
# Hyundai
|
||||
HYUNDAI_AZERA_7TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Azera 2023-2024", "All", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=1700, wheelbase=2.895, steerRatio=16.5),
|
||||
)
|
||||
HYUNDAI_AZERA_6TH_GEN = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Azera 2022", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
CarSpecs(mass=1600, wheelbase=2.885, steerRatio=14.5),
|
||||
@@ -260,9 +279,9 @@ class CAR(Platforms):
|
||||
flags=HyundaiFlags.CLUSTER_GEARS | HyundaiFlags.ALT_LIMITS,
|
||||
)
|
||||
HYUNDAI_KONA_2022 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona 2022-23", car_parts=CarParts.common([CarHarness.hyundai_o]))],
|
||||
[HyundaiCarDocs("Hyundai Kona 2022", car_parts=CarParts.common([CarHarness.hyundai_o]))],
|
||||
CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2,
|
||||
flags=HyundaiFlags.CAMERA_SCC,
|
||||
)
|
||||
HYUNDAI_KONA_EV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Electric 2018-21", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
@@ -285,6 +304,11 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=1425, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.HYBRID | HyundaiFlags.ALT_LIMITS,
|
||||
)
|
||||
HYUNDAI_KONA_HEV_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Kona Hybrid 2024", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.HYBRID,
|
||||
)
|
||||
HYUNDAI_NEXO_1ST_GEN = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Nexo 2021", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))],
|
||||
CarSpecs(mass=3990 * CV.LB_TO_KG, wheelbase=2.79, steerRatio=14.19), # https://www.hyundainews.com/assets/documents/original/42768-2021NEXOProductGuideSpecs.pdf
|
||||
@@ -300,17 +324,17 @@ class CAR(Platforms):
|
||||
[HyundaiCarDocs("Hyundai Santa Fe 2021-23", "All", video="https://youtu.be/VnHzSTygTS4",
|
||||
car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
HYUNDAI_SANTA_FE.specs,
|
||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
)
|
||||
HYUNDAI_SANTA_FE_HEV_2022 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Santa Fe Hybrid 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
HYUNDAI_SANTA_FE.specs,
|
||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
||||
)
|
||||
HYUNDAI_SANTA_FE_PHEV_2022 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Santa Fe Plug-in Hybrid 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
HYUNDAI_SANTA_FE.specs,
|
||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
||||
)
|
||||
HYUNDAI_SONATA = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Sonata 2020-23", "All", video="https://www.youtube.com/watch?v=ix63r9kE3Fw",
|
||||
@@ -321,8 +345,14 @@ class CAR(Platforms):
|
||||
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
|
||||
|
||||
flags=HyundaiFlags.UNSUPPORTED_LONGITUDINAL | HyundaiFlags.TCU_GEARS,
|
||||
)
|
||||
HYUNDAI_SONATA_2024 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Sonata 2024-25", "All", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=1556, wheelbase=2.84, steerRatio=12.81),
|
||||
flags=HyundaiFlags.CAMERA_SCC,
|
||||
)
|
||||
HYUNDAI_STARIA_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Staria 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
CarSpecs(mass=2205, wheelbase=3.273, steerRatio=11.94), # https://www.hyundai.com/content/dam/hyundai/au/en/models/staria-load/premium-pip-update-2023/spec-sheet/STARIA_Load_Spec-Table_March_2023_v3.1.pdf
|
||||
@@ -362,11 +392,32 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65),
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
HYUNDAI_IONIQ_5_PE = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Hyundai IONIQ 5 PE (NE1)", car_parts=CarParts.common([CarHarness.hyundai_q])),
|
||||
HyundaiCarDocs("Hyundai Ioniq 5 PE (with HDA II) 2024", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])),
|
||||
],
|
||||
#CarSpecs(mass=2012, wheelbase=3.0, steerRatio=14.26, tireStiffnessFactor=0.65),
|
||||
CarSpecs(mass=2012, wheelbase=3.0, steerRatio=14.26, tireStiffnessFactor=1.0),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.ANGLE_CONTROL,
|
||||
)
|
||||
HYUNDAI_IONIQ_5_N = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Ioniq 5 N (with HDA II) 2024", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_m]))],
|
||||
CarSpecs(mass=2200, wheelbase=3.00, steerRatio=12.54),
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
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,
|
||||
)
|
||||
HYUNDAI_IONIQ_9 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Hyundai Ioniq 9", "All", car_parts=CarParts.common([CarHarness.hyundai_m])),
|
||||
],
|
||||
CarSpecs(mass=2505, wheelbase=3.13, steerRatio=16.02),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.ANGLE_CONTROL,
|
||||
)
|
||||
HYUNDAI_TUCSON_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Hyundai Tucson 2022", car_parts=CarParts.common([CarHarness.hyundai_n])),
|
||||
@@ -386,6 +437,37 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=1690, wheelbase=3.055, steerRatio=17), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
)
|
||||
HYUNDAI_CASPER = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Casper 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
CarSpecs(mass=1060, wheelbase=2.4, steerRatio=14.3), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner
|
||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.CHECKSUM_CRC8,
|
||||
)
|
||||
|
||||
HYUNDAI_CASPER_EV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Casper EV 2024", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
CarSpecs(mass=1355, wheelbase=2.58, steerRatio=14.3), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner
|
||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.EV
|
||||
)
|
||||
HYUNDAI_PORTER_II_EV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Porter II EV 2024", car_parts=CarParts.common([CarHarness.hyundai_h]))],
|
||||
CarSpecs(mass=1970, wheelbase=2.64, steerRatio=14.5),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.CC_ONLY_CAR,
|
||||
)
|
||||
HYUNDAI_SANTAFE_MX5 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Hyundai SANTAFE (MX5)", car_parts=CarParts.common([CarHarness.hyundai_k])),
|
||||
],
|
||||
CarSpecs(mass=1910, wheelbase=2.76, steerRatio=15.8, tireStiffnessFactor=0.82),
|
||||
flags=HyundaiFlags.ANGLE_CONTROL,
|
||||
)
|
||||
HYUNDAI_SANTAFE_MX5_HEV = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Hyundai SANTAFE HYBRID (MX5)", car_parts=CarParts.common([CarHarness.hyundai_k])),
|
||||
],
|
||||
HYUNDAI_SANTAFE_MX5.specs,
|
||||
flags=HyundaiFlags.ANGLE_CONTROL,
|
||||
)
|
||||
|
||||
|
||||
# Kia
|
||||
KIA_FORTE = HyundaiPlatformConfig(
|
||||
@@ -405,6 +487,18 @@ class CAR(Platforms):
|
||||
KIA_K5_2021.specs,
|
||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
||||
)
|
||||
KIA_K5_DL3_24 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia K5 2024", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_k])),
|
||||
],
|
||||
CarSpecs(mass=1553, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5),
|
||||
)
|
||||
KIA_K5_DL3_24_HEV = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia K5 Hybrid 2024", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_k])),
|
||||
],
|
||||
CarSpecs(mass=1553, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5),
|
||||
)
|
||||
KIA_K8_HEV_1ST_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K8 Hybrid (with HDA II) 2023", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q]))],
|
||||
# mass: https://carprices.ae/brands/kia/2023/k8/1.6-turbo-hybrid, steerRatio: guesstimate from K5 platform
|
||||
@@ -421,16 +515,13 @@ class CAR(Platforms):
|
||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.EV,
|
||||
)
|
||||
KIA_NIRO_EV_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia Niro EV (without HDA II) 2023-25", "All", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||
HyundaiCarDocs("Kia Niro EV (with HDA II) 2025", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_r])),
|
||||
],
|
||||
[HyundaiCarDocs("Kia Niro EV 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
KIA_NIRO_EV.specs,
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
KIA_NIRO_PHEV = HyundaiPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia Niro Hybrid 2018", min_enable_speed=10. * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_c])),
|
||||
HyundaiCarDocs("Kia Niro Hybrid 2018", "All", min_enable_speed=10. * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_c])),
|
||||
HyundaiCarDocs("Kia Niro Plug-in Hybrid 2018-19", "All", min_enable_speed=10. * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_c])),
|
||||
HyundaiCarDocs("Kia Niro Plug-in Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_d])),
|
||||
],
|
||||
@@ -471,7 +562,7 @@ class CAR(Platforms):
|
||||
# TODO: may support adjacent years. may have a non-zero minimum steering speed
|
||||
KIA_OPTIMA_H = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Optima Hybrid 2017", "Advanced Smart Cruise Control", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=3558 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5),
|
||||
CarSpecs(mass=3758 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5),
|
||||
flags=HyundaiFlags.HYBRID | HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_OPTIMA_H_G4_FL = HyundaiPlatformConfig(
|
||||
@@ -499,6 +590,7 @@ class CAR(Platforms):
|
||||
HyundaiCarDocs("Kia Sorento 2019", video="https://www.youtube.com/watch?v=Fkh3s6WHJz8", car_parts=CarParts.common([CarHarness.hyundai_e])),
|
||||
],
|
||||
CarSpecs(mass=1985, wheelbase=2.78, steerRatio=14.4 * 1.1), # 10% higher at the center seems reasonable
|
||||
dbc_dict={Bus.pt: "hyundai_kia_generic", Bus.radar: "hyundai_kia_denso_front_radar_generated"},
|
||||
flags=HyundaiFlags.CHECKSUM_6B | HyundaiFlags.UNSUPPORTED_LONGITUDINAL,
|
||||
)
|
||||
KIA_SORENTO_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
@@ -528,6 +620,11 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=1450, wheelbase=2.65, steerRatio=13.75, tireStiffnessFactor=0.5),
|
||||
flags=HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_EV4 = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Kia EV4 2025", "All", car_parts=CarParts.common([CarHarness.hyundai_q]))],
|
||||
CarSpecs(mass=1710, wheelbase=2.83, steerRatio=14.5, tireStiffnessFactor=0.65),
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
KIA_EV6 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia EV6 (Southeast Asia only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_p])),
|
||||
@@ -537,6 +634,14 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=2055, wheelbase=2.9, steerRatio=16, tireStiffnessFactor=0.65),
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
KIA_EV6_PE = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia EV6 PE (CV1)", car_parts=CarParts.common([CarHarness.hyundai_p])),
|
||||
HyundaiCarDocs("Kia EV6 PE (with HDA II) 2025", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))
|
||||
],
|
||||
CarSpecs(mass=2055, wheelbase=2.9, steerRatio=16, tireStiffnessFactor=0.65),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.ANGLE_CONTROL,
|
||||
)
|
||||
KIA_CARNIVAL_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia Carnival 2022-24", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||
@@ -605,54 +710,116 @@ class CAR(Platforms):
|
||||
CarSpecs(mass=2258, wheelbase=2.95, steerRatio=14.14),
|
||||
flags=HyundaiFlags.RADAR_SCC,
|
||||
)
|
||||
|
||||
# port extensions
|
||||
HYUNDAI_BAYON_1ST_GEN_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Hyundai Bayon Non-SCC 2021", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||
CarSpecs(mass=1150, wheelbase=2.58, steerRatio=13.27 * 1.15),
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
GENESIS_GV70_EV_1ST_GEN = HyundaiCanFDPlatformConfig(
|
||||
[HyundaiCarDocs("Genesis GV70 EV 2020-2023", "All", car_parts=CarParts.common([CarHarness.hyundai_m]))],
|
||||
CarSpecs(mass=2230, wheelbase=2.87, steerRatio=14.6),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.RADAR_SCC,
|
||||
)
|
||||
HYUNDAI_ELANTRA_2022_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Hyundai Elantra Non-SCC 2022", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
HYUNDAI_ELANTRA_2021.specs,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
HYUNDAI_GRANDEUR_IG = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Grandeur 2018-19", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1570, wheelbase=2.845, steerRatio=16., tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY | HyundaiFlags.CLUSTER_GEARS,
|
||||
)
|
||||
HYUNDAI_KONA_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Hyundai Kona Non-SCC 2019", car_parts=CarParts.common([CarHarness.hyundai_b]))],
|
||||
HYUNDAI_KONA.specs,
|
||||
flags=HyundaiFlags.ALT_LIMITS,
|
||||
HYUNDAI_GRANDEUR_IG_HEV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Grandeur HEV 2018-19", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1570, wheelbase=2.845, steerRatio=16., tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.HYBRID | HyundaiFlags.LEGACY,
|
||||
)
|
||||
HYUNDAI_KONA_EV_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Hyundai Kona Electric Non-SCC 2019", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
HYUNDAI_KONA_EV.specs,
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS,
|
||||
GENESIS_EQ900 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Genesis EQ900 2017", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=2200, wheelbase=3.15, steerRatio=16., tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_CEED_PHEV_2022_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Kia Ceed Plug-in Hybrid Non-SCC 2022", car_parts=CarParts.common([CarHarness.hyundai_i]))],
|
||||
CarSpecs(mass=1650, wheelbase=2.65, steerRatio=13.75, tireStiffnessFactor=0.5),
|
||||
GENESIS_EQ900_L = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Genesis EQ900 LIMOUSINE", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=2290, wheelbase=3.45, steerRatio=16., tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY,
|
||||
)
|
||||
GENESIS_G90_2019 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Genesis G90 2019", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=2150, wheelbase=3.16, steerRatio=16., tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY,
|
||||
)
|
||||
HYUNDAI_NEXO = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Hyundai Nexo", "All", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||
CarSpecs(mass=1885, wheelbase=2.79, steerRatio=15.3, tireStiffnessFactor=0.385),
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
KIA_MOHAVE = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Mohave 2019", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||
CarSpecs(mass=2285, wheelbase=2.895, steerRatio=16., tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_K5 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K5 2019 & 2016", "All", car_parts=CarParts.common([CarHarness.hyundai_b]))],
|
||||
CarSpecs(mass=1515, wheelbase=2.80, steerRatio=15.5, tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY | HyundaiFlags.TCU_GEARS,
|
||||
)
|
||||
KIA_K5_HEV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K5 Hybrid 2017", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1705, wheelbase=2.80, steerRatio=15.5, tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.HYBRID | HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_K5_HEV_2022 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K5 Hybrid 2022", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1515, wheelbase=2.85, steerRatio=15.5, tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.HYBRID | HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_K7 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K7 2016-2019", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1850, wheelbase=2.855, steerRatio=15.5, tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY | HyundaiFlags.CLUSTER_GEARS,
|
||||
)
|
||||
KIA_K7_HEV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K7 Hybrid 2016-2019", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1515, wheelbase=2.855, steerRatio=15.5, tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.HYBRID | HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_K7_PE = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K7 2020", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1850, wheelbase=2.855, steerRatio=15.5, tireStiffnessFactor=0.7),
|
||||
)
|
||||
KIA_K7_HEV_PE = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K7 Hybrid 2020", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1515, wheelbase=2.855, steerRatio=15.5, tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.HYBRID,
|
||||
)
|
||||
KIA_FORTE_2019_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Kia Forte Non-SCC 2019", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
KIA_FORTE.specs,
|
||||
iq_flags=HyundaiFlagsIQ.NON_SCC_NO_FCA,
|
||||
KIA_K9 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia K9 2016-2019", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))],
|
||||
CarSpecs(mass=2075, wheelbase=3.15, steerRatio=14.5, tireStiffnessFactor=0.7),
|
||||
flags=HyundaiFlags.LEGACY,
|
||||
)
|
||||
KIA_FORTE_2021_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Kia Forte Non-SCC 2021", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||
KIA_FORTE.specs,
|
||||
KIA_EV_SK3 = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Soul EV 2019", car_parts=CarParts.common([CarHarness.hyundai_c]))],
|
||||
CarSpecs(mass=1695, wheelbase=2.6, steerRatio=13.75),
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.EV,
|
||||
)
|
||||
KIA_SELTOS_2023_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Kia Seltos Non-SCC 2023-24", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||
KIA_SELTOS.specs,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
KIA_EV9 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia EV9 (MV)", car_parts=CarParts.common([CarHarness.hyundai_k])),
|
||||
],
|
||||
CarSpecs(mass=2625, wheelbase=3.1, steerRatio=16.02),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.ANGLE_CONTROL,
|
||||
)
|
||||
GENESIS_G70_2021_NON_SCC = HyundaiNonSccPlatformConfig(
|
||||
[HyundaiNonSccCarDocs("Genesis G70 Non-SCC 2021", car_parts=CarParts.common([CarHarness.hyundai_f]))],
|
||||
GENESIS_G70_2020.specs,
|
||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||
iq_flags=HyundaiFlagsIQ.NON_SCC_RADAR_FCA,
|
||||
KIA_EV3 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia EV3 (SV1)", car_parts=CarParts.common([CarHarness.hyundai_n])),
|
||||
],
|
||||
CarSpecs(mass=2055, wheelbase=2.90, steerRatio=16.0, tireStiffnessFactor=0.65),
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
KIA_PV5 = HyundaiCanFDPlatformConfig(
|
||||
[
|
||||
HyundaiCarDocs("Kia PV5 (SW1)", car_parts=CarParts.common([CarHarness.hyundai_n])),
|
||||
],
|
||||
CarSpecs(mass=2600, wheelbase=2.995, steerRatio=16.0, tireStiffnessFactor=0.65),
|
||||
flags=HyundaiFlags.EV,
|
||||
)
|
||||
KIA_RAY_EV = HyundaiPlatformConfig(
|
||||
[HyundaiCarDocs("Kia Ray EV", car_parts=CarParts.common([CarHarness.hyundai_h]))],
|
||||
CarSpecs(mass=1295, wheelbase=2.520, steerRatio=14.5),
|
||||
flags=HyundaiFlags.EV | HyundaiFlags.CC_ONLY_CAR | HyundaiFlags.CHECKSUM_CRC8,
|
||||
)
|
||||
|
||||
|
||||
class Buttons:
|
||||
NONE = 0
|
||||
@@ -660,6 +827,7 @@ class Buttons:
|
||||
SET_DECEL = 2
|
||||
GAP_DIST = 3
|
||||
CANCEL = 4 # on newer models, this is a pause/resume button
|
||||
LFA_BUTTON = 5
|
||||
|
||||
|
||||
def get_platform_codes(fw_versions: list[bytes]) -> set[tuple[bytes, bytes | None]]:
|
||||
@@ -840,11 +1008,21 @@ CAN_GEARS = {
|
||||
# which message has the gear. hybrid and EV use ELECT_GEAR
|
||||
"use_cluster_gears": CAR.with_flags(HyundaiFlags.CLUSTER_GEARS),
|
||||
"use_tcu_gears": CAR.with_flags(HyundaiFlags.TCU_GEARS),
|
||||
"send_mdps12": {CAR.GENESIS_G90, CAR.GENESIS_G90_2019, CAR.KIA_K9, CAR.KIA_K7},
|
||||
}
|
||||
|
||||
CANFD_CAR = CAR.with_flags(HyundaiFlags.CANFD)
|
||||
CANFD_RADAR_SCC_CAR = CAR.with_flags(HyundaiFlags.RADAR_SCC) # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR
|
||||
|
||||
CANFD_HYBRID_STATUS_ADDR = 0xFA
|
||||
CANFD_HYBRID_STATUS_DLC = 32
|
||||
|
||||
EV_MODE_STATUS_ADDR = 0x230
|
||||
EV_MODE_STATUS_DLC = 32
|
||||
EV_MODE_STATUS_MSG = "HCU_STATUS_230"
|
||||
EV_MODE_STATUS_SIGNAL = "HYBRID_POWER_FLOW_MODE"
|
||||
EV_MODE_ACTIVE_VALUES = frozenset((1, 2, 6))
|
||||
|
||||
CANFD_UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.CANFD_NO_RADAR_DISABLE) # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR
|
||||
|
||||
CAMERA_SCC_CAR = CAR.with_flags(HyundaiFlags.CAMERA_SCC)
|
||||
@@ -859,7 +1037,13 @@ LEGACY_SAFETY_MODE_CAR = CAR.with_flags(HyundaiFlags.LEGACY)
|
||||
# HyundaiFlags.CANFD_RADAR_SCC | HyundaiFlags.CANFD_NO_RADAR_DISABLE | )
|
||||
UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.LEGACY) | CAR.with_flags(HyundaiFlags.UNSUPPORTED_LONGITUDINAL)
|
||||
|
||||
# port extensions
|
||||
NON_SCC_CAR = CAR.with_iq_flags(HyundaiFlagsIQ.NON_SCC)
|
||||
|
||||
DBC = CAR.create_dbc_map()
|
||||
|
||||
if __name__ == "__main__":
|
||||
cars = []
|
||||
for platform in CAR:
|
||||
for doc in platform.config.car_docs:
|
||||
cars.append(doc.name)
|
||||
cars.sort()
|
||||
for c in cars:
|
||||
print(c)
|
||||
|
||||
@@ -332,6 +332,12 @@ class CarStateBase(ABC):
|
||||
x0=[[0.0], [0.0]]
|
||||
K = get_kalman_gain(DT_CTRL, np.array(A), np.array(C), np.array(Q), R)
|
||||
self.v_ego_kf = KF1D(x0=x0, A=A, C=C[0], K=K)
|
||||
self.v_ego_clu_kf = KF1D(x0=x0, A=A, C=C[0], K=K)
|
||||
|
||||
self.softHoldActive = 0
|
||||
self.is_metric = True
|
||||
self.lkas_enabled = False
|
||||
self.modelV2 = None
|
||||
|
||||
@abstractmethod
|
||||
def update(self, can_parsers) -> tuple[structs.CarState, structs.IQCarState]:
|
||||
@@ -348,6 +354,22 @@ class CarStateBase(ABC):
|
||||
v_ego_x = self.v_ego_kf.update(v_ego_raw)
|
||||
return float(v_ego_x[0]), float(v_ego_x[1])
|
||||
|
||||
def update_clu_speed_kf(self, v_ego_raw):
|
||||
if abs(v_ego_raw - self.v_ego_clu_kf.x[0][0]) > 2.0:
|
||||
self.v_ego_clu_kf.set_x([[v_ego_raw], [0.0]])
|
||||
|
||||
v_ego_x = self.v_ego_clu_kf.update(v_ego_raw)
|
||||
return float(v_ego_x[0]), float(v_ego_x[1])
|
||||
|
||||
def get_wheel_speeds(self, fl, fr, rl, rr, unit=CV.KPH_TO_MS):
|
||||
factor = unit * self.CP.wheelSpeedFactor
|
||||
wheel_speeds = structs.CarState.WheelSpeeds()
|
||||
wheel_speeds.fl = fl * factor
|
||||
wheel_speeds.fr = fr * factor
|
||||
wheel_speeds.rl = rl * factor
|
||||
wheel_speeds.rr = rr * factor
|
||||
return wheel_speeds
|
||||
|
||||
def update_blinker_from_lamp(self, blinker_time: int, left_blinker_lamp: bool, right_blinker_lamp: bool):
|
||||
"""Update blinkers from lights. Enable output when light was seen within the last `blinker_time`
|
||||
iterations"""
|
||||
|
||||
@@ -7,9 +7,6 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"NISSAN_LEAF" = [nan, 1.5, nan]
|
||||
"NISSAN_ROGUE" = [nan, 1.5, nan]
|
||||
|
||||
# PSA angle based controllers
|
||||
"PSA_PEUGEOT_208" = [nan, 2.0, nan]
|
||||
|
||||
# New subarus angle based controllers
|
||||
"SUBARU_FORESTER_2022" = [nan, 3.0, nan]
|
||||
"SUBARU_OUTBACK_2023" = [nan, 3.0, nan]
|
||||
@@ -21,14 +18,11 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
# Tesla angle based controllers
|
||||
"TESLA_MODEL_3" = [nan, 2.5, nan]
|
||||
"TESLA_MODEL_Y" = [nan, 2.5, nan]
|
||||
"TESLA_MODEL_X" = [nan, 2.5, nan]
|
||||
|
||||
# Guess
|
||||
"FORD_BRONCO_SPORT_MK1" = [nan, 1.5, nan]
|
||||
"FORD_ESCAPE_MK4" = [nan, 1.5, nan]
|
||||
"FORD_ESCAPE_MK4_5" = [nan, 1.5, nan]
|
||||
"FORD_EXPLORER_MK6" = [nan, 1.5, nan]
|
||||
"FORD_EXPEDITION_MK4" = [nan, 1.5, nan]
|
||||
"FORD_F_150_MK14" = [nan, 1.5, nan]
|
||||
"FORD_FOCUS_MK4" = [nan, 1.5, nan]
|
||||
"FORD_MAVERICK_MK1" = [nan, 1.5, nan]
|
||||
@@ -44,30 +38,23 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"RAM_1500_5TH_GEN" = [2.0, 2.0, 0.05]
|
||||
"RAM_HD_5TH_GEN" = [1.4, 1.4, 0.05]
|
||||
"SUBARU_OUTBACK" = [2.0, 1.5, 0.2]
|
||||
"BUICK_BABYENCLAVE" = [1.45, 1.6, 0.2]
|
||||
"CADILLAC_ESCALADE" = [1.899999976158142, 1.842270016670227, 0.1120000034570694]
|
||||
"CADILLAC_ESCALADE_ESV_2019" = [1.15, 1.3, 0.2]
|
||||
"CADILLAC_XT4" = [1.45, 1.6, 0.2]
|
||||
"CHEVROLET_BOLT_EUV" = [1.0, 2.0, 0.175]
|
||||
"CHEVROLET_BOLT_EUV" = [2.0, 2.0, 0.05]
|
||||
"CHEVROLET_MALIBU_CC" = [1.85, 1.85, 0.075]
|
||||
"CHEVROLET_SILVERADO" = [1.9, 1.9, 0.112]
|
||||
"CHEVROLET_TRAILBLAZER" = [1.33, 1.9, 0.16]
|
||||
"CHEVROLET_TRAVERSE" = [1.33, 1.33, 0.18]
|
||||
"CHEVROLET_EQUINOX" = [2.5, 2.5, 0.05]
|
||||
"CHEVROLET_VOLT_2019" = [1.4, 1.4, 0.16]
|
||||
"VOLKSWAGEN_GOLF_MK8" = [nan, 2.5, nan]
|
||||
"CUPRA_BORN_MK1" = [nan, 2.5, nan]
|
||||
"VOLKSWAGEN_ID3_MK1" = [nan, 2.5, nan]
|
||||
"VOLKSWAGEN_ID3_MK2" = [nan, 2.5, nan]
|
||||
"VOLKSWAGEN_ID4_MK1" = [nan, 2.5, nan]
|
||||
"VOLKSWAGEN_ID4_MK2" = [nan, 2.5, nan]
|
||||
"AUDI_Q4_MK1" = [nan, 2.5, nan]
|
||||
"AUDI_Q4_MK2" = [nan, 2.5, nan]
|
||||
"SEAT_LEON_MK4" = [nan, 2.5, nan]
|
||||
"SKODA_ENYAQ_MK1" = [nan, 2.5, nan]
|
||||
"SKODA_ENYAQ_MK2" = [nan, 2.5, nan]
|
||||
"CHEVROLET_TRAX" = [1.33, 1.9, 0.16]
|
||||
"VOLKSWAGEN_ID4_MK1" = [2.0, 2.0, 0.1]
|
||||
"VOLKSWAGEN_ID4_MK2" = [2.0, 2.0, 0.1]
|
||||
"VOLKSWAGEN_CADDY_MK3" = [1.2, 1.2, 0.1]
|
||||
"VOLKSWAGEN_PASSAT_NMS" = [2.5, 2.5, 0.1]
|
||||
"VOLKSWAGEN_SHARAN_MK2" = [2.5, 2.5, 0.1]
|
||||
"SEAT_ALHAMBRA_MK1" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_SANTA_CRUZ_1ST_GEN" = [2.7, 2.7, 0.1]
|
||||
"KIA_SPORTAGE_5TH_GEN" = [2.6, 2.6, 0.1]
|
||||
"GENESIS_GV70_1ST_GEN" = [2.42, 2.42, 0.1]
|
||||
@@ -82,33 +69,22 @@ 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_KONA_HEV_2ND_GEN" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_IONIQ_6" = [2.5, 2.5, 0.005]
|
||||
"HYUNDAI_IONIQ_9" = [1.75, 1.75, 0.15]
|
||||
"HYUNDAI_AZERA_7TH_GEN" = [1.8, 1.8, 0.1]
|
||||
"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]
|
||||
"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]
|
||||
"HYUNDAI_PORTER_II_EV" = [1.8, 2.0, 0.15]
|
||||
"KIA_RAY_EV" = [1.8, 2.0, 0.15]
|
||||
"GENESIS_GV70_ELECTRIFIED_1ST_GEN" = [1.9, 1.9, 0.09]
|
||||
"GENESIS_G80_2ND_GEN_FL" = [2.5819356441497803, 2.5, 0.11244568973779678]
|
||||
# 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]
|
||||
"HONDA_ACCORD_11G" = [1.35, 1.35, 0.17]
|
||||
"HONDA_PILOT_4G" = [1.25, 1.25, 0.21]
|
||||
"HONDA_PASSPORT_4G" = [1.2, 1.2, 0.16]
|
||||
"ACURA_MDX_4G_MMR" = [1.25, 1.25, 0.15]
|
||||
"HONDA_CRV_6G" = [1.3, 1.3, 0.2]
|
||||
"HONDA_CITY_7G" = [1.2, 1.2, 0.23]
|
||||
"HONDA_ODYSSEY_5G_MMR" = [0.9, 0.9, 0.2]
|
||||
"HONDA_NBOX_2G" = [1.2, 1.2, 0.2]
|
||||
"ACURA_TLX_2G" = [1.2, 1.2, 0.15]
|
||||
"ACURA_TLX_2G_MMR" = [1.7, 1.7, 0.16]
|
||||
"PORSCHE_MACAN_MK1" = [2.0, 2.0, 0.2]
|
||||
"AUDI_Q5_MK1" = [1.8, 1.8, 0.18]
|
||||
"LEXUS_LS" = [1.35, 1.7, 0.17]
|
||||
"TOYOTA_RAV4_PRIME" = [1.7, 2.0, 0.14]
|
||||
"TOYOTA_RAV4_TSS2_2022" = [1.9, 1.9304407208090029, 0.112174]
|
||||
|
||||
# Dashcam or fallback configured as ideal car
|
||||
"MOCK" = [10.0, 10, 0.0]
|
||||
@@ -117,6 +93,25 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"HONDA_CIVIC_2022" = [2.5, 1.2, 0.15]
|
||||
"HONDA_HRV_3G" = [2.5, 1.2, 0.2]
|
||||
|
||||
# port extensions
|
||||
"HONDA_CLARITY" = [0.96, 0.4018518740819229, 0.19]
|
||||
"CHEVROLET_MALIBU_NON_ACC_9TH_GEN" = [1.85, 1.85, 0.075]
|
||||
# Community
|
||||
"HYUNDAI_GRANDEUR_IG" = [2.3, 2.3, 0.1]
|
||||
"HYUNDAI_GRANDEUR_IG_HEV" = [2.3, 2.3, 0.1]
|
||||
"GENESIS_EQ900" = [2.3, 2.3, 0.1]
|
||||
"GENESIS_EQ900_L" = [2.3, 2.3, 0.1]
|
||||
"GENESIS_G90_2019" = [2.3, 2.3, 0.1]
|
||||
"KIA_MOHAVE" = [2.3, 2.3, 0.1]
|
||||
"KIA_K5" = [2.3, 2.3, 0.1]
|
||||
"KIA_K5_HEV" = [2.3, 2.3, 0.1]
|
||||
"KIA_K5_HEV_2022" = [2.3, 2.3, 0.1]
|
||||
"KIA_K7" = [2.3, 2.3, 0.1]
|
||||
"KIA_K7_HEV" = [2.3, 2.3, 0.1]
|
||||
"KIA_K7_PE" = [2.3, 2.3, 0.1]
|
||||
"KIA_K7_HEV_PE" = [2.3, 2.3, 0.1]
|
||||
"KIA_K9" = [2.3, 2.3, 0.1]
|
||||
"GENESIS_GV70_EV_1ST_GEN" = [2.42, 2.42, 0.1]
|
||||
"HYUNDAI_NEXO" = [2.7, 2.7, 0.1]
|
||||
"KIA_EV_SK3" = [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_CASPER"= [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_CASPER_EV"= [2.5, 2.5, 0.1]
|
||||
"HYUNDAI_IONIQ_5_N" = [3.17, 2.71, 0.097]
|
||||
"HYUNDAI_IONIQ_5_PE" = [1.75, 1.75, 0.15]
|
||||
|
||||
@@ -37,13 +37,21 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"HYUNDAI_SONATA" = [2.9638737459977467, 2.1259108157250735, 0.07813665616927593]
|
||||
"HYUNDAI_SONATA_HYBRID" = [2.8990264092395734, 2.061410192222139, 0.0899805488717382]
|
||||
"HYUNDAI_TUCSON_4TH_GEN" = [2.960174, 2.860284, 0.108745]
|
||||
"HYUNDAI_SANTAFE_MX5" = [3.2, 3.0, 0.05]
|
||||
"HYUNDAI_SANTAFE_MX5_HEV" = [3.2, 3.0, 0.05]
|
||||
"JEEP_GRAND_CHEROKEE_2019" = [2.30972, 1.289689569171081, 0.117048]
|
||||
"JEEP_GRAND_CHEROKEE" = [2.27116, 1.4057367824262523, 0.11725947414922003]
|
||||
"KIA_EV6" = [3.2, 2.093457, 0.005]
|
||||
"KIA_EV6_PE" = [3.2, 2.093457, 0.005]
|
||||
"KIA_K5_2021" = [2.405339728085138, 1.460032270828705, 0.11650989850813716]
|
||||
"KIA_K5_DL3_24" = [2.5, 2.5, 0.1]
|
||||
"KIA_K5_DL3_24_HEV" = [2.5, 2.5, 0.1]
|
||||
"KIA_NIRO_EV" = [2.9215954981365337, 2.1500583840260044, 0.09236802474810267]
|
||||
"KIA_SORENTO" = [2.464854685101844, 1.5335274218367956, 0.12056170567599558]
|
||||
"KIA_STINGER" = [2.7499043387418967, 1.849652021986449, 0.12048334239559202]
|
||||
"KIA_EV9" = [1.75, 1.75, 0.15]
|
||||
"KIA_EV3" = [3.2, 2.093457, 0.005]
|
||||
"KIA_PV5" = [3.2, 2.093457, 0.005]
|
||||
"LEXUS_ES_TSS2" = [2.0357564999999997, 1.999082295195227, 0.101533]
|
||||
"LEXUS_NX" = [2.3525924753753613, 1.9731412277641067, 0.15168101064205927]
|
||||
"LEXUS_NX_TSS2" = [2.4331999786982936, 2.1045680431705414, 0.14099899317761067]
|
||||
@@ -69,8 +77,9 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"TOYOTA_PRIUS" = [1.60, 1.5023147650693636, 0.151515]
|
||||
"TOYOTA_PRIUS_TSS2" = [1.972600, 1.9104337425537743, 0.170968]
|
||||
"TOYOTA_RAV4" = [2.085695074355425, 2.2142832316984733, 0.13339165270103975]
|
||||
"TOYOTA_RAV4_TSS2" = [1.9557514786720276, 2.087101966779332, 0.12075843289494514]
|
||||
"TOYOTA_RAV4_TSS2" = [2.279239424615458, 2.087101966779332, 0.13682208413446817]
|
||||
"TOYOTA_RAV4H" = [1.9796257271652042, 1.7503987331707576, 0.14628860048885406]
|
||||
"TOYOTA_RAV4_TSS2_2022" = [2.241883248393209, 1.9304407208090029, 0.112174]
|
||||
"TOYOTA_SIENNA" = [1.689726, 1.3208264576110418, 0.140456]
|
||||
"TOYOTA_YARIS" = [2.22984, 1.86145, 0.168189]
|
||||
"VOLKSWAGEN_ARTEON_MK1" = [1.45136518053819, 1.3639364049316804, 0.23806361745695032]
|
||||
|
||||
@@ -9,12 +9,12 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
|
||||
"TOYOTA_ALPHARD_TSS2" = "TOYOTA_SIENNA"
|
||||
"TOYOTA_PRIUS_V" = "TOYOTA_PRIUS"
|
||||
"TOYOTA_SIENNA_4TH_GEN" = "TOYOTA_RAV4_PRIME"
|
||||
"TOYOTA_RAV4_PRIME" = "TOYOTA_RAV4_TSS2"
|
||||
"TOYOTA_SIENNA_4TH_GEN" = "TOYOTA_RAV4_TSS2"
|
||||
"LEXUS_IS" = "LEXUS_NX"
|
||||
"LEXUS_CTH" = "LEXUS_NX"
|
||||
"LEXUS_ES" = "TOYOTA_CAMRY"
|
||||
"LEXUS_RC" = "LEXUS_NX_TSS2"
|
||||
"LEXUS_RC_TSS2" = "LEXUS_NX_TSS2"
|
||||
"LEXUS_LC_TSS2" = "LEXUS_NX_TSS2"
|
||||
|
||||
"KIA_OPTIMA_G4" = "HYUNDAI_SONATA"
|
||||
@@ -25,6 +25,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"KIA_CEED" = "HYUNDAI_SONATA"
|
||||
"KIA_SELTOS" = "HYUNDAI_SONATA"
|
||||
"KIA_NIRO_PHEV" = "KIA_NIRO_EV"
|
||||
"KIA_EV4" = "KIA_EV6"
|
||||
"KIA_NIRO_PHEV_2022" = "KIA_NIRO_EV"
|
||||
"KIA_NIRO_HEV_2021" = "KIA_NIRO_EV"
|
||||
"HYUNDAI_VELOSTER" = "HYUNDAI_SONATA_LF"
|
||||
@@ -45,12 +46,13 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"GENESIS_G90" = "GENESIS_G70"
|
||||
"GENESIS_G80" = "GENESIS_G70"
|
||||
"GENESIS_G70_2020" = "HYUNDAI_SONATA"
|
||||
"HYUNDAI_SONATA_2024" = "HYUNDAI_SONATA"
|
||||
|
||||
"HONDA_FREED" = "HONDA_ODYSSEY"
|
||||
"HONDA_CRV_EU" = "HONDA_CRV"
|
||||
"HONDA_CIVIC_BOSCH_DIESEL" = "HONDA_CIVIC_BOSCH"
|
||||
"HONDA_E" = "HONDA_CIVIC_BOSCH"
|
||||
"HONDA_ODYSSEY_TWN" = "HONDA_ODYSSEY"
|
||||
"HONDA_ODYSSEY_CHN" = "HONDA_ODYSSEY"
|
||||
|
||||
"BUICK_LACROSSE" = "CHEVROLET_VOLT"
|
||||
"BUICK_REGAL" = "CHEVROLET_VOLT"
|
||||
@@ -58,6 +60,18 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"CADILLAC_ATS" = "CHEVROLET_VOLT"
|
||||
"CHEVROLET_MALIBU" = "CHEVROLET_VOLT"
|
||||
"HOLDEN_ASTRA" = "CHEVROLET_VOLT"
|
||||
"CHEVROLET_VOLT_CC" = "CHEVROLET_VOLT"
|
||||
"CHEVROLET_BOLT_CC" = "CHEVROLET_BOLT_EUV"
|
||||
"CHEVROLET_BOLT_2017" = "CHEVROLET_BOLT_EUV"
|
||||
"CHEVROLET_BOLT_2018" = "CHEVROLET_BOLT_EUV"
|
||||
"CHEVROLET_EQUINOX_CC" = "CHEVROLET_EQUINOX"
|
||||
"CHEVROLET_SUBURBAN" = "CHEVROLET_SILVERADO"
|
||||
"CHEVROLET_SUBURBAN_CC" = "CHEVROLET_SILVERADO"
|
||||
"CHEVROLET_TRAX_2024" = "CHEVROLET_VOLT"
|
||||
"CADILLAC_CT6_CC" = "CHEVROLET_VOLT"
|
||||
"CADILLAC_CT6_ACC" = "CHEVROLET_VOLT"
|
||||
"CHEVROLET_TRAILBLAZER_CC" = "CHEVROLET_TRAILBLAZER"
|
||||
"CADILLAC_XT5_CC" = "GMC_ACADIA"
|
||||
|
||||
"SKODA_FABIA_MK4" = "VOLKSWAGEN_GOLF_MK7"
|
||||
"SKODA_OCTAVIA_MK3" = "SKODA_SUPERB_MK3"
|
||||
@@ -74,9 +88,6 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"VOLKSWAGEN_POLO_MK6" = "VOLKSWAGEN_GOLF_MK7"
|
||||
"SEAT_ATECA_MK1" = "VOLKSWAGEN_GOLF_MK7"
|
||||
"VOLKSWAGEN_JETTA_MK6" = "VOLKSWAGEN_PASSAT_NMS"
|
||||
"VOLKSWAGEN_PASSAT_MK7" = "VOLKSWAGEN_PASSAT_NMS"
|
||||
"VOLKSWAGEN_PASSAT_NMS_PLUS" = "VOLKSWAGEN_PASSAT_NMS"
|
||||
"VOLKSWAGEN_PASSAT_B7" = "VOLKSWAGEN_PASSAT_NMS"
|
||||
|
||||
"SUBARU_CROSSTREK_HYBRID" = "SUBARU_IMPREZA_2020"
|
||||
"SUBARU_FORESTER_HYBRID" = "SUBARU_IMPREZA_2020"
|
||||
@@ -88,22 +99,3 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"SUBARU_FORESTER_PREGLOBAL" = "SUBARU_IMPREZA"
|
||||
"SUBARU_LEGACY_PREGLOBAL" = "SUBARU_IMPREZA"
|
||||
"SUBARU_ASCENT" = "SUBARU_FORESTER"
|
||||
|
||||
# port extensions
|
||||
"KIA_CEED_PHEV_2022_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"HYUNDAI_KONA_EV_NON_SCC" = "HYUNDAI_KONA_EV"
|
||||
"KIA_FORTE_2019_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"KIA_FORTE_2021_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"KIA_SELTOS_2023_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"HYUNDAI_KONA_NON_SCC" = "HYUNDAI_KONA_EV"
|
||||
"HYUNDAI_ELANTRA_2022_NON_SCC" = "HYUNDAI_ELANTRA_2021"
|
||||
"GENESIS_G70_2021_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"HYUNDAI_BAYON_1ST_GEN_NON_SCC" = "HYUNDAI_SONATA"
|
||||
"CHEVROLET_BOLT_NON_ACC_2ND_GEN" = "CHEVROLET_BOLT_EUV"
|
||||
"CHEVROLET_BOLT_NON_ACC" = "CHEVROLET_BOLT_EUV"
|
||||
"CHEVROLET_BOLT_NON_ACC_1ST_GEN" = "CHEVROLET_BOLT_EUV"
|
||||
"CHEVROLET_EQUINOX_NON_ACC_3RD_GEN" = "CHEVROLET_EQUINOX"
|
||||
"CHEVROLET_SUBURBAN_NON_ACC_11TH_GEN" = "CHEVROLET_SILVERADO"
|
||||
"CADILLAC_CT6_NON_ACC_1ST_GEN" = "CHEVROLET_VOLT"
|
||||
"CHEVROLET_TRAILBLAZER_NON_ACC_2ND_GEN" = "CHEVROLET_TRAILBLAZER"
|
||||
"CADILLAC_XT5_NON_ACC_1ST_GEN" = "GMC_ACADIA"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
hyundai_kia_mando_front_radar.dbc
|
||||
hyundai_kia_denso_front_radar.dbc
|
||||
hyundai_kia_mando_corner_radar.dbc
|
||||
|
||||
@@ -40,18 +40,21 @@ BO_ 80 LKAS: 16 XXX
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ LKA_MODE : 24|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ LKA_AVAILABLE : 27|2@1+ (1,0) [0|255] "" XXX
|
||||
SG_ LKA_ACTIVE : 27|2@1+ (1,0) [0|255] "" XXX
|
||||
SG_ LKA_WARNING : 32|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ LKA_ICON : 38|2@1+ (1,0) [0|255] "" XXX
|
||||
SG_ FCA_SYSWARN : 40|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ TORQUE_REQUEST : 41|11@1+ (1,-1024) [0|4095] "" XXX
|
||||
SG_ STEER_REQ : 52|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ LFA_BUTTON : 56|1@1+ (1,0) [0|255] "" XXX
|
||||
SG_ LKA_ASSIST : 62|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ STEER_MODE : 65|3@1+ (1,0) [0|1] "" XXX
|
||||
SG_ NEW_SIGNAL_2 : 70|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ VALUE63 : 63|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ VALUE64 : 64|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_1 : 75|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ LKAS_ANGLE_ACTIVE : 77|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ HAS_LANE_SAFETY : 80|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DAMP_FACTOR : 64|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ LKAS_ANGLE_CMD : 82|14@1- (-0.1,0) [0|511] "" XXX
|
||||
SG_ LKAS_ANGLE_MAX_TORQUE : 96|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ VALUE104 : 104|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 81 ADRV_0x51: 32 ADRV
|
||||
SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,140 @@
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
ENVVAR_TYPE_
|
||||
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 RADAR
|
||||
|
||||
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000;
|
||||
BA_DEF_DEF_ "GenMsgCycleTime" 0;
|
||||
|
||||
BO_ 384 CORNER_RADAR_180_OBJECTS_180: 32 RADAR
|
||||
SG_ SLOT1_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT1_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT1_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT1_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT1_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT1_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT1_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
SG_ SLOT2_QUAL_LEVEL : 152|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT2_AGE : 160|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_OBJECT_ID : 172|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT2_REL_POS_X : 192|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT2_REL_POS_Y : 206|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT2_REL_VEL_X : 219|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT2_REL_VEL_Y : 232|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT2_REL_ACCEL_X : 243|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 384 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 384 30;
|
||||
|
||||
BO_ 385 CORNER_RADAR_180_OBJECTS_181: 32 RADAR
|
||||
SG_ SLOT1_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT1_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT1_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT1_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT1_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT1_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT1_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
SG_ SLOT2_QUAL_LEVEL : 152|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT2_AGE : 160|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_OBJECT_ID : 172|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT2_REL_POS_X : 192|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT2_REL_POS_Y : 206|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT2_REL_VEL_X : 219|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT2_REL_VEL_Y : 232|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT2_REL_ACCEL_X : 243|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 385 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 385 30;
|
||||
|
||||
BO_ 386 CORNER_RADAR_180_OBJECTS_182: 32 RADAR
|
||||
SG_ SLOT1_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT1_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT1_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT1_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT1_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT1_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT1_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
SG_ SLOT2_QUAL_LEVEL : 152|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT2_AGE : 160|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_OBJECT_ID : 172|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT2_REL_POS_X : 192|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT2_REL_POS_Y : 206|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT2_REL_VEL_X : 219|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT2_REL_VEL_Y : 232|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT2_REL_ACCEL_X : 243|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 386 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 386 30;
|
||||
|
||||
BO_ 387 CORNER_RADAR_180_OBJECTS_183: 32 RADAR
|
||||
SG_ SLOT1_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT1_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT1_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT1_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT1_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT1_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT1_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
SG_ SLOT2_QUAL_LEVEL : 152|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT2_AGE : 160|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_OBJECT_ID : 172|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT2_REL_POS_X : 192|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT2_REL_POS_Y : 206|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT2_REL_VEL_X : 219|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT2_REL_VEL_Y : 232|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT2_REL_ACCEL_X : 243|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 387 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 387 30;
|
||||
|
||||
BO_ 388 CORNER_RADAR_180_OBJECTS_184: 32 RADAR
|
||||
SG_ SLOT1_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT1_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT1_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT1_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT1_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT1_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT1_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
SG_ SLOT2_QUAL_LEVEL : 152|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT2_AGE : 160|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_OBJECT_ID : 172|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT2_REL_POS_X : 192|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT2_REL_POS_Y : 206|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT2_REL_VEL_X : 219|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT2_REL_VEL_Y : 232|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT2_REL_ACCEL_X : 243|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 388 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 388 30;
|
||||
81
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_corner_radar_180.py
Executable file
81
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_corner_radar_180.py
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
|
||||
HEADER = """VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
ENVVAR_TYPE_
|
||||
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 RADAR
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def write_object_msg(f, addr):
|
||||
name = f"CORNER_RADAR_180_OBJECTS_{addr:x}"
|
||||
f.write(f"""
|
||||
BO_ {addr} {name}: 32 RADAR
|
||||
SG_ SLOT1_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT1_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT1_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT1_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT1_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT1_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT1_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
SG_ SLOT2_QUAL_LEVEL : 152|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ SLOT2_AGE : 160|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_OBJECT_ID : 172|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ SLOT2_REL_POS_X : 192|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ SLOT2_REL_POS_Y : 206|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ SLOT2_REL_VEL_X : 219|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ SLOT2_REL_VEL_Y : 232|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ SLOT2_REL_ACCEL_X : 243|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
""")
|
||||
|
||||
f.write(f"""CM_ BO_ {addr} "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ {addr} 30;
|
||||
""")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbc_name = os.path.basename(__file__).replace(".py", ".dbc")
|
||||
out_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), dbc_name)
|
||||
with open(out_path, "w", encoding="ascii") as f:
|
||||
f.write(HEADER)
|
||||
f.write('BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000;\n')
|
||||
f.write('BA_DEF_DEF_ "GenMsgCycleTime" 0;\n')
|
||||
for addr in range(0x180, 0x185):
|
||||
write_object_msg(f, addr)
|
||||
@@ -0,0 +1,278 @@
|
||||
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_
|
||||
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 RADAR
|
||||
|
||||
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000;
|
||||
BA_DEF_DEF_ "GenMsgCycleTime" 0;
|
||||
|
||||
BO_ 565 CORNER_RADAR_235_OBJECTS_235: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 565 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 565 30;
|
||||
|
||||
BO_ 566 CORNER_RADAR_235_OBJECTS_236: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 566 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 566 30;
|
||||
|
||||
BO_ 567 CORNER_RADAR_235_OBJECTS_237: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 567 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 567 30;
|
||||
|
||||
BO_ 568 CORNER_RADAR_235_OBJECTS_238: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 568 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 568 30;
|
||||
|
||||
BO_ 569 CORNER_RADAR_235_OBJECTS_239: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 569 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 569 30;
|
||||
|
||||
BO_ 570 CORNER_RADAR_235_OBJECTS_23a: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 570 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 570 30;
|
||||
|
||||
BO_ 571 CORNER_RADAR_235_OBJECTS_23b: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 571 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 571 30;
|
||||
|
||||
BO_ 572 CORNER_RADAR_235_OBJECTS_23c: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 572 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 572 30;
|
||||
|
||||
BO_ 573 CORNER_RADAR_235_OBJECTS_23d: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 573 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 573 30;
|
||||
|
||||
BO_ 574 CORNER_RADAR_235_OBJECTS_23e: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 574 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 574 30;
|
||||
|
||||
BO_ 575 CORNER_RADAR_235_OBJECTS_23f: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 575 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 575 30;
|
||||
|
||||
BO_ 576 CORNER_RADAR_235_OBJECTS_240: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 576 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 576 30;
|
||||
|
||||
BO_ 577 CORNER_RADAR_235_OBJECTS_241: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 577 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 577 30;
|
||||
|
||||
BO_ 578 CORNER_RADAR_235_OBJECTS_242: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 578 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 578 30;
|
||||
|
||||
BO_ 579 CORNER_RADAR_235_OBJECTS_243: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 579 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 579 30;
|
||||
|
||||
BO_ 580 CORNER_RADAR_235_OBJECTS_244: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 580 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 580 30;
|
||||
|
||||
BO_ 581 CORNER_RADAR_235_OBJECTS_245: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 581 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 581 30;
|
||||
|
||||
BO_ 582 CORNER_RADAR_235_OBJECTS_246: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 582 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 582 30;
|
||||
|
||||
BO_ 583 CORNER_RADAR_235_OBJECTS_247: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 583 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 583 30;
|
||||
|
||||
BO_ 584 CORNER_RADAR_235_OBJECTS_248: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
CM_ BO_ 584 "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ 584 30;
|
||||
71
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_corner_radar_235.py
Executable file
71
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_corner_radar_235.py
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
|
||||
HEADER = """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_
|
||||
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 RADAR
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def write_object_msg(f, addr):
|
||||
name = f"CORNER_RADAR_235_OBJECTS_{addr:x}"
|
||||
f.write(f"""
|
||||
BO_ {addr} {name}: 32 RADAR
|
||||
SG_ OBJ_QUAL_LEVEL : 24|7@1+ (1,0) [0|100] "%" XXX
|
||||
SG_ OBJ_AGE : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ OBJ_OBJECT_ID : 44|7@1+ (1,0) [0|127] "" XXX
|
||||
SG_ OBJ_REL_POS_X : 64|13@1+ (0.05,0) [0|409.55] "m" XXX
|
||||
SG_ OBJ_REL_POS_Y : 78|12@1+ (0.05,-102.4) [-102.4|102.35] "m" XXX
|
||||
SG_ OBJ_REL_VEL_X : 91|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX
|
||||
SG_ OBJ_REL_VEL_Y : 104|10@1+ (0.05,-25) [-25|26.15] "m/s" XXX
|
||||
SG_ OBJ_REL_ACCEL_X : 115|9@1- (0.05,0) [-12.8|12.75] "m/s^2" XXX
|
||||
""")
|
||||
|
||||
f.write(f"""CM_ BO_ {addr} "Corner radar object payload on bus 1. Only signals consumed by Hyundai radar_interface are defined.";
|
||||
BA_ "GenMsgCycleTime" BO_ {addr} 30;
|
||||
""")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbc_name = os.path.basename(__file__).replace(".py", ".dbc")
|
||||
out_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), dbc_name)
|
||||
with open(out_path, "w", encoding="ascii") as f:
|
||||
f.write(HEADER)
|
||||
f.write('BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000;\n')
|
||||
f.write('BA_DEF_DEF_ "GenMsgCycleTime" 0;\n')
|
||||
for addr in range(0x235, 0x249):
|
||||
write_object_msg(f, addr)
|
||||
@@ -0,0 +1,614 @@
|
||||
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_
|
||||
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 RADAR
|
||||
|
||||
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000;
|
||||
BA_DEF_DEF_ "GenMsgCycleTime" 0;
|
||||
|
||||
BO_ 1072 CORNER_RADAR_430_OBJECTS_430: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1072 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1072 30;
|
||||
|
||||
BO_ 1073 CORNER_RADAR_430_OBJECTS_431: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1073 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1073 30;
|
||||
|
||||
BO_ 1074 CORNER_RADAR_430_OBJECTS_432: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1074 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1074 30;
|
||||
|
||||
BO_ 1075 CORNER_RADAR_430_OBJECTS_433: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1075 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1075 30;
|
||||
|
||||
BO_ 1076 CORNER_RADAR_430_OBJECTS_434: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1076 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1076 30;
|
||||
|
||||
BO_ 1077 CORNER_RADAR_430_OBJECTS_435: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1077 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1077 30;
|
||||
|
||||
BO_ 1078 CORNER_RADAR_430_OBJECTS_436: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1078 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1078 30;
|
||||
|
||||
BO_ 1079 CORNER_RADAR_430_OBJECTS_437: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1079 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1079 30;
|
||||
|
||||
BO_ 1088 CORNER_RADAR_430_OBJECTS_440: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1088 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1088 30;
|
||||
|
||||
BO_ 1089 CORNER_RADAR_430_OBJECTS_441: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1089 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1089 30;
|
||||
|
||||
BO_ 1090 CORNER_RADAR_430_OBJECTS_442: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1090 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1090 30;
|
||||
|
||||
BO_ 1091 CORNER_RADAR_430_OBJECTS_443: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1091 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1091 30;
|
||||
|
||||
BO_ 1092 CORNER_RADAR_430_OBJECTS_444: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1092 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1092 30;
|
||||
|
||||
BO_ 1093 CORNER_RADAR_430_OBJECTS_445: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1093 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1093 30;
|
||||
|
||||
BO_ 1094 CORNER_RADAR_430_OBJECTS_446: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1094 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1094 30;
|
||||
|
||||
BO_ 1095 CORNER_RADAR_430_OBJECTS_447: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_DISTANCE_RAW : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT1_META_13_15 : 45|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT1_META_BYTE_2 : 48|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT1_META_BYTE_3 : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_DISTANCE_RAW : 64|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT2_META_13_15 : 77|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT2_META_BYTE_2 : 80|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT2_META_BYTE_3 : 88|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_DISTANCE_RAW : 96|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT3_META_13_15 : 109|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT3_META_BYTE_2 : 112|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT3_META_BYTE_3 : 120|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_DISTANCE_RAW : 128|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT4_META_13_15 : 141|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT4_META_BYTE_2 : 144|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT4_META_BYTE_3 : 152|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_DISTANCE_RAW : 160|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT5_META_13_15 : 173|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT5_META_BYTE_2 : 176|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT5_META_BYTE_3 : 184|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_DISTANCE_RAW : 192|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT6_META_13_15 : 205|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT6_META_BYTE_2 : 208|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT6_META_BYTE_3 : 216|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_DISTANCE_RAW : 224|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ SLOT7_META_13_15 : 237|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SLOT7_META_BYTE_2 : 240|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLOT7_META_BYTE_3 : 248|8@1+ (1,0) [0|255] "" XXX
|
||||
CM_ BO_ 1095 "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ 1095 30;
|
||||
76
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_corner_radar_430.py
Executable file
76
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_corner_radar_430.py
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
|
||||
HEADER = """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_
|
||||
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 RADAR
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def write_object_msg(f, addr):
|
||||
name = f"CORNER_RADAR_430_OBJECTS_{addr:x}"
|
||||
f.write(f"""
|
||||
BO_ {addr} {name}: 32 RADAR
|
||||
SG_ HEADER_BYTE_0 : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_1 : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_2 : 16|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ HEADER_BYTE_3 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
""")
|
||||
for slot in range(7):
|
||||
bit = 32 + slot * 32
|
||||
prefix = f"SLOT{slot + 1}"
|
||||
f.write(f""" SG_ {prefix}_DISTANCE_RAW : {bit}|13@1+ (1,0) [0|8191] "" XXX
|
||||
SG_ {prefix}_META_13_15 : {bit + 13}|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ {prefix}_META_BYTE_2 : {bit + 16}|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ {prefix}_META_BYTE_3 : {bit + 24}|8@1+ (1,0) [0|255] "" XXX
|
||||
""")
|
||||
f.write(f"""CM_ BO_ {addr} "IONIQ 9 candidate corner radar bin container. 0x430-0x437 correlate with left side and 0x440-0x447 with right side. Bytes 4-31 appear as seven 4-byte slots; lower 13 bits are a distance candidate at 0.05 m scale. This DBC intentionally exposes only raw candidate fields until lateral and velocity fields are validated.";
|
||||
BA_ "GenMsgCycleTime" BO_ {addr} 30;
|
||||
""")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbc_name = os.path.basename(__file__).replace(".py", ".dbc")
|
||||
out_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), dbc_name)
|
||||
with open(out_path, "w", encoding="ascii") as f:
|
||||
f.write(HEADER)
|
||||
f.write('BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000;\n')
|
||||
f.write('BA_DEF_DEF_ "GenMsgCycleTime" 0;\n')
|
||||
for addr in range(0x430, 0x438):
|
||||
write_object_msg(f, addr)
|
||||
for addr in range(0x440, 0x448):
|
||||
write_object_msg(f, addr)
|
||||
1178
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_radar.dbc
Normal file
1178
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_radar.dbc
Normal file
File diff suppressed because it is too large
Load Diff
106
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_radar.py
Executable file
106
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_canfd_radar.py
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/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_ NEW_SIGNAL_25 : 26|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ NEW_SIGNAL_24 : 28|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_21 : 36|5@0+ (1,0) [0|31] "" XXX
|
||||
SG_ NEW_SIGNAL_20 : 39|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ VALID_CNT1 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_15 : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_14 : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_5 : 63|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ LONG_DIST1 : 64|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ LAT_DIST1 : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ REL_SPEED1 : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ NEW_SIGNAL_16 : 103|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LAT_SPEED1 : 104|13@1- (0.01,0) [0|8191] "" XXX
|
||||
SG_ REL_ACCEL1 : 118|10@1- (0.05,0) [0|1023] "" XXX
|
||||
SG_ NEW_SIGNAL_27 : 154|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ NEW_SIGNAL_26 : 156|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_23 : 164|5@0+ (1,0) [0|31] "" XXX
|
||||
SG_ NEW_SIGNAL_22 : 167|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ VALID_CNT2 : 175|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_13 : 179|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_12 : 183|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_11 : 191|8@0- (1,0) [0|255] "" XXX
|
||||
SG_ LONG_DIST2 : 192|12@1+ (0.05,0) [0|4095] "" XXX
|
||||
SG_ LAT_DIST2 : 204|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ REL_SPEED2 : 216|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ NEW_SIGNAL_17 : 231|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LAT_SPEED2 : 232|13@1- (0.01,0) [0|8191] "" XXX
|
||||
SG_ REL_ACCEL2 : 246|10@1- (0.05,0) [0|1023] "" XXX
|
||||
""")
|
||||
for a in range(0x3a5, 0x3a5 + 32):
|
||||
f.write(f"""
|
||||
BO_ {a} RADAR_TRACK_{a:x}: 24 RADAR
|
||||
SG_ VALID : 25|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ VALID2 : 28|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ PROB : 30|10@1+ (1,0) [0|1023] "" XXX
|
||||
SG_ VALID_CNT : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_7 : 51|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_6 : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ NEW_SIGNAL_2 : 62|7@0- (1,0) [0|127] "" XXX
|
||||
SG_ LONG_DIST : 63|13@1+ (0.05,0) [0|8191] "" XXX
|
||||
SG_ LAT_DIST : 76|12@1- (0.05,0) [0|4095] "" XXX
|
||||
SG_ REL_SPEED : 88|14@1- (0.01,0) [0|16383] "" XXX
|
||||
SG_ IN_MYLANE : 103|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LAT_SPEED : 104|13@1- (0.01,0) [0|8191] "" XXX
|
||||
SG_ REL_ACCEL : 118|10@1- (0.05,0) [0|1023] "" XXX
|
||||
""")
|
||||
|
||||
# Group 3 radar object list:
|
||||
# 30 one-object messages at 20 Hz, with an empty distance sentinel of 0x7ff.
|
||||
for a in range(0x400, 0x400 + 30):
|
||||
f.write(f"""
|
||||
BO_ {a} RADAR_TRACK_{a:x}: 24 RADAR
|
||||
SG_ OBJECT_LENGTH : 41|7@1+ (0.1,0) [0|12.7] "m" XXX
|
||||
SG_ LONG_DIST : 64|11@1+ (0.1,0) [0|204.7] "m" XXX
|
||||
SG_ LAT_DIST : 75|12@1- (0.05,0) [-102.4|102.35] "m" XXX
|
||||
SG_ REL_SPEED : 87|11@1- (0.1,0) [-102.4|102.3] "m/s" XXX
|
||||
""")
|
||||
65
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_kia_denso_front_radar.py
Executable file
65
iqdbc_repo/iqdbc/dbc/generator/hyundai/hyundai_kia_denso_front_radar.py
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/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
|
||||
""")
|
||||
|
||||
# EN: The Denso DNMWR006 radar in the 2018-2019 Kia Sorento UM publishes
|
||||
# eight stable tracked objects at 20 Hz from 0x500 through 0x507.
|
||||
# Do not decode 0x508+ distance-sorted raw detections as stable tracks.
|
||||
# KO: 2018-2019 Kia Sorento UM의 Denso DNMWR006 레이더는 0x500~0x507에서
|
||||
# 안정적인 추적 객체 8개를 20Hz로 전송함. 0x508 이후의 거리순 raw
|
||||
# detection은 안정적인 트랙으로 디코딩하지 않음.
|
||||
for address in range(0x500, 0x508):
|
||||
f.write(f"""
|
||||
BO_ {address} RADAR_TRACK_{address:x}: 8 RADAR
|
||||
SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ LONG_DIST : 15|16@0+ (0.00625,0) [0|409.59375] "m" XXX
|
||||
SG_ LAT_DIST : 31|11@0- (0.0625,0) [-64|63.9375] "m" XXX
|
||||
SG_ OBJECT_FLAGS_1 : 36|5@0+ (1,0) [0|31] "" XXX
|
||||
SG_ OBJECT_FLAG_2 : 47|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ REL_SPEED : 46|12@0- (0.015625,0) [-32|31.984375] "m/s" XXX
|
||||
SG_ OBJECT_STATE : 50|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ OBJECT_DETAIL : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
""")
|
||||
@@ -1,4 +1,4 @@
|
||||
CM_ "IMPORT _hyundai_canfd_common.dbc";
|
||||
CM_ "IMPORT _hyundai_common.dbc";
|
||||
|
||||
BO_ 67 DATC13: 8 XXX
|
||||
SG_ CF_Datc_AcDisp : 22|2@1+ (1,0) [0|0] "" XXX
|
||||
|
||||
@@ -1341,6 +1341,17 @@ BO_ 273 TCU11: 8 TCU
|
||||
BO_ 16 ACU13: 8 ACU
|
||||
SG_ CF_Acu_CshAct : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CUBIS,IBOX,ODS
|
||||
|
||||
BO_ 1007 CRUISE_BUTTON_ALT: 8 XXX
|
||||
SG_ SET_ME_1 : 52|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CruiseSwMain : 58|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CruiseSwState : 60|3@1+ (1,0) [0|7] "" XXX
|
||||
|
||||
BO_ 1046 CRUISE_BUTTON_LFA: 8 XXX
|
||||
SG_ NEW_SIGNAL_2 : 49|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ NEW_SIGNAL_1 : 54|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ NEW_SIGNAL_3 : 57|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CruiseSwLfa : 58|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1040 CGW_USM1: 8 BCM
|
||||
SG_ CF_Gway_ATTurnRValue : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU
|
||||
SG_ CF_Gway_PTGMRValue : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU
|
||||
@@ -1384,6 +1395,8 @@ BO_ 1290 SCC13: 8 SCC
|
||||
SG_ SCC_Equip : 3|1@1+ (1,0) [0|1] "" ESC
|
||||
SG_ AebDrvSetStatus : 4|3@1+ (1,0) [0|7] "" CLU,ESC
|
||||
SG_ Lead_Veh_Dep_Alert_USM : 13|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_1 : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_2 : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 1287 TCS15: 4 ESC
|
||||
SG_ ABS_W_LAMP : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,CUBIS,IBOX
|
||||
@@ -1478,18 +1491,21 @@ BO_ 905 SCC14: 8 SCC
|
||||
SG_ ComfortBandLower : 6|6@1+ (0.02,0) [0|1.26] "m/s^2" ESC
|
||||
SG_ JerkUpperLimit : 12|7@1+ (0.1,0) [0|12.7] "m/s^3" ESC
|
||||
SG_ JerkLowerLimit : 19|7@1+ (0.1,0) [0|12.7] "m/s^3" ESC
|
||||
SG_ NEW_SIGNAL_1 : 26|6@1+ (1,0) [0|63] "" XXX
|
||||
SG_ ACCMode : 32|3@1+ (1,0) [0|7] "" CLU,HUD,LDWS_LKAS,ESC
|
||||
SG_ ObjGap : 56|8@1+ (1,0) [0|255] "" CLU,HUD,ESC
|
||||
SG_ ObjDistStat : 42|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ NEW_SIGNAL_2 : 55|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ ObjGap : 56|8@1+ (1,0) [0|255] "" CLU,HUD,ESC
|
||||
|
||||
BO_ 1157 LFAHDA_MFC: 4 XXX
|
||||
BO_ 1157 LFAHDA_MFC: 8 XXX
|
||||
SG_ HDA_USM : 0|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ HDA_Active : 2|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ HDA_Icon_State : 3|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ HDA_Chime : 7|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ HDA_VSetReq : 8|8@1+ (1,0) [0|255] "km/h" XXX
|
||||
SG_ LFA_SysWarning : 16|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ NEW_SIGNAL_1 : 20|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ HDA_Icon_Wheel : 20|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ HDA_LdwSysState : 21|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ LFA_Icon_State : 24|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ LFA_USM : 27|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ HDA_SysWarning : 29|2@1+ (1,0) [0|3] "" XXX
|
||||
@@ -1497,11 +1513,10 @@ BO_ 1157 LFAHDA_MFC: 4 XXX
|
||||
BO_ 913 BCM_PO_11: 8 Vector__XXX
|
||||
SG_ BCM_Door_Dri_Status : 5|1@0+ (1,0) [0|1] "" PT_ESC_ABS
|
||||
SG_ BCM_Shift_R_MT_SW_Status : 39|2@0+ (1,0) [0|3] "" PT_ESC_ABS
|
||||
SG_ LDA_BTN : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LFA_Pressed : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1426 LABEL11: 8 XXX
|
||||
SG_ CC_React : 34|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ CC_ACT : 35|1@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 910 WHL_SPD12_FS: 5 iBAU
|
||||
SG_ CRC : 0|8@1+ (1,0) [0|0] "" Vector__XXX
|
||||
@@ -1522,7 +1537,10 @@ BO_ 865 ADAS_PRK_11: 8 ADAS_PRK
|
||||
SG_ PCA_CHECK_SUM : 48|8@1+ (1,0) [0|0] "" Vector__XXX
|
||||
|
||||
BO_ 882 ELECT_GEAR: 8 XXX
|
||||
SG_ Elect_Gear_Shifter : 16|4@1+ (1,0) [0|7] "" CLU
|
||||
SG_ Elect_Gear_Shifter : 16|4@1+ (1,0) [0|7] "" CLU
|
||||
SG_ Elect_Gear_Shifter_NEXO : 16|16@1+ (1,0) [0|65535] "" CLU
|
||||
SG_ Elect_Gear_Step : 22|3@0+ (1,0) [0|7] "" XXX
|
||||
SG_ Elect_Motor_Speed : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SLC_ON : 31|1@0+ (1,0) [0|1] "" CLU
|
||||
SG_ SLC_SET_SPEED : 32|8@1+ (1,0) [0|255] "" CLU
|
||||
|
||||
@@ -1534,14 +1552,12 @@ BO_ 881 E_EMS11: 8 XXX
|
||||
SG_ Cruise_Limit_Target : 23|8@1+ (1,0) [0|15] "" XXX
|
||||
SG_ Accel_Pedal_Pos : 31|8@1+ (1,0) [0|254] "" XXX
|
||||
SG_ CR_Vcu_AccPedDep_Pos : 56|8@1+ (1,0) [0|254] "" XXX
|
||||
SG_ Engine_Run : 14|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ N : 18|13@1+ (1,0) [0|15] "" XXX
|
||||
|
||||
BO_ 1355 EV_PC6: 8 CGW
|
||||
SG_ CF_Vcu_SbwWarnMsg : 16|3@1+ (1,0) [0|7] "" Vector__XXX
|
||||
|
||||
BO_ 1429 E_CRUISE_CONTROL: 8 XXX
|
||||
SG_ CRUISE_LAMP_M : 50|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CRUISE_LAMP_S : 51|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1430 EV_PC2: 8 CGW
|
||||
SG_ CR_Ldc_ActVol_LS_V : 32|8@1+ (0.1,0) [0|0] "V" Vector__XXX
|
||||
|
||||
@@ -1584,7 +1600,7 @@ BO_ 352 AHB1: 8 iBAU
|
||||
SG_ CF_Ahb_Bzzr : 26|1@1+ (1,0) [0|1] "" Vector__XXX
|
||||
SG_ CF_Ahb_ChkSum : 56|8@1+ (1,0) [0|255] "" Vector__XXX
|
||||
|
||||
BO_ 1191 MFC_4a7: 8 XXX
|
||||
BO_ 1191 MFC_4a7: 2 XXX
|
||||
SG_ PAINT1 : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1162 BCA11: 8 BCW
|
||||
@@ -1658,33 +1674,22 @@ BO_ 1348 Navi_HU: 8 XXX
|
||||
SG_ SpeedLim_Nav_General : 29|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SpeedLim_Nav_Cam : 30|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 683 ESCC: 8 XXX
|
||||
SG_ FCA_CmdAct : 0|1@1+ (1,0) [0|1] "" ESC
|
||||
SG_ CF_VSM_Warn_FCA11 : 1|2@1+ (1,0) [0|3] "" ACU,CLU,ESC
|
||||
SG_ AEB_CmdAct : 3|1@1+ (1,0) [0|1] "" ESC
|
||||
SG_ CF_VSM_Warn_SCC12 : 4|2@1+ (1,0) [0|3] "" CLU,ESC,IAP
|
||||
SG_ CF_VSM_DecCmdAct_SCC12 : 6|1@1+ (1,0) [0|1] "" ESC
|
||||
SG_ CF_VSM_DecCmdAct_FCA11 : 7|1@1+ (1,0) [0|1] "" ESC
|
||||
SG_ CR_VSM_DecCmd_SCC12 : 8|8@1+ (0.01,0) [0|2.55] "g" ESC
|
||||
SG_ ObjValid : 16|1@1+ (1,0) [0|1] "" CLU,ESC,TCU
|
||||
SG_ ACC_ObjStatus : 17|2@1+ (1,0) [0|3] "" ABS,ESC
|
||||
SG_ ACC_ObjLatPos : 24|9@1+ (0.1,-20) [-20|31.1] "m" ABS,ESC
|
||||
SG_ ACC_ObjRelSpd : 44|12@1+ (0.1,-170) [-170|239.5] "m/s" ABS,ESC
|
||||
SG_ ACC_ObjDist : 33|11@1+ (0.1,0) [0|204.7] "m" ABS,ESC
|
||||
SG_ CR_VSM_DecCmd_FCA11 : 56|8@1+ (0.01,0) [0|2.55] "g" ESC
|
||||
|
||||
BO_ 1291 EV_Info: 8 XXX
|
||||
SG_ OPKR_EV_Charge_Level : 17|7@1+ (1,0) [0|100] "%" XXX
|
||||
CM_ "BO_ E_EMS11: All (plug-in) hybrids use this gas signal: CR_Vcu_AccPedDep_Pos, and all EVs use the Accel_Pedal_Pos signal. See hyundai/values.py for a specific car list";
|
||||
CM_ 145 "Contains signal with accelerator pedal press. Used by fuel cell hydrogen-powered (FCEV) cars such as the 2021 Hyundai Nexo.";
|
||||
CM_ 512 "Contains signal with gear shifter. Used by fuel cell hydrogen-powered (FCEV) cars such as the 2021 Hyundai Nexo.";
|
||||
CM_ SG_ 871 CF_Lvr_IsgState "Idle Stop and Go";
|
||||
CM_ SG_ 1056 SCCInfoDisplay "Goes to 1 for a second while transitioning from Cruise Control to No Message";
|
||||
CM_ SG_ 1348 SpeedLim_Nav_Clu "Speed limit displayed on Nav, Cluster and HUD";
|
||||
CM_ SG_ 1348 SpeedLim_Nav_Cam "Speed limit if speed cam exist";
|
||||
VAL_ 882 Elect_Gear_Shifter_NEXO 1546 "D" 2314 "N" 2566 "R" 2569 "P";
|
||||
|
||||
VAL_ 274 CUR_GR 1 "D" 2 "D" 3 "D" 4 "D" 5 "D" 6 "D" 7 "D" 8 "D" 14 "R" 0 "P";
|
||||
VAL_ 512 HYDROGEN_GEAR_SHIFTER 5 "D" 8 "S" 6 "N" 7 "R" 0 "P";
|
||||
VAL_ 871 CF_Lvr_IsgState 0 "enabled" 1 "activated" 2 "unknown" 3 "disabled";
|
||||
VAL_ 871 CF_Lvr_Gear 12 "T" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P";
|
||||
VAL_ 882 Elect_Gear_Shifter 4 "S" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P";
|
||||
VAL_ 882 Elect_Gear_Shifter 4 "S" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P" 12 "T";
|
||||
VAL_ 905 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled";
|
||||
VAL_ 905 ObjDistStat 0 "no_object" 1 "receding" 2 "approaching";
|
||||
VAL_ 909 CF_VSM_Warn 2 "FCW" 3 "AEB";
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
"""
|
||||
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
|
||||
"""
|
||||
@@ -1,99 +0,0 @@
|
||||
from enum import StrEnum
|
||||
from collections import namedtuple
|
||||
|
||||
from iqdbc.car import Bus, DT_CTRL, structs
|
||||
from iqdbc.car.hyundai.values import CAR
|
||||
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ
|
||||
from iqdbc.iqpilot.aol_base import AolCarStateBase
|
||||
from iqdbc.can.parser import CANParser
|
||||
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
|
||||
AolDataIQ = namedtuple("AolDataIQ",
|
||||
["enable_aol", "lat_active", "disengaging", "paused"])
|
||||
|
||||
|
||||
class AolCarController:
|
||||
def __init__(self):
|
||||
self.aol = AolDataIQ(False, False, False, False)
|
||||
|
||||
self.lat_disengage_blink = 0
|
||||
self.lat_disengage_init = False
|
||||
self.prev_lat_active = False
|
||||
|
||||
self.lkas_icon = 0
|
||||
self.lfa_icon = 0
|
||||
|
||||
def aol_status_update(self, CC: structs.CarControl, CC_IQ: structs.IQCarControl, frame: int) -> AolDataIQ:
|
||||
enable_aol = CC_IQ.aol.available
|
||||
|
||||
if CC.latActive:
|
||||
self.lat_disengage_init = False
|
||||
elif self.prev_lat_active:
|
||||
self.lat_disengage_init = True
|
||||
|
||||
if not self.lat_disengage_init:
|
||||
self.lat_disengage_blink = frame
|
||||
|
||||
paused = CC_IQ.aol.enabled and not CC.latActive
|
||||
disengaging = (frame - self.lat_disengage_blink) * DT_CTRL < 1.0 if self.lat_disengage_init else False
|
||||
|
||||
self.prev_lat_active = CC.latActive
|
||||
|
||||
return AolDataIQ(enable_aol, CC.latActive, disengaging, paused)
|
||||
|
||||
def create_lkas_icon(self, CP: structs.CarParams, enabled: bool) -> int:
|
||||
if self.aol.enable_aol:
|
||||
lkas_icon = 2 if self.aol.lat_active else 3 if self.aol.disengaging else 1
|
||||
else:
|
||||
lkas_icon = 2 if enabled else 1
|
||||
|
||||
if CP.carFingerprint in (CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.HYUNDAI_KONA_NON_SCC):
|
||||
lkas_icon = 3 if (self.aol.lat_active if self.aol.enable_aol else enabled) else 1
|
||||
|
||||
return lkas_icon
|
||||
|
||||
def create_lfa_icon(self, enabled: bool) -> int:
|
||||
if self.aol.enable_aol:
|
||||
lfa_icon = 2 if self.aol.lat_active else 3 if self.aol.disengaging else 1 if self.aol.paused else 0
|
||||
else:
|
||||
lfa_icon = 2 if enabled else 0
|
||||
|
||||
return lfa_icon
|
||||
|
||||
def update(self, CP: structs.CarParams, CC: structs.CarControl, CC_IQ: structs.IQCarControl, frame: int) -> None:
|
||||
self.aol = self.aol_status_update(CC, CC_IQ, frame)
|
||||
self.lkas_icon = self.create_lkas_icon(CP, CC.enabled)
|
||||
self.lfa_icon = self.create_lfa_icon(CC.enabled)
|
||||
|
||||
|
||||
class AolCarState(AolCarStateBase):
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.CarParams):
|
||||
super().__init__(CP, CP_IQ)
|
||||
self.main_cruise_enabled: bool = False
|
||||
|
||||
@staticmethod
|
||||
def get_parser(CP, CP_IQ, pt_messages) -> None:
|
||||
pass
|
||||
|
||||
def get_main_cruise(self, ret: structs.CarState) -> bool:
|
||||
if self.CP_IQ.flags & HyundaiFlagsIQ.MAIN_BTN_LONG_TOGGLE:
|
||||
if any(be.type == ButtonType.mainCruise and be.pressed for be in ret.buttonEvents):
|
||||
self.main_cruise_enabled = not self.main_cruise_enabled
|
||||
else:
|
||||
self.main_cruise_enabled = True
|
||||
|
||||
return self.main_cruise_enabled if ret.cruiseState.available else False
|
||||
|
||||
def update_aol(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
|
||||
pass
|
||||
|
||||
def update_aol_canfd(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
|
||||
cp = can_parsers[Bus.pt]
|
||||
cp_cam = can_parsers[Bus.cam]
|
||||
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp
|
||||
ret.cruiseState.available = cp_cruise_info.vl["SCC_CONTROL"]["MainMode_ACC"] == 1
|
||||
@@ -1,79 +0,0 @@
|
||||
from enum import StrEnum
|
||||
|
||||
from iqdbc.car import Bus, structs
|
||||
from iqdbc.can.parser import CANParser
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ
|
||||
|
||||
|
||||
class CarStateExt:
|
||||
def __init__(self, CP, CP_IQ):
|
||||
self.CP = CP
|
||||
self.CP_IQ = CP_IQ
|
||||
|
||||
self.aBasis = 0.0
|
||||
|
||||
def update_speed_limit(self, cp, cp_cam) -> float:
|
||||
speed_limit = 0
|
||||
|
||||
if self.CP.flags & HyundaiFlags.CANFD:
|
||||
if self.CP_IQ.flags & HyundaiFlagsIQ.SPEED_LIMIT_AVAILABLE:
|
||||
bus = cp if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING else cp_cam
|
||||
speed_limit = bus.vl["FR_CMR_02_100ms"]["ISLW_SpdCluMainDis"]
|
||||
else:
|
||||
nav, cam = 0, 0
|
||||
if self.CP_IQ.flags & HyundaiFlagsIQ.SPEED_LIMIT_AVAILABLE:
|
||||
nav = cp.vl["Navi_HU"]["SpeedLim_Nav_Clu"]
|
||||
if self.CP_IQ.flags & HyundaiFlagsIQ.HAS_LKAS12:
|
||||
cam = cp_cam.vl["LKAS12"]["CF_Lkas_TsrSpeed_Display_Clu"]
|
||||
|
||||
speed_limit = cam if cam not in (0, 255) else nav
|
||||
|
||||
if speed_limit in (0, 255):
|
||||
speed_limit = 0
|
||||
|
||||
return speed_limit
|
||||
|
||||
def update(self, ret: structs.CarState, ret_iq: structs.IQCarState, can_parsers: dict[StrEnum, CANParser], speed_conv: float) -> None:
|
||||
cp = can_parsers[Bus.pt]
|
||||
cp_cam = can_parsers[Bus.cam]
|
||||
|
||||
self.aBasis = cp.vl["TCS13"]["aBasis"]
|
||||
|
||||
if self.CP_IQ.flags & HyundaiFlagsIQ.NON_SCC:
|
||||
cruise_msg = "LABEL11" if self.CP.flags & HyundaiFlags.EV else \
|
||||
"E_CRUISE_CONTROL" if self.CP.flags & HyundaiFlags.HYBRID else \
|
||||
"EMS16"
|
||||
cruise_available_sig = "CC_React" if self.CP.flags & HyundaiFlags.EV else "CRUISE_LAMP_M"
|
||||
cruise_enabled_sig = "CC_ACT" if self.CP.flags & HyundaiFlags.EV else "CRUISE_LAMP_S"
|
||||
cruise_speed_msg = "E_EMS11" if self.CP.flags & HyundaiFlags.EV else \
|
||||
"ELECT_GEAR" if self.CP.flags & HyundaiFlags.HYBRID else \
|
||||
"LVR12"
|
||||
cruise_speed_sig = "Cruise_Limit_Target" if self.CP.flags & HyundaiFlags.EV else \
|
||||
"SLC_SET_SPEED" if self.CP.flags & HyundaiFlags.HYBRID else \
|
||||
"CF_Lvr_CruiseSet"
|
||||
ret.cruiseState.available = cp.vl[cruise_msg][cruise_available_sig] != 0
|
||||
ret.cruiseState.enabled = cp.vl[cruise_msg][cruise_enabled_sig] != 0
|
||||
ret.cruiseState.speed = cp.vl[cruise_speed_msg][cruise_speed_sig] * speed_conv
|
||||
ret.cruiseState.standstill = False
|
||||
ret.cruiseState.nonAdaptive = False
|
||||
|
||||
if not self.CP_IQ.flags & HyundaiFlagsIQ.NON_SCC_NO_FCA:
|
||||
cp_cruise = cp if self.CP_IQ.flags & HyundaiFlagsIQ.NON_SCC_RADAR_FCA else cp_cam
|
||||
|
||||
aeb_src = "FCA11"
|
||||
aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0
|
||||
aeb_braking = cp_cruise.vl[aeb_src]["CF_VSM_DecCmdAct"] != 0 or cp_cruise.vl[aeb_src]["FCA_CmdAct"] != 0
|
||||
ret.stockFcw = aeb_warning and not aeb_braking
|
||||
ret.stockAeb = aeb_warning and aeb_braking
|
||||
|
||||
ret_iq.speedLimit = self.update_speed_limit(cp, cp_cam) * speed_conv
|
||||
|
||||
def update_canfd_ext(self, ret: structs.CarState, ret_iq: structs.IQCarState, can_parsers: dict[StrEnum, CANParser],
|
||||
speed_factor: float) -> None:
|
||||
cp = can_parsers[Bus.pt]
|
||||
cp_cam = can_parsers[Bus.cam]
|
||||
|
||||
self.aBasis = cp.vl["TCS"]["aBasis"]
|
||||
|
||||
ret_iq.speedLimit = self.update_speed_limit(cp, cp_cam) * speed_factor
|
||||
@@ -1,67 +0,0 @@
|
||||
from iqdbc.car import uds
|
||||
from iqdbc.car.carlog import carlog
|
||||
from iqdbc.car.isotp_parallel_query import IsoTpParallelQuery
|
||||
|
||||
DEVELOPER_DIAGNOSTIC = 0x07
|
||||
CUSTOM_DIAGNOSTIC_REQUEST = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, DEVELOPER_DIAGNOSTIC])
|
||||
CUSTOM_DIAGNOSTIC_RESPONSE = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL + 0x40, DEVELOPER_DIAGNOSTIC])
|
||||
|
||||
READ_DATA_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER])
|
||||
READ_DATA_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40])
|
||||
|
||||
WRITE_DATA_REQUEST = bytes([uds.SERVICE_TYPE.WRITE_DATA_BY_IDENTIFIER])
|
||||
WRITE_DATA_RESPONSE = bytes([uds.SERVICE_TYPE.WRITE_DATA_BY_IDENTIFIER + 0x40])
|
||||
|
||||
CONFIG_DATA_ID = bytes([0x01, 0x42])
|
||||
DEFAULT_CONFIG = bytes([0x00, 0x00, 0x00, 0x01, 0x00, 0x00])
|
||||
TRACKS_ENABLED_CONFIG = bytes([0x00, 0x00, 0x00, 0x01, 0x00, 0x01])
|
||||
TRACKS_ENABLED_CONFIG_BYTES = b"\x00\x00\x01\x00\x01"
|
||||
|
||||
|
||||
def enable_radar_tracks(logcan, sendcan, bus=0, addr=0x7d0, timeout=0.1, retry=2):
|
||||
carlog.error("radar_tracks: enabling ...")
|
||||
|
||||
for i in range(retry):
|
||||
try:
|
||||
query = IsoTpParallelQuery(sendcan, logcan, bus, [addr], [CUSTOM_DIAGNOSTIC_REQUEST], [CUSTOM_DIAGNOSTIC_RESPONSE])
|
||||
|
||||
for _, _ in query.get_data(timeout).items():
|
||||
carlog.error("radar_tracks: check current config ...")
|
||||
|
||||
request = READ_DATA_REQUEST + CONFIG_DATA_ID
|
||||
query = IsoTpParallelQuery(sendcan, logcan, bus, [addr], [request], [READ_DATA_RESPONSE])
|
||||
|
||||
for _, data in query.get_data(timeout).items():
|
||||
current_config = data[3:]
|
||||
|
||||
carlog.error(f"radar_tracks: current config: {current_config.hex()}")
|
||||
|
||||
if current_config == TRACKS_ENABLED_CONFIG_BYTES:
|
||||
carlog.error("radar_tracks: already enabled, skipping ...")
|
||||
else:
|
||||
carlog.error("radar_tracks: reconfigure radar to output radar points ...")
|
||||
request = WRITE_DATA_REQUEST + CONFIG_DATA_ID + TRACKS_ENABLED_CONFIG
|
||||
query = IsoTpParallelQuery(sendcan, logcan, bus, [addr], [request], [WRITE_DATA_RESPONSE])
|
||||
query.get_data(0)
|
||||
|
||||
carlog.error("radar_tracks: successfully enabled")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
carlog.exception(f"radar_tracks exception: {e}")
|
||||
|
||||
carlog.error(f"radar_tracks retry ({i + 1}) ...")
|
||||
carlog.error("radar_tracks: failed")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import time
|
||||
import cereal.messaging as messaging
|
||||
sendcan = messaging.pub_sock('sendcan')
|
||||
logcan = messaging.sub_sock('can')
|
||||
time.sleep(1)
|
||||
|
||||
enabled = enable_radar_tracks(logcan, sendcan, bus=0, addr=0x7d0, timeout=0.1)
|
||||
print(f"enabled: {enabled}")
|
||||
@@ -1,51 +0,0 @@
|
||||
from iqdbc.car import structs
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ
|
||||
|
||||
ESCC_MSG = 0x2AB
|
||||
|
||||
|
||||
class EnhancedSmartCruiseControl:
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
|
||||
self.CP = CP
|
||||
self.CP_IQ = CP_IQ
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
return self.CP_IQ.flags & HyundaiFlagsIQ.ENHANCED_SCC
|
||||
|
||||
@property
|
||||
def trigger_msg(self):
|
||||
return ESCC_MSG
|
||||
|
||||
def update_car_state(self, car_state):
|
||||
self.car_state = car_state
|
||||
|
||||
def update_scc12(self, values):
|
||||
values["AEB_CmdAct"] = self.car_state.escc_cmd_act
|
||||
values["CF_VSM_Warn"] = self.car_state.escc_aeb_warning
|
||||
values["CF_VSM_DecCmdAct"] = self.car_state.escc_aeb_dec_cmd_act
|
||||
values["CR_VSM_DecCmd"] = self.car_state.escc_aeb_dec_cmd
|
||||
values["AEB_Status"] = 2 # AEB enabled
|
||||
|
||||
|
||||
class EsccCarStateBase:
|
||||
def __init__(self):
|
||||
self.escc_aeb_warning = 0
|
||||
self.escc_aeb_dec_cmd_act = 0
|
||||
self.escc_cmd_act = 0
|
||||
self.escc_aeb_dec_cmd = 0
|
||||
|
||||
|
||||
class EsccCarController:
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
|
||||
self.ESCC = EnhancedSmartCruiseControl(CP, CP_IQ)
|
||||
|
||||
def update(self, car_state):
|
||||
self.ESCC.update_car_state(car_state)
|
||||
|
||||
|
||||
class EsccRadarInterfaceBase:
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
|
||||
self.ESCC = EnhancedSmartCruiseControl(CP, CP_IQ)
|
||||
self.use_escc = False
|
||||
@@ -1,95 +0,0 @@
|
||||
from iqdbc.car.structs import CarParams
|
||||
from iqdbc.car.hyundai.values import CAR
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
|
||||
FW_VERSIONS_EXT = {
|
||||
CAR.KIA_CEED_PHEV_2022_NON_SCC: {
|
||||
(Ecu.eps, 0x7D4, None): [
|
||||
b'\xf1\x00CD MDPS C 1.00 1.01 56310-XX000 4CPHC101',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7C4, None): [
|
||||
b'\xf1\x00CDH LKAS AT EUR LHD 1.00 1.01 99211-CR700 931',
|
||||
],
|
||||
},
|
||||
CAR.GENESIS_G70_2021_NON_SCC: {
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00IK MDPS R 1.00 1.08 57700-G9200 4I2CL108',
|
||||
],
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00IK__ SCC --CUP 1.00 1.02 96400-G9100 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00IK MFC MT USA LHD 1.00 1.01 95740-G9000 170920',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_KONA_NON_SCC: {
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00OS MDPS C 1.00 1.05 56310J9030\x00 4OSDC105',
|
||||
b'\xf1\x00OS MDPS C 1.00 1.04 56310J9030\x00 4OSDC104',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00OS9 LKAS AT USA LHD 1.00 1.00 95740-J9200 g30',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x006T6J0_C2\x00\x006T6K1051\x00\x00TOS4N20NS2\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.KIA_FORTE_2019_NON_SCC: {
|
||||
(Ecu.eps, 0x7D4, None): [
|
||||
b'\xf1\x00BD MDPS C 1.00 1.04 56310/M6000 4BDDC104',
|
||||
b'\xf1\x00BD MDPS C 1.00 1.05 56310/M6000 4BDDC105',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7C4, None): [
|
||||
b'\xf1\x00BD LKAS AT USA LHD 1.00 1.02 95740-M6000 J31',
|
||||
],
|
||||
},
|
||||
CAR.KIA_FORTE_2021_NON_SCC: {
|
||||
(Ecu.eps, 0x7D4, None): [
|
||||
b'\xf1\x00BD MDPS C 1.00 1.08 56310M6000\x00 4BDDC108',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7C4, None): [
|
||||
b'\xf1\x00BD LKAS AT USA LHD 1.00 1.04 95740-M6000 J33',
|
||||
],
|
||||
},
|
||||
CAR.KIA_SELTOS_2023_NON_SCC: {
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00SP ESC \t 101"\t\x01 58910-Q5510',
|
||||
b'\xf1\x00SP ESC \r 100"\x04\x01 58910-Q5510',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00SP2 MDPS C 1.00 1.04 56310Q5240 4SPSC104',
|
||||
b'\xf1\x00SP2 MDPS C 1.00 1.01 56300Q5920 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00SP2 MFC AT USA LHD 1.00 1.03 99210-Q5500 230208',
|
||||
b'\xf1\x00SP2 MFC AT AUS RHD 1.00 1.02 99210-Q5500 220624',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x006V2B0_C2\x00\x006V2D5051\x00\x00CSP2N20NL0\x00\x00\x00\x00',
|
||||
b'\xf1\x006V2B0_C2\x00\x006V2D4051\x00\x00CSP2N20KL1\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_ELANTRA_2022_NON_SCC: {
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00CN7 MDPS R 1.00 1.04 57700-IB000 4CNNP104',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.01 99210-AB000 210205',
|
||||
b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.00 99210-IB000 210531',
|
||||
],
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00CN ESC \t 100!\x05\x01 58910-IB000',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x00T02601BL T02900A1 WCN7T20XXX900NS4\xf7\xccz\xf6',
|
||||
],
|
||||
},
|
||||
CAR.HYUNDAI_BAYON_1ST_GEN_NON_SCC: {
|
||||
# TODO: Check working route for more FW
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00BC3 LKA AT EUR LHD 1.00 1.01 99211-Q0100 261'
|
||||
],
|
||||
},
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from iqdbc.car import structs
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags
|
||||
|
||||
|
||||
class LeadData(ABC):
|
||||
def __init__(self, object_gap: int, lead_distance: float, lead_rel_speed: float, lead_visible: bool):
|
||||
self.object_gap = object_gap
|
||||
self.lead_distance = lead_distance
|
||||
self.lead_rel_speed = lead_rel_speed
|
||||
self.lead_visible = lead_visible
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def object_rel_gap(self) -> int:
|
||||
raise NotImplementedError("Subclasses must implement this method")
|
||||
|
||||
|
||||
class CanLeadData(LeadData):
|
||||
@property
|
||||
def object_rel_gap(self) -> int:
|
||||
return 0 if self.lead_distance == 0 else 2 if self.lead_rel_speed < -0.2 else 1
|
||||
|
||||
|
||||
class CanFdLeadData(LeadData):
|
||||
@property
|
||||
def object_rel_gap(self) -> int:
|
||||
return 0 if not self.lead_visible else 2 if self.lead_rel_speed < 0 else 1
|
||||
|
||||
|
||||
def _hysteresis_update(current, new_value, counter, threshold):
|
||||
"""
|
||||
Updates a value based on a hysteresis threshold mechanism. This function
|
||||
compares a new value against the current value and uses a counter to detect
|
||||
when a transition should occur, avoiding rapid oscillations between states.
|
||||
A new value will only be adopted if it differs from the current value and
|
||||
the counter reaches the specified threshold.
|
||||
|
||||
:param current: The current value being tracked.
|
||||
:param new_value: The potential new value to compare against the current.
|
||||
:param counter: The count of consecutive different values encountered.
|
||||
:param threshold: The minimum count required before switching to the new value.
|
||||
:return: A tuple containing:
|
||||
- The updated current value, which is either the original current
|
||||
value or the new value if the hysteresis condition was met.
|
||||
- The updated counter, reset to 0 if the new value was adopted,
|
||||
or incremented by 1 otherwise.
|
||||
"""
|
||||
if new_value == current:
|
||||
return current, 0
|
||||
counter += 1
|
||||
return (new_value, 0) if counter >= threshold else (current, counter)
|
||||
|
||||
|
||||
class LeadDataCarController:
|
||||
# Hysteresis parameters
|
||||
LEAD_HYSTERESIS_FRAMES: int = 50
|
||||
|
||||
def __init__(self, CP: structs.CarParams):
|
||||
self.CP = CP
|
||||
|
||||
self.lead_one = {}
|
||||
self.lead_two = {}
|
||||
|
||||
self._lead_on_counter = 0
|
||||
self._lead_off_counter = 0
|
||||
self.lead_visible = False
|
||||
self.gap_counter = 0
|
||||
self.object_gap = 0
|
||||
self.lead_distance = 0
|
||||
self.lead_rel_speed = 0
|
||||
|
||||
def _update_object_gap(self, lead_distance: float | None):
|
||||
new_gap = 5 # Default gap value if no lead distance is provided
|
||||
if lead_distance is None or lead_distance == 0:
|
||||
new_gap = 0
|
||||
elif lead_distance < 20:
|
||||
new_gap = 2
|
||||
elif lead_distance < 25:
|
||||
new_gap = 3
|
||||
elif lead_distance < 30:
|
||||
new_gap = 4
|
||||
|
||||
self.object_gap, self.gap_counter = _hysteresis_update(self.object_gap, new_gap, self.gap_counter, self.LEAD_HYSTERESIS_FRAMES)
|
||||
|
||||
def _update_lead_visible_hysteresis(self, raw_lead_visible: bool):
|
||||
counter = self._lead_on_counter if raw_lead_visible else self._lead_off_counter
|
||||
self.lead_visible, counter = _hysteresis_update(self.lead_visible, raw_lead_visible, counter, self.LEAD_HYSTERESIS_FRAMES)
|
||||
|
||||
if raw_lead_visible:
|
||||
self._lead_on_counter = counter
|
||||
self._lead_off_counter = 0 # reset opposite counter
|
||||
else:
|
||||
self._lead_off_counter = counter
|
||||
self._lead_on_counter = 0 # reset opposite counter
|
||||
|
||||
def update(self, CC_IQ: structs.IQCarControl) -> None:
|
||||
self.lead_one = CC_IQ.leadOne
|
||||
self.lead_two = CC_IQ.leadTwo
|
||||
|
||||
self.lead_distance = self.lead_one.dRel
|
||||
self.lead_rel_speed = self.lead_one.vRel
|
||||
self._update_lead_visible_hysteresis(self.lead_one.status)
|
||||
self._update_object_gap(self.lead_distance)
|
||||
|
||||
@property
|
||||
def lead_data(self) -> CanLeadData | CanFdLeadData:
|
||||
if self.CP.flags & HyundaiFlags.CANFD:
|
||||
return CanFdLeadData(self.object_gap, self.lead_distance, self.lead_rel_speed, self.lead_visible)
|
||||
|
||||
return CanLeadData(self.object_gap, self.lead_distance, self.lead_rel_speed, self.lead_visible)
|
||||
@@ -1,49 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from iqdbc.car.hyundai.values import CAR
|
||||
|
||||
|
||||
@dataclass
|
||||
class CarTuningConfig:
|
||||
lookahead_jerk_bp: list[float] = field(default_factory=lambda: [5., 20.])
|
||||
lookahead_jerk_upper_v: list[float] = field(default_factory=lambda: [0.25, 0.5])
|
||||
lookahead_jerk_lower_v: list[float] = field(default_factory=lambda: [0.15, 0.3])
|
||||
longitudinal_actuator_delay: float = 0.45
|
||||
jerk_limits: float = 4.0
|
||||
|
||||
|
||||
# Default configurations for different car types
|
||||
TUNING_CONFIGS = {
|
||||
"CANFD": CarTuningConfig(
|
||||
lookahead_jerk_bp=[2., 5., 20.],
|
||||
lookahead_jerk_upper_v=[0.25, 0.5, 1.0],
|
||||
lookahead_jerk_lower_v=[0.05, 0.10, 0.325],
|
||||
),
|
||||
"EV": CarTuningConfig(
|
||||
lookahead_jerk_upper_v=[0.3, 0.7],
|
||||
lookahead_jerk_lower_v=[0.2, 0.4],
|
||||
),
|
||||
"HYBRID": CarTuningConfig(),
|
||||
"DEFAULT": CarTuningConfig(
|
||||
lookahead_jerk_bp=[2., 5., 20.],
|
||||
lookahead_jerk_upper_v=[0.25, 0.5, 1.0],
|
||||
lookahead_jerk_lower_v=[0.05, 0.10, 0.3],
|
||||
)
|
||||
}
|
||||
|
||||
# Car-specific configs
|
||||
CAR_SPECIFIC_CONFIGS = {
|
||||
CAR.KIA_NIRO_EV: CarTuningConfig(
|
||||
lookahead_jerk_upper_v=[0.3, 1.0],
|
||||
lookahead_jerk_lower_v=[0.2, 0.4],
|
||||
jerk_limits=2.5,
|
||||
),
|
||||
CAR.KIA_NIRO_PHEV_2022: CarTuningConfig(
|
||||
lookahead_jerk_upper_v=[0.3, 1.0],
|
||||
lookahead_jerk_lower_v=[0.15, 0.3],
|
||||
jerk_limits=4.0,
|
||||
),
|
||||
CAR.HYUNDAI_IONIQ: CarTuningConfig(
|
||||
jerk_limits=4.5,
|
||||
)
|
||||
}
|
||||
@@ -1,288 +0,0 @@
|
||||
import numpy as np
|
||||
from dataclasses import dataclass
|
||||
|
||||
from iqdbc.car import structs, DT_CTRL
|
||||
from iqdbc.car.interfaces import CarStateBase
|
||||
from iqdbc.car.hyundai.values import CarControllerParams
|
||||
from iqdbc.iqpilot.car.hyundai.longitudinal.helpers import get_car_config, jerk_limited_integrator, ramp_update
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ
|
||||
|
||||
LongCtrlState = structs.CarControl.Actuators.LongControlState
|
||||
|
||||
MIN_JERK = 0.5
|
||||
COMFORT_BAND_VAL = 0.01
|
||||
|
||||
DYNAMIC_LOWER_JERK_BP = [-2.0, -1.5, -1.0, -0.25, -0.1, -0.025, -0.01, -0.005]
|
||||
DYNAMIC_LOWER_JERK_V = [3.3, 2.5, 2.0, 1.9, 1.8, 1.65, 1.15, 0.5]
|
||||
|
||||
|
||||
@dataclass
|
||||
class LongitudinalState:
|
||||
desired_accel: float = 0.0
|
||||
actual_accel: float = 0.0
|
||||
accel_last: float = 0.0
|
||||
jerk_upper: float = 0.0
|
||||
jerk_lower: float = 0.0
|
||||
comfort_band_upper: float = 0.0
|
||||
comfort_band_lower: float = 0.0
|
||||
stopping: bool = False
|
||||
|
||||
|
||||
class LongitudinalController:
|
||||
"""Longitudinal controller which gets injected into CarControllerParams."""
|
||||
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams) -> None:
|
||||
self.CP = CP
|
||||
self.CP_IQ = CP_IQ
|
||||
|
||||
self.tuning = LongitudinalState()
|
||||
self.car_config = get_car_config(CP)
|
||||
self.long_control_state_last = LongCtrlState.off
|
||||
self.stopping_count = 0
|
||||
|
||||
self.accel_cmd = 0.0
|
||||
self.desired_accel = 0.0
|
||||
self.actual_accel = 0.0
|
||||
self.accel_last = 0.0
|
||||
self.jerk_upper = 0.0
|
||||
self.jerk_lower = 0.0
|
||||
self.comfort_band_upper = 0.0
|
||||
self.comfort_band_lower = 0.0
|
||||
self.stopping = False
|
||||
|
||||
@property
|
||||
def enabled(self) -> bool:
|
||||
return bool(self.CP_IQ.flags & (HyundaiFlagsIQ.LONG_TUNING_DYNAMIC | HyundaiFlagsIQ.LONG_TUNING_PREDICTIVE))
|
||||
|
||||
def get_stopping_state(self, actuators: structs.CarControl.Actuators) -> None:
|
||||
stopping = actuators.longControlState == LongCtrlState.stopping
|
||||
|
||||
# If custom tuning is not enabled, use upstream stopping logic
|
||||
if not self.enabled:
|
||||
self.stopping = stopping
|
||||
self.stopping_count = 0
|
||||
return
|
||||
|
||||
# Reset stopping state when not in stopping mode
|
||||
if not stopping:
|
||||
self.stopping = False
|
||||
self.stopping_count = 0
|
||||
return
|
||||
|
||||
# When transitioning from off state to stopping
|
||||
if self.long_control_state_last == LongCtrlState.off:
|
||||
self.stopping = True
|
||||
return
|
||||
|
||||
# Keep track of time in stopping state (in control cycles)
|
||||
if self.stopping_count > 1 / (DT_CTRL * 2):
|
||||
self.stopping = True
|
||||
|
||||
self.stopping_count += 1
|
||||
|
||||
@staticmethod
|
||||
def _calculate_speed_based_jerk_limits(velocity: float, long_control_state: LongCtrlState) -> tuple[float, float]:
|
||||
"""Calculate jerk limits based on vehicle speed according to ISO 15622:2018.
|
||||
|
||||
Args:
|
||||
velocity: Current vehicle speed (m/s)
|
||||
long_control_state: Current longitudinal control state
|
||||
|
||||
Returns:
|
||||
Tuple of (upper_limit, lower_limit) in m/s³
|
||||
"""
|
||||
|
||||
# Upper jerk limit varies based on speed and control state
|
||||
if long_control_state == LongCtrlState.pid:
|
||||
upper_limit = float(np.interp(velocity, [0.0, 5.0, 20.0], [2.0, 3.0, 1.6]))
|
||||
else:
|
||||
upper_limit = 0.5 # Default for non-PID states
|
||||
|
||||
# Lower jerk limit varies based on speed
|
||||
lower_limit = float(np.interp(velocity, [0.0, 5.0, 20.0], [5.0, 4.0, 2.5]))
|
||||
|
||||
return upper_limit, lower_limit
|
||||
|
||||
def _calculate_lookahead_jerk(self, accel_error: float, velocity: float) -> tuple[float, float]:
|
||||
"""Calculate lookahead jerk needed to reach target acceleration.
|
||||
|
||||
Args:
|
||||
accel_error: Difference between target and current acceleration (m/s²)
|
||||
velocity: Current vehicle speed (m/s)
|
||||
|
||||
Returns:
|
||||
Tuple of (upper_jerk, lower_jerk) in m/s³
|
||||
"""
|
||||
|
||||
# Time window to reach target acceleration, varies with speed
|
||||
future_t_upper = float(np.interp(velocity, self.car_config.lookahead_jerk_bp, self.car_config.lookahead_jerk_upper_v))
|
||||
future_t_lower = float(np.interp(velocity, self.car_config.lookahead_jerk_bp, self.car_config.lookahead_jerk_lower_v))
|
||||
|
||||
# Required jerk to reach target acceleration in lookahead window
|
||||
j_ego_upper = accel_error / future_t_upper
|
||||
j_ego_lower = accel_error / future_t_lower
|
||||
|
||||
return j_ego_upper, j_ego_lower
|
||||
|
||||
def _calculate_dynamic_lower_jerk(self, accel_error: float, velocity: float) -> float:
|
||||
"""Calculate dynamic jerk for braking based on acceleration error.
|
||||
|
||||
Used for the dynamic tuning approach (non-predictive).
|
||||
|
||||
Args:
|
||||
accel_error: Difference between actual and previous acceleration (m/s²)
|
||||
velocity: Current vehicle speed (m/s)
|
||||
|
||||
Returns:
|
||||
Dynamic lower jerk limit (m/s³)
|
||||
"""
|
||||
|
||||
if self.CP.radarUnavailable:
|
||||
return 5.0
|
||||
|
||||
if accel_error < 0:
|
||||
# Scale the brake jerk values based on car config
|
||||
lower_max = self.car_config.jerk_limits
|
||||
original_values = np.array(DYNAMIC_LOWER_JERK_V)
|
||||
scaled_values = original_values * (lower_max / original_values[0])
|
||||
|
||||
# Interpolate based on acceleration error
|
||||
dynamic_lower_jerk = float(np.interp(accel_error, DYNAMIC_LOWER_JERK_BP, scaled_values))
|
||||
else:
|
||||
dynamic_lower_jerk = 0.5
|
||||
|
||||
return dynamic_lower_jerk
|
||||
|
||||
def calculate_jerk(self, CC: structs.CarControl, CS: CarStateBase, long_control_state: LongCtrlState) -> None:
|
||||
"""Calculate appropriate jerk limits for smooth acceleration/deceleration.
|
||||
|
||||
Args:
|
||||
CC: Car control signals
|
||||
CS: Car state
|
||||
long_control_state: Current longitudinal control state
|
||||
"""
|
||||
|
||||
# If custom tuning is disabled, use upstream fixed values
|
||||
if not self.enabled:
|
||||
jerk_limit = 3.0 if long_control_state == LongCtrlState.pid else 1.0
|
||||
self.jerk_upper = jerk_limit
|
||||
self.jerk_lower = 5.0
|
||||
return
|
||||
|
||||
velocity = CS.out.vEgo
|
||||
accel_error = self.accel_cmd - self.accel_last
|
||||
|
||||
# Calculate jerk limits based on speed
|
||||
upper_speed_factor, lower_speed_factor = self._calculate_speed_based_jerk_limits(velocity, long_control_state)
|
||||
|
||||
# Calculate lookahead jerk
|
||||
j_ego_upper, j_ego_lower = self._calculate_lookahead_jerk(accel_error, velocity)
|
||||
|
||||
# Calculate lower jerk limit
|
||||
lower_jerk = max(-j_ego_lower, MIN_JERK)
|
||||
if self.CP.radarUnavailable:
|
||||
lower_jerk = 5.0
|
||||
|
||||
# Final jerk limits with thresholds
|
||||
desired_jerk_upper = min(max(j_ego_upper, MIN_JERK), upper_speed_factor)
|
||||
desired_jerk_lower = min(lower_jerk, lower_speed_factor)
|
||||
|
||||
# Calculate dynamic lower jerk for non-predictive tuning
|
||||
a_ego_blended = float(np.interp(velocity, [1.0, 2.0], [CS.aBasis, CS.out.aEgo]))
|
||||
dynamic_accel_error = a_ego_blended - self.accel_last
|
||||
dynamic_lower_jerk = self._calculate_dynamic_lower_jerk(dynamic_accel_error, velocity)
|
||||
dynamic_desired_lower_jerk = min(dynamic_lower_jerk, lower_speed_factor)
|
||||
|
||||
# Apply jerk limits based on tuning approach
|
||||
self.jerk_upper = ramp_update(self.jerk_upper, desired_jerk_upper)
|
||||
|
||||
# Predictive tuning uses calculated desired jerk directly
|
||||
# Dynamic tuning applies a ramped approach for smoother transitions
|
||||
if self.CP_IQ.flags & HyundaiFlagsIQ.LONG_TUNING_PREDICTIVE:
|
||||
self.jerk_lower = desired_jerk_lower
|
||||
else:
|
||||
self.jerk_lower = ramp_update(self.jerk_lower, dynamic_desired_lower_jerk)
|
||||
|
||||
# Disable jerk when longitudinal control is inactive
|
||||
if not CC.longActive:
|
||||
self.jerk_upper = 0.0
|
||||
self.jerk_lower = 0.0
|
||||
|
||||
def calculate_accel(self, CC: structs.CarControl) -> None:
|
||||
"""Calculate commanded acceleration using jerk-limited approach.
|
||||
|
||||
Args:
|
||||
CC: Car control signals
|
||||
"""
|
||||
|
||||
# Skip custom processing if tuning is disabled or radar unavailable
|
||||
if not self.enabled or self.CP.radarUnavailable:
|
||||
self.desired_accel = self.accel_cmd
|
||||
self.actual_accel = self.accel_cmd
|
||||
return
|
||||
|
||||
# Reset acceleration when control is inactive
|
||||
if not CC.longActive:
|
||||
self.desired_accel = 0.0
|
||||
self.actual_accel = 0.0
|
||||
self.accel_last = 0.0
|
||||
return
|
||||
|
||||
# Force zero acceleration during stopping
|
||||
if self.stopping:
|
||||
self.desired_accel = 0.0
|
||||
else:
|
||||
self.desired_accel = float(np.clip(self.accel_cmd, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX))
|
||||
|
||||
# Apply jerk-limited integration to get smooth acceleration
|
||||
self.actual_accel = jerk_limited_integrator(self.desired_accel, self.accel_last, self.jerk_upper, self.jerk_lower)
|
||||
|
||||
self.accel_last = self.actual_accel
|
||||
|
||||
def calculate_comfort_band(self, CC: structs.CarControl) -> None:
|
||||
if not self.enabled or self.CP.radarUnavailable or not CC.longActive:
|
||||
self.comfort_band_upper = 0.0
|
||||
self.comfort_band_lower = 0.0
|
||||
return
|
||||
|
||||
self.comfort_band_upper = COMFORT_BAND_VAL
|
||||
self.comfort_band_lower = COMFORT_BAND_VAL
|
||||
|
||||
def get_tuning_state(self) -> None:
|
||||
"""Update the tuning state object with current control values.
|
||||
|
||||
External components depend on this state for longitudinal control.
|
||||
"""
|
||||
|
||||
self.tuning = LongitudinalState(
|
||||
desired_accel=self.desired_accel,
|
||||
actual_accel=self.actual_accel,
|
||||
accel_last=self.accel_last,
|
||||
jerk_upper=self.jerk_upper,
|
||||
jerk_lower=self.jerk_lower,
|
||||
comfort_band_upper=self.comfort_band_upper,
|
||||
comfort_band_lower=self.comfort_band_lower,
|
||||
stopping=self.stopping,
|
||||
)
|
||||
|
||||
def update(self, CC: structs.CarControl, CS: CarStateBase) -> None:
|
||||
"""Update longitudinal control calculations.
|
||||
|
||||
This is the main entry point called externally.
|
||||
|
||||
Args:
|
||||
CC: Car control signals including actuators
|
||||
CS: Car state information
|
||||
"""
|
||||
|
||||
actuators = CC.actuators
|
||||
long_control_state = actuators.longControlState
|
||||
self.accel_cmd = CC.actuators.accel
|
||||
|
||||
self.get_stopping_state(actuators)
|
||||
self.calculate_jerk(CC, CS, long_control_state)
|
||||
self.calculate_accel(CC)
|
||||
self.calculate_comfort_band(CC)
|
||||
self.get_tuning_state()
|
||||
|
||||
self.long_control_state_last = long_control_state
|
||||
@@ -1,52 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
from iqdbc.car import structs, DT_CTRL, rate_limit
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags
|
||||
from iqdbc.iqpilot.car.hyundai.longitudinal.config import CarTuningConfig, TUNING_CONFIGS, CAR_SPECIFIC_CONFIGS
|
||||
|
||||
JERK_THRESHOLD = 0.1
|
||||
JERK_STEP = 0.1
|
||||
|
||||
|
||||
class LongitudinalTuningType:
|
||||
OFF = 0
|
||||
DYNAMIC = 1
|
||||
PREDICTIVE = 2
|
||||
|
||||
|
||||
def get_car_config(CP: structs.CarParams) -> CarTuningConfig:
|
||||
# Get car type flags from specific configs or determine from car flags
|
||||
car_config = CAR_SPECIFIC_CONFIGS.get(CP.carFingerprint)
|
||||
# If car is not in specific configs, determine from flags
|
||||
if car_config is None:
|
||||
if CP.flags & HyundaiFlags.CANFD:
|
||||
car_config = TUNING_CONFIGS["CANFD"]
|
||||
elif CP.flags & HyundaiFlags.EV:
|
||||
car_config = TUNING_CONFIGS["EV"]
|
||||
elif CP.flags & HyundaiFlags.HYBRID:
|
||||
car_config = TUNING_CONFIGS["HYBRID"]
|
||||
else:
|
||||
car_config = TUNING_CONFIGS["DEFAULT"]
|
||||
|
||||
return car_config
|
||||
|
||||
|
||||
def get_longitudinal_tune(CP: structs.CarParams) -> None:
|
||||
config = get_car_config(CP)
|
||||
CP.longitudinalActuatorDelay = config.longitudinal_actuator_delay
|
||||
|
||||
|
||||
def jerk_limited_integrator(desired_accel, last_accel, jerk_upper, jerk_lower) -> float:
|
||||
if desired_accel >= last_accel:
|
||||
val = jerk_upper * DT_CTRL * 2
|
||||
else:
|
||||
val = jerk_lower * DT_CTRL * 2
|
||||
|
||||
return rate_limit(desired_accel, last_accel, -val, val)
|
||||
|
||||
|
||||
def ramp_update(current, target):
|
||||
error = target - current
|
||||
if abs(error) > JERK_THRESHOLD:
|
||||
return current + float(np.clip(error, -JERK_STEP, JERK_STEP))
|
||||
return target
|
||||
@@ -1,85 +0,0 @@
|
||||
from iqdbc.can.parser import CANParser
|
||||
from iqdbc.car import structs, Bus
|
||||
from iqdbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from iqdbc.car.hyundai.values import DBC, HyundaiFlags
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.escc import EsccRadarInterfaceBase
|
||||
|
||||
|
||||
class RadarInterfaceExt(EsccRadarInterfaceBase):
|
||||
msg_src: str
|
||||
trigger_msg: int
|
||||
rcp: CANParser
|
||||
pts: dict[int, structs.RadarData.RadarPoint]
|
||||
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
|
||||
EsccRadarInterfaceBase.__init__(self, CP, CP_IQ)
|
||||
self.CP = CP
|
||||
self.CP_IQ = CP_IQ
|
||||
|
||||
self.track_id = 0
|
||||
|
||||
@property
|
||||
def use_radar_interface_ext(self) -> bool:
|
||||
return self.use_escc or self.CP.flags & (HyundaiFlags.CAMERA_SCC | HyundaiFlags.CANFD_CAMERA_SCC)
|
||||
|
||||
def get_msg_src(self) -> str | None:
|
||||
if self.use_escc:
|
||||
return "ESCC"
|
||||
if self.CP.flags & (HyundaiFlags.CAMERA_SCC | HyundaiFlags.CANFD_CAMERA_SCC):
|
||||
return "SCC_CONTROL" if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else "SCC11"
|
||||
|
||||
def get_radar_ext_can_parser(self) -> CANParser:
|
||||
if self.ESCC.enabled:
|
||||
lead_src, bus = "ESCC", 0
|
||||
elif self.CP.flags & (HyundaiFlags.CAMERA_SCC | HyundaiFlags.CANFD_CAMERA_SCC):
|
||||
lead_src = "SCC_CONTROL" if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else "SCC11"
|
||||
bus = CanBus(self.CP).CAM if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else 2
|
||||
else:
|
||||
return None
|
||||
|
||||
messages = [(lead_src, 50)]
|
||||
return CANParser(DBC[self.CP.carFingerprint][Bus.pt], messages, bus)
|
||||
|
||||
def get_trigger_msg(self, default_trigger_msg) -> int:
|
||||
if self.ESCC.enabled:
|
||||
return self.ESCC.trigger_msg
|
||||
if self.CP.flags & (HyundaiFlags.CAMERA_SCC | HyundaiFlags.CANFD_CAMERA_SCC):
|
||||
return 0x1A0 if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else 0x420
|
||||
return default_trigger_msg
|
||||
|
||||
def initialize_radar_ext(self, default_trigger_msg) -> None:
|
||||
if self.ESCC.enabled:
|
||||
self.use_escc = True
|
||||
|
||||
self.rcp = self.get_radar_ext_can_parser()
|
||||
self.trigger_msg = self.get_trigger_msg(default_trigger_msg)
|
||||
|
||||
def update_ext(self, ret: structs.RadarData) -> structs.RadarData:
|
||||
if not self.rcp.can_valid:
|
||||
ret.errors.canError = True
|
||||
return ret
|
||||
|
||||
for ii in range(1):
|
||||
msg_src = self.get_msg_src()
|
||||
msg = self.rcp.vl[msg_src]
|
||||
|
||||
if ii not in self.pts:
|
||||
self.pts[ii] = structs.RadarData.RadarPoint()
|
||||
self.pts[ii].trackId = self.track_id
|
||||
self.track_id += 1
|
||||
|
||||
valid = msg['ACC_ObjDist'] < 204.6 if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else msg['ACC_ObjStatus']
|
||||
if valid:
|
||||
self.pts[ii].measured = True
|
||||
self.pts[ii].dRel = msg['ACC_ObjDist']
|
||||
self.pts[ii].yRel = float('nan')
|
||||
self.pts[ii].vRel = msg['ACC_ObjRelSpd']
|
||||
self.pts[ii].aRel = float('nan')
|
||||
self.pts[ii].yvRel = float('nan')
|
||||
|
||||
else:
|
||||
del self.pts[ii]
|
||||
|
||||
ret.points = list(self.pts.values())
|
||||
return ret
|
||||
@@ -1,25 +0,0 @@
|
||||
from enum import IntFlag
|
||||
|
||||
|
||||
class HyundaiSafetyFlagsIQ:
|
||||
DEFAULT = 0
|
||||
ESCC = 16
|
||||
MAIN_BTN_LONG_TOGGLE = 32
|
||||
HAS_LDA_BUTTON = 64
|
||||
NON_SCC = 128
|
||||
|
||||
|
||||
class HyundaiFlagsIQ(IntFlag):
|
||||
ENHANCED_SCC = 1
|
||||
HAS_LFA_BUTTON = 2
|
||||
MAIN_BTN_LONG_TOGGLE = 2 ** 2
|
||||
ENABLE_RADAR_TRACKS_DEPRECATED = 2 ** 3
|
||||
LONG_TUNING_DYNAMIC = 2 ** 4
|
||||
LONG_TUNING_PREDICTIVE = 2 ** 5
|
||||
NON_SCC = 2 ** 6
|
||||
NON_SCC_RADAR_FCA = 2 ** 7
|
||||
NON_SCC_NO_FCA = 2 ** 8
|
||||
SPEED_LIMIT_AVAILABLE = 2 ** 9
|
||||
HAS_LKAS12 = 2 ** 10
|
||||
|
||||
|
||||
@@ -8,11 +8,7 @@ from collections.abc import Callable
|
||||
|
||||
from iqdbc.car import structs
|
||||
from iqdbc.car.can_definitions import CanRecvCallable, CanSendCallable
|
||||
from iqdbc.car.hyundai.values import HyundaiFlags
|
||||
from iqdbc.car.subaru.values import SubaruFlags
|
||||
from iqdbc.iqpilot.car.hyundai.enable_radar_tracks import enable_radar_tracks as hyundai_enable_radar_tracks
|
||||
from iqdbc.iqpilot.car.hyundai.longitudinal.helpers import LongitudinalTuningType
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ
|
||||
from iqdbc.iqpilot.car.subaru.values_ext import SubaruFlagsIQ, SubaruSafetyFlagsIQ
|
||||
from iqdbc.iqpilot.car.tesla.values import TeslaFlagsIQ
|
||||
from iqdbc.iqpilot.car.toyota.values import ToyotaFlagsIQ
|
||||
@@ -81,7 +77,6 @@ def setup_interfaces(CI, CP: structs.CarParams, CP_IQ: structs.IQCarParams,
|
||||
|
||||
_initialize_custom_longitudinal_tuning(CI, CP, CP_IQ, params_dict)
|
||||
_initialize_coop_steering(CP, CP_IQ, params_dict)
|
||||
_initialize_radar_tracks(CP, CP_IQ, can_recv, can_send)
|
||||
_initialize_stop_and_go(CP, CP_IQ, params_dict)
|
||||
_initialize_toyota(CP, CP_IQ, params_dict)
|
||||
|
||||
@@ -89,16 +84,6 @@ def setup_interfaces(CI, CP: structs.CarParams, CP_IQ: structs.IQCarParams,
|
||||
def _initialize_custom_longitudinal_tuning(CI, CP: structs.CarParams, CP_IQ: structs.IQCarParams,
|
||||
params_dict: dict[str, str]) -> None:
|
||||
|
||||
# HKG longitudinal tuning lineage in this port traces to Jason Wen, James
|
||||
# Vecellio-Grant, and carrotpilot; keep that attribution with this path.
|
||||
# Hyundai Custom Longitudinal Tuning
|
||||
if CP.brand == 'hyundai':
|
||||
hyundai_longitudinal_tuning = int(params_dict.get("HyundaiLongitudinalTuning", 0))
|
||||
if hyundai_longitudinal_tuning == LongitudinalTuningType.DYNAMIC:
|
||||
CP_IQ.flags |= HyundaiFlagsIQ.LONG_TUNING_DYNAMIC.value
|
||||
if hyundai_longitudinal_tuning == LongitudinalTuningType.PREDICTIVE:
|
||||
CP_IQ.flags |= HyundaiFlagsIQ.LONG_TUNING_PREDICTIVE.value
|
||||
|
||||
_ = CI.get_longitudinal_tuning_iq(CP, CP_IQ)
|
||||
|
||||
|
||||
@@ -110,14 +95,6 @@ def _initialize_coop_steering(CP: structs.CarParams, CP_IQ: structs.IQCarParams,
|
||||
CP_IQ.flags |= TeslaFlagsIQ.COOP_STEERING.value
|
||||
|
||||
|
||||
def _initialize_radar_tracks(CP: structs.CarParams, CP_IQ: structs.IQCarParams,
|
||||
can_recv: CanRecvCallable | None = None, can_send: CanSendCallable | None = None) -> None:
|
||||
if CP.brand == 'hyundai':
|
||||
if CP.flags & HyundaiFlags.MANDO_RADAR and (CP.radarUnavailable or CP_IQ.flags & HyundaiFlagsIQ.ENHANCED_SCC):
|
||||
tracks_enabled = hyundai_enable_radar_tracks(can_recv, can_send, bus=0, addr=0x7d0)
|
||||
CP.radarUnavailable = not tracks_enabled
|
||||
|
||||
|
||||
def _initialize_stop_and_go(CP: structs.CarParams, CP_IQ: structs.IQCarParams, params_dict: dict[str, str]) -> None:
|
||||
if CP.brand == 'subaru' and not CP.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.HYBRID):
|
||||
stop_and_go = int(params_dict.get("SubaruStopAndGo", 0)) == 1
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "iqdbc/safety/declarations.h"
|
||||
#include "iqdbc/safety/modes/hyundai_common.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
|
||||
#define HYUNDAI_LIMITS(steer, rate_up, rate_down) { \
|
||||
.max_torque = (steer), \
|
||||
.max_rate_up = (rate_up), \
|
||||
@@ -21,96 +23,84 @@
|
||||
|
||||
extern const LongitudinalLimits HYUNDAI_LONG_LIMITS;
|
||||
const LongitudinalLimits HYUNDAI_LONG_LIMITS = {
|
||||
.max_accel = 200, // 1/100 m/s2
|
||||
.min_accel = -350, // 1/100 m/s2
|
||||
.zero_accel = 0,
|
||||
.max_accel = 250, // 1/100 m/s2
|
||||
.min_accel = -400, // 1/100 m/s2
|
||||
};
|
||||
|
||||
#define HYUNDAI_COMMON_TX_MSGS(scc_bus) \
|
||||
{0x340, 0, 8, .check_relay = true}, /* LKAS11 Bus 0 */ \
|
||||
{0x4F1, scc_bus, 4, .check_relay = false}, /* CLU11 Bus 0 (radar-SCC) or 2 (camera-SCC) */ \
|
||||
{0x485, 0, 4, .check_relay = true}, /* LFAHDA_MFC Bus 0 */ \
|
||||
|
||||
#define HYUNDAI_LONG_COMMON_TX_MSGS(scc_bus) \
|
||||
HYUNDAI_COMMON_TX_MSGS(scc_bus) \
|
||||
{0x420, 0, 8, .check_relay = true}, /* SCC11 Bus 0 */ \
|
||||
{0x421, 0, 8, .check_relay = true}, /* SCC12 Bus 0 */ \
|
||||
{0x50A, 0, 8, .check_relay = true}, /* SCC13 Bus 0 */ \
|
||||
{0x389, 0, 8, .check_relay = true}, /* SCC14 Bus 0 */ \
|
||||
{0x4A2, 0, 2, .check_relay = false}, /* FRT_RADAR11 Bus 0 */ \
|
||||
|
||||
#define HYUNDAI_COMMON_RX_CHECKS(legacy) \
|
||||
{.msg = {{0x260, 0, 8, 100U, .max_counter = 3U, .ignore_quality_flag = true}, \
|
||||
{0x371, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }}}, \
|
||||
{.msg = {{0x386, 0, 8, 100U, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x394, 0, 8, 100U, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 7U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x251, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x4F1, 0, 4, 50U, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_SCC11_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x420, (scc_bus), 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_SCC12_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x421, (scc_bus), 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_FCEV_GAS_ADDR_CHECK \
|
||||
{.msg = {{0x91, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_LDA_BUTTON_ADDR_CHECK \
|
||||
{.msg = {{0x391, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_NON_SCC_HEV_ADDR_CHECK \
|
||||
{.msg = {{0x595U, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_NON_SCC_EV_ADDR_CHECK \
|
||||
{.msg = {{0x592U, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
|
||||
static const CanMsg HYUNDAI_TX_MSGS[] = {
|
||||
HYUNDAI_COMMON_TX_MSGS(0)
|
||||
{0x340, 0, 8}, // LKAS11 Bus 0
|
||||
{0x4F1, 0, 4}, // CLU11 Bus 0
|
||||
{0x485, 0, 8}, // LFAHDA_MFC Bus 0
|
||||
{593, 2, 8}, // MDPS12, Bus 2
|
||||
{1056, 0, 8}, // SCC11, Bus 0
|
||||
{1057, 0, 8}, // SCC12, Bus 0
|
||||
{1290, 0, 8}, // SCC13, Bus 0
|
||||
{905, 0, 8}, // SCC14, Bus 0
|
||||
{909, 0, 8}, // FCA11 Bus 0
|
||||
{1155, 0, 8}, // FCA12 Bus 0
|
||||
{1186, 0, 8}, // FRT_RADAR11, Bus 0
|
||||
{1265, 2, 4}, // CLU11, Bus 0, 2
|
||||
{0x7D0, 0, 8}, // radar UDS TX addr Bus 0 (for radar disable) // 2000
|
||||
{0x7b1, 0, 8},
|
||||
};
|
||||
|
||||
static bool hyundai_legacy = false;
|
||||
#define HYUNDAI_COMMON_RX_CHECKS(legacy) \
|
||||
{.msg = {{0x260, 0, 8, .max_counter = 3U, .frequency = 100U}, \
|
||||
{0x371, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}, \
|
||||
{0x91, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 100U}}}, \
|
||||
{.msg = {{0x386, 0, 8, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 15U, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x394, 0, 8, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 7U, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static uint8_t hyundai_get_counter(const CANPacket_t *msg) {
|
||||
#define HYUNDAI_SCC12_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x421, (scc_bus), 8, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static bool hyundai_legacy = false;
|
||||
static bool hyundai_cruise_buttons_alt = false;
|
||||
|
||||
static uint8_t hyundai_get_counter(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
uint8_t cnt = 0;
|
||||
if (msg->addr == 0x260U) {
|
||||
cnt = (msg->data[7] >> 4) & 0x3U;
|
||||
} else if (msg->addr == 0x386U) {
|
||||
cnt = ((msg->data[3] >> 6) << 2) | (msg->data[1] >> 6);
|
||||
} else if (msg->addr == 0x394U) {
|
||||
cnt = (msg->data[1] >> 5) & 0x7U;
|
||||
} else if (msg->addr == 0x421U) {
|
||||
cnt = msg->data[7] & 0xFU;
|
||||
} else if (msg->addr == 0x4F1U) {
|
||||
cnt = (msg->data[3] >> 4) & 0xFU;
|
||||
if (addr == 0x260) {
|
||||
cnt = (GET_BYTE(to_push, 7) >> 4) & 0x3U;
|
||||
} else if (addr == 0x386) {
|
||||
cnt = ((GET_BYTE(to_push, 3) >> 6) << 2) | (GET_BYTE(to_push, 1) >> 6);
|
||||
} else if (addr == 0x394) {
|
||||
cnt = (GET_BYTE(to_push, 1) >> 5) & 0x7U;
|
||||
} else if (addr == 0x421) {
|
||||
cnt = GET_BYTE(to_push, 7) & 0xFU;
|
||||
} else if (addr == 0x4F1) {
|
||||
cnt = (GET_BYTE(to_push, 3) >> 4) & 0xFU;
|
||||
} else {
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static uint32_t hyundai_get_checksum(const CANPacket_t *msg) {
|
||||
static uint32_t hyundai_get_checksum(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
uint8_t chksum = 0;
|
||||
if (msg->addr == 0x260U) {
|
||||
chksum = msg->data[7] & 0xFU;
|
||||
} else if (msg->addr == 0x386U) {
|
||||
chksum = ((msg->data[7] >> 6) << 2) | (msg->data[5] >> 6);
|
||||
} else if (msg->addr == 0x394U) {
|
||||
chksum = msg->data[6] & 0xFU;
|
||||
} else if (msg->addr == 0x421U) {
|
||||
chksum = msg->data[7] >> 4;
|
||||
if (addr == 0x260) {
|
||||
chksum = GET_BYTE(to_push, 7) & 0xFU;
|
||||
} else if (addr == 0x386) {
|
||||
chksum = ((GET_BYTE(to_push, 7) >> 6) << 2) | (GET_BYTE(to_push, 5) >> 6);
|
||||
} else if (addr == 0x394) {
|
||||
chksum = GET_BYTE(to_push, 6) & 0xFU;
|
||||
} else if (addr == 0x421) {
|
||||
chksum = GET_BYTE(to_push, 7) >> 4;
|
||||
} else {
|
||||
}
|
||||
return chksum;
|
||||
}
|
||||
|
||||
static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) {
|
||||
static uint32_t hyundai_compute_checksum(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
uint8_t chksum = 0;
|
||||
if (msg->addr == 0x386U) {
|
||||
if (addr == 0x386) {
|
||||
// count the bits
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t b = msg->data[i];
|
||||
uint8_t b = GET_BYTE(to_push, i);
|
||||
for (int j = 0; j < 8; j++) {
|
||||
uint8_t bit = 0;
|
||||
// exclude checksum and counter
|
||||
@@ -124,12 +114,12 @@ static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) {
|
||||
} else {
|
||||
// sum of nibbles
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if ((msg->addr == 0x394U) && (i == 7)) {
|
||||
if ((addr == 0x394) && (i == 7)) {
|
||||
continue; // exclude
|
||||
}
|
||||
uint8_t b = msg->data[i];
|
||||
if (((msg->addr == 0x260U) && (i == 7)) || ((msg->addr == 0x394U) && (i == 6)) || ((msg->addr == 0x421U) && (i == 7))) {
|
||||
b &= (msg->addr == 0x421U) ? 0x0FU : 0xF0U; // remove checksum
|
||||
uint8_t b = GET_BYTE(to_push, i);
|
||||
if (((addr == 0x260) && (i == 7)) || ((addr == 0x394) && (i == 6)) || ((addr == 0x421) && (i == 7))) {
|
||||
b &= (addr == 0x421) ? 0x0FU : 0xF0U; // remove checksum
|
||||
}
|
||||
chksum += (b % 16U) + (b / 16U);
|
||||
}
|
||||
@@ -139,127 +129,115 @@ static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) {
|
||||
return chksum;
|
||||
}
|
||||
|
||||
static void hyundai_rx_hook(const CANPacket_t *msg) {
|
||||
static void hyundai_rx_hook(const CANPacket_t *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
// SCC12 is on bus 2 for camera-based SCC cars, bus 0 on all others
|
||||
if (msg->addr == 0x421U) {
|
||||
if (((msg->bus == 0U) && !hyundai_camera_scc) || ((msg->bus == 2U) && hyundai_camera_scc)) {
|
||||
if (addr == 0x421) {
|
||||
if (((bus == 0) && !hyundai_camera_scc) || ((bus == 2) && hyundai_camera_scc)) {
|
||||
// 2 bits: 13-14
|
||||
int cruise_engaged = (GET_BYTES(msg, 0, 4) >> 13) & 0x3U;
|
||||
int cruise_engaged = (GET_BYTES(to_push, 0, 4) >> 13) & 0x3U;
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->addr == 0x420U) {
|
||||
if (((msg->bus == 0U) && !hyundai_camera_scc) || ((msg->bus == 2U) && hyundai_camera_scc)) {
|
||||
if (!hyundai_longitudinal) {
|
||||
acc_main_on = GET_BIT(msg, 0U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->bus == 0U) {
|
||||
if (msg->addr == 0x251U) {
|
||||
int torque_driver_new = (GET_BYTES(msg, 0, 2) & 0x7ffU) - 1024U;
|
||||
if (bus == 0) {
|
||||
if (addr == 0x251) {
|
||||
int torque_driver_new = (GET_BYTES(to_push, 0, 2) & 0x7ffU) - 1024U;
|
||||
// update array of samples
|
||||
update_sample(&torque_driver, torque_driver_new);
|
||||
}
|
||||
|
||||
if (msg->addr == 0x391U) {
|
||||
aol_button_press = GET_BIT(msg, 4U) ? AOL_BUTTON_PRESSED : AOL_BUTTON_NOT_PRESSED;
|
||||
}
|
||||
|
||||
// ACC steering wheel buttons
|
||||
if (msg->addr == 0x4F1U) {
|
||||
int cruise_button = msg->data[0] & 0x7U;
|
||||
bool main_button = GET_BIT(msg, 3U);
|
||||
if (addr == 1007) hyundai_cruise_buttons_alt = true; // CASPER_EV: 1007
|
||||
if (addr == 1007) {
|
||||
int cruise_button = (GET_BYTE(to_push, 7) >> 4) & 0x07U;
|
||||
bool main_button = GET_BIT(to_push, 58U);
|
||||
hyundai_common_cruise_buttons_check(cruise_button, main_button);
|
||||
}
|
||||
else if (addr == 0x4F1 && !hyundai_cruise_buttons_alt) {
|
||||
int cruise_button = GET_BYTE(to_push, 0) & 0x7U;
|
||||
bool main_button = GET_BIT(to_push, 3U);
|
||||
hyundai_common_cruise_buttons_check(cruise_button, main_button);
|
||||
}
|
||||
|
||||
// gas press, different for EV, hybrid, and ICE models
|
||||
if ((msg->addr == 0x371U) && hyundai_ev_gas_signal) {
|
||||
gas_pressed = (((msg->data[4] & 0x7FU) << 1) | (msg->data[3] >> 7)) != 0U;
|
||||
} else if ((msg->addr == 0x371U) && hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = msg->data[7] != 0U;
|
||||
} else if ((msg->addr == 0x91U) && hyundai_fcev_gas_signal) {
|
||||
gas_pressed = msg->data[6] != 0U;
|
||||
} else if ((msg->addr == 0x260U) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = (msg->data[7] >> 6) != 0U;
|
||||
if ((addr == 0x371) && hyundai_ev_gas_signal) {
|
||||
gas_pressed = (((GET_BYTE(to_push, 4) & 0x7FU) << 1) | GET_BYTE(to_push, 3) >> 7) != 0U;
|
||||
} else if ((addr == 0x371) && hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = GET_BYTE(to_push, 7) != 0U;
|
||||
} else if ((addr == 0x91) && hyundai_fcev_gas_signal) {
|
||||
gas_pressed = GET_BYTE(to_push, 6) != 0U;
|
||||
} else if ((addr == 0x260) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = (GET_BYTE(to_push, 7) >> 6) != 0U;
|
||||
} else {
|
||||
}
|
||||
|
||||
// sample wheel speed, averaging opposite corners
|
||||
if (msg->addr == 0x386U) {
|
||||
uint32_t front_left_speed = GET_BYTES(msg, 0, 2) & 0x3FFFU;
|
||||
uint32_t rear_right_speed = GET_BYTES(msg, 6, 2) & 0x3FFFU;
|
||||
if (addr == 0x386) {
|
||||
uint32_t front_left_speed = GET_BYTES(to_push, 0, 2) & 0x3FFFU;
|
||||
uint32_t rear_right_speed = GET_BYTES(to_push, 6, 2) & 0x3FFFU;
|
||||
vehicle_moving = (front_left_speed > HYUNDAI_STANDSTILL_THRSLD) || (rear_right_speed > HYUNDAI_STANDSTILL_THRSLD);
|
||||
}
|
||||
|
||||
if (msg->addr == 0x394U) {
|
||||
brake_pressed = ((msg->data[5] >> 5U) & 0x3U) == 0x2U;
|
||||
if (addr == 0x394) {
|
||||
brake_pressed = ((GET_BYTE(to_push, 5) >> 5U) & 0x3U) == 0x2U;
|
||||
}
|
||||
|
||||
if (msg->addr == 0x592U) {
|
||||
acc_main_on = GET_BIT(msg, 34U);
|
||||
bool cruise_engaged = GET_BIT(msg, 35U);
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
}
|
||||
bool stock_ecu_detected = (addr == 0x340);
|
||||
|
||||
if (msg->addr == 0x595U) {
|
||||
acc_main_on = GET_BIT(msg, 50U);
|
||||
bool cruise_engaged = GET_BIT(msg, 51U);
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
}
|
||||
|
||||
if ((msg->addr == 0x260U) && hyundai_non_scc && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) {
|
||||
acc_main_on = GET_BIT(msg, 25U);
|
||||
bool cruise_engaged = GET_BIT(msg, 26U);
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
// If openpilot is controlling longitudinal we need to ensure the radar is turned off
|
||||
// Enforce by checking we don't see SCC12
|
||||
if (hyundai_longitudinal && (addr == 0x421)) {
|
||||
stock_ecu_detected = true;
|
||||
}
|
||||
generic_rx_checks();
|
||||
stock_ecu_check(stock_ecu_detected);
|
||||
}
|
||||
|
||||
hyundai_common_reset_acc_main_on_mismatches();
|
||||
}
|
||||
|
||||
static bool hyundai_tx_hook(const CANPacket_t *msg) {
|
||||
const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS = HYUNDAI_LIMITS(384, 3, 7);
|
||||
const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS_ALT = HYUNDAI_LIMITS(270, 2, 3);
|
||||
uint32_t last_ts_lkas11_from_op = 0;
|
||||
uint32_t last_ts_scc12_from_op = 0;
|
||||
uint32_t last_ts_scc13_from_op = 0;
|
||||
uint32_t last_ts_mdps12_from_op = 0;
|
||||
uint32_t last_ts_fca11_from_op = 0;
|
||||
uint32_t last_ts_fca12_from_op = 0;
|
||||
uint32_t last_ts_lfahda_mfc_from_op = 0;
|
||||
|
||||
static bool hyundai_tx_hook(const CANPacket_t *to_send) {
|
||||
const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS = HYUNDAI_LIMITS(512, 10, 10);
|
||||
const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS_ALT = HYUNDAI_LIMITS(512, 10, 10);
|
||||
const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS_ALT_2 = HYUNDAI_LIMITS(170, 2, 3);
|
||||
|
||||
bool tx = true;
|
||||
int addr = GET_ADDR(to_send);
|
||||
|
||||
// FCA11: Block any potential actuation
|
||||
if (msg->addr == 0x38DU) {
|
||||
int CR_VSM_DecCmd = msg->data[1];
|
||||
bool FCA_CmdAct = GET_BIT(msg, 20U);
|
||||
bool CF_VSM_DecCmdAct = GET_BIT(msg, 31U);
|
||||
if (addr == 0x38D) {
|
||||
int CR_VSM_DecCmd = GET_BYTE(to_send, 1);
|
||||
bool FCA_CmdAct = GET_BIT(to_send, 20U);
|
||||
bool CF_VSM_DecCmdAct = GET_BIT(to_send, 31U);
|
||||
|
||||
if ((CR_VSM_DecCmd != 0) || FCA_CmdAct || CF_VSM_DecCmdAct) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->addr == 0x420U) {
|
||||
acc_main_on_tx = GET_BIT(msg, 0U);
|
||||
hyundai_common_acc_main_on_sync();
|
||||
}
|
||||
|
||||
// ACCEL: safety check
|
||||
if (msg->addr == 0x421U) {
|
||||
int desired_accel_raw = (((msg->data[4] & 0x7U) << 8) | msg->data[3]) - 1023U;
|
||||
int desired_accel_val = ((msg->data[5] << 3) | (msg->data[4] >> 5)) - 1023U;
|
||||
if (addr == 0x421) {
|
||||
int desired_accel_raw = (((GET_BYTE(to_send, 4) & 0x7U) << 8) | GET_BYTE(to_send, 3)) - 1023U;
|
||||
int desired_accel_val = ((GET_BYTE(to_send, 5) << 3) | (GET_BYTE(to_send, 4) >> 5)) - 1023U;
|
||||
|
||||
int aeb_decel_cmd = msg->data[2];
|
||||
bool aeb_req = GET_BIT(msg, 54U);
|
||||
int aeb_decel_cmd = GET_BYTE(to_send, 2);
|
||||
bool aeb_req = GET_BIT(to_send, 54U);
|
||||
|
||||
bool violation = false;
|
||||
|
||||
violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS);
|
||||
violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS);
|
||||
if (!hyundai_escc) {
|
||||
violation |= (aeb_decel_cmd != 0);
|
||||
violation |= aeb_req;
|
||||
}
|
||||
violation |= (aeb_decel_cmd != 0);
|
||||
violation |= aeb_req;
|
||||
|
||||
if (violation) {
|
||||
tx = false;
|
||||
@@ -267,9 +245,9 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
// LKA STEER: safety check
|
||||
if (msg->addr == 0x340U) {
|
||||
int desired_torque = ((GET_BYTES(msg, 0, 4) >> 16) & 0x7ffU) - 1024U;
|
||||
bool steer_req = GET_BIT(msg, 27U);
|
||||
if (addr == 0x340) {
|
||||
int desired_torque = ((GET_BYTES(to_send, 0, 4) >> 16) & 0x7ffU) - 1024U;
|
||||
bool steer_req = GET_BIT(to_send, 27U);
|
||||
|
||||
const TorqueSteeringLimits limits = hyundai_alt_limits_2 ? HYUNDAI_STEERING_LIMITS_ALT_2 :
|
||||
hyundai_alt_limits ? HYUNDAI_STEERING_LIMITS_ALT : HYUNDAI_STEERING_LIMITS;
|
||||
@@ -280,220 +258,199 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
// UDS: Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address
|
||||
if (msg->addr == 0x7D0U) {
|
||||
if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) {
|
||||
if (addr == 0x7D0) {
|
||||
if ((GET_BYTES(to_send, 0, 4) != 0x00803E02U) || (GET_BYTES(to_send, 4, 4) != 0x0U)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
// BUTTONS: used for resume spamming and cruise cancellation
|
||||
if ((msg->addr == 0x4F1U) && !hyundai_longitudinal) {
|
||||
int button = msg->data[0] & 0x7U;
|
||||
if ((addr == 0x4F1) && !hyundai_longitudinal) {
|
||||
int button = GET_BYTE(to_send, 0) & 0x7U;
|
||||
|
||||
bool allowed_resume = (button == 1) && controls_allowed;
|
||||
bool allowed_set = (button == 2) && controls_allowed;
|
||||
bool allowed_cancel = (button == 4) && cruise_engaged_prev;
|
||||
if (!(allowed_resume || allowed_set || allowed_cancel)) {
|
||||
bool allowed_cancel = (button == 4) && (cruise_engaged_prev || controls_allowed);
|
||||
if (!(allowed_resume || allowed_cancel)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
uint32_t now = microsecond_timer_get();
|
||||
if(addr == 832)
|
||||
last_ts_lkas11_from_op = (tx == 0 ? 0 : now);
|
||||
else if(addr == 1057)
|
||||
last_ts_scc12_from_op = (tx == 0 ? 0 : now);
|
||||
else if(addr == 593)
|
||||
last_ts_mdps12_from_op = (tx == 0 ? 0 : now);
|
||||
else if (addr == 909)
|
||||
last_ts_fca11_from_op = (tx == 0 ? 0 : now);
|
||||
else if (addr == 1155)
|
||||
last_ts_fca12_from_op = (tx == 0 ? 0 : now);
|
||||
else if(addr == 1290)
|
||||
last_ts_scc13_from_op = (tx == 0 ? 0 : now);
|
||||
else if(addr == 0x485)
|
||||
last_ts_lfahda_mfc_from_op = (tx == 0 ? 0 : now);
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
static safety_config hyundai_init(uint16_t param) {
|
||||
static const CanMsg HYUNDAI_LONG_TX_MSGS[] = {
|
||||
HYUNDAI_LONG_COMMON_TX_MSGS(0)
|
||||
{0x38D, 0, 8, .check_relay = false}, // FCA11 Bus 0
|
||||
{0x483, 0, 8, .check_relay = false}, // FCA12 Bus 0
|
||||
{0x7D0, 0, 8, .check_relay = false}, // radar UDS TX addr Bus 0 (for radar disable)
|
||||
};
|
||||
static bool hyundai_fwd_hook(int bus_num, int addr) {
|
||||
int bus_fwd = -1;
|
||||
|
||||
static const CanMsg HYUNDAI_CAMERA_SCC_TX_MSGS[] = {
|
||||
HYUNDAI_COMMON_TX_MSGS(2)
|
||||
};
|
||||
uint32_t now = microsecond_timer_get();
|
||||
|
||||
static const CanMsg HYUNDAI_CAMERA_SCC_LONG_TX_MSGS[] = {
|
||||
HYUNDAI_LONG_COMMON_TX_MSGS(2)
|
||||
};
|
||||
// forward cam to ccan and viceversa, except lkas cmd
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2;
|
||||
|
||||
static const CanMsg HYUNDAI_LONG_ESCC_TX_MSGS[] = {
|
||||
HYUNDAI_LONG_COMMON_TX_MSGS(0)
|
||||
};
|
||||
|
||||
hyundai_common_init(param);
|
||||
hyundai_legacy = false;
|
||||
|
||||
safety_config ret;
|
||||
if (hyundai_longitudinal) {
|
||||
// Use CLU11 (buttons) to manage controls allowed instead of SCC cruise state
|
||||
static RxCheck hyundai_long_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
};
|
||||
|
||||
static RxCheck hyundai_lda_button_long_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_fcev_long_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_FCEV_GAS_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_fcev_lda_button_long_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_FCEV_GAS_ADDR_CHECK
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
if (hyundai_fcev_gas_signal) {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_fcev_lda_button_long_rx_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_fcev_long_rx_checks, ret);
|
||||
}
|
||||
} else {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_lda_button_long_rx_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_long_rx_checks, ret);
|
||||
}
|
||||
}
|
||||
if (hyundai_escc) {
|
||||
SET_TX_MSGS(HYUNDAI_LONG_ESCC_TX_MSGS, ret);
|
||||
} else if (hyundai_camera_scc) {
|
||||
SET_TX_MSGS(HYUNDAI_CAMERA_SCC_LONG_TX_MSGS, ret);
|
||||
} else {
|
||||
SET_TX_MSGS(HYUNDAI_LONG_TX_MSGS, ret);
|
||||
}
|
||||
|
||||
} else if (hyundai_camera_scc) {
|
||||
static RxCheck hyundai_cam_scc_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(2)
|
||||
HYUNDAI_SCC11_ADDR_CHECK(2)
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
ret = BUILD_SAFETY_CFG(hyundai_cam_scc_rx_checks, HYUNDAI_CAMERA_SCC_TX_MSGS);
|
||||
} else {
|
||||
static RxCheck hyundai_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(0)
|
||||
HYUNDAI_SCC11_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
static RxCheck hyundai_lda_button_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(0)
|
||||
HYUNDAI_SCC11_ADDR_CHECK(0)
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_fcev_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(0)
|
||||
HYUNDAI_SCC11_ADDR_CHECK(0)
|
||||
HYUNDAI_FCEV_GAS_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_fcev_lda_button_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(0)
|
||||
HYUNDAI_SCC11_ADDR_CHECK(0)
|
||||
HYUNDAI_FCEV_GAS_ADDR_CHECK
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_non_scc_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
};
|
||||
|
||||
static RxCheck hyundai_non_scc_lda_button_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_hev_non_scc_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_HEV_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_hev_non_scc_lda_button_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_HEV_ADDR_CHECK
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_ev_non_scc_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_EV_ADDR_CHECK
|
||||
};
|
||||
|
||||
static RxCheck hyundai_ev_non_scc_lda_button_addr_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_NON_SCC_EV_ADDR_CHECK
|
||||
HYUNDAI_LDA_BUTTON_ADDR_CHECK
|
||||
};
|
||||
|
||||
SET_TX_MSGS(HYUNDAI_TX_MSGS, ret);
|
||||
if (hyundai_fcev_gas_signal) {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_fcev_lda_button_rx_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_fcev_rx_checks, ret);
|
||||
}
|
||||
} else if (hyundai_non_scc) {
|
||||
if (hyundai_ev_gas_signal) {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_ev_non_scc_lda_button_addr_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_ev_non_scc_addr_checks, ret);
|
||||
}
|
||||
} else if (hyundai_hybrid_gas_signal) {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_hev_non_scc_lda_button_addr_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_hev_non_scc_addr_checks, ret);
|
||||
}
|
||||
} else {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_non_scc_lda_button_addr_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_non_scc_addr_checks, ret);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hyundai_has_lda_button) {
|
||||
SET_RX_CHECKS(hyundai_lda_button_rx_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_rx_checks, ret);
|
||||
if(addr == 593) {
|
||||
if(now - last_ts_mdps12_from_op < 200000) {
|
||||
bus_fwd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
if (bus_num == 2) {
|
||||
bool is_lkas_msg = addr == 832;
|
||||
bool is_lfahda_msg = addr == 1157;
|
||||
bool is_scc_msg = addr == 1056 || addr == 1057 || addr == 905;
|
||||
bool is_scc13_msg = addr == 1290;
|
||||
bool is_fca11_msg = addr == 909;
|
||||
bool is_fca12_msg = addr == 1155;
|
||||
|
||||
bool block_msg = is_lkas_msg || is_lfahda_msg || is_scc_msg || is_scc13_msg || is_fca11_msg || is_fca12_msg;
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
else {
|
||||
if(is_lkas_msg) {
|
||||
if(now - last_ts_lkas11_from_op >= 200000) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
}
|
||||
else if(is_lfahda_msg) {
|
||||
if (now - last_ts_lfahda_mfc_from_op >= 200000)
|
||||
bus_fwd = 0;
|
||||
}
|
||||
else if (is_scc_msg) {
|
||||
if (now - last_ts_scc12_from_op >= 400000)
|
||||
bus_fwd = 0;
|
||||
}
|
||||
else if (is_scc13_msg) {
|
||||
if (now - last_ts_scc13_from_op >= 800000)
|
||||
bus_fwd = 0;
|
||||
}
|
||||
else if (is_fca11_msg) {
|
||||
if (now - last_ts_fca11_from_op >= 400000)
|
||||
bus_fwd = 0;
|
||||
}
|
||||
else if (is_fca12_msg) {
|
||||
if (now - last_ts_fca12_from_op >= 400000)
|
||||
bus_fwd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bus_fwd == -1;
|
||||
}
|
||||
|
||||
/* case
|
||||
- legacy(on/off) + camera_scc(allways longitudinal on) + longitudinal(scc off)
|
||||
*/
|
||||
static safety_config hyundai_init_carrot(bool legacy_car) {
|
||||
static const CanMsg HYUNDAI_LONG_TX_MSGS[] = {
|
||||
{0x340, 0, 8}, // LKAS11 Bus 0
|
||||
{0x4F1, 0, 4}, // CLU11 Bus 0
|
||||
{0x485, 0, 8}, // LFAHDA_MFC Bus 0
|
||||
{0x251, 2, 8}, // MDPS12 Bus 2
|
||||
{0x420, 0, 8}, // SCC11 Bus 0
|
||||
{0x421, 0, 8}, // SCC12 Bus 0
|
||||
{0x50A, 0, 8}, // SCC13 Bus 0
|
||||
{0x389, 0, 8}, // SCC14 Bus 0
|
||||
{0x4A2, 0, 2}, // FRT_RADAR11 Bus 0
|
||||
{0x38D, 0, 8}, // FCA11 Bus 0
|
||||
{0x483, 0, 8}, // FCA12 Bus 0
|
||||
{0x7D0, 0, 8}, // radar UDS TX addr Bus 0 (for radar disable)
|
||||
};
|
||||
|
||||
static const CanMsg HYUNDAI_CAMERA_SCC_TX_MSGS[] = {
|
||||
{0x340, 0, 8}, // LKAS11 Bus 0
|
||||
{0x4F1, 2, 4}, // CLU11 Bus 2
|
||||
{0x485, 0, 8}, // LFAHDA_MFC Bus 0
|
||||
{593, 2, 8}, // MDPS12, Bus 2
|
||||
{1056, 0, 8}, // SCC11, Bus 0
|
||||
{1057, 0, 8}, // SCC12, Bus 0
|
||||
{1290, 0, 8}, // SCC13, Bus 0
|
||||
{905, 0, 8}, // SCC14, Bus 0
|
||||
{909, 0, 8}, // FCA11 Bus 0
|
||||
{1155, 0, 8}, // FCA12 Bus 0
|
||||
{1186, 0, 8}, // FRT_RADAR11, Bus 0
|
||||
{0x4F1, 0, 4}, // CLU11 Bus 0
|
||||
};
|
||||
|
||||
safety_config ret;
|
||||
if (hyundai_camera_scc) {
|
||||
static RxCheck hyundai_cam_scc_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(2)
|
||||
};
|
||||
static RxCheck hyundai_cam_scc_rx_checks_legacy[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(true)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(2)
|
||||
};
|
||||
if(legacy_car) ret = BUILD_SAFETY_CFG(hyundai_cam_scc_rx_checks_legacy, HYUNDAI_CAMERA_SCC_TX_MSGS);
|
||||
else ret = BUILD_SAFETY_CFG(hyundai_cam_scc_rx_checks, HYUNDAI_CAMERA_SCC_TX_MSGS);
|
||||
}
|
||||
else if (hyundai_longitudinal) {
|
||||
static RxCheck hyundai_long_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
// Use CLU11 (buttons) to manage controls allowed instead of SCC cruise state
|
||||
{.msg = {{0x4F1, 0, 4, .ignore_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}
|
||||
},
|
||||
};
|
||||
static RxCheck hyundai_long_rx_checks_legacy[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(true)
|
||||
// Use CLU11 (buttons) to manage controls allowed instead of SCC cruise state
|
||||
{.msg = {{0x4F1, 0, 4, .ignore_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}
|
||||
},
|
||||
};
|
||||
|
||||
if(legacy_car) ret = BUILD_SAFETY_CFG(hyundai_long_rx_checks_legacy, HYUNDAI_LONG_TX_MSGS);
|
||||
else ret = BUILD_SAFETY_CFG(hyundai_long_rx_checks, HYUNDAI_LONG_TX_MSGS);
|
||||
}
|
||||
else {
|
||||
static RxCheck hyundai_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(false)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(0)
|
||||
};
|
||||
static RxCheck hyundai_rx_checks_legacy[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(true)
|
||||
//HYUNDAI_SCC12_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
if(legacy_car) ret = BUILD_SAFETY_CFG(hyundai_rx_checks_legacy, HYUNDAI_TX_MSGS);
|
||||
else ret = BUILD_SAFETY_CFG(hyundai_rx_checks, HYUNDAI_TX_MSGS);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static safety_config hyundai_init(uint16_t param) {
|
||||
hyundai_common_init(param);
|
||||
hyundai_legacy = false;
|
||||
return hyundai_init_carrot(hyundai_legacy);
|
||||
}
|
||||
|
||||
static safety_config hyundai_legacy_init(uint16_t param) {
|
||||
// older hyundai models have less checks due to missing counters and checksums
|
||||
static RxCheck hyundai_legacy_rx_checks[] = {
|
||||
HYUNDAI_COMMON_RX_CHECKS(true)
|
||||
HYUNDAI_SCC12_ADDR_CHECK(0)
|
||||
HYUNDAI_SCC11_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
hyundai_common_init(param);
|
||||
hyundai_legacy = true;
|
||||
hyundai_longitudinal = false;
|
||||
hyundai_camera_scc = false;
|
||||
return BUILD_SAFETY_CFG(hyundai_legacy_rx_checks, HYUNDAI_TX_MSGS);
|
||||
return hyundai_init_carrot(hyundai_legacy);
|
||||
}
|
||||
|
||||
const safety_hooks hyundai_hooks = {
|
||||
.init = hyundai_init,
|
||||
.rx = hyundai_rx_hook,
|
||||
.tx = hyundai_tx_hook,
|
||||
.fwd = hyundai_fwd_hook,
|
||||
.get_counter = hyundai_get_counter,
|
||||
.get_checksum = hyundai_get_checksum,
|
||||
.compute_checksum = hyundai_compute_checksum,
|
||||
@@ -503,6 +460,7 @@ const safety_hooks hyundai_legacy_hooks = {
|
||||
.init = hyundai_legacy_init,
|
||||
.rx = hyundai_rx_hook,
|
||||
.tx = hyundai_tx_hook,
|
||||
.fwd = hyundai_fwd_hook,
|
||||
.get_counter = hyundai_get_counter,
|
||||
.get_checksum = hyundai_get_checksum,
|
||||
.compute_checksum = hyundai_compute_checksum,
|
||||
|
||||
@@ -3,149 +3,550 @@
|
||||
#include "iqdbc/safety/declarations.h"
|
||||
#include "iqdbc/safety/modes/hyundai_common.h"
|
||||
|
||||
#define HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(bus) \
|
||||
{0x1CF, bus, 8, .check_relay = false}, /* CRUISE_BUTTON */ \
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
|
||||
#define HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(a_can, e_can) \
|
||||
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \
|
||||
{0x50, a_can, 16, .check_relay = (a_can) == 0}, /* LKAS */ \
|
||||
{0x2A4, a_can, 24, .check_relay = (a_can) == 0}, /* CAM_0x2A4 */ \
|
||||
const TorqueSteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = {
|
||||
.max_torque = 512, //270,
|
||||
.max_rt_delta = 112,
|
||||
|
||||
#define HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(a_can, e_can) \
|
||||
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \
|
||||
{0x110, a_can, 32, .check_relay = (a_can) == 0}, /* LKAS_ALT */ \
|
||||
{0x362, a_can, 32, .check_relay = (a_can) == 0}, /* CAM_0x362 */ \
|
||||
.max_rate_up = 2,
|
||||
.max_rate_down = 3,
|
||||
.driver_torque_allowance = 250,
|
||||
.driver_torque_multiplier = 2,
|
||||
.type = TorqueDriverLimited,
|
||||
|
||||
#define HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(e_can) \
|
||||
{0x12A, e_can, 16, .check_relay = (e_can) == 0}, /* LFA */ \
|
||||
{0x1E0, e_can, 16, .check_relay = (e_can) == 0}, /* LFAHDA_CLUSTER */ \
|
||||
// the EPS faults when the steering angle is above a certain threshold for too long. to prevent this,
|
||||
// we allow setting torque actuation bit to 0 while maintaining the requested torque value for two consecutive frames
|
||||
.min_valid_request_frames = 89,
|
||||
.max_invalid_request_frames = 2,
|
||||
.min_valid_request_rt_interval = 810000, // 810ms; a ~10% buffer on cutting every 90 frames
|
||||
.has_steer_req_tolerance = true,
|
||||
};
|
||||
|
||||
const CanMsg HYUNDAI_CANFD_HDA2_TX_MSGS[] = {
|
||||
{0x50, 0, 16}, // LKAS
|
||||
{0x1CF, 1, 8}, // CRUISE_BUTTON
|
||||
{0x2A4, 0, 24}, // CAM_0x2A4
|
||||
};
|
||||
|
||||
const CanMsg HYUNDAI_CANFD_HDA2_ALT_STEERING_TX_MSGS[] = {
|
||||
{0x110, 0, 32}, // LKAS_ALT
|
||||
{0x1CF, 1, 8}, // CRUISE_BUTTON
|
||||
{0x362, 0, 32}, // CAM_0x362
|
||||
{0x1AA, 1, 16}, // CRUISE_ALT_BUTTONS , carrot
|
||||
};
|
||||
|
||||
const CanMsg HYUNDAI_CANFD_HDA2_LONG_TX_MSGS[] = {
|
||||
{0x50, 0, 16}, // LKAS
|
||||
{0x1CF, 0, 8}, // CRUISE_BUTTON
|
||||
{0x1CF, 1, 8}, // CRUISE_BUTTON
|
||||
{0x1CF, 2, 8}, // CRUISE_BUTTON
|
||||
{0x1AA, 0, 16}, // CRUISE_ALT_BUTTONS , carrot
|
||||
{0x1AA, 1, 16}, // CRUISE_ALT_BUTTONS , carrot
|
||||
{0x1AA, 2, 16}, // CRUISE_ALT_BUTTONS , carrot
|
||||
{0x2A4, 0, 24}, // CAM_0x2A4
|
||||
{0x51, 0, 32}, // ADRV_0x51
|
||||
{0x730, 1, 8}, // tester present for ADAS ECU disable
|
||||
{0x12A, 1, 16}, // LFA
|
||||
{0x160, 1, 16}, // ADRV_0x160
|
||||
{0x1E0, 1, 16}, // LFAHDA_CLUSTER
|
||||
{0x1A0, 1, 32}, // CRUISE_INFO
|
||||
{0x1EA, 1, 32}, // ADRV_0x1ea
|
||||
{0x200, 1, 8}, // ADRV_0x200
|
||||
{0x345, 1, 8}, // ADRV_0x345
|
||||
{0x1DA, 1, 32}, // ADRV_0x1da
|
||||
|
||||
{0x12A, 0, 16}, // LFA
|
||||
{0x1E0, 0, 16}, // LFAHDA_CLUSTER
|
||||
{0x160, 0, 16}, // ADRV_0x160
|
||||
{0x1EA, 0, 32}, // ADRV_0x1ea
|
||||
{0x200, 0, 8}, // ADRV_0x200
|
||||
{0x1A0, 0, 32}, // CRUISE_INFO
|
||||
{0x345, 0, 8}, // ADRV_0x345
|
||||
{0x1DA, 0, 32}, // ADRV_0x1da
|
||||
|
||||
{0x362, 0, 32}, // CAM_0x362
|
||||
{0x362, 1, 32}, // CAM_0x362
|
||||
{0x2a4, 1, 24}, // CAM_0x2a4
|
||||
|
||||
{0x110, 0, 32}, // LKAS_ALT (272)
|
||||
{0x110, 1, 32}, // LKAS_ALT (272)
|
||||
|
||||
{0x50, 1, 16}, //
|
||||
{0x51, 1, 32}, //
|
||||
|
||||
{353, 0, 32}, // ADRV_353
|
||||
{354, 0, 32}, // CORNER_RADAR_HIGHWAY
|
||||
{512, 0, 8}, // ADRV_0x200
|
||||
{1187, 2, 8}, // 4A3
|
||||
{1204, 2, 8}, // 4B4
|
||||
|
||||
{203, 0, 24}, // CB
|
||||
{373, 2, 24}, // TCS(0x175)
|
||||
{506, 2, 32}, // CLUSTER_SPEED_LIMIT
|
||||
{234, 2, 24}, // MDPS
|
||||
{687, 2, 8}, // STEER_TOUCH_2AF
|
||||
|
||||
{0x4BE, 2, 8}, // NEW_MSG_4BE (may be corner radar enabler x)
|
||||
{0x4B9, 2, 8}, // NEW_MSG_4B9 (may be corner radar enabler)
|
||||
};
|
||||
|
||||
const CanMsg HYUNDAI_CANFD_HDA1_TX_MSGS[] = {
|
||||
{0x12A, 0, 16}, // LFA
|
||||
{0x1A0, 0, 32}, // CRUISE_INFO
|
||||
{0x1CF, 0, 8}, // CRUISE_BUTTON
|
||||
{0x1CF, 2, 8}, // CRUISE_BUTTON
|
||||
{0x1E0, 0, 16}, // LFAHDA_CLUSTER
|
||||
{0x160, 0, 16}, // ADRV_0x160
|
||||
{0x7D0, 0, 8}, // tester present for radar ECU disable
|
||||
{0x1AA, 2, 16}, // CRUISE_ALT_BUTTONS , carrot
|
||||
{203, 0, 24}, // CB
|
||||
{373, 2, 24}, // TCS(0x175)
|
||||
|
||||
{353, 0, 32}, // ADRV_353
|
||||
{354, 0, 32}, // CORNER_RADAR_HIGHWAY
|
||||
{512, 0, 8}, // ADRV_0x200
|
||||
{1187, 2, 8}, // 4A3
|
||||
{1204, 2, 8}, // 4B4
|
||||
{373, 2, 24}, // TCS(0x175)
|
||||
{234, 2, 24}, // MDPS
|
||||
{687, 2, 8}, // STEER_TOUCH_2AF
|
||||
|
||||
};
|
||||
|
||||
#define HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(e_can, longitudinal) \
|
||||
{0x1A0, e_can, 32, .check_relay = (longitudinal)}, /* SCC_CONTROL */ \
|
||||
|
||||
// *** Addresses checked in rx hook ***
|
||||
// EV, ICE, HYBRID: ACCELERATOR (0x35), ACCELERATOR_BRAKE_ALT (0x100), ACCELERATOR_ALT (0x105)
|
||||
#define HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x35, (pt_bus), 32, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, \
|
||||
{0x100, (pt_bus), 32, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, \
|
||||
{0x105, (pt_bus), 32, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}}}, \
|
||||
{.msg = {{0x175, (pt_bus), 24, 50U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xa0, (pt_bus), 24, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xea, (pt_bus), 24, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x35, (pt_bus), 32, .max_counter = 0xffU, .frequency = 100U}, \
|
||||
{0x100, (pt_bus), 32, .max_counter = 0xffU, .frequency = 100U}, \
|
||||
{0x105, (pt_bus), 32, .max_counter = 0xffU, .frequency = 100U}}}, \
|
||||
{.msg = {{0x175, (pt_bus), 24, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xa0, (pt_bus), 24, .max_counter = 0xffU, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0xea, (pt_bus), 24, .max_counter = 0xffU, .frequency = 100U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(pt_bus) \
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1cf, (pt_bus), 8, 50U, .ignore_checksum = true, .max_counter = 0xfU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(pt_bus) \
|
||||
{.msg = {{0x1cf, (pt_bus), 8, .ignore_checksum = true, .max_counter = 0xfU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(pt_bus) \
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \
|
||||
{.msg = {{0x1aa, (pt_bus), 16, 50U, .ignore_checksum = true, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(pt_bus) \
|
||||
{.msg = {{0x1aa, (pt_bus), 16, .ignore_checksum = true, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
// SCC_CONTROL (from ADAS unit or camera)
|
||||
#define HYUNDAI_CANFD_SCC_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x1a0, (scc_bus), 32, 50U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
#define HYUNDAI_CANFD_SCC_ADDR_CHECK(scc_bus) \
|
||||
{.msg = {{0x1a0, (scc_bus), 32, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \
|
||||
|
||||
static bool hyundai_canfd_alt_buttons = false;
|
||||
static bool hyundai_canfd_lka_steering_alt = false;
|
||||
//static bool hyundai_canfd_alt_buttons = false;
|
||||
//static bool hyundai_canfd_hda2_alt_steering = false;
|
||||
|
||||
static unsigned int hyundai_canfd_get_lka_addr(void) {
|
||||
return hyundai_canfd_lka_steering_alt ? 0x110U : 0x50U;
|
||||
// *** Non-HDA2 checks ***
|
||||
// Camera sends SCC messages on HDA1.
|
||||
// Both button messages exist on some platforms, so we ensure we track the correct one using flag
|
||||
RxCheck hyundai_canfd_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(2)
|
||||
};
|
||||
RxCheck hyundai_canfd_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(2)
|
||||
};
|
||||
|
||||
// Longitudinal checks for HDA1
|
||||
RxCheck hyundai_canfd_long_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0)
|
||||
};
|
||||
RxCheck hyundai_canfd_long_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
// Radar sends SCC messages on these cars instead of camera
|
||||
RxCheck hyundai_canfd_radar_scc_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(0)
|
||||
};
|
||||
RxCheck hyundai_canfd_radar_scc_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
|
||||
// *** HDA2 checks ***
|
||||
// E-CAN is on bus 1, ADAS unit sends SCC messages on HDA2.
|
||||
// Does not use the alt buttons message
|
||||
RxCheck hyundai_canfd_hda2_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(1)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(1) // TODO: carrot: canival no 0x1cf
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(1)
|
||||
};
|
||||
RxCheck hyundai_canfd_hda2_rx_checks_scc2[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0) // TODO: carrot: canival no 0x1cf
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(2)
|
||||
};
|
||||
RxCheck hyundai_canfd_hda2_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(1)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(1)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(1)
|
||||
};
|
||||
RxCheck hyundai_canfd_hda2_alt_buttons_rx_checks_scc2[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(2)
|
||||
};
|
||||
RxCheck hyundai_canfd_hda2_long_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(1)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(1) // TODO: carrot: canival no 0x1cf
|
||||
};
|
||||
RxCheck hyundai_canfd_hda2_long_rx_checks_scc2[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0)
|
||||
};
|
||||
RxCheck hyundai_canfd_hda2_long_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(1)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(1)
|
||||
};
|
||||
RxCheck hyundai_canfd_hda2_long_alt_buttons_rx_checks_scc2[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
|
||||
const int HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32;
|
||||
const int HYUNDAI_PARAM_CANFD_HDA2_ALT_STEERING = 128;
|
||||
bool hyundai_canfd_alt_buttons = false;
|
||||
bool hyundai_canfd_hda2_alt_steering = false;
|
||||
bool hyundai_canfd_buffered_fwd = false;
|
||||
|
||||
int hyundai_canfd_hda2_get_lkas_addr(void) {
|
||||
return hyundai_canfd_hda2_alt_steering ? 0x110 : 0x50;
|
||||
}
|
||||
|
||||
static uint8_t hyundai_canfd_get_counter(const CANPacket_t *msg) {
|
||||
static uint8_t hyundai_canfd_get_counter(const CANPacket_t* to_push) {
|
||||
uint8_t ret = 0;
|
||||
if (GET_LEN(msg) == 8U) {
|
||||
ret = msg->data[1] >> 4;
|
||||
} else {
|
||||
ret = msg->data[2];
|
||||
if (GET_LEN(to_push) == 8U) {
|
||||
ret = GET_BYTE(to_push, 1) >> 4;
|
||||
}
|
||||
else {
|
||||
ret = GET_BYTE(to_push, 2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t hyundai_canfd_get_checksum(const CANPacket_t *msg) {
|
||||
uint32_t chksum = msg->data[0] | (msg->data[1] << 8);
|
||||
static uint32_t hyundai_canfd_get_checksum(const CANPacket_t* to_push) {
|
||||
uint32_t chksum = GET_BYTE(to_push, 0) | (GET_BYTE(to_push, 1) << 8);
|
||||
return chksum;
|
||||
}
|
||||
|
||||
static void hyundai_canfd_rx_hook(const CANPacket_t *msg) {
|
||||
|
||||
const unsigned pt_bus = hyundai_canfd_lka_steering ? 1U : 0U;
|
||||
const unsigned int scc_bus = hyundai_camera_scc ? 2U : pt_bus;
|
||||
typedef struct {
|
||||
int addr;
|
||||
int bus; // forwarding block <20><><EFBFBD> tx bus: 0 or 2
|
||||
int hz;
|
||||
uint32_t timeout_us;
|
||||
uint32_t last_tx_us;
|
||||
} CanfdTxState;
|
||||
|
||||
if (msg->bus == pt_bus) {
|
||||
// forwarding block<63><6B>: bus 0,2<><32> <20><><EFBFBD>
|
||||
CanfdTxState canfd_tx_states[] = {
|
||||
{0x50, 0, 100, 0U, 0U}, // 80: LKAS
|
||||
{0x51, 0, 100, 0U, 0U}, // 81: ADRV_0x51
|
||||
{0x110, 0, 100, 0U, 0U}, // 272: LKAS_ALT
|
||||
{0x12A, 0, 100, 0U, 0U}, // 298: LFA
|
||||
{0x160, 0, 50, 0U, 0U}, // 352: ADRV_0x160
|
||||
{0x161, 0, 20, 0U, 0U}, // 353: ADRV_0x161
|
||||
{0x162, 0, 20, 0U, 0U}, // 354: CCNC_0x162
|
||||
{0x1A0, 0, 50, 0U, 0U}, // 416: SCC_CONTROL
|
||||
{0x1DA, 0, 1, 0U, 0U}, // 474: ADRV_0x1da
|
||||
{0x1E0, 0, 20, 0U, 0U}, // 480: LFAHDA_CLUSTER
|
||||
{0x1EA, 0, 20, 0U, 0U}, // 490: ADRV_0x1ea
|
||||
{0x200, 0, 20, 0U, 0U}, // 512: ADRV_0x200
|
||||
{0x2A4, 0, 20, 0U, 0U}, // 676: CAM_0x2a4
|
||||
{0x345, 0, 5, 0U, 0U}, // 837: ADRV_0x345
|
||||
{0x362, 0, 10, 0U, 0U}, // 866: CAM_0x362
|
||||
{0x0CB, 0, 100, 0U, 0U}, // 203: LFA_ALT
|
||||
|
||||
{0x175, 2, 50, 0U, 0U}, // 373: TCS
|
||||
{0x1AA, 2, 50, 0U, 0U}, // 426: CRUISE_ALT_BUTTONS
|
||||
{0x1CF, 2, 50, 0U, 0U}, // 463: CRUISE_BUTTON
|
||||
{0x1FA, 2, 10, 0U, 0U}, // 506: CLUSTER_SPEED_LIMIT
|
||||
{0x0EA, 2, 100, 0U, 0U}, // 234: MDPS
|
||||
{0x2AF, 2, 10, 0U, 0U}, // 687: STEER_TOUCH_2AF
|
||||
{0x4A3, 2, 5, 0U, 0U}, // 1187: HDA_INFO_4A3
|
||||
{0x4B4, 2, 10, 0U, 0U}, // 1204: NEW_MSG_4B4
|
||||
{0x4BE, 2, 10, 0U, 0U}, // 1214: NEW_MSG_4BE
|
||||
{0x4B9, 2, 10, 0U, 0U}, // 1209: NEW_MSG_4B9
|
||||
|
||||
{0, 0, 0, 0U, 0U},
|
||||
};
|
||||
|
||||
static CanfdTxState* find_canfd_tx_state(int bus, int addr) {
|
||||
for (int i = 0; canfd_tx_states[i].addr > 0; i++) {
|
||||
if ((canfd_tx_states[i].addr == addr) && (canfd_tx_states[i].bus == bus)) {
|
||||
return &canfd_tx_states[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void hyundai_canfd_set_counter(CANPacket_t* to_push, uint8_t counter) {
|
||||
if (GET_LEN(to_push) == 8U) {
|
||||
to_push->data[1] = (to_push->data[1] & 0x0FU) | ((counter & 0x0FU) << 4);
|
||||
}
|
||||
else {
|
||||
to_push->data[2] = counter;
|
||||
}
|
||||
}
|
||||
|
||||
static void hyundai_canfd_set_checksum(CANPacket_t* to_push, uint16_t checksum) {
|
||||
to_push->data[0] = (uint8_t)(checksum & 0xFFU);
|
||||
to_push->data[1] = (uint8_t)((checksum >> 8U) & 0xFFU);
|
||||
}
|
||||
|
||||
static void hyundai_canfd_update_checksum(CANPacket_t* to_push) {
|
||||
to_push->data[0] = 0U;
|
||||
to_push->data[1] = 0U;
|
||||
uint32_t checksum = hyundai_common_canfd_compute_checksum(to_push);
|
||||
hyundai_canfd_set_checksum(to_push, (uint16_t)checksum);
|
||||
}
|
||||
static void canfd_apply_counter_and_update_checksum(CANPacket_t* dst, uint8_t counter) {
|
||||
hyundai_canfd_set_counter(dst, counter);
|
||||
hyundai_canfd_update_checksum(dst);
|
||||
}
|
||||
static void canfd_record_tx_time(int bus, int addr, bool tx) {
|
||||
CanfdTxState* st = find_canfd_tx_state(bus, addr);
|
||||
if (st != NULL) {
|
||||
st->last_tx_us = tx ? microsecond_timer_get() : 0U;
|
||||
}
|
||||
}
|
||||
|
||||
static bool canfd_should_block_fwd(int tx_bus, int addr, uint32_t now) {
|
||||
CanfdTxState* st = find_canfd_tx_state(tx_bus, addr);
|
||||
if (st == NULL) {
|
||||
return false;
|
||||
}
|
||||
return (now - st->last_tx_us) < st->timeout_us;
|
||||
}
|
||||
|
||||
#define CANFD_BFWD_MAX_QUEUE 2
|
||||
#define CANFD_BFWD_REUSE_MAX 2
|
||||
|
||||
typedef struct {
|
||||
int addr;
|
||||
int dst_bus;
|
||||
bool enabled;
|
||||
|
||||
bool started;
|
||||
uint8_t head;
|
||||
uint8_t tail;
|
||||
uint8_t count;
|
||||
|
||||
uint8_t reuse_left;
|
||||
bool has_last_pkt;
|
||||
CANPacket_t last_pkt;
|
||||
|
||||
CANPacket_t q[CANFD_BFWD_MAX_QUEUE];
|
||||
} CanfdBufferedFwd;
|
||||
|
||||
CanfdBufferedFwd canfd_bfwd[] = {
|
||||
{.addr = 0x1A0, .dst_bus = 0, .enabled = true }, // SCC_CONTROL
|
||||
{.addr = 0x12A, .dst_bus = 0, .enabled = true }, // LFA
|
||||
{.addr = 0x0CB, .dst_bus = 0, .enabled = true }, // LFA_ALT
|
||||
{.addr = 0x0EA, .dst_bus = 2, .enabled = true }, // MDPS
|
||||
{.addr = 0x1AA, .dst_bus = 2, .enabled = true }, // CRUISE_ALT_BUTTONS
|
||||
// {.addr = 0x1CF, .dst_bus = 2, .enabled = true }, // CRUISE_BUTTON
|
||||
{.addr = 0x175, .dst_bus = 2, .enabled = true }, // TCS
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void canfd_copy_packet(CANPacket_t* dst, const CANPacket_t* src) {
|
||||
dst->fd = src->fd;
|
||||
dst->returned = 0U;
|
||||
dst->rejected = 0U;
|
||||
dst->extended = src->extended;
|
||||
dst->addr = src->addr;
|
||||
dst->bus = src->bus;
|
||||
dst->data_len_code = src->data_len_code;
|
||||
for (uint8_t i = 0U; i < GET_LEN(src); i++) {
|
||||
dst->data[i] = src->data[i];
|
||||
}
|
||||
}
|
||||
static CanfdBufferedFwd* canfd_bfwd_find(int addr, int dst_bus) {
|
||||
for (int i = 0; canfd_bfwd[i].addr > 0; i++) {
|
||||
if (canfd_bfwd[i].enabled &&
|
||||
(canfd_bfwd[i].addr == addr) &&
|
||||
(canfd_bfwd[i].dst_bus == dst_bus)) {
|
||||
return &canfd_bfwd[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void canfd_bfwd_reset(CanfdBufferedFwd* st) {
|
||||
st->started = false;
|
||||
st->head = 0U;
|
||||
st->tail = 0U;
|
||||
st->count = 0U;
|
||||
st->reuse_left = 0U;
|
||||
st->has_last_pkt = false;
|
||||
st->last_pkt = (CANPacket_t){0};
|
||||
}
|
||||
static void canfd_bfwd_push(CanfdBufferedFwd* st, const CANPacket_t* pkt) {
|
||||
if ((st == NULL) || !st->enabled) return;
|
||||
if (GET_BUS(pkt) != st->dst_bus) return;
|
||||
|
||||
// queue<75><65> <20>̹<EFBFBD> 2<><32><EFBFBD><EFBFBD> <20>̹<EFBFBD> <20><> packet<65><74> <20><><EFBFBD><EFBFBD>
|
||||
if (st->count >= CANFD_BFWD_MAX_QUEUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
canfd_copy_packet(&st->q[st->tail], pkt);
|
||||
st->tail = (st->tail + 1U) % CANFD_BFWD_MAX_QUEUE;
|
||||
st->count++;
|
||||
st->started = true;
|
||||
}
|
||||
|
||||
static bool canfd_bfwd_pop(CanfdBufferedFwd* st, CANPacket_t* pkt) {
|
||||
if ((st == NULL) || !st->enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!st->started || (st->count == 0U)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
canfd_copy_packet(pkt, &st->q[st->head]);
|
||||
st->head = (st->head + 1U) % CANFD_BFWD_MAX_QUEUE;
|
||||
st->count--;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> packet <20><><EFBFBD><EFBFBD>
|
||||
canfd_copy_packet(&st->last_pkt, pkt);
|
||||
st->has_last_pkt = true;
|
||||
st->reuse_left = CANFD_BFWD_REUSE_MAX;
|
||||
|
||||
if (st->count == 0U) {
|
||||
st->started = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
static bool canfd_bfwd_reuse_last(CanfdBufferedFwd* st, CANPacket_t* pkt) {
|
||||
if ((st == NULL) || !st->enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!st->has_last_pkt || (st->reuse_left == 0U)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
canfd_copy_packet(pkt, &st->last_pkt);
|
||||
st->reuse_left--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void hyundai_canfd_rx_hook(const CANPacket_t *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
int pt_bus = hyundai_canfd_hda2 ? 1 : 0;
|
||||
const int scc_bus = hyundai_camera_scc ? 2 : pt_bus;
|
||||
|
||||
if (hyundai_camera_scc) pt_bus = 0;
|
||||
|
||||
if (bus == pt_bus) {
|
||||
// driver torque
|
||||
if (msg->addr == 0xeaU) {
|
||||
int torque_driver_new = ((msg->data[11] & 0x1fU) << 8U) | msg->data[10];
|
||||
if (addr == 0xea) {
|
||||
int torque_driver_new = ((GET_BYTE(to_push, 11) & 0x1fU) << 8U) | GET_BYTE(to_push, 10);
|
||||
torque_driver_new -= 4095;
|
||||
update_sample(&torque_driver, torque_driver_new);
|
||||
}
|
||||
|
||||
// cruise buttons
|
||||
const unsigned int button_addr = hyundai_canfd_alt_buttons ? 0x1aaU : 0x1cfU;
|
||||
if (msg->addr == button_addr) {
|
||||
const int button_addr = hyundai_canfd_alt_buttons ? 0x1aa : 0x1cf;
|
||||
if (addr == button_addr) {
|
||||
bool main_button = false;
|
||||
int cruise_button = 0;
|
||||
if (msg->addr == 0x1cfU) {
|
||||
cruise_button = msg->data[2] & 0x7U;
|
||||
main_button = GET_BIT(msg, 19U);
|
||||
aol_button_press = GET_BIT(msg, 23U) ? AOL_BUTTON_PRESSED : AOL_BUTTON_NOT_PRESSED;
|
||||
if (addr == 0x1cf) {
|
||||
cruise_button = GET_BYTE(to_push, 2) & 0x7U;
|
||||
main_button = GET_BIT(to_push, 19U);
|
||||
} else {
|
||||
cruise_button = (msg->data[4] >> 4) & 0x7U;
|
||||
main_button = GET_BIT(msg, 34U);
|
||||
aol_button_press = GET_BIT(msg, 39U) ? AOL_BUTTON_PRESSED : AOL_BUTTON_NOT_PRESSED;
|
||||
cruise_button = (GET_BYTE(to_push, 4) >> 4) & 0x7U;
|
||||
main_button = GET_BIT(to_push, 34U);
|
||||
}
|
||||
hyundai_common_cruise_buttons_check(cruise_button, main_button);
|
||||
}
|
||||
|
||||
// gas press, different for EV, hybrid, and ICE models
|
||||
if ((msg->addr == 0x35U) && hyundai_ev_gas_signal) {
|
||||
gas_pressed = msg->data[5] != 0U;
|
||||
} else if ((msg->addr == 0x105U) && hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = GET_BIT(msg, 103U) || (msg->data[13] != 0U) || GET_BIT(msg, 112U);
|
||||
} else if ((msg->addr == 0x100U) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = GET_BIT(msg, 176U);
|
||||
if ((addr == 0x35) && hyundai_ev_gas_signal) {
|
||||
gas_pressed = GET_BYTE(to_push, 5) != 0U;
|
||||
} else if ((addr == 0x105) && hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = GET_BIT(to_push, 103U) || (GET_BYTE(to_push, 13) != 0U) || GET_BIT(to_push, 112U);
|
||||
} else if ((addr == 0x100) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = GET_BIT(to_push, 176U);
|
||||
} else {
|
||||
}
|
||||
|
||||
// brake press
|
||||
if (msg->addr == 0x175U) {
|
||||
brake_pressed = GET_BIT(msg, 81U);
|
||||
if (addr == 0x175) {
|
||||
brake_pressed = GET_BIT(to_push, 81U);
|
||||
}
|
||||
|
||||
// vehicle moving
|
||||
if (msg->addr == 0xa0U) {
|
||||
uint32_t fl = (GET_BYTES(msg, 8, 2)) & 0x3FFFU;
|
||||
uint32_t fr = (GET_BYTES(msg, 10, 2)) & 0x3FFFU;
|
||||
uint32_t rl = (GET_BYTES(msg, 12, 2)) & 0x3FFFU;
|
||||
uint32_t rr = (GET_BYTES(msg, 14, 2)) & 0x3FFFU;
|
||||
if (addr == 0xa0) {
|
||||
uint32_t fl = (GET_BYTES(to_push, 8, 2)) & 0x3FFFU;
|
||||
uint32_t fr = (GET_BYTES(to_push, 10, 2)) & 0x3FFFU;
|
||||
uint32_t rl = (GET_BYTES(to_push, 12, 2)) & 0x3FFFU;
|
||||
uint32_t rr = (GET_BYTES(to_push, 14, 2)) & 0x3FFFU;
|
||||
vehicle_moving = (fl > HYUNDAI_STANDSTILL_THRSLD) || (fr > HYUNDAI_STANDSTILL_THRSLD) ||
|
||||
(rl > HYUNDAI_STANDSTILL_THRSLD) || (rr > HYUNDAI_STANDSTILL_THRSLD);
|
||||
|
||||
// average of all 4 wheel speeds. Conversion: raw * 0.03125 / 3.6 = m/s
|
||||
UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.03125 * KPH_TO_MS);
|
||||
UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.03125 / 3.6);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->bus == scc_bus) {
|
||||
if (bus == scc_bus) {
|
||||
// cruise state
|
||||
if ((msg->addr == 0x1a0U) && !hyundai_longitudinal) {
|
||||
if ((addr == 0x1a0) && !hyundai_longitudinal) {
|
||||
// 1=enabled, 2=driver override
|
||||
int cruise_status = ((msg->data[8] >> 4) & 0x7U);
|
||||
int cruise_status = ((GET_BYTE(to_push, 8) >> 4) & 0x7U);
|
||||
bool cruise_engaged = (cruise_status == 1) || (cruise_status == 2);
|
||||
hyundai_common_cruise_state_check(cruise_engaged);
|
||||
acc_main_on = GET_BIT(msg, 66U);
|
||||
}
|
||||
}
|
||||
|
||||
hyundai_common_reset_acc_main_on_mismatches();
|
||||
const int steer_addr = hyundai_canfd_hda2 ? hyundai_canfd_hda2_get_lkas_addr() : 0x12a;
|
||||
bool stock_ecu_detected = (addr == steer_addr) && (bus == 0);
|
||||
if (hyundai_longitudinal) {
|
||||
// on HDA2, ensure ADRV ECU is still knocked out
|
||||
// on others, ensure accel msg is blocked from camera
|
||||
const int stock_scc_bus = hyundai_canfd_hda2 ? 1 : 0;
|
||||
stock_ecu_detected = stock_ecu_detected || ((addr == 0x1a0) && (bus == stock_scc_bus));
|
||||
}
|
||||
generic_rx_checks();
|
||||
stock_ecu_check(stock_ecu_detected);
|
||||
|
||||
}
|
||||
|
||||
static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
|
||||
static bool hyundai_canfd_tx_hook(const CANPacket_t *to_send_const) {
|
||||
CANPacket_t* to_send = (CANPacket_t*)to_send_const;
|
||||
|
||||
const TorqueSteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = {
|
||||
.max_torque = 270,
|
||||
.max_torque = 512,
|
||||
.max_rt_delta = 112,
|
||||
.max_rate_up = 2,
|
||||
.max_rate_down = 3,
|
||||
|
||||
.max_rate_up = 10,
|
||||
.max_rate_down = 10,
|
||||
.driver_torque_allowance = 250,
|
||||
.driver_torque_multiplier = 2,
|
||||
.type = TorqueDriverLimited,
|
||||
@@ -159,12 +560,14 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
|
||||
};
|
||||
|
||||
bool tx = true;
|
||||
int addr = GET_ADDR(to_send);
|
||||
bool violation = false;
|
||||
|
||||
// steering
|
||||
const unsigned int steer_addr = (hyundai_canfd_lka_steering && !hyundai_longitudinal) ? hyundai_canfd_get_lka_addr() : 0x12aU;
|
||||
if (msg->addr == steer_addr) {
|
||||
int desired_torque = (((msg->data[6] & 0xFU) << 7U) | (msg->data[5] >> 1U)) - 1024U;
|
||||
bool steer_req = GET_BIT(msg, 52U);
|
||||
const int steer_addr = (hyundai_canfd_hda2 && !hyundai_longitudinal) ? hyundai_canfd_hda2_get_lkas_addr() : 0x12a;
|
||||
if (addr == steer_addr) {
|
||||
int desired_torque = (((GET_BYTE(to_send, 6) & 0xFU) << 7U) | (GET_BYTE(to_send, 5) >> 1U)) - 1024U;
|
||||
bool steer_req = GET_BIT(to_send, 52U);
|
||||
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, HYUNDAI_CANFD_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
@@ -172,209 +575,166 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
// cruise buttons check
|
||||
if (msg->addr == 0x1cfU) {
|
||||
int button = msg->data[2] & 0x7U;
|
||||
if (addr == 0x1cf) {
|
||||
int button = GET_BYTE(to_send, 2) & 0x7U;
|
||||
bool is_cancel = (button == HYUNDAI_BTN_CANCEL);
|
||||
bool is_resume = (button == HYUNDAI_BTN_RESUME);
|
||||
bool is_set = (button == HYUNDAI_BTN_SET);
|
||||
|
||||
bool allowed = (is_cancel && cruise_engaged_prev) || ((is_resume || is_set) && controls_allowed);
|
||||
bool allowed = (is_cancel && (cruise_engaged_prev || controls_allowed)) || (is_resume && controls_allowed);
|
||||
if (!allowed) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
// UDS: only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address
|
||||
if (((msg->addr == 0x730U) && hyundai_canfd_lka_steering) || ((msg->addr == 0x7D0U) && !hyundai_camera_scc)) {
|
||||
if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) {
|
||||
if ((addr == 0x730) && hyundai_canfd_hda2) {
|
||||
if ((GET_BYTES(to_send, 0, 4) != 0x00803E02U) || (GET_BYTES(to_send, 4, 4) != 0x0U)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ACCEL: safety check
|
||||
if (msg->addr == 0x1a0U) {
|
||||
int desired_accel_raw = (((msg->data[17] & 0x7U) << 8) | msg->data[16]) - 1023U;
|
||||
int desired_accel_val = ((msg->data[18] << 4) | (msg->data[17] >> 4)) - 1023U;
|
||||
if (addr == 0x1a0) {
|
||||
int desired_accel_raw = (((GET_BYTE(to_send, 17) & 0x7U) << 8) | GET_BYTE(to_send, 16)) - 1023U;
|
||||
int desired_accel_val = ((GET_BYTE(to_send, 18) << 4) | (GET_BYTE(to_send, 17) >> 4)) - 1023U;
|
||||
|
||||
bool violation = false;
|
||||
|
||||
if (hyundai_longitudinal) {
|
||||
violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS);
|
||||
violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// only used to cancel on here
|
||||
const int acc_mode = (msg->data[8] >> 4) & 0x7U;
|
||||
const int acc_mode = (GET_BYTE(to_send, 8) >> 4) & 0x7U;
|
||||
if (acc_mode != 4) {
|
||||
violation = true;
|
||||
}
|
||||
|
||||
if ((desired_accel_raw != 0) || (desired_accel_val != 0)) {
|
||||
violation = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (violation) {
|
||||
tx = false;
|
||||
}
|
||||
|
||||
acc_main_on_tx = GET_BIT(msg, 66U);
|
||||
hyundai_common_acc_main_on_sync();
|
||||
}
|
||||
|
||||
if (violation) {
|
||||
tx = false;
|
||||
}
|
||||
else if (hyundai_canfd_buffered_fwd) {
|
||||
CanfdBufferedFwd* bfwd = canfd_bfwd_find(addr, GET_BUS(to_send));
|
||||
if (bfwd != NULL) {
|
||||
canfd_bfwd_push(bfwd, to_send);
|
||||
//tx = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
canfd_record_tx_time(GET_BUS(to_send), addr, tx);
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
static bool hyundai_canfd_fwd_hook(int bus_num, int addr) {
|
||||
uint32_t now = microsecond_timer_get();
|
||||
if (bus_num == 0) {
|
||||
if (canfd_should_block_fwd(2, addr, now)) {
|
||||
return true;
|
||||
}
|
||||
if (addr == 0x4B9) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return (bus_num != 2) || canfd_should_block_fwd(0, addr, now);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
static const CanMsg HYUNDAI_CANFD_LKA_STEERING_TX_MSGS[] = {
|
||||
HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1)
|
||||
};
|
||||
for (int i = 0; canfd_tx_states[i].addr > 0; i++) {
|
||||
canfd_tx_states[i].timeout_us = (uint32_t)(1000000.0 / canfd_tx_states[i].hz) + 20000U;
|
||||
canfd_tx_states[i].last_tx_us = 0U;
|
||||
}
|
||||
|
||||
static const CanMsg HYUNDAI_CANFD_LKA_STEERING_ALT_TX_MSGS[] = {
|
||||
HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(0, 1)
|
||||
};
|
||||
|
||||
static const CanMsg HYUNDAI_CANFD_LKA_STEERING_LONG_TX_MSGS[] = {
|
||||
HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1)
|
||||
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(1)
|
||||
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(1, true)
|
||||
{0x51, 0, 32, .check_relay = false}, // ADRV_0x51
|
||||
{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
|
||||
{0x200, 1, 8, .check_relay = false}, // ADRV_0x200
|
||||
{0x345, 1, 8, .check_relay = false}, // ADRV_0x345
|
||||
{0x1DA, 1, 32, .check_relay = false}, // ADRV_0x1da
|
||||
};
|
||||
|
||||
static const CanMsg HYUNDAI_CANFD_LFA_STEERING_TX_MSGS[] = {
|
||||
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2)
|
||||
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0)
|
||||
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, false)
|
||||
};
|
||||
|
||||
// ADRV_0x160 is checked for radar liveness
|
||||
static const CanMsg HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS[] = {
|
||||
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2)
|
||||
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0)
|
||||
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, true)
|
||||
{0x160, 0, 16, .check_relay = true}, // ADRV_0x160
|
||||
{0x7D0, 0, 8, .check_relay = false}, // tester present for radar ECU disable
|
||||
};
|
||||
|
||||
// ADRV_0x160 is checked for relay malfunction
|
||||
#define HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_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)) \
|
||||
{0x160, 0, 16, .check_relay = (longitudinal)}, /* ADRV_0x160 */ \
|
||||
for (int i = 0; canfd_bfwd[i].addr > 0; i++) {
|
||||
canfd_bfwd_reset(&canfd_bfwd[i]);
|
||||
}
|
||||
|
||||
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_hda2_alt_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_HDA2_ALT_STEERING);
|
||||
hyundai_canfd_buffered_fwd = hyundai_camera_scc;
|
||||
|
||||
// no long for radar-SCC HDA1 yet
|
||||
//if (!hyundai_canfd_hda2 && !hyundai_camera_scc) {
|
||||
// hyundai_longitudinal = false;
|
||||
//}
|
||||
safety_config ret;
|
||||
if (hyundai_longitudinal) {
|
||||
if (hyundai_canfd_lka_steering) {
|
||||
static RxCheck hyundai_canfd_lka_steering_long_rx_checks[] = {
|
||||
HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(1)
|
||||
};
|
||||
|
||||
ret = BUILD_SAFETY_CFG(hyundai_canfd_lka_steering_long_rx_checks, HYUNDAI_CANFD_LKA_STEERING_LONG_TX_MSGS);
|
||||
|
||||
if (hyundai_canfd_hda2) {
|
||||
if (hyundai_canfd_alt_buttons) { // carrot : for CANIVAL 4TH HDA2
|
||||
if (hyundai_camera_scc) ret = BUILD_SAFETY_CFG(hyundai_canfd_hda2_long_alt_buttons_rx_checks_scc2, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
else ret = BUILD_SAFETY_CFG(hyundai_canfd_hda2_long_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
}
|
||||
else {
|
||||
if (hyundai_camera_scc) ret = BUILD_SAFETY_CFG(hyundai_canfd_hda2_long_rx_checks_scc2, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
else ret = BUILD_SAFETY_CFG(hyundai_canfd_hda2_long_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
}
|
||||
} else {
|
||||
// Longitudinal checks for LFA steering
|
||||
static RxCheck hyundai_canfd_long_rx_checks[] = {
|
||||
HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(0)
|
||||
};
|
||||
|
||||
static RxCheck hyundai_canfd_alt_buttons_long_rx_checks[] = {
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(0)
|
||||
};
|
||||
|
||||
static CanMsg hyundai_canfd_lfa_steering_camera_scc_tx_msgs[] = {
|
||||
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(true)
|
||||
};
|
||||
|
||||
if (hyundai_canfd_alt_buttons) {
|
||||
SET_RX_CHECKS(hyundai_canfd_alt_buttons_long_rx_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_canfd_long_rx_checks, ret);
|
||||
}
|
||||
|
||||
if (hyundai_camera_scc) {
|
||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
||||
} else {
|
||||
SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret);
|
||||
}
|
||||
ret = hyundai_canfd_alt_buttons ? BUILD_SAFETY_CFG(hyundai_canfd_long_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(hyundai_canfd_long_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (hyundai_canfd_lka_steering) {
|
||||
// *** LKA steering checks ***
|
||||
// E-CAN is on bus 1, SCC messages are sent on cars with ADRV ECU.
|
||||
// Does not use the alt buttons message
|
||||
static RxCheck hyundai_canfd_lka_steering_rx_checks[] = {
|
||||
HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(1)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(1)
|
||||
if (hyundai_canfd_hda2 && hyundai_camera_scc) {
|
||||
if (hyundai_canfd_alt_buttons) { // carrot : for CANIVAL 4TH HDA2
|
||||
ret = hyundai_canfd_hda2_alt_steering ? BUILD_SAFETY_CFG(hyundai_canfd_hda2_alt_buttons_rx_checks_scc2, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(hyundai_canfd_hda2_alt_buttons_rx_checks_scc2, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
}
|
||||
else {
|
||||
ret = hyundai_canfd_hda2_alt_steering ? BUILD_SAFETY_CFG(hyundai_canfd_hda2_rx_checks_scc2, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(hyundai_canfd_hda2_rx_checks_scc2, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
}
|
||||
}else if (hyundai_canfd_hda2) {
|
||||
if (hyundai_canfd_alt_buttons) { // carrot : for CANIVAL 4TH HDA2
|
||||
ret = hyundai_canfd_hda2_alt_steering ? BUILD_SAFETY_CFG(hyundai_canfd_hda2_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(hyundai_canfd_hda2_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
}
|
||||
else {
|
||||
ret = hyundai_canfd_hda2_alt_steering ? BUILD_SAFETY_CFG(hyundai_canfd_hda2_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(hyundai_canfd_hda2_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS);
|
||||
}
|
||||
} else if (!hyundai_camera_scc) {
|
||||
static RxCheck hyundai_canfd_radar_scc_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
SET_RX_CHECKS(hyundai_canfd_lka_steering_rx_checks, ret);
|
||||
if (hyundai_canfd_lka_steering_alt) {
|
||||
SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_ALT_TX_MSGS, ret);
|
||||
} else {
|
||||
SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_TX_MSGS, ret);
|
||||
}
|
||||
|
||||
} else if (!hyundai_camera_scc) {
|
||||
// Radar sends SCC messages on these cars instead of camera
|
||||
static RxCheck hyundai_canfd_radar_scc_rx_checks[] = {
|
||||
HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
static RxCheck hyundai_canfd_alt_buttons_radar_scc_rx_checks[] = {
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(0)
|
||||
};
|
||||
|
||||
SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_TX_MSGS, ret);
|
||||
|
||||
if (hyundai_canfd_alt_buttons) {
|
||||
SET_RX_CHECKS(hyundai_canfd_alt_buttons_radar_scc_rx_checks, ret);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_canfd_radar_scc_rx_checks, ret);
|
||||
}
|
||||
|
||||
ret = hyundai_canfd_alt_buttons ? BUILD_SAFETY_CFG(hyundai_canfd_radar_scc_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(hyundai_canfd_radar_scc_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS);
|
||||
} else {
|
||||
// *** LFA steering checks ***
|
||||
// Camera sends SCC messages on LFA steering cars.
|
||||
// *** Non-HDA2 checks ***
|
||||
static RxCheck hyundai_canfd_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(2)
|
||||
};
|
||||
|
||||
// Camera sends SCC messages on HDA1.
|
||||
// Both button messages exist on some platforms, so we ensure we track the correct one using flag
|
||||
static RxCheck hyundai_canfd_rx_checks[] = {
|
||||
HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_COMMON_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(2)
|
||||
};
|
||||
|
||||
static RxCheck hyundai_canfd_alt_buttons_rx_checks[] = {
|
||||
HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(0)
|
||||
HYUNDAI_CANFD_SCC_ADDR_CHECK(2)
|
||||
};
|
||||
|
||||
static CanMsg hyundai_canfd_lfa_steering_camera_scc_tx_msgs[] = {
|
||||
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(false)
|
||||
};
|
||||
|
||||
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);
|
||||
} else {
|
||||
SET_RX_CHECKS(hyundai_canfd_rx_checks, ret);
|
||||
}
|
||||
ret = hyundai_canfd_alt_buttons ? BUILD_SAFETY_CFG(hyundai_canfd_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(hyundai_canfd_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,6 +745,7 @@ const safety_hooks hyundai_canfd_hooks = {
|
||||
.init = hyundai_canfd_init,
|
||||
.rx = hyundai_canfd_rx_hook,
|
||||
.tx = hyundai_canfd_tx_hook,
|
||||
.fwd = hyundai_canfd_fwd_hook,
|
||||
.get_counter = hyundai_canfd_get_counter,
|
||||
.get_checksum = hyundai_canfd_get_checksum,
|
||||
.compute_checksum = hyundai_common_canfd_compute_checksum,
|
||||
|
||||
@@ -2,11 +2,20 @@
|
||||
|
||||
#include "iqdbc/safety/declarations.h"
|
||||
|
||||
#define GET_ADDR(msg) ((msg)->addr)
|
||||
#define GET_BUS(msg) ((msg)->bus)
|
||||
#define GET_BYTE(msg, b) ((msg)->data[(b)])
|
||||
|
||||
static int cruise_main_prev = 0;
|
||||
|
||||
static void generic_rx_checks(void);
|
||||
static void stock_ecu_check(bool stock_ecu_detected);
|
||||
|
||||
extern uint16_t hyundai_canfd_crc_lut[256];
|
||||
uint16_t hyundai_canfd_crc_lut[256];
|
||||
|
||||
static const uint8_t HYUNDAI_PREV_BUTTON_SAMPLES = 8; // roughly 160 ms
|
||||
|
||||
//
|
||||
extern const uint32_t HYUNDAI_STANDSTILL_THRSLD;
|
||||
const uint32_t HYUNDAI_STANDSTILL_THRSLD = 12; // 0.375 kph
|
||||
|
||||
@@ -17,13 +26,6 @@ enum {
|
||||
HYUNDAI_BTN_CANCEL = 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
HYUNDAI_PARAM_IQ_ESCC = 16,
|
||||
HYUNDAI_PARAM_IQ_MAIN_BTN_LONG_TOGGLE = 32,
|
||||
HYUNDAI_PARAM_IQ_HAS_LDA_BUTTON = 64,
|
||||
HYUNDAI_PARAM_IQ_NON_SCC = 128,
|
||||
};
|
||||
|
||||
// common state
|
||||
extern bool hyundai_ev_gas_signal;
|
||||
bool hyundai_ev_gas_signal = false;
|
||||
@@ -37,8 +39,8 @@ bool hyundai_longitudinal = false;
|
||||
extern bool hyundai_camera_scc;
|
||||
bool hyundai_camera_scc = false;
|
||||
|
||||
extern bool hyundai_canfd_lka_steering;
|
||||
bool hyundai_canfd_lka_steering = false;
|
||||
extern bool hyundai_canfd_hda2;
|
||||
bool hyundai_canfd_hda2 = false;
|
||||
|
||||
extern bool hyundai_alt_limits;
|
||||
bool hyundai_alt_limits = false;
|
||||
@@ -49,57 +51,29 @@ bool hyundai_fcev_gas_signal = false;
|
||||
extern bool hyundai_alt_limits_2;
|
||||
bool hyundai_alt_limits_2 = false;
|
||||
|
||||
// ESCC
|
||||
extern bool hyundai_escc;
|
||||
bool hyundai_escc = false;
|
||||
|
||||
extern bool hyundai_main_btn_long_toggle;
|
||||
bool hyundai_main_btn_long_toggle = false;
|
||||
|
||||
extern bool hyundai_has_lda_button;
|
||||
bool hyundai_has_lda_button = false;
|
||||
|
||||
extern bool hyundai_non_scc;
|
||||
bool hyundai_non_scc = false;
|
||||
|
||||
static uint8_t hyundai_last_button_interaction; // button messages since the user pressed an enable button
|
||||
|
||||
static bool main_button_prev;
|
||||
static bool acc_main_on_prev;
|
||||
static bool acc_main_on_tx;
|
||||
static uint32_t acc_main_on_mismatches;
|
||||
|
||||
void hyundai_common_init(uint16_t param) {
|
||||
const uint16_t HYUNDAI_PARAM_EV_GAS = 1;
|
||||
const uint16_t HYUNDAI_PARAM_HYBRID_GAS = 2;
|
||||
const uint16_t HYUNDAI_PARAM_CAMERA_SCC = 8;
|
||||
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEERING = 16;
|
||||
const uint16_t HYUNDAI_PARAM_ALT_LIMITS = 64; // TODO: shift this down with the rest of the common flags
|
||||
const uint16_t HYUNDAI_PARAM_FCEV_GAS = 256;
|
||||
const uint16_t HYUNDAI_PARAM_ALT_LIMITS_2 = 512;
|
||||
const int HYUNDAI_PARAM_EV_GAS = 1;
|
||||
const int HYUNDAI_PARAM_HYBRID_GAS = 2;
|
||||
const int HYUNDAI_PARAM_CAMERA_SCC = 8;
|
||||
const int HYUNDAI_PARAM_CANFD_HDA2 = 16;
|
||||
const int HYUNDAI_PARAM_ALT_LIMITS = 64; // TODO: shift this down with the rest of the common flags
|
||||
const int HYUNDAI_PARAM_FCEV_GAS = 256;
|
||||
const int HYUNDAI_PARAM_ALT_LIMITS_2 = 512;
|
||||
|
||||
hyundai_ev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_EV_GAS);
|
||||
hyundai_hybrid_gas_signal = !hyundai_ev_gas_signal && GET_FLAG(param, HYUNDAI_PARAM_HYBRID_GAS);
|
||||
hyundai_camera_scc = GET_FLAG(param, HYUNDAI_PARAM_CAMERA_SCC);
|
||||
hyundai_canfd_lka_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING);
|
||||
hyundai_canfd_hda2 = GET_FLAG(param, HYUNDAI_PARAM_CANFD_HDA2);
|
||||
hyundai_alt_limits = GET_FLAG(param, HYUNDAI_PARAM_ALT_LIMITS);
|
||||
hyundai_fcev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_FCEV_GAS);
|
||||
hyundai_alt_limits_2 = GET_FLAG(param, HYUNDAI_PARAM_ALT_LIMITS_2);
|
||||
|
||||
hyundai_escc = GET_FLAG(current_safety_param_iq, HYUNDAI_PARAM_IQ_ESCC);
|
||||
hyundai_main_btn_long_toggle = GET_FLAG(current_safety_param_iq, HYUNDAI_PARAM_IQ_MAIN_BTN_LONG_TOGGLE);
|
||||
hyundai_has_lda_button = GET_FLAG(current_safety_param_iq, HYUNDAI_PARAM_IQ_HAS_LDA_BUTTON);
|
||||
hyundai_non_scc = GET_FLAG(current_safety_param_iq, HYUNDAI_PARAM_IQ_NON_SCC);
|
||||
|
||||
hyundai_last_button_interaction = HYUNDAI_PREV_BUTTON_SAMPLES;
|
||||
|
||||
main_button_prev = false;
|
||||
acc_main_on_prev = false;
|
||||
acc_main_on_tx = false;
|
||||
acc_main_on_mismatches = 0U;
|
||||
|
||||
#ifdef ALLOW_DEBUG
|
||||
const uint16_t HYUNDAI_PARAM_LONGITUDINAL = 4;
|
||||
const int HYUNDAI_PARAM_LONGITUDINAL = 4;
|
||||
hyundai_longitudinal = GET_FLAG(param, HYUNDAI_PARAM_LONGITUDINAL);
|
||||
#else
|
||||
hyundai_longitudinal = false;
|
||||
@@ -112,19 +86,27 @@ void hyundai_common_cruise_state_check(const bool cruise_engaged) {
|
||||
|
||||
// enter controls on rising edge of ACC and recent user button press, exit controls when ACC off
|
||||
if (!hyundai_longitudinal) {
|
||||
if (cruise_engaged && !cruise_engaged_prev && (hyundai_last_button_interaction < HYUNDAI_PREV_BUTTON_SAMPLES)) {
|
||||
hyundai_last_button_interaction = 0U; // carrot
|
||||
//if (cruise_engaged && !cruise_engaged_prev && (hyundai_last_button_interaction < HYUNDAI_PREV_BUTTON_SAMPLES)) {
|
||||
if (cruise_engaged) {
|
||||
controls_allowed = true;
|
||||
}
|
||||
|
||||
if (!cruise_engaged) {
|
||||
controls_allowed = false;
|
||||
|
||||
}
|
||||
cruise_engaged_prev = cruise_engaged;
|
||||
}
|
||||
}
|
||||
|
||||
void hyundai_common_cruise_buttons_check(const int cruise_button, const bool main_button) {
|
||||
if ((cruise_button == HYUNDAI_BTN_RESUME) || (cruise_button == HYUNDAI_BTN_SET) || (cruise_button == HYUNDAI_BTN_CANCEL) || main_button) {
|
||||
if(main_button && main_button != cruise_main_prev) {
|
||||
acc_main_on = !acc_main_on;
|
||||
}
|
||||
cruise_main_prev = main_button;
|
||||
if ((cruise_button == HYUNDAI_BTN_RESUME) || (cruise_button == HYUNDAI_BTN_SET) || (cruise_button == HYUNDAI_BTN_CANCEL) ||
|
||||
(main_button)) {
|
||||
hyundai_last_button_interaction = 0U;
|
||||
} else {
|
||||
hyundai_last_button_interaction = SAFETY_MIN(hyundai_last_button_interaction + 1U, HYUNDAI_PREV_BUTTON_SAMPLES);
|
||||
@@ -141,66 +123,38 @@ void hyundai_common_cruise_buttons_check(const int cruise_button, const bool mai
|
||||
// exit controls on cancel press
|
||||
if (cruise_button == HYUNDAI_BTN_CANCEL) {
|
||||
controls_allowed = false;
|
||||
}
|
||||
|
||||
// toggle main cruise state on rising edge of main cruise button
|
||||
if (main_button && !main_button_prev && hyundai_main_btn_long_toggle) {
|
||||
acc_main_on = !acc_main_on;
|
||||
}
|
||||
|
||||
cruise_button_prev = cruise_button;
|
||||
main_button_prev = main_button;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t hyundai_common_canfd_compute_checksum(const CANPacket_t *msg) {
|
||||
int len = GET_LEN(msg);
|
||||
uint32_t address = msg->addr;
|
||||
uint32_t hyundai_common_canfd_compute_checksum(const CANPacket_t *to_push) {
|
||||
int len = GET_LEN(to_push);
|
||||
uint32_t address = GET_ADDR(to_push);
|
||||
|
||||
uint16_t crc = 0;
|
||||
|
||||
for (int i = 2; i < len; i++) {
|
||||
crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ msg->data[i]];
|
||||
crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ GET_BYTE(to_push, i)];
|
||||
}
|
||||
|
||||
// Add address to crc
|
||||
crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ ((address >> 0U) & 0xFFU)];
|
||||
crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ ((address >> 8U) & 0xFFU)];
|
||||
|
||||
if (len == 24) {
|
||||
if (len == 8) {
|
||||
crc ^= 0x5f29U;
|
||||
}
|
||||
else if (len == 16) {
|
||||
crc ^= 0x041dU;
|
||||
}
|
||||
else if (len == 24) {
|
||||
crc ^= 0x819dU;
|
||||
} else if (len == 32) {
|
||||
}
|
||||
else if (len == 32) {
|
||||
crc ^= 0x9f5bU;
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
// reset mismatches on rising edge of acc_main_on to avoid rare race conditions when using non-PCM main cruise state
|
||||
void hyundai_common_reset_acc_main_on_mismatches(void) {
|
||||
if (acc_main_on && !acc_main_on_prev) {
|
||||
acc_main_on_mismatches = 0U;
|
||||
}
|
||||
|
||||
acc_main_on_prev = acc_main_on;
|
||||
}
|
||||
|
||||
// exit lateral controls allowed if iqpilot and panda main cruise states are desynced
|
||||
void hyundai_common_acc_main_on_sync(void) {
|
||||
if (acc_main_on && !acc_main_on_tx) {
|
||||
acc_main_on_mismatches += 1U;
|
||||
|
||||
if (acc_main_on_mismatches >= 3U) { // desync by 3 frames
|
||||
acc_main_on = false;
|
||||
aol_exit_controls(AOL_DISENGAGE_REASON_NON_PCM_ACC_MAIN_DESYNC);
|
||||
}
|
||||
} else {
|
||||
acc_main_on_mismatches = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_acc_main_on_mismatches(void) {
|
||||
return acc_main_on_mismatches;
|
||||
}
|
||||
|
||||
@@ -1,296 +1,46 @@
|
||||
import unittest
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiSafetyFlagsIQ
|
||||
import iqdbc.safety.tests.common as common
|
||||
from iqdbc.safety.tests.libsafety import libsafety_py
|
||||
from iqdbc.safety.tests.common import make_msg
|
||||
|
||||
|
||||
class Buttons:
|
||||
NONE = 0
|
||||
RESUME = 1
|
||||
SET = 2
|
||||
CANCEL = 4
|
||||
def packet(addr: int, bus: int, length: int, updates: dict[int, int] | None = None):
|
||||
data = bytearray(length)
|
||||
for index, value in (updates or {}).items():
|
||||
data[index] = value
|
||||
return libsafety_py.make_CANPacket(addr, bus, data)
|
||||
|
||||
|
||||
PREV_BUTTON_SAMPLES = 8
|
||||
ENABLE_BUTTONS = (Buttons.RESUME, Buttons.SET, Buttons.CANCEL)
|
||||
def classic_steer(torque: int, request: bool = True):
|
||||
value = torque + 1024
|
||||
word = (value << 16) | (int(request) << 27)
|
||||
return packet(0x340, 0, 8, {i: (word >> (8 * i)) & 0xFF for i in range(4)})
|
||||
|
||||
|
||||
class HyundaiButtonBase:
|
||||
BUTTONS_TX_BUS = 0 # tx on this bus, rx on 0
|
||||
SCC_BUS = 0 # rx on this bus
|
||||
|
||||
def test_button_sends(self):
|
||||
"""
|
||||
RES, SET and CANCEL buttons are allowed
|
||||
- RES and SET allowed while controls allowed
|
||||
- CANCEL allowed while cruise is enabled
|
||||
"""
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertFalse(self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS)))
|
||||
self.assertFalse(self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS)))
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS)))
|
||||
self.assertTrue(self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS)))
|
||||
|
||||
for enabled in (True, False):
|
||||
self._rx(self._pcm_status_msg(enabled))
|
||||
self.assertEqual(enabled, self._tx(self._button_msg(Buttons.CANCEL, bus=self.BUTTONS_TX_BUS)))
|
||||
|
||||
def test_enable_control_allowed_from_cruise(self):
|
||||
"""
|
||||
Hyundai non-longitudinal only enables on PCM rising edge and recent button press. Tests PCM enabling with:
|
||||
- disallowed: No buttons
|
||||
- disallowed: Buttons that don't enable cruise
|
||||
- allowed: Buttons that do enable cruise
|
||||
- allowed: Main button with all above combinations
|
||||
"""
|
||||
for main_button in (0, 1):
|
||||
for btn in range(8):
|
||||
for _ in range(PREV_BUTTON_SAMPLES): # reset
|
||||
self._rx(self._button_msg(Buttons.NONE))
|
||||
|
||||
self._rx(self._pcm_status_msg(False))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self._rx(self._button_msg(btn, main_button=main_button))
|
||||
self._rx(self._pcm_status_msg(True))
|
||||
controls_allowed = btn in ENABLE_BUTTONS or main_button
|
||||
self.assertEqual(controls_allowed, self.safety.get_controls_allowed())
|
||||
|
||||
def test_sampling_cruise_buttons(self):
|
||||
"""
|
||||
Test that we allow controls on recent button press, but not as button leaves sliding window
|
||||
"""
|
||||
self._rx(self._button_msg(Buttons.SET))
|
||||
for i in range(2 * PREV_BUTTON_SAMPLES):
|
||||
self._rx(self._pcm_status_msg(False))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self._rx(self._pcm_status_msg(True))
|
||||
controls_allowed = i < PREV_BUTTON_SAMPLES
|
||||
self.assertEqual(controls_allowed, self.safety.get_controls_allowed())
|
||||
self._rx(self._button_msg(Buttons.NONE))
|
||||
def canfd_steer(addr: int, length: int, torque: int, request: bool = True):
|
||||
value = torque + 1024
|
||||
return packet(addr, 0, length, {
|
||||
5: (value & 0x7F) << 1,
|
||||
6: ((value >> 7) & 0xF) | (int(request) << 4),
|
||||
})
|
||||
|
||||
|
||||
class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
|
||||
def classic_accel(accel: int, *, aeb_decel: int = 0, aeb_request: bool = False):
|
||||
value = accel + 1023
|
||||
return packet(0x421, 0, 8, {
|
||||
2: aeb_decel,
|
||||
3: value & 0xFF,
|
||||
4: ((value >> 8) & 0x7) | ((value & 0x7) << 5),
|
||||
5: (value >> 3) & 0xFF,
|
||||
6: int(aeb_request) << 6,
|
||||
})
|
||||
|
||||
DISABLED_ECU_UDS_MSG: tuple[int, int]
|
||||
DISABLED_ECU_ACTUATION_MSG: tuple[int, int]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "HyundaiLongitudinalBase":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
def canfd_accel(accel: int, *, acc_mode: int = 0, bus: int = 0):
|
||||
value = accel + 1023
|
||||
return packet(0x1A0, bus, 32, {
|
||||
8: (acc_mode & 0x7) << 4,
|
||||
16: value & 0xFF,
|
||||
17: ((value >> 8) & 0x7) | ((value & 0xF) << 4),
|
||||
18: (value >> 4) & 0xFF,
|
||||
})
|
||||
|
||||
# override these tests from CarSafetyTest, hyundai longitudinal uses button enable
|
||||
def test_disable_control_allowed_from_cruise(self):
|
||||
pass
|
||||
|
||||
def test_enable_control_allowed_from_cruise(self):
|
||||
pass
|
||||
|
||||
def test_sampling_cruise_buttons(self):
|
||||
pass
|
||||
|
||||
def test_cruise_engaged_prev(self):
|
||||
pass
|
||||
|
||||
def test_button_sends(self):
|
||||
pass
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
raise Exception
|
||||
|
||||
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
|
||||
raise NotImplementedError
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
raise NotImplementedError
|
||||
|
||||
def _tx_acc_state_msg(self, enable):
|
||||
raise NotImplementedError
|
||||
|
||||
def test_pcm_main_cruise_state_availability(self):
|
||||
pass
|
||||
|
||||
def test_set_resume_buttons(self):
|
||||
"""
|
||||
SET and RESUME enter controls allowed on their falling edge.
|
||||
"""
|
||||
for btn_prev in range(8):
|
||||
for btn_cur in range(8):
|
||||
self._rx(self._button_msg(Buttons.NONE))
|
||||
self.safety.set_controls_allowed(0)
|
||||
for _ in range(10):
|
||||
self._rx(self._button_msg(btn_prev))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# should enter controls allowed on falling edge and not transitioning to cancel
|
||||
should_enable = btn_cur != btn_prev and \
|
||||
btn_cur != Buttons.CANCEL and \
|
||||
btn_prev in (Buttons.RESUME, Buttons.SET)
|
||||
|
||||
self._rx(self._button_msg(btn_cur))
|
||||
self.assertEqual(should_enable, self.safety.get_controls_allowed())
|
||||
|
||||
def test_cancel_button(self):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self._rx(self._button_msg(Buttons.CANCEL))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_main_cruise_button(self):
|
||||
"""Test that main cruise button correctly toggles acc_main_on state"""
|
||||
default_safety_mode = self.safety.get_current_safety_mode()
|
||||
default_safety_param = self.safety.get_current_safety_param()
|
||||
default_safety_param_iq = self.safety.get_current_safety_param_iq()
|
||||
|
||||
for enable_aol in (True, False):
|
||||
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
||||
for main_cruise_toggleable in (True, False):
|
||||
with self.subTest("main_cruise_toggleable", main_cruise_toggleable=main_cruise_toggleable):
|
||||
main_cruise_toggleable_flag = HyundaiSafetyFlagsIQ.MAIN_BTN_LONG_TOGGLE if main_cruise_toggleable else 0
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq | main_cruise_toggleable_flag)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
# Test initial state
|
||||
self.safety.set_aol_params(enable_aol, False, False)
|
||||
|
||||
self.assertFalse(self.safety.get_acc_main_on())
|
||||
|
||||
self._rx(self._main_cruise_button_msg(0))
|
||||
self._rx(self._main_cruise_button_msg(1))
|
||||
self.assertEqual(enable_aol and main_cruise_toggleable, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._main_cruise_button_msg(0))
|
||||
self.assertEqual(enable_aol and main_cruise_toggleable, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._main_cruise_button_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
for _ in range(10):
|
||||
self._rx(self._main_cruise_button_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq)
|
||||
|
||||
def test_acc_main_sync_mismatches_reset(self):
|
||||
"""Test that acc_main_on_mismatches resets properly on rising edge of main button"""
|
||||
default_safety_mode = self.safety.get_current_safety_mode()
|
||||
default_safety_param = self.safety.get_current_safety_param()
|
||||
default_safety_param_iq = self.safety.get_current_safety_param_iq()
|
||||
|
||||
for enable_aol in (True, False):
|
||||
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
||||
main_cruise_toggleable_flag = HyundaiSafetyFlagsIQ.MAIN_BTN_LONG_TOGGLE
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq | main_cruise_toggleable_flag)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self.safety.set_aol_params(enable_aol, False, False)
|
||||
|
||||
# Initial state
|
||||
self._rx(self._main_cruise_button_msg(0))
|
||||
self.assertFalse(self.safety.get_acc_main_on())
|
||||
|
||||
# Set up mismatch condition
|
||||
self._rx(self._main_cruise_button_msg(1)) # Press button - acc_main_on = True
|
||||
self._rx(self._main_cruise_button_msg(0)) # Release button
|
||||
self._tx(self._tx_acc_state_msg(False)) # acc_main_on_tx = False
|
||||
self.assertTrue(self.safety.get_acc_main_on())
|
||||
self.assertEqual(1, self.safety.get_acc_main_on_mismatches())
|
||||
|
||||
# Rising edge of acc_main_on should reset
|
||||
self._rx(self._main_cruise_button_msg(1)) # Press button again
|
||||
self._rx(self._main_cruise_button_msg(0)) # Release button
|
||||
self._tx(self._tx_acc_state_msg(False)) # acc_main_on_tx = False
|
||||
self.assertFalse(self.safety.get_acc_main_on())
|
||||
self.assertEqual(0, self.safety.get_acc_main_on_mismatches())
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq)
|
||||
|
||||
def test_acc_main_sync_mismatch_counter(self):
|
||||
"""Test mismatch counter behavior and disengagement"""
|
||||
default_safety_mode = self.safety.get_current_safety_mode()
|
||||
default_safety_param = self.safety.get_current_safety_param()
|
||||
default_safety_param_iq = self.safety.get_current_safety_param_iq()
|
||||
|
||||
for enable_aol in (True, False):
|
||||
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
||||
main_cruise_toggleable_flag = HyundaiSafetyFlagsIQ.MAIN_BTN_LONG_TOGGLE
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq | main_cruise_toggleable_flag)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self.safety.set_aol_params(enable_aol, False, False)
|
||||
self.safety.set_controls_allowed_lat(True)
|
||||
|
||||
# Start with matched states
|
||||
self._rx(self._main_cruise_button_msg(0))
|
||||
self._tx(self._tx_acc_state_msg(False))
|
||||
self.assertEqual(0, self.safety.get_acc_main_on_mismatches())
|
||||
|
||||
# Create mismatch by enabling acc_main_on
|
||||
self._rx(self._main_cruise_button_msg(1)) # Press button
|
||||
self._rx(self._main_cruise_button_msg(0)) # Release button
|
||||
self._tx(self._tx_acc_state_msg(False)) # acc_main_on_tx stays false
|
||||
self.assertTrue(self.safety.get_acc_main_on())
|
||||
self.assertEqual(1, self.safety.get_acc_main_on_mismatches())
|
||||
|
||||
# Second mismatch
|
||||
self._tx(self._tx_acc_state_msg(False))
|
||||
self.assertTrue(self.safety.get_acc_main_on())
|
||||
self.assertEqual(2, self.safety.get_acc_main_on_mismatches())
|
||||
|
||||
# Third mismatch should trigger disengagement
|
||||
self._tx(self._tx_acc_state_msg(False))
|
||||
self.assertFalse(self.safety.get_acc_main_on())
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
# Counter should reset after disengagement
|
||||
self._tx(self._tx_acc_state_msg(False))
|
||||
self.assertEqual(0, self.safety.get_acc_main_on_mismatches())
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq)
|
||||
|
||||
def test_acc_main_sync_mismatch_recovery(self):
|
||||
default_safety_mode = self.safety.get_current_safety_mode()
|
||||
default_safety_param = self.safety.get_current_safety_param()
|
||||
default_safety_param_iq = self.safety.get_current_safety_param_iq()
|
||||
|
||||
"""Test that mismatch counter resets when states resync"""
|
||||
for enable_aol in (True, False):
|
||||
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
||||
main_cruise_toggleable_flag = HyundaiSafetyFlagsIQ.MAIN_BTN_LONG_TOGGLE
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq | main_cruise_toggleable_flag)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self.safety.set_aol_params(enable_aol, False, False)
|
||||
|
||||
# Create initial mismatch
|
||||
self._rx(self._main_cruise_button_msg(1)) # Press button
|
||||
self._rx(self._main_cruise_button_msg(0)) # Release button
|
||||
self._tx(self._tx_acc_state_msg(False)) # acc_main_on_tx = False
|
||||
self.assertEqual(1, self.safety.get_acc_main_on_mismatches())
|
||||
|
||||
# Sync states
|
||||
self._tx(self._tx_acc_state_msg(True)) # Match acc_main_on_tx to acc_main_on
|
||||
self.assertEqual(0, self.safety.get_acc_main_on_mismatches())
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq)
|
||||
|
||||
def test_tester_present_allowed(self, ecu_disable: bool = True):
|
||||
"""
|
||||
Ensure tester present diagnostic message is allowed to keep ECU knocked out
|
||||
for longitudinal control.
|
||||
"""
|
||||
|
||||
addr, bus = self.DISABLED_ECU_UDS_MSG
|
||||
for should_tx, msg in ((True, b"\x02\x3E\x80\x00\x00\x00\x00\x00"),
|
||||
(False, b"\x03\xAA\xAA\x00\x00\x00\x00\x00")):
|
||||
tester_present = libsafety_py.make_CANPacket(addr, bus, msg)
|
||||
self.assertEqual(should_tx and ecu_disable, self._tx(tester_present))
|
||||
|
||||
def test_disabled_ecu_alive(self):
|
||||
"""
|
||||
If the ECU knockout failed, make sure the relay malfunction is shown
|
||||
"""
|
||||
|
||||
addr, bus = self.DISABLED_ECU_ACTUATION_MSG
|
||||
self.assertFalse(self.safety.get_relay_malfunction())
|
||||
self._rx(make_msg(bus, addr, 8))
|
||||
self.assertTrue(self.safety.get_relay_malfunction())
|
||||
TESTER_PRESENT = bytes.fromhex("023e800000000000")
|
||||
|
||||
664
iqdbc_repo/iqdbc/safety/tests/test_hyundai.py
Executable file → Normal file
664
iqdbc_repo/iqdbc/safety/tests/test_hyundai.py
Executable file → Normal file
@@ -1,569 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
from parameterized import parameterized_class
|
||||
import random
|
||||
import unittest
|
||||
import pytest
|
||||
|
||||
from iqdbc.car.hyundai.values import HyundaiSafetyFlags
|
||||
from iqdbc.car.structs import CarParams
|
||||
from iqdbc.safety.tests.hyundai_common import TESTER_PRESENT, classic_accel, classic_steer, packet
|
||||
from iqdbc.safety.tests.libsafety import libsafety_py
|
||||
import iqdbc.safety.tests.common as common
|
||||
from iqdbc.safety.tests.common import CANPackerSafety
|
||||
from iqdbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase
|
||||
|
||||
from iqdbc.iqpilot.car.hyundai.values import HyundaiSafetyFlagsIQ
|
||||
|
||||
# LDA button availability
|
||||
LDA_BUTTON = [
|
||||
{"SAFETY_PARAM_IQ": HyundaiSafetyFlagsIQ.DEFAULT},
|
||||
{"SAFETY_PARAM_IQ": HyundaiSafetyFlagsIQ.HAS_LDA_BUTTON},
|
||||
]
|
||||
|
||||
# All combinations of non-SCC HEV/PHEV/EV cars
|
||||
_ALL_NON_SCC_HEV_EV_COMBOS = [
|
||||
# Hybrid
|
||||
{"PCM_STATUS_MSG": ("E_CRUISE_CONTROL", "CRUISE_LAMP_S"),
|
||||
"ACC_STATE_MSG": ("E_CRUISE_CONTROL", "CRUISE_LAMP_M"),
|
||||
"GAS_MSG": ("E_EMS11", "CR_Vcu_AccPedDep_Pos"),
|
||||
"SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS},
|
||||
# EV
|
||||
{"PCM_STATUS_MSG": ("LABEL11", "CC_ACT"),
|
||||
"ACC_STATE_MSG": ("LABEL11", "CC_React"),
|
||||
"GAS_MSG": ("E_EMS11", "Accel_Pedal_Pos"),
|
||||
"SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS},
|
||||
]
|
||||
ALL_NON_SCC_HEV_EV_COMBOS = [{**p, **lda} for lda in LDA_BUTTON for p in _ALL_NON_SCC_HEV_EV_COMBOS]
|
||||
|
||||
|
||||
# 4 bit checkusm used in some hyundai messages
|
||||
# lives outside the can packer because we never send this msg
|
||||
def checksum(msg):
|
||||
addr, dat, bus = msg
|
||||
|
||||
chksum = 0
|
||||
if addr == 0x386:
|
||||
for i, b in enumerate(dat):
|
||||
for j in range(8):
|
||||
# exclude checksum and counter bits
|
||||
if (i != 1 or j < 6) and (i != 3 or j < 6) and (i != 5 or j < 6) and (i != 7 or j < 6):
|
||||
bit = (b >> j) & 1
|
||||
else:
|
||||
bit = 0
|
||||
chksum += bit
|
||||
chksum = (chksum ^ 9) & 0xF
|
||||
ret = bytearray(dat)
|
||||
ret[5] |= (chksum & 0x3) << 6
|
||||
ret[7] |= (chksum & 0xc) << 4
|
||||
else:
|
||||
for i, b in enumerate(dat):
|
||||
if addr in [0x260, 0x421] and i == 7:
|
||||
b &= 0x0F if addr == 0x421 else 0xF0
|
||||
elif addr == 0x394 and i == 6:
|
||||
b &= 0xF0
|
||||
elif addr == 0x394 and i == 7:
|
||||
continue
|
||||
chksum += sum(divmod(b, 16))
|
||||
chksum = (16 - chksum) % 16
|
||||
ret = bytearray(dat)
|
||||
ret[6 if addr == 0x394 else 7] |= chksum << (4 if addr == 0x421 else 0)
|
||||
|
||||
return addr, ret, bus
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiSafety(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
|
||||
TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0]]
|
||||
STANDSTILL_THRESHOLD = 12 # 0.375 kph
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485)} # LKAS11
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485]}
|
||||
|
||||
MAX_RATE_UP = 3
|
||||
MAX_RATE_DOWN = 7
|
||||
MAX_TORQUE_LOOKUP = [0], [384]
|
||||
MAX_RT_DELTA = 112
|
||||
DRIVER_TORQUE_ALLOWANCE = 50
|
||||
DRIVER_TORQUE_FACTOR = 2
|
||||
|
||||
# Safety around steering req bit
|
||||
MIN_VALID_STEERING_FRAMES = 89
|
||||
MAX_INVALID_STEERING_FRAMES = 2
|
||||
|
||||
cnt_gas = 0
|
||||
cnt_speed = 0
|
||||
cnt_brake = 0
|
||||
cnt_cruise = 0
|
||||
cnt_button = 0
|
||||
|
||||
SAFETY_PARAM_IQ: int = 0
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiSafety":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _button_msg(self, buttons, main_button=0, bus=0):
|
||||
values = {"CF_Clu_CruiseSwState": buttons, "CF_Clu_CruiseSwMain": main_button, "CF_Clu_AliveCnt1": self.cnt_button}
|
||||
self.__class__.cnt_button += 1
|
||||
return self.packer.make_can_msg_safety("CLU11", bus, values)
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {"CF_Ems_AclAct": gas, "AliveCounter": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return self.packer.make_can_msg_safety("EMS16", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _user_brake_msg(self, brake):
|
||||
values = {"DriverOverride": 2 if brake else random.choice((0, 1, 3)),
|
||||
"AliveCounterTCS": self.cnt_brake % 8}
|
||||
self.__class__.cnt_brake += 1
|
||||
return self.packer.make_can_msg_safety("TCS13", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
# safety doesn't scale, so undo the scaling
|
||||
values = {"WHL_SPD_%s" % s: speed * 0.03125 for s in ["FL", "FR", "RL", "RR"]}
|
||||
values["WHL_SPD_AliveCounter_LSB"] = (self.cnt_speed % 16) & 0x3
|
||||
values["WHL_SPD_AliveCounter_MSB"] = (self.cnt_speed % 16) >> 2
|
||||
self.__class__.cnt_speed += 1
|
||||
return self.packer.make_can_msg_safety("WHL_SPD11", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
values = {"ACCMode": enable, "CR_VSM_Alive": self.cnt_cruise % 16}
|
||||
self.__class__.cnt_cruise += 1
|
||||
return self.packer.make_can_msg_safety("SCC12", self.SCC_BUS, values, fix_checksum=checksum)
|
||||
|
||||
def _torque_driver_msg(self, torque):
|
||||
values = {"CR_Mdps_StrColTq": torque}
|
||||
return self.packer.make_can_msg_safety("MDPS12", 0, values)
|
||||
|
||||
def _torque_cmd_msg(self, torque, steer_req=1):
|
||||
values = {"CR_Lkas_StrToqReq": torque, "CF_Lkas_ActToi": steer_req}
|
||||
return self.packer.make_can_msg_safety("LKAS11", 0, values)
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
values = {"MainMode_ACC": enable}
|
||||
return self.packer.make_can_msg_safety("SCC11", self.SCC_BUS, values)
|
||||
|
||||
def _lkas_button_msg(self, enabled):
|
||||
if self.SAFETY_PARAM_IQ & HyundaiSafetyFlagsIQ.HAS_LDA_BUTTON:
|
||||
values = {"LDA_BTN": enabled}
|
||||
return self.packer.make_can_msg_safety("BCM_PO_11", 0, values)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
def _main_cruise_button_msg(self, enabled):
|
||||
return self._button_msg(0, enabled)
|
||||
|
||||
def test_pcm_main_cruise_state_availability(self):
|
||||
"""Test that ACC main state is correctly set when receiving 0x420 message, toggling HYUNDAI_LONG flag"""
|
||||
prior_safety_mode = self.safety.get_current_safety_mode()
|
||||
prior_safety_param = self.safety.get_current_safety_param()
|
||||
|
||||
for hyundai_longitudinal in (True, False):
|
||||
with self.subTest("hyundai_longitudinal", hyundai_longitudinal=hyundai_longitudinal):
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0 if hyundai_longitudinal else HyundaiSafetyFlags.LONG)
|
||||
for should_turn_acc_main_on in (True, False):
|
||||
with self.subTest("acc_main_on", should_turn_acc_main_on=should_turn_acc_main_on):
|
||||
self._rx(self._acc_state_msg(should_turn_acc_main_on)) # Send the ACC state message
|
||||
expected_acc_main = should_turn_acc_main_on and hyundai_longitudinal # ACC main should only be set if hyundai_longitudinal is True
|
||||
self.assertEqual(expected_acc_main, self.safety.get_acc_main_on())
|
||||
self.safety.set_safety_hooks(prior_safety_mode, prior_safety_param)
|
||||
|
||||
def test_enable_control_allowed_with_aol_button(self):
|
||||
default_safety_mode = self.safety.get_current_safety_mode()
|
||||
default_safety_param = self.safety.get_current_safety_param()
|
||||
default_safety_param_iq = self.safety.get_current_safety_param_iq()
|
||||
"""Toggle AOL with AOL button"""
|
||||
try:
|
||||
self._lkas_button_msg(False)
|
||||
except NotImplementedError as err:
|
||||
raise unittest.SkipTest("Skipping test because LDA button is not supported") from err
|
||||
|
||||
try:
|
||||
for enable_aol in (True, False):
|
||||
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
||||
for has_lda_button_param in (True, False):
|
||||
with self.subTest("has_lda_button", has_lda_button_param=has_lda_button_param):
|
||||
has_lda_button = HyundaiSafetyFlagsIQ.HAS_LDA_BUTTON if has_lda_button_param else 0
|
||||
self.safety.set_current_safety_param_iq(has_lda_button)
|
||||
self.safety.set_safety_hooks(default_safety_mode, default_safety_param)
|
||||
|
||||
self.safety.set_aol_params(enable_aol, False, False)
|
||||
self.assertEqual(enable_aol, self.safety.get_enable_aol())
|
||||
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertEqual(enable_aol and has_lda_button_param, self.safety.get_controls_allowed_lat())
|
||||
finally:
|
||||
self.safety.set_current_safety_param_iq(default_safety_param_iq)
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiSafetyAltLimits(TestHyundaiSafety):
|
||||
MAX_RATE_UP = 2
|
||||
MAX_RATE_DOWN = 3
|
||||
MAX_TORQUE_LOOKUP = [0], [270]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiSafetyAltLimits":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.ALT_LIMITS)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiSafetyAltLimits2(TestHyundaiSafety):
|
||||
MAX_RATE_UP = 2
|
||||
MAX_RATE_DOWN = 3
|
||||
MAX_TORQUE_LOOKUP = [0], [170]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiSafetyAltLimits2":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.ALT_LIMITS_2)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiSafetyCameraSCC(TestHyundaiSafety):
|
||||
BUTTONS_TX_BUS = 2 # tx on 2, rx on 0
|
||||
SCC_BUS = 2 # rx on 2
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiSafetyCameraSCC":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.CAMERA_SCC)
|
||||
self.safety.init_tests()
|
||||
|
||||
def test_pcm_main_cruise_state_availability(self):
|
||||
"""
|
||||
Test that ACC main state is correctly set when receiving 0x420 message.
|
||||
For camera SCC, ACC main should always be on when receiving 0x420 message
|
||||
"""
|
||||
|
||||
for should_turn_acc_main_on in (True, False):
|
||||
with self.subTest("acc_main_on", should_turn_acc_main_on=should_turn_acc_main_on):
|
||||
self._rx(self._acc_state_msg(should_turn_acc_main_on))
|
||||
self.assertEqual(should_turn_acc_main_on, self.safety.get_acc_main_on())
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiSafetyFCEV(TestHyundaiSafety):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiSafetyFCEV":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.FCEV_GAS)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {"ACCELERATOR_PEDAL": gas}
|
||||
return self.packer.make_can_msg_safety("FCEV_ACCELERATOR", 0, values)
|
||||
|
||||
|
||||
class TestHyundaiLegacySafety(TestHyundaiSafety):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
class TestHyundaiLegacySafetyEV(TestHyundaiSafety):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.EV_GAS)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {"Accel_Pedal_Pos": gas}
|
||||
return self.packer.make_can_msg_safety("E_EMS11", 0, values, fix_checksum=checksum)
|
||||
|
||||
|
||||
class TestHyundaiLegacySafetyHEV(TestHyundaiSafety):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.HYBRID_GAS)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {"CR_Vcu_AccPedDep_Pos": gas}
|
||||
return self.packer.make_can_msg_safety("E_EMS11", 0, values, fix_checksum=checksum)
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety):
|
||||
TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0], [0x38D, 0], [0x483, 0], [0x7D0, 0]]
|
||||
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485, 0x421, 0x420, 0x50A, 0x389]}
|
||||
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485, 0x421, 0x420, 0x50A, 0x389)} # LKAS11, LFAHDA_MFC, SCC12, SCC11, SCC13, SCC14
|
||||
|
||||
DISABLED_ECU_UDS_MSG = (0x7D0, 0)
|
||||
DISABLED_ECU_ACTUATION_MSG = (0x421, 0)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiLongitudinalSafety":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
|
||||
values = {
|
||||
"aReqRaw": accel,
|
||||
"aReqValue": accel,
|
||||
"AEB_CmdAct": int(aeb_req),
|
||||
"CR_VSM_DecCmd": aeb_decel,
|
||||
}
|
||||
return self.packer.make_can_msg_safety("SCC12", self.SCC_BUS, values)
|
||||
|
||||
def _fca11_msg(self, idx=0, vsm_aeb_req=False, fca_aeb_req=False, aeb_decel=0):
|
||||
values = {
|
||||
"CR_FCA_Alive": idx % 0xF,
|
||||
"FCA_Status": 2,
|
||||
"CR_VSM_DecCmd": aeb_decel,
|
||||
"CF_VSM_DecCmdAct": int(vsm_aeb_req),
|
||||
"FCA_CmdAct": int(fca_aeb_req),
|
||||
}
|
||||
return self.packer.make_can_msg_safety("FCA11", 0, values)
|
||||
|
||||
def _tx_acc_state_msg(self, enable):
|
||||
values = {"MainMode_ACC": enable}
|
||||
return self.packer.make_can_msg_safety("SCC11", 0, values)
|
||||
|
||||
def test_no_aeb_fca11(self):
|
||||
self.assertTrue(self._tx(self._fca11_msg()))
|
||||
self.assertFalse(self._tx(self._fca11_msg(vsm_aeb_req=True)))
|
||||
self.assertFalse(self._tx(self._fca11_msg(fca_aeb_req=True)))
|
||||
self.assertFalse(self._tx(self._fca11_msg(aeb_decel=1.0)))
|
||||
|
||||
def test_no_aeb_scc12(self):
|
||||
self.assertTrue(self._tx(self._accel_msg(0)))
|
||||
self.assertFalse(self._tx(self._accel_msg(0, aeb_req=True)))
|
||||
self.assertFalse(self._tx(self._accel_msg(0, aeb_decel=1.0)))
|
||||
|
||||
|
||||
class TestHyundaiLongitudinalSafetyCameraSCC(HyundaiLongitudinalBase, TestHyundaiSafety):
|
||||
TX_MSGS = [[0x340, 0], [0x4F1, 2], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0]]
|
||||
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485, 0x420, 0x421, 0x50A, 0x389]}
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485, 0x421, 0x420, 0x50A, 0x389)} # LKAS11, LFAHDA_MFC, SCC12, SCC11, SCC13, SCC14
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(HyundaiSafetyFlagsIQ.HAS_LDA_BUTTON)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CAMERA_SCC)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
|
||||
values = {
|
||||
"aReqRaw": accel,
|
||||
"aReqValue": accel,
|
||||
"AEB_CmdAct": int(aeb_req),
|
||||
"CR_VSM_DecCmd": aeb_decel,
|
||||
}
|
||||
return self.packer.make_can_msg_safety("SCC12", self.SCC_BUS, values)
|
||||
|
||||
def _tx_acc_state_msg(self, enable):
|
||||
values = {"MainMode_ACC": enable}
|
||||
return self.packer.make_can_msg_safety("SCC11", self.SCC_BUS, values)
|
||||
|
||||
def test_no_aeb_scc12(self):
|
||||
self.assertTrue(self._tx(self._accel_msg(0)))
|
||||
self.assertFalse(self._tx(self._accel_msg(0, aeb_req=True)))
|
||||
self.assertFalse(self._tx(self._accel_msg(0, aeb_decel=1.0)))
|
||||
|
||||
def test_tester_present_allowed(self):
|
||||
pass
|
||||
|
||||
def test_disabled_ecu_alive(self):
|
||||
pass
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiSafetyFCEVLong(TestHyundaiLongitudinalSafety, TestHyundaiSafetyFCEV):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiSafetyFCEVLong":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.FCEV_GAS | HyundaiSafetyFlags.LONG)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiLongitudinalESCCSafety(HyundaiLongitudinalBase, TestHyundaiSafety):
|
||||
TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0]]
|
||||
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485, 0x420, 0x421, 0x50A, 0x389]}
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485, 0x420, 0x421, 0x50A, 0x389)} # LKAS11, LFAHDA_MFC, SCC12, SCC11, SCC13, SCC14
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiLongitudinalESCCSafety":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(HyundaiSafetyFlagsIQ.ESCC | self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
|
||||
values = {
|
||||
"aReqRaw": accel,
|
||||
"aReqValue": accel,
|
||||
}
|
||||
return self.packer.make_can_msg_safety("SCC12", self.SCC_BUS, values)
|
||||
|
||||
def _tx_acc_state_msg(self, enable):
|
||||
values = {"MainMode_ACC": enable}
|
||||
return self.packer.make_can_msg_safety("SCC11", 0, values)
|
||||
|
||||
def test_tester_present_allowed(self):
|
||||
pass
|
||||
|
||||
def test_disabled_ecu_alive(self):
|
||||
pass
|
||||
|
||||
|
||||
@parameterized_class(LDA_BUTTON)
|
||||
class TestHyundaiNonSCCSafety(TestHyundaiSafety):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiNonSCCSafety":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(HyundaiSafetyFlagsIQ.NON_SCC | self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
values = {"CRUISE_LAMP_S": enable, "AliveCounter": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return self.packer.make_can_msg_safety("EMS16", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
values = {"CRUISE_LAMP_M": enable, "AliveCounter": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return self.packer.make_can_msg_safety("EMS16", 0, values, fix_checksum=checksum)
|
||||
|
||||
def _user_gas_msg(self, gas: float, controls_allowed: bool = True):
|
||||
values = {"CF_Ems_AclAct": gas, "CRUISE_LAMP_M": 1, "CRUISE_LAMP_S": controls_allowed, "AliveCounter": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return self.packer.make_can_msg_safety("EMS16", 0, values, fix_checksum=checksum)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self._rx(self._user_gas_msg(1, self.safety.get_controls_allowed()))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._user_gas_msg(1, self.safety.get_controls_allowed()))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self._rx(self._user_gas_msg(1, self.safety.get_controls_allowed()))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_no_disengage_on_gas(self):
|
||||
self._rx(self._user_gas_msg(0, self.safety.get_controls_allowed()))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._rx(self._user_gas_msg(self.GAS_PRESSED_THRESHOLD + 1, self.safety.get_controls_allowed()))
|
||||
# Test we allow lateral, but not longitudinal
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.assertFalse(self.safety.get_longitudinal_brake_allowed())
|
||||
self.assertTrue(self.safety.get_longitudinal_gas_allowed())
|
||||
# Make sure we can re-gain longitudinal actuation
|
||||
self._rx(self._user_gas_msg(0, self.safety.get_controls_allowed()))
|
||||
self.assertTrue(self.safety.get_longitudinal_brake_allowed())
|
||||
self.assertTrue(self.safety.get_longitudinal_gas_allowed())
|
||||
|
||||
|
||||
@parameterized_class(ALL_NON_SCC_HEV_EV_COMBOS)
|
||||
class TestHyundaiNonSCCSafety_HEV_EV(TestHyundaiSafety):
|
||||
|
||||
PCM_STATUS_MSG = ("", "")
|
||||
ACC_STATE_MSG = ("", "")
|
||||
GAS_MSG = ("", "")
|
||||
SAFETY_PARAM = 0
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiNonSCCSafety_HEV_EV":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_current_safety_param_iq(HyundaiSafetyFlagsIQ.NON_SCC | self.SAFETY_PARAM_IQ)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, self.SAFETY_PARAM)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
values = {self.PCM_STATUS_MSG[1]: enable}
|
||||
return self.packer.make_can_msg_safety(self.PCM_STATUS_MSG[0], 0, values)
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
values = {self.ACC_STATE_MSG[1]: enable}
|
||||
return self.packer.make_can_msg_safety(self.ACC_STATE_MSG[0], 0, values)
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {self.GAS_MSG[1]: gas}
|
||||
return self.packer.make_can_msg_safety(self.GAS_MSG[0], 0, values, fix_checksum=checksum)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@pytest.fixture
|
||||
def safety():
|
||||
return libsafety_py.libsafety
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", (CarParams.SafetyModel.hyundai, CarParams.SafetyModel.hyundaiLegacy))
|
||||
@pytest.mark.parametrize("param", (
|
||||
0,
|
||||
HyundaiSafetyFlags.EV_GAS,
|
||||
HyundaiSafetyFlags.HYBRID_GAS,
|
||||
HyundaiSafetyFlags.LONG,
|
||||
HyundaiSafetyFlags.CAMERA_SCC,
|
||||
HyundaiSafetyFlags.ALT_LIMITS,
|
||||
HyundaiSafetyFlags.FCEV_GAS,
|
||||
HyundaiSafetyFlags.ALT_LIMITS_2,
|
||||
))
|
||||
def test_classic_safety_configurations_initialize(safety, mode, param):
|
||||
assert safety.set_safety_hooks(mode, param) == 0
|
||||
safety.init_tests()
|
||||
assert safety.get_current_safety_param() == param
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", (CarParams.SafetyModel.hyundai, CarParams.SafetyModel.hyundaiLegacy))
|
||||
def test_classic_tx_whitelist_and_steering_limits(safety, mode):
|
||||
safety.set_safety_hooks(mode, 0)
|
||||
safety.init_tests()
|
||||
|
||||
assert not safety.safety_tx_hook(packet(0x123, 0, 8))
|
||||
assert not safety.safety_tx_hook(packet(0x340, 1, 8))
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
assert safety.safety_tx_hook(classic_steer(0, False))
|
||||
assert not safety.safety_tx_hook(classic_steer(1))
|
||||
|
||||
safety.set_controls_allowed(True)
|
||||
assert safety.safety_tx_hook(classic_steer(10))
|
||||
safety.set_desired_torque_last(512)
|
||||
safety.set_rt_torque_last(512)
|
||||
assert safety.safety_tx_hook(classic_steer(512))
|
||||
assert not safety.safety_tx_hook(classic_steer(513))
|
||||
assert not safety.safety_tx_hook(classic_steer(-513))
|
||||
|
||||
|
||||
def test_classic_alt_limits_2(safety):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.ALT_LIMITS_2)
|
||||
safety.init_tests()
|
||||
safety.set_controls_allowed(True)
|
||||
safety.set_desired_torque_last(170)
|
||||
safety.set_rt_torque_last(170)
|
||||
assert safety.safety_tx_hook(classic_steer(170))
|
||||
assert not safety.safety_tx_hook(classic_steer(171))
|
||||
|
||||
|
||||
def test_classic_longitudinal_accel_and_aeb_guards(safety):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG)
|
||||
safety.init_tests()
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
assert safety.safety_tx_hook(classic_accel(0))
|
||||
assert not safety.safety_tx_hook(classic_accel(1))
|
||||
|
||||
safety.set_controls_allowed(True)
|
||||
for accel in (-400, 0, 250):
|
||||
assert safety.safety_tx_hook(classic_accel(accel))
|
||||
for accel in (-401, 251):
|
||||
assert not safety.safety_tx_hook(classic_accel(accel))
|
||||
assert not safety.safety_tx_hook(classic_accel(0, aeb_decel=1))
|
||||
assert not safety.safety_tx_hook(classic_accel(0, aeb_request=True))
|
||||
|
||||
assert safety.safety_tx_hook(packet(0x38D, 0, 8))
|
||||
assert not safety.safety_tx_hook(packet(0x38D, 0, 8, {1: 1}))
|
||||
assert not safety.safety_tx_hook(packet(0x38D, 0, 8, {2: 1 << 4}))
|
||||
assert not safety.safety_tx_hook(packet(0x38D, 0, 8, {3: 1 << 7}))
|
||||
|
||||
|
||||
def test_classic_buttons(safety):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0)
|
||||
safety.init_tests()
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
assert not safety.safety_tx_hook(packet(0x4F1, 0, 4, {0: 1}))
|
||||
assert not safety.safety_tx_hook(packet(0x4F1, 0, 4, {0: 2}))
|
||||
assert not safety.safety_tx_hook(packet(0x4F1, 0, 4, {0: 4}))
|
||||
|
||||
safety.set_controls_allowed(True)
|
||||
assert safety.safety_tx_hook(packet(0x4F1, 0, 4, {0: 1}))
|
||||
assert not safety.safety_tx_hook(packet(0x4F1, 0, 4, {0: 2}))
|
||||
assert safety.safety_tx_hook(packet(0x4F1, 0, 4, {0: 4}))
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
safety.set_cruise_engaged_prev(True)
|
||||
assert safety.safety_tx_hook(packet(0x4F1, 0, 4, {0: 4}))
|
||||
|
||||
|
||||
def test_classic_diagnostic_payload_is_restricted(safety):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG)
|
||||
safety.init_tests()
|
||||
assert safety.safety_tx_hook(packet(0x7D0, 0, 8, dict(enumerate(TESTER_PRESENT))))
|
||||
assert not safety.safety_tx_hook(packet(0x7D0, 0, 8, {0: 3, 1: 0x22}))
|
||||
|
||||
404
iqdbc_repo/iqdbc/safety/tests/test_hyundai_canfd.py
Executable file → Normal file
404
iqdbc_repo/iqdbc/safety/tests/test_hyundai_canfd.py
Executable file → Normal file
@@ -1,312 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
from parameterized import parameterized_class
|
||||
import unittest
|
||||
import pytest
|
||||
|
||||
from iqdbc.car.hyundai.values import HyundaiSafetyFlags
|
||||
from iqdbc.car.structs import CarParams
|
||||
from iqdbc.safety.tests.hyundai_common import TESTER_PRESENT, canfd_accel, canfd_steer, packet
|
||||
from iqdbc.safety.tests.libsafety import libsafety_py
|
||||
import iqdbc.safety.tests.common as common
|
||||
from iqdbc.safety.tests.common import CANPackerSafety
|
||||
from iqdbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase
|
||||
|
||||
# All combinations of radar/camera-SCC and gas/hybrid/EV cars
|
||||
ALL_GAS_EV_HYBRID_COMBOS = [
|
||||
# Radar SCC
|
||||
{"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": 0},
|
||||
{"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS},
|
||||
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS},
|
||||
# Camera SCC
|
||||
{"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.CAMERA_SCC},
|
||||
{"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CAMERA_SCC},
|
||||
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
|
||||
]
|
||||
|
||||
|
||||
class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
|
||||
|
||||
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
|
||||
STANDSTILL_THRESHOLD = 12 # 0.375 kph
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]}
|
||||
|
||||
MAX_RATE_UP = 2
|
||||
MAX_RATE_DOWN = 3
|
||||
MAX_TORQUE_LOOKUP = [0], [270]
|
||||
|
||||
MAX_RT_DELTA = 112
|
||||
|
||||
DRIVER_TORQUE_ALLOWANCE = 250
|
||||
DRIVER_TORQUE_FACTOR = 2
|
||||
|
||||
# Safety around steering req bit
|
||||
MIN_VALID_STEERING_FRAMES = 89
|
||||
MAX_INVALID_STEERING_FRAMES = 2
|
||||
|
||||
PT_BUS = 0
|
||||
SCC_BUS = 2
|
||||
STEER_BUS = 0
|
||||
STEER_MSG = ""
|
||||
GAS_MSG = ("", "")
|
||||
BUTTONS_TX_BUS = 1
|
||||
|
||||
def _torque_driver_msg(self, torque):
|
||||
values = {"STEERING_COL_TORQUE": torque}
|
||||
return self.packer.make_can_msg_safety("MDPS", self.PT_BUS, values)
|
||||
|
||||
def _torque_cmd_msg(self, torque, steer_req=1):
|
||||
values = {"TORQUE_REQUEST": torque, "STEER_REQ": steer_req}
|
||||
return self.packer.make_can_msg_safety(self.STEER_MSG, self.STEER_BUS, values)
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
values = {f"WHL_Spd{pos}Val": speed * 0.03125 for pos in ["FL", "FR", "RL", "RR"]}
|
||||
return self.packer.make_can_msg_safety("WHEEL_SPEEDS", self.PT_BUS, values)
|
||||
|
||||
def _user_brake_msg(self, brake):
|
||||
values = {"DriverBraking": brake}
|
||||
return self.packer.make_can_msg_safety("TCS", self.PT_BUS, values)
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {self.GAS_MSG[1]: gas}
|
||||
return self.packer.make_can_msg_safety(self.GAS_MSG[0], self.PT_BUS, values)
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
values = {"ACCMode": 1 if enable else 0}
|
||||
return self.packer.make_can_msg_safety("SCC_CONTROL", self.SCC_BUS, values)
|
||||
|
||||
def _button_msg(self, buttons, main_button=0, bus=None):
|
||||
if bus is None:
|
||||
bus = self.PT_BUS
|
||||
values = {
|
||||
"CRUISE_BUTTONS": buttons,
|
||||
"ADAPTIVE_CRUISE_MAIN_BTN": main_button,
|
||||
}
|
||||
return self.packer.make_can_msg_safety("CRUISE_BUTTONS", bus, values)
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
values = {"MainMode_ACC": enable}
|
||||
return self.packer.make_can_msg_safety("SCC_CONTROL", self.SCC_BUS, values)
|
||||
|
||||
def _lkas_button_msg(self, enabled):
|
||||
values = {"LDA_BTN": enabled}
|
||||
return self.packer.make_can_msg_safety("CRUISE_BUTTONS", self.PT_BUS, values)
|
||||
|
||||
def _main_cruise_button_msg(self, enabled):
|
||||
return self._button_msg(0, enabled)
|
||||
|
||||
|
||||
class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdBase):
|
||||
|
||||
TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]]
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0)} # LFA, LFAHDA_CLUSTER
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0]}
|
||||
|
||||
STEER_MSG = "LFA"
|
||||
BUTTONS_TX_BUS = 2
|
||||
SAFETY_PARAM: int
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
if cls.__name__ in ("TestHyundaiCanfdLFASteering", "TestHyundaiCanfdLFASteeringAltButtons"):
|
||||
cls.packer = None
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, self.SAFETY_PARAM)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
|
||||
class TestHyundaiCanfdLFASteering(TestHyundaiCanfdLFASteeringBase):
|
||||
pass
|
||||
|
||||
|
||||
class TestHyundaiCanfdLFASteeringAltButtonsBase(TestHyundaiCanfdLFASteeringBase):
|
||||
|
||||
SAFETY_PARAM: int
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _button_msg(self, buttons, main_button=0, bus=1):
|
||||
values = {
|
||||
"CRUISE_BUTTONS": buttons,
|
||||
"ADAPTIVE_CRUISE_MAIN_BTN": main_button,
|
||||
}
|
||||
return self.packer.make_can_msg_safety("CRUISE_BUTTONS_ALT", self.PT_BUS, values)
|
||||
|
||||
def _lkas_button_msg(self, enabled):
|
||||
values = {"LDA_BTN": enabled}
|
||||
return self.packer.make_can_msg_safety("CRUISE_BUTTONS_ALT", self.PT_BUS, values)
|
||||
|
||||
def _acc_cancel_msg(self, cancel, accel=0):
|
||||
values = {"ACCMode": 4 if cancel else 0, "aReqRaw": accel, "aReqValue": accel}
|
||||
return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values)
|
||||
|
||||
def test_button_sends(self):
|
||||
"""
|
||||
No button send allowed with alt buttons.
|
||||
"""
|
||||
for enabled in (True, False):
|
||||
for btn in range(8):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
self.assertFalse(self._tx(self._button_msg(btn)))
|
||||
|
||||
def test_acc_cancel(self):
|
||||
# FIXME: the CANFD_ALT_BUTTONS cars are the only ones that use SCC_CONTROL to cancel, why can't we use buttons?
|
||||
for enabled in (True, False):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
self.assertTrue(self._tx(self._acc_cancel_msg(True)))
|
||||
self.assertFalse(self._tx(self._acc_cancel_msg(True, accel=1)))
|
||||
self.assertFalse(self._tx(self._acc_cancel_msg(False)))
|
||||
|
||||
|
||||
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
|
||||
class TestHyundaiCanfdLFASteeringAltButtons(TestHyundaiCanfdLFASteeringAltButtonsBase):
|
||||
pass
|
||||
|
||||
|
||||
class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase):
|
||||
|
||||
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4)} # LKAS, CAM_0x2A4
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]}
|
||||
|
||||
PT_BUS = 1
|
||||
SCC_BUS = 1
|
||||
STEER_MSG = "LKAS"
|
||||
GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL")
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
# TODO: Handle ICE and HEV configurations once we see cars that use the new messages
|
||||
class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase):
|
||||
|
||||
TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]]
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)} # LKAS_ALT, CAM_0x362
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]}
|
||||
|
||||
PT_BUS = 1
|
||||
SCC_BUS = 1
|
||||
STEER_MSG = "LKAS_ALT"
|
||||
GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL")
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS |
|
||||
HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdLKASteeringEV):
|
||||
|
||||
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1],
|
||||
[0x1e0, 1], [0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]]
|
||||
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4), 1: (0x1a0,)} # LKAS, CAM_0x2A4, SCC_CONTROL
|
||||
|
||||
DISABLED_ECU_UDS_MSG = (0x730, 1)
|
||||
DISABLED_ECU_ACTUATION_MSG = (0x1a0, 1)
|
||||
|
||||
STEER_MSG = "LFA"
|
||||
GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL")
|
||||
STEER_BUS = 1
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING |
|
||||
HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.EV_GAS)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
|
||||
values = {
|
||||
"aReqRaw": accel,
|
||||
"aReqValue": accel,
|
||||
}
|
||||
return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values)
|
||||
|
||||
def _tx_acc_state_msg(self, enable):
|
||||
values = {"MainMode_ACC": enable}
|
||||
return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values)
|
||||
|
||||
|
||||
# Tests longitudinal for ICE, hybrid, EV cars with LFA steering
|
||||
class TestHyundaiCanfdLFASteeringLongBase(HyundaiLongitudinalBase, TestHyundaiCanfdLFASteeringBase):
|
||||
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x12a, 0x1e0, 0x1a0, 0x160]}
|
||||
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0, 0x1a0, 0x160)} # LFA, LFAHDA_CLUSTER, SCC_CONTROL, ADRV_0x160
|
||||
|
||||
DISABLED_ECU_UDS_MSG = (0x7D0, 0)
|
||||
DISABLED_ECU_ACTUATION_MSG = (0x1a0, 0)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiCanfdLFASteeringLongBase":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | self.SAFETY_PARAM)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
|
||||
values = {
|
||||
"aReqRaw": accel,
|
||||
"aReqValue": accel,
|
||||
}
|
||||
return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values)
|
||||
|
||||
def _tx_acc_state_msg(self, enable):
|
||||
values = {"MainMode_ACC": enable}
|
||||
return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values)
|
||||
|
||||
# no knockout
|
||||
def test_tester_present_allowed(self):
|
||||
pass
|
||||
|
||||
|
||||
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
|
||||
class TestHyundaiCanfdLFASteeringLong(TestHyundaiCanfdLFASteeringLongBase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiCanfdLFASteeringLong":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
|
||||
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
|
||||
class TestHyundaiCanfdLFASteeringLongAltButtons(TestHyundaiCanfdLFASteeringLongBase, TestHyundaiCanfdLFASteeringAltButtonsBase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHyundaiCanfdLFASteeringLongAltButtons":
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM)
|
||||
self.safety.init_tests()
|
||||
|
||||
def test_acc_cancel(self):
|
||||
# Alt buttons does not use SCC_CONTROL to cancel if longitudinal
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@pytest.fixture
|
||||
def safety():
|
||||
return libsafety_py.libsafety
|
||||
|
||||
|
||||
@pytest.mark.parametrize("param", (
|
||||
0,
|
||||
HyundaiSafetyFlags.EV_GAS,
|
||||
HyundaiSafetyFlags.HYBRID_GAS,
|
||||
HyundaiSafetyFlags.LONG,
|
||||
HyundaiSafetyFlags.CAMERA_SCC,
|
||||
HyundaiSafetyFlags.CANFD_LKA_STEERING,
|
||||
HyundaiSafetyFlags.CANFD_ALT_BUTTONS,
|
||||
HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT,
|
||||
HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.LONG,
|
||||
HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CANFD_ALT_BUTTONS,
|
||||
))
|
||||
def test_canfd_safety_configurations_initialize(safety, param):
|
||||
assert safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, param) == 0
|
||||
safety.init_tests()
|
||||
assert safety.get_current_safety_param() == param
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("param", "addr", "length"), (
|
||||
(0, 0x12A, 16),
|
||||
(HyundaiSafetyFlags.CANFD_LKA_STEERING, 0x50, 16),
|
||||
(HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT, 0x110, 32),
|
||||
(HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.LONG, 0x12A, 16),
|
||||
))
|
||||
def test_canfd_steering_limits(safety, param, addr, length):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, param)
|
||||
safety.init_tests()
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
assert safety.safety_tx_hook(canfd_steer(addr, length, 0, False))
|
||||
assert not safety.safety_tx_hook(canfd_steer(addr, length, 1))
|
||||
|
||||
safety.set_controls_allowed(True)
|
||||
assert safety.safety_tx_hook(canfd_steer(addr, length, 10))
|
||||
safety.set_desired_torque_last(512)
|
||||
safety.set_rt_torque_last(512)
|
||||
assert safety.safety_tx_hook(canfd_steer(addr, length, 512))
|
||||
assert not safety.safety_tx_hook(canfd_steer(addr, length, 513))
|
||||
assert not safety.safety_tx_hook(canfd_steer(addr, length, -513))
|
||||
|
||||
|
||||
def test_canfd_tx_whitelist_and_buttons(safety):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, 0)
|
||||
safety.init_tests()
|
||||
assert not safety.safety_tx_hook(packet(0x123, 0, 8))
|
||||
assert not safety.safety_tx_hook(packet(0x12A, 1, 16))
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
assert not safety.safety_tx_hook(packet(0x1CF, 0, 8, {2: 1}))
|
||||
assert not safety.safety_tx_hook(packet(0x1CF, 0, 8, {2: 2}))
|
||||
assert not safety.safety_tx_hook(packet(0x1CF, 0, 8, {2: 4}))
|
||||
|
||||
safety.set_controls_allowed(True)
|
||||
assert safety.safety_tx_hook(packet(0x1CF, 0, 8, {2: 1}))
|
||||
assert not safety.safety_tx_hook(packet(0x1CF, 0, 8, {2: 2}))
|
||||
assert safety.safety_tx_hook(packet(0x1CF, 0, 8, {2: 4}))
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
safety.set_cruise_engaged_prev(True)
|
||||
assert safety.safety_tx_hook(packet(0x1CF, 0, 8, {2: 4}))
|
||||
|
||||
|
||||
def test_canfd_stock_longitudinal_only_allows_cancel(safety):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, 0)
|
||||
safety.init_tests()
|
||||
assert safety.safety_tx_hook(canfd_accel(0, acc_mode=4))
|
||||
assert not safety.safety_tx_hook(canfd_accel(1, acc_mode=4))
|
||||
assert not safety.safety_tx_hook(canfd_accel(0, acc_mode=0))
|
||||
|
||||
|
||||
def test_canfd_longitudinal_accel_limits(safety):
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG)
|
||||
safety.init_tests()
|
||||
|
||||
safety.set_controls_allowed(False)
|
||||
assert safety.safety_tx_hook(canfd_accel(0))
|
||||
assert not safety.safety_tx_hook(canfd_accel(1))
|
||||
|
||||
safety.set_controls_allowed(True)
|
||||
for accel in (-400, 0, 250):
|
||||
assert safety.safety_tx_hook(canfd_accel(accel))
|
||||
for accel in (-401, 251):
|
||||
assert not safety.safety_tx_hook(canfd_accel(accel))
|
||||
|
||||
|
||||
def test_canfd_hda2_diagnostic_payload_is_restricted(safety):
|
||||
param = HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.LONG
|
||||
safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, param)
|
||||
safety.init_tests()
|
||||
assert safety.safety_tx_hook(packet(0x730, 1, 8, dict(enumerate(TESTER_PRESENT))))
|
||||
assert not safety.safety_tx_hook(packet(0x730, 1, 8, {0: 3, 1: 0x22}))
|
||||
|
||||
39
iqdbc_repo/iqdbc/safety/tests/test_hyundai_controller.py
Normal file
39
iqdbc_repo/iqdbc/safety/tests/test_hyundai_controller.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import pytest
|
||||
|
||||
from iqdbc.car import gen_empty_fingerprint, structs
|
||||
from iqdbc.car.hyundai.interface import CarInterface
|
||||
from iqdbc.car.hyundai.values import CAR
|
||||
from iqdbc.safety.tests.libsafety import libsafety_py
|
||||
|
||||
|
||||
@pytest.mark.parametrize("candidate", list(CAR), ids=lambda candidate: candidate.value)
|
||||
@pytest.mark.parametrize("alpha_long", (False, True), ids=("stock_long", "openpilot_long"))
|
||||
def test_controller_frames_match_configured_safety(candidate, alpha_long, monkeypatch, tmp_path):
|
||||
"""Run real controller output through the safety configuration selected for every HKG platform."""
|
||||
monkeypatch.setenv("PARAMS_ROOT", str(tmp_path / candidate.value))
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
cp = CarInterface.get_params(candidate, fingerprint, [], alpha_long, False, False)
|
||||
cp_iq = CarInterface.get_params_iq(cp, candidate, fingerprint, [], alpha_long, False, False)
|
||||
interface = CarInterface(cp, cp_iq)
|
||||
interface.update([])
|
||||
|
||||
safety_config = cp.safetyConfigs[-1]
|
||||
safety = libsafety_py.libsafety
|
||||
assert safety.set_safety_hooks(safety_config.safetyModel.raw, safety_config.safetyParam) == 0
|
||||
safety.init_tests()
|
||||
safety.set_controls_allowed(True)
|
||||
|
||||
control = structs.CarControl.new_message()
|
||||
control.enabled = True
|
||||
control.latActive = True
|
||||
control.longActive = alpha_long
|
||||
control.actuators.torque = 0.01
|
||||
control.actuators.accel = 0.0
|
||||
|
||||
for frame in range(20):
|
||||
_, can_sends = interface.apply(control.as_reader(), structs.IQCarControl())
|
||||
assert isinstance(can_sends, list)
|
||||
for address, data, bus in can_sends:
|
||||
packet = libsafety_py.make_CANPacket(address, bus, data)
|
||||
rejection = f"{candidate.value} frame {frame}: safety rejected address={address:#x} bus={bus} data={data.hex()}"
|
||||
assert safety.safety_tx_hook(packet), rejection
|
||||
Reference in New Issue
Block a user