From 330f2860addb3f91e03ee0cafb011038de97ec61 Mon Sep 17 00:00:00 2001 From: Brian Hanson Date: Mon, 13 Apr 2026 03:21:12 +0000 Subject: [PATCH] telemetry: log Hyundai CAN-FD HDA2 vehicle data Logs high-value CAN bus data every frame in update_canfd(): - car: vEgo, aEgo, steering angle, gear, brake/gas, blinkers, standstill - cruise: enabled, speed, ACCMode, VSetDis, aReq, distance setting, lead dist - speed_limit: all 3 CLUSTER_SPEED_LIMIT values, school zone, chimes, calculated speed limit, metric flag - buttons: cruise buttons, main button, LKAS, main_enabled state Data flows through the diff-based telemetry logger (only changed values written to CSV) when TelemetryEnabled param is set. Co-Authored-By: Claude Opus 4.6 (1M context) --- selfdrive/car/hyundai/carstate.py | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py index 47e2646..c69878f 100755 --- a/selfdrive/car/hyundai/carstate.py +++ b/selfdrive/car/hyundai/carstate.py @@ -420,6 +420,59 @@ class CarState(CarStateBase): # self.params_memory.put_float("CarSpeedLimitLiteral", self.calculate_speed_limit(cp, cp_cam)) self.params_memory.put_float("CarSpeedLimit", self.calculate_speed_limit(cp, cp_cam) * speed_factor) + # CLEARPILOT: telemetry logging + from openpilot.selfdrive.clearpilot.telemetry import tlog + + speed_limit_bus = cp if self.CP.flags & HyundaiFlags.CANFD_HDA2 else cp_cam + scc = cp_cam.vl["SCC_CONTROL"] if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp.vl["SCC_CONTROL"] + cluster = speed_limit_bus.vl["CLUSTER_SPEED_LIMIT"] + + tlog("car", { + "vEgo": round(ret.vEgo, 3), + "vEgoRaw": round(ret.vEgoRaw, 3), + "aEgo": round(ret.aEgo, 3), + "steeringAngleDeg": round(ret.steeringAngleDeg, 1), + "gear": str(ret.gearShifter), + "brakePressed": ret.brakePressed, + "gasPressed": ret.gasPressed, + "standstill": ret.standstill, + "leftBlinker": ret.leftBlinker, + "rightBlinker": ret.rightBlinker, + }) + + tlog("cruise", { + "enabled": ret.cruiseState.enabled, + "available": ret.cruiseState.available, + "speed": round(ret.cruiseState.speed, 3), + "standstill": ret.cruiseState.standstill, + "accFaulted": ret.accFaulted, + "ACCMode": scc.get("ACCMode", 0), + "VSetDis": scc.get("VSetDis", 0), + "aReqRaw": round(scc.get("aReqRaw", 0), 3), + "aReqValue": round(scc.get("aReqValue", 0), 3), + "DISTANCE_SETTING": scc.get("DISTANCE_SETTING", 0), + "ACC_ObjDist": round(scc.get("ACC_ObjDist", 0), 1), + }) + + tlog("speed_limit", { + "SPEED_LIMIT_1": cluster.get("SPEED_LIMIT_1", 0), + "SPEED_LIMIT_2": cluster.get("SPEED_LIMIT_2", 0), + "SPEED_LIMIT_3": cluster.get("SPEED_LIMIT_3", 0), + "SCHOOL_ZONE": cluster.get("SCHOOL_ZONE", 0), + "CHIME_1": cluster.get("CHIME_1", 0), + "CHIME_2": cluster.get("CHIME_2", 0), + "SPEED_CHANGE_BLINKING": cluster.get("SPEED_CHANGE_BLINKING", 0), + "calculated": self.calculate_speed_limit(cp, cp_cam), + "is_metric": self.is_metric, + }) + + tlog("buttons", { + "cruise_button": self.cruise_buttons[-1], + "main_button": self.main_buttons[-1], + "lkas_enabled": self.lkas_enabled, + "main_enabled": self.main_enabled, + }) + return ret def get_can_parser(self, CP):