IQ.Pilot Prebuilt Release @ 67fd9c2
This commit is contained in:
36
artifacts/package_runtime/iqdbc/lvbs/car/subaru/aol.py
Normal file
36
artifacts/package_runtime/iqdbc/lvbs/car/subaru/aol.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""
|
||||
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
|
||||
|
||||
Always-on-Lateral input adapter for Subaru: turns the dashboard LKAS button into
|
||||
a carState lkas ButtonEvent so the shared AOL state machine can toggle lateral.
|
||||
"""
|
||||
from enum import StrEnum
|
||||
|
||||
from iqdbc.car import Bus, structs
|
||||
from iqdbc.car.subaru.values import SubaruFlags
|
||||
from iqdbc.lvbs.aol_base import AolCarStateBase
|
||||
from iqdbc.can.parser import CANParser
|
||||
|
||||
_LKAS = structs.CarState.ButtonEvent.Type.lkas
|
||||
|
||||
# ES_LKAS_State/LKAS_Dash_State: 0 = neutral, 1 = LKAS shown on, 2 = LKAS shown off
|
||||
_DASH_ON = 1
|
||||
_DASH_OFF = 2
|
||||
|
||||
|
||||
class AolCarState(AolCarStateBase):
|
||||
def update_aol(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
|
||||
if self.CP.flags & SubaruFlags.PREGLOBAL:
|
||||
return
|
||||
|
||||
self.prev_lkas_button = self.lkas_button
|
||||
self.lkas_button = can_parsers[Bus.cam].vl["ES_LKAS_State"]["LKAS_Dash_State"]
|
||||
|
||||
if self._is_toggle_edge():
|
||||
ret.buttonEvents = [*ret.buttonEvents, structs.CarState.ButtonEvent(type=_LKAS, pressed=True)]
|
||||
|
||||
def _is_toggle_edge(self) -> bool:
|
||||
# every dash-state change is a deliberate press except the off->on rebound (2 -> 1)
|
||||
if self.lkas_button == self.prev_lkas_button:
|
||||
return False
|
||||
return not (self.prev_lkas_button == _DASH_OFF and self.lkas_button == _DASH_ON)
|
||||
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
|
||||
|
||||
IQ.Pilot Subaru stop-and-go: nudges the ACC out of a standstill it would
|
||||
otherwise hold. Two variants gated by user flags — an electronic-parking-brake
|
||||
resume pulse (distance/lead triggered) and a manual-parking-brake hold-timer
|
||||
resume. Both work by spoofing the camera-bus throttle/brake frames.
|
||||
"""
|
||||
import copy
|
||||
from enum import StrEnum
|
||||
|
||||
from iqdbc.car import Bus, structs, DT_CTRL
|
||||
from iqdbc.car.can_definitions import CanData
|
||||
from iqdbc.car.interfaces import CarStateBase
|
||||
from iqdbc.car.subaru.values import SubaruFlags
|
||||
|
||||
from iqdbc.lvbs.car.subaru import iq_subarucan
|
||||
from iqdbc.lvbs.car.subaru.iq_values import SubaruFlagsIQ
|
||||
from iqdbc.can.parser import CANParser
|
||||
|
||||
# EPB resume fires only while the lead is pulling away within this gap band (m).
|
||||
_RESUME_GAP_MIN = 3.0
|
||||
_RESUME_GAP_MAX = 4.5
|
||||
_EPB_PULSE_FRAMES = 15
|
||||
|
||||
|
||||
class IQStopAndGoController:
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
|
||||
self.CP = CP
|
||||
self.CP_IQ = CP_IQ
|
||||
self.enabled = bool(CP_IQ.flags & (SubaruFlagsIQ.STOP_AND_GO | SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE))
|
||||
self.manual_parking_brake = bool(CP_IQ.flags & SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE)
|
||||
|
||||
self.standstill_since = 0
|
||||
self._pulse_left = 0
|
||||
self.prev_gap = 0.0
|
||||
|
||||
def _epb_pulse(self, trigger: bool) -> bool:
|
||||
# A trigger arms a fixed-length resume pulse; the pulse then plays out frame by frame.
|
||||
if self.manual_parking_brake:
|
||||
return False
|
||||
if trigger:
|
||||
self._pulse_left = _EPB_PULSE_FRAMES
|
||||
if self._pulse_left > 0:
|
||||
self._pulse_left -= 1
|
||||
return True
|
||||
return False
|
||||
|
||||
def _want_resume(self, CC: structs.CarControl, CS: CarStateBase, frame: int) -> bool:
|
||||
if not CC.enabled or not CC.hudControl.leadVisible:
|
||||
return False
|
||||
|
||||
gap = CS.es_distance_msg["Close_Distance"]
|
||||
standing = CS.out.standstill
|
||||
if not standing:
|
||||
self.standstill_since = frame
|
||||
|
||||
hold_arm, hold_reset = (0.75, 0.8) if self.CP.flags & SubaruFlags.PREGLOBAL else (0.5, 0.55)
|
||||
held_for = (frame - self.standstill_since) * DT_CTRL
|
||||
held_long_enough = held_for > hold_arm
|
||||
if held_for >= hold_reset:
|
||||
self.standstill_since = frame
|
||||
|
||||
lead_pulling_away = _RESUME_GAP_MIN < gap < _RESUME_GAP_MAX and gap > self.prev_gap
|
||||
self.prev_gap = gap
|
||||
|
||||
if self.manual_parking_brake:
|
||||
return held_long_enough
|
||||
return self._epb_pulse(standing and lead_pulling_away)
|
||||
|
||||
def create_creep_assist(self, packer, CC: structs.CarControl, CS: CarStateBase, frame: int) -> list[CanData]:
|
||||
if not self.enabled:
|
||||
return []
|
||||
|
||||
resume = self._want_resume(CC, CS, frame)
|
||||
can_sends = [iq_subarucan.create_throttle(packer, self.CP, CS.throttle_msg, resume and not self.manual_parking_brake)]
|
||||
if frame % 2 == 0:
|
||||
can_sends.append(iq_subarucan.create_brake_pedal(packer, self.CP, CS.brake_pedal_msg, resume and self.manual_parking_brake))
|
||||
return can_sends
|
||||
|
||||
|
||||
class IQStopAndGoState:
|
||||
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
|
||||
self.CP = CP
|
||||
self.CP_IQ = CP_IQ
|
||||
self.brake_pedal_msg: dict[str, float] = {}
|
||||
self.throttle_msg: dict[str, float] = {}
|
||||
|
||||
def update(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
|
||||
cp = can_parsers[Bus.pt]
|
||||
self.brake_pedal_msg = copy.copy(cp.vl["Brake_Pedal"])
|
||||
if not self.CP.flags & SubaruFlags.HYBRID:
|
||||
self.throttle_msg = copy.copy(cp.vl["Throttle"])
|
||||
@@ -0,0 +1,41 @@
|
||||
"""
|
||||
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
|
||||
|
||||
Camera-bus message spoofers for Subaru stop-and-go: re-emit the stock Throttle
|
||||
and Brake_Pedal frames, nudging a single field to trigger an ACC resume from a
|
||||
standstill. Field sets mirror the DBC message layout.
|
||||
"""
|
||||
from iqdbc.car.subaru.values import CanBus, SubaruFlags
|
||||
|
||||
_THROTTLE_FIELDS_PREGLOBAL = ("Throttle_Pedal", "Signal1", "Not_Full_Throttle", "Signal2", "Engine_RPM",
|
||||
"Off_Throttle", "Signal3", "Throttle_Cruise", "Throttle_Combo", "Throttle_Body",
|
||||
"Off_Throttle_2", "Signal4")
|
||||
_THROTTLE_FIELDS_GLOBAL = ("CHECKSUM", "Signal1", "Engine_RPM", "Neutral", "Throttle_Pedal", "Throttle_Cruise",
|
||||
"Throttle_Combo", "Signal3", "Off_Accel")
|
||||
_BRAKE_FIELDS_PREGLOBAL = ("Speed", "Brake_Pedal", "Signal1")
|
||||
_BRAKE_FIELDS_GLOBAL = ("CHECKSUM", "Signal1", "Speed", "Signal2", "Brake_Lights", "Signal3", "Brake_Pedal", "Signal4")
|
||||
|
||||
|
||||
def _next_counter(msg):
|
||||
return (msg["COUNTER"] + 1) % 0x10
|
||||
|
||||
|
||||
def create_throttle(packer, CP, throttle_msg, send_resume):
|
||||
preglobal = bool(CP.flags & SubaruFlags.PREGLOBAL)
|
||||
fields = _THROTTLE_FIELDS_PREGLOBAL if preglobal else _THROTTLE_FIELDS_GLOBAL
|
||||
values = {name: throttle_msg[name] for name in fields}
|
||||
values["COUNTER"] = _next_counter(throttle_msg)
|
||||
if send_resume:
|
||||
values["Throttle_Pedal"] = 5
|
||||
return packer.make_can_msg("Throttle", CanBus.camera, values)
|
||||
|
||||
|
||||
def create_brake_pedal(packer, CP, brake_pedal_msg, send_resume):
|
||||
preglobal = bool(CP.flags & SubaruFlags.PREGLOBAL)
|
||||
fields = _BRAKE_FIELDS_PREGLOBAL if preglobal else _BRAKE_FIELDS_GLOBAL
|
||||
values = {name: brake_pedal_msg[name] for name in fields}
|
||||
if not preglobal:
|
||||
values["COUNTER"] = _next_counter(brake_pedal_msg)
|
||||
if send_resume:
|
||||
values["Speed"] = 1 if preglobal else 3
|
||||
return packer.make_can_msg("Brake_Pedal", CanBus.camera, values)
|
||||
16
artifacts/package_runtime/iqdbc/lvbs/car/subaru/iq_values.py
Normal file
16
artifacts/package_runtime/iqdbc/lvbs/car/subaru/iq_values.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
|
||||
|
||||
IQ.Pilot Subaru extension flags. Selected in apply_iq_car_config() from the user's
|
||||
stop-and-go params and consumed by the stop-and-go controller and panda safety.
|
||||
"""
|
||||
from enum import IntFlag
|
||||
|
||||
|
||||
class SubaruFlagsIQ(IntFlag):
|
||||
STOP_AND_GO = 1
|
||||
STOP_AND_GO_MANUAL_PARKING_BRAKE = 2
|
||||
|
||||
|
||||
class SubaruSafetyFlagsIQ:
|
||||
STOP_AND_GO = 1
|
||||
Reference in New Issue
Block a user