Files
StarPilot/openpilot/starpilot/ui/preap_radar_feature.py
T
2026-10-20 18:35:44 -05:00

72 lines
4.1 KiB
Python

from opendbc.car import structs
from opendbc.car.tesla.values import CAR
from openpilot.starpilot.saved_document import commit_exact
from openpilot.starpilot.car.tesla.radar_settings import DOCUMENT_KEY, MAX_BYTES, encode, read_radar_settings
from openpilot.starpilot.ui.feature_settings_state import FeatureRow
KEYS = frozenset(("preap_radar:mode", "preap_radar:offset"))
FLOAT32_MAX = 3.4028234663852886e38
def capability(cp):
if cp is None or cp.brand != "tesla" or cp.carFingerprint != CAR.TESLA_MODEL_S_PREAP:
return None
if (cp.flags or cp.notCar or cp.transmissionType == structs.CarParams.TransmissionType.manual or
cp.fingerprintSource == structs.CarParams.FingerprintSource.fixed):
return None
configurations = tuple((str(s.safetyModel), int(s.safetyParam)) for s in cp.safetyConfigs)
if len(configurations) != 1 or configurations[0] not in (("teslaPreap", 0), ("teslaPreap", 2), ("teslaPreap", 6), ("noOutput", 0)):
return None
return (cp.carFingerprint, configurations, bool(cp.dashcamOnly), bool(cp.passive))
class PreAPRadarFeature:
def __init__(self, owner):
self.owner = owner
def rows(self):
owner = self.owner
capable = capability(owner.vehicle_params())
if capable is None:
return []
saved = read_radar_settings(owner.params)
source = dict(saved.sources).get(DOCUMENT_KEY)
allowed = owner.authority("parked_preferences")
mode = "Behind nosecone" if saved.behind_nosecone else "Front" if saved.enabled else "Off"
return [FeatureRow("preap_radar:mode", "Hardware radar", mode if saved.valid else "Invalid saved configuration", source,
choices=("Off", "Front", "Behind nosecone") if saved.valid else (),
repair_value="" if saved.valid else "Off", available=allowed, capability=capable, vehicle_fingerprint=owner.vehicle_fingerprint(),
dependencies=saved.sources, reason="Parked hardware setup. Applies after restart."),
FeatureRow("preap_radar:offset", "Radar lateral offset", str(saved.offset) if saved.valid else "Invalid saved configuration", source,
step=0.05 if saved.valid else 0.0, minimum=-FLOAT32_MAX, maximum=FLOAT32_MAX, unit="m",
repair_value="" if saved.valid else "0.0", available=allowed, capability=capable, vehicle_fingerprint=owner.vehicle_fingerprint(),
dependencies=saved.sources, reason="Parked hardware setup. Applies after restart.")]
def apply(self, request):
if request.key not in KEYS or request.related_source is not None or request.direction or request.display_unit:
return False
row = next((row for row in self.rows() if row.key == request.key), None)
if row is None or not row.available or request.capability != row.capability or request.dependencies != row.dependencies or request.expected != row.source:
return False
saved = read_radar_settings(self.owner.params)
try:
if request.key == "preap_radar:mode":
if request.value not in ("Off", "Front", "Behind nosecone") or (not saved.valid and request.value != "Off"):
return False
mode = {"Off": "off", "Front": "front", "Behind nosecone": "nosecone"}[request.value]
raw = encode(mode, saved.offset if saved.valid else 0.0)
else:
if not saved.valid and request.value != "0.0":
return False
mode = "nosecone" if saved.behind_nosecone else "front" if saved.enabled else "off"
raw = encode(mode, request.value)
except (ValueError, TypeError, OverflowError):
return False
def authorized():
fresh = next((row for row in self.rows() if row.key == request.key), None)
return bool(fresh is not None and fresh.available and fresh.capability == request.capability and
fresh.dependencies == request.dependencies and self.owner.vehicle_fingerprint() == request.vehicle_fingerprint)
result = commit_exact(self.owner.params, key=DOCUMENT_KEY, max_bytes=MAX_BYTES, raw=raw, expected=request.expected,
authorized=authorized, temp_prefix=".preap-radar-")
return result.committed and result.verified