Files
StarPilot/openpilot/starpilot/legacy_cache_migration.py
T
firestar5683 80fbb4f6db Feature registration
Register vehicle controls, planner modes, UI actions and Galaxy services after their providers exist. Wire the shared runtime entrypoints and cover their combined behavior.

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com>
Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com>
Co-authored-by: Kacper Rączy <gfw.kra@gmail.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>
Co-authored-by: stef <19478336+stefpi@users.noreply.github.com>
Co-authored-by: whoisdomi <dcantu83@gmail.com>

Co-authored-by: Intelli <contact@intelli.software>
Co-authored-by: haraschax <6804392+haraschax@users.noreply.github.com>
Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 20:02:39 -05:00

83 lines
4.2 KiB
Python

import math
import capnp
from openpilot.starpilot import schema_cache as cache
LEGACY_CALIBRATION_FIELDS = {
"calStatus": (11, "Status"), "calCycle": (2, "Int32"), "calPerc": (3, "Int8"),
"validBlocks": (9, "Int32"), "extrinsicMatrix": (4, "List(Float32)"),
"rpyCalib": (7, "List(Float32)"), "rpyCalibSpread": (8, "List(Float32)"),
"wideFromDeviceEuler": (10, "List(Float32)"), "height": (12, "List(Float32)"),
}
class LegacyCalibrationError(ValueError):
pass
class _EnvelopeSink:
def put(self, key, value, *, block):
self.raw = value
def _validate_calibration(values):
for key, lengths in (("rpyCalib", (3,)), ("wideFromDeviceEuler", (3,)),
("height", (1,)), ("rpyCalibSpread", (0, 3)), ("extrinsicMatrix", (0, 12))):
vector = values[key]
if len(vector) not in lengths or any(not math.isfinite(value) for value in vector):
raise LegacyCalibrationError(f"Invalid legacy calibration {key}")
if not 0 <= values["validBlocks"] <= 50 or not 0 <= values["calPerc"] <= 100 or values["calCycle"] < 0:
raise LegacyCalibrationError("Invalid legacy calibration progress")
if values["calStatus"] not in ("uncalibrated", "calibrated", "invalid", "recalibrating"):
raise LegacyCalibrationError("Invalid legacy calibration status")
rpy = values["rpyCalib"]
if abs(rpy[0]) > math.pi or not -0.15 <= rpy[1] <= 0.23 or abs(rpy[2]) > 0.075:
raise LegacyCalibrationError("Legacy calibration angles exceed producer limits")
if any(abs(value) > math.pi for value in values["wideFromDeviceEuler"]) or not 0 < values["height"][0] < 10:
raise LegacyCalibrationError("Invalid legacy calibration camera geometry")
if any(value < 0 or value > math.pi for value in values["rpyCalibSpread"]):
raise LegacyCalibrationError("Invalid legacy calibration spread")
def migrate_legacy_cache(key, raw):
inspected = cache.inspect_cache(key, raw)
if inspected.status == "valid":
return raw
if key != "CalibrationParams":
return None
if not raw or raw.startswith(cache.MAGIC) or len(raw) > cache.MAX_PAYLOAD_BYTES:
raise LegacyCalibrationError("Unsupported legacy calibration encoding")
try:
with cache.CONTRACTS[key].root.from_bytes(raw, traversal_limit_in_words=cache.MAX_PAYLOAD_BYTES // 8) as source:
if source.which() != "extrinsicsCalibration":
raise LegacyCalibrationError("Legacy calibration has the wrong Event service")
selected = source.extrinsicsCalibration
values = {name: getattr(selected, name) for name in LEGACY_CALIBRATION_FIELDS}
values = {name: list(value) if field_type.startswith("List") else str(value) if field_type == "Status" else value
for name, value in values.items() for _, field_type in (LEGACY_CALIBRATION_FIELDS[name],)}
_validate_calibration(values)
converted = cache.CONTRACTS[key].root.new_message(
logMonoTime=source.logMonoTime, valid=source.valid, extrinsicsCalibration=values,
)
sink = _EnvelopeSink()
cache.put_cache(sink, key, converted, block=True)
check = cache.inspect_cache(key, sink.raw)
if check.status != "valid":
raise LegacyCalibrationError("Converted calibration envelope failed validation")
with cache.CONTRACTS[key].root.from_bytes(check.payload) as result:
if any(getattr(result.extrinsicsCalibration, name) != getattr(converted.extrinsicsCalibration, name)
for name, (_, field_type) in LEGACY_CALIBRATION_FIELDS.items() if not field_type.startswith("List")):
raise LegacyCalibrationError("Converted calibration scalar readback differs")
for name, (_, field_type) in LEGACY_CALIBRATION_FIELDS.items():
if field_type.startswith("List") and list(getattr(result.extrinsicsCalibration, name)) != values[name]:
raise LegacyCalibrationError("Converted calibration vector readback differs")
if result.logMonoTime != source.logMonoTime or result.valid != source.valid:
raise LegacyCalibrationError("Converted calibration metadata readback differs")
return sink.raw
except LegacyCalibrationError:
raise
except (capnp.KjException, ValueError, TypeError, OverflowError) as error:
raise LegacyCalibrationError("Legacy calibration could not be decoded completely") from error