diff --git a/artifacts/iqpilot_emac_private/manifest.json b/artifacts/iqpilot_emac_private/manifest.json index cdecac46a..da3247969 100644 --- a/artifacts/iqpilot_emac_private/manifest.json +++ b/artifacts/iqpilot_emac_private/manifest.json @@ -1,8 +1,8 @@ { "python/_iqclosure/_vendored.json": { "mode": 420, - "sha256": "2cd59a784bfe6c6d1ce382e832dd355f62900b1f73a74ed91c53397aa8581754", - "size": 3495 + "sha256": "5cae92c259782dd90e2523851ba0b5262fb4e7325f42578af7c55977e9c120b9", + "size": 3558 }, "python/_iqclosure/iqpilot/__init__.py": { "mode": 420, @@ -141,8 +141,8 @@ }, "python/_iqclosure/iqpilot/selfdrive/controls/lib/desire_helper.py": { "mode": 420, - "sha256": "407b7fcdd2699f7f64404df420b9a2ccfef2cfa4a66d5634f6dd7cb2f23ff3f4", - "size": 11737 + "sha256": "91008a050069861404b3f20977f5b8b6fdab4b3919e76e1ae95be49ce92f4ad8", + "size": 12298 }, "python/_iqclosure/iqpilot/selfdrive/controls/lib/drive_helpers.py": { "mode": 420, @@ -164,6 +164,11 @@ "sha256": "faa6f87b227c805e8890a91139e8d16d7874c4b99b330dda08080392ce3479ec", "size": 4618 }, + "python/_iqclosure/iqpilot/selfdrive/controls/lib/helpers/lateral_edge_guard.py": { + "mode": 420, + "sha256": "6bb6bcb8e5323480bf1b992549279a7d4c17a1bd1bd260863cf7b61b887fa735", + "size": 10227 + }, "python/_iqclosure/iqpilot/selfdrive/iqmodeld/__init__.py": { "mode": 420, "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", @@ -186,8 +191,8 @@ }, "python/_iqclosure/iqpilot/selfdrive/iqmodeld/daemon.py": { "mode": 420, - "sha256": "bbfe0c839d22286c2293c3fac11c5cae2206c2e69f0ae2aa4bdf64a3c772fc4f", - "size": 30210 + "sha256": "15002cb6c81cca8c7aec572568da1e202c55777bbd21fefaf8fda36fd0d39b6e", + "size": 30295 }, "python/_iqclosure/iqpilot/selfdrive/iqmodeld/driving_action.py": { "mode": 420, @@ -531,22 +536,27 @@ }, "python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "cc7a4087336116187655ea52bc48391e447b81529c2b923e60bf886bc3c7f58a", - "size": 334016 + "sha256": "2130f52658e9e6bbb2c3354b497c84a80fd29d0cd81c2c7d524ad31de56dc3f1", + "size": 333888 + }, + "python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": { + "mode": 493, + "sha256": "4dea04cbb68903af8af7745b4691941d4dfd703e9b01bc238791d03d103192aa", + "size": 68072 }, "python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "9d48157df0d78be709cf3722743b6137cbf73eb53c315d7307e6a214ae140664", + "sha256": "87db24c0c6c5cc200cadaaf0348a3f969da3a9fdc99c3fc9e7624b6664d4f895", "size": 267952 }, "python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "9b7dc1997e780198c2532045e41236dd342b4dc4d3cd31b06be27246121d6ab7", + "sha256": "1db2acc63c5538d47b336bb9703bcfbfa0de89f431d102fd727bb0c3e1a2248f", "size": 203544 }, "python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "ec1f1f0ce541abf00021757fa25c4de54c0037d36eb0d194bdf4ad6c77c778e6", + "sha256": "a7a3ca084886882e8d61e3511a59c621bb44ff5e80a27ed6fcee36e9687d31d3", "size": 333336 }, "runtime": { @@ -558,9 +568,10 @@ } }, "signatures": { - "python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": "hclRnmzBp4zVtU1CKeTqxG59yYTRHAGcwAbHgKgmw1/82SuqvyP4MbU0pFG9UpwtskIdpVsppHqriZjqGb5rAg==", - "python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": "wQoF1yRiJxfo3NMOJ4PC2RDRRkfromNc2n1JpHyizsSK12Sf16Sjy1+yf2muujcs2n/gWjZbhozrCFgD++12Bg==", - "python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": "kQT6AOQlvYTbVu+B6FzjCdmNMbZj37WEvBdDKNCaHtJuyYmgkrFxmhCjm1KNaNlHQNXQjO8MyI8aYYNocAKGDQ==", - "python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": "MJXrXlkDjgdUeNxck8kh4SeLCBRLUaalY3vJ8nOAOGFCwGFE1UXrw+wBl6HaBNu86v0MlBrT1cN89GkNtdZUDg==" + "python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": "ufSruB5sta4eGn6fuqxIp5v+uBkUTrot/V+Yf2kiZbrA3xcgOU2qG2AllwWDrn7Hg7a+eczvhJDHLzupuRZaAQ==", + "python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": "G+hzeZYCDOph6YPDRVGbcWxojtJcBGjXcm6EPfUtfvYxvAu3QDjHXd+B3XdtOSekE/6AiH2CWURpDIwDqgZSBw==", + "python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": "8byO3iMIYoPD9r9SoS1LcxekC+9vdQaFW9s+CZ4MIZmq6h9scsIHNCq3peh6tUcScj/WRFuES/bdZxTItHycAg==", + "python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": "YYmTLXA024Dgu8zxXxfXMWIv/lmMvhuH1/C7aaNumZD/b5pkV6gihKomGlM7v/EnE8lYVtWo5wsnUCvl9a9BCQ==", + "python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": "f59Fh4UaquFHnDXTAmKdtOwc+++QN5MWi3Zx74L2qZgMLgk3T0/ouTb0WMSTbHgoWn61r+/g/2bH1//Y+NUeAw==" } } diff --git a/artifacts/iqpilot_emac_private/manifest.json.sig b/artifacts/iqpilot_emac_private/manifest.json.sig index 666f8ba16..ee720e1e6 100644 --- a/artifacts/iqpilot_emac_private/manifest.json.sig +++ b/artifacts/iqpilot_emac_private/manifest.json.sig @@ -1 +1 @@ -ViYlJji0FjCcbz07ouwB45Lnj1xSE5DytMonAUAg0KskmG9gyid8fEGvrHNZxQDPRD4EpL0N9oIasaFTKFWcDA== +OSV+ZbTBvP8stU4KDyT4wavo+fGUZEqcuvN7ltBw4LyMopdaMcbz9jYyIimicnQQniA1d4vaGuWRRQmvm0emAg== diff --git a/artifacts/iqpilot_emac_private/python/_iqclosure/_vendored.json b/artifacts/iqpilot_emac_private/python/_iqclosure/_vendored.json index 7519942ae..996cdfc5c 100644 --- a/artifacts/iqpilot_emac_private/python/_iqclosure/_vendored.json +++ b/artifacts/iqpilot_emac_private/python/_iqclosure/_vendored.json @@ -24,6 +24,7 @@ "iqpilot.selfdrive.controls.lib.drive_helpers", "iqpilot.selfdrive.controls.lib.helpers.lane_change", "iqpilot.selfdrive.controls.lib.helpers.lane_turn", + "iqpilot.selfdrive.controls.lib.helpers.lateral_edge_guard", "iqpilot.selfdrive.iqmodeld.big_catalog", "iqpilot.selfdrive.iqmodeld.camera", "iqpilot.selfdrive.iqmodeld.config", diff --git a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/controls/lib/desire_helper.py b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/controls/lib/desire_helper.py index e19a2e24f..ce77ab134 100644 --- a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/controls/lib/desire_helper.py +++ b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/controls/lib/desire_helper.py @@ -14,11 +14,13 @@ from iqpilot.selfdrive.controls.lib.helpers.lane_change import ( AutoLaneChangeMode, NavExitLaneChangeController, ) +from iqpilot.selfdrive.controls.lib.helpers.lateral_edge_guard import LateralEdgeGuard from iqpilot.selfdrive.controls.lib.helpers.lane_turn import IQNavTurnController LaneChangeState = log.LaneChangeState LaneChangeDirection = log.LaneChangeDirection TurnDirection = custom.IQTurnSignalDirection +LateralEdgeBlock = custom.IQLateralEdgeBlock NavManeuverPhase = custom.IQNavState.ManeuverPhase LANE_CHANGE_SPEED_MIN = 20 * CV.MPH_TO_MS @@ -105,6 +107,8 @@ class DesireHelper: self.alc = IQLaneSwapController(self) self.lane_turn_controller = IQNavTurnController(self) self.nav_exit = NavExitLaneChangeController(_read_enable_bsm()) + self.lateral_edge_guard = LateralEdgeGuard() + self.lateral_edge_block = LateralEdgeBlock.none self.lane_turn_direction = TurnDirection.none self.nav_turn_direction = TurnDirection.none self.turn_desire_stop_timer = 0.0 @@ -174,6 +178,8 @@ class DesireHelper: def _step_pre_lane_change(self, one_blinker: bool, nav_exit_active: bool, below_speed: bool) -> None: self._refresh_requested_direction(one_blinker, nav_exit_active) blindspot_detected = _blindspot_matches(self._last_carstate, self.lane_change_direction) + self.lateral_edge_block = self.lateral_edge_guard.block_for_direction(self.lane_change_direction) + lateral_edge_blocked = self.lateral_edge_block != LateralEdgeBlock.none steering_ready = _steering_nudge_matches(self._last_carstate, self.lane_change_direction) nav_auto_start = nav_exit_active and self.nav_exit.auto_allowed @@ -182,7 +188,7 @@ class DesireHelper: if (not (one_blinker or nav_exit_active)) or below_speed: self._clear_lane_change() - elif allowed_to_launch and not blindspot_detected: + elif allowed_to_launch and not blindspot_detected and not lateral_edge_blocked: self.lane_change_state = LaneChangeState.laneChangeStarting def _step_lane_change_starting(self, lane_change_prob: float) -> None: @@ -269,6 +275,8 @@ class DesireHelper: def update(self, carstate, lateral_active, lane_change_prob, nav_state=None, modeldata=None, radar_state=None): self._last_carstate = carstate + self.lateral_edge_guard.update(modeldata, carstate.vEgo, DT_MDL) + self.lateral_edge_block = LateralEdgeBlock.none one_blinker = carstate.leftBlinker != carstate.rightBlinker below_speed = carstate.vEgo < LANE_CHANGE_SPEED_MIN nav_exit_active = self._refresh_turn_overrides(carstate, nav_state) diff --git a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/controls/lib/helpers/lateral_edge_guard.py b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/controls/lib/helpers/lateral_edge_guard.py new file mode 100644 index 000000000..602ca2231 --- /dev/null +++ b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/controls/lib/helpers/lateral_edge_guard.py @@ -0,0 +1,268 @@ +""" +Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos/ +""" + +from __future__ import annotations + +import math +from dataclasses import dataclass, replace +from enum import IntEnum +from typing import Any + +from iqpilot.cereal import custom, log +from iqpilot.common.constants import CV +from iqpilot.common.params import Params +from iqpilot.common.swaglog import cloudlog + + +MIN_ACTIVE_SPEED_MPS = 20.0 * CV.MPH_TO_MS +MAX_VALID_ROAD_EDGE_STD_M = 1.0 +EDGE_CONFIDENCE_SIGMA = 1.0 +ROAD_EDGE_LOOKAHEAD_MIN_M = 5.0 +ROAD_EDGE_LOOKAHEAD_MAX_M = 40.0 +LANE_CENTER_OFFSET_M = 3.5 +VEHICLE_LATERAL_HALF_WIDTH_M = 1.90 / 2.0 +EDGE_CLEARANCE_MARGIN_M = 0.25 +ADJACENT_LANE_LINE_PROB = 0.5 +EGO_LANE_LINE_PROB_MIN = 0.5 +MIN_MEASURED_LANE_WIDTH_M = 2.5 +MAX_MEASURED_LANE_WIDTH_M = 4.5 +OUTER_LANE_LINE_INDEX = (0, 3) +EGO_LANE_LINE_INDEX = (1, 2) +REQUIRED_ROAD_EDGE_DISTANCE_M = LANE_CENTER_OFFSET_M + VEHICLE_LATERAL_HALF_WIDTH_M + EDGE_CLEARANCE_MARGIN_M +BLOCK_DEBOUNCE_S = 0.30 +CLEAR_DEBOUNCE_S = 0.50 +UNAVAILABLE_HOLD_S = 0.50 +TIMER_EPSILON_S = 1e-9 +PARAM_REFRESH_FRAMES = 50 + +LaneChangeDirection = log.LaneChangeDirection +LateralEdgeBlock = custom.IQLateralEdgeBlock + + +class RoadEdgeDataState(IntEnum): + VALID = 0 + UNAVAILABLE = 1 + INVALID = 2 + + +@dataclass(frozen=True, slots=True) +class RoadEdgeMeasurement: + state: RoadEdgeDataState + lateral_distance_m: float | None = None + conservative_distance_m: float | None = None + should_block: bool | None = None + + +@dataclass(frozen=True, slots=True) +class _SideState: + blocked: bool = False + block_timer_s: float = 0.0 + clear_timer_s: float = 0.0 + unavailable_timer_s: float = 0.0 + fallback_reported: bool = False + + +def evaluate_road_edge(edge: Any, std_m: Any, direction: int, + lane_width_m: float = LANE_CENTER_OFFSET_M) -> RoadEdgeMeasurement: + if edge is None or std_m is None: + return RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + + try: + xs = edge.x + ys = edge.y + count = len(xs) + y_count = len(ys) + except (AttributeError, TypeError): + return RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + + if count == 0 or y_count != count: + return RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + + try: + std = float(std_m) + except (TypeError, ValueError): + return RoadEdgeMeasurement(RoadEdgeDataState.INVALID) + if not math.isfinite(std) or std < 0.0 or std > MAX_VALID_ROAD_EDGE_STD_M: + return RoadEdgeMeasurement(RoadEdgeDataState.INVALID) + + lateral_distance_m: float | None = None + for idx in range(count): + try: + x_m = float(xs[idx]) + y_m = float(ys[idx]) + except (IndexError, TypeError, ValueError): + return RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + if not math.isfinite(x_m) or not math.isfinite(y_m): + return RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + if not ROAD_EDGE_LOOKAHEAD_MIN_M <= x_m <= ROAD_EDGE_LOOKAHEAD_MAX_M: + continue + if ((direction == LaneChangeDirection.left and y_m >= 0.0) or + (direction == LaneChangeDirection.right and y_m <= 0.0)): + return RoadEdgeMeasurement(RoadEdgeDataState.INVALID) + distance_m = abs(y_m) + lateral_distance_m = distance_m if lateral_distance_m is None else min(lateral_distance_m, distance_m) + + if lateral_distance_m is None: + return RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + + conservative_distance_m = lateral_distance_m - EDGE_CONFIDENCE_SIGMA * std + required_distance_m = lane_width_m + VEHICLE_LATERAL_HALF_WIDTH_M + EDGE_CLEARANCE_MARGIN_M + return RoadEdgeMeasurement( + RoadEdgeDataState.VALID, + lateral_distance_m, + conservative_distance_m, + conservative_distance_m < required_distance_m, + ) + + +def step_side_guard(state: _SideState, measurement: RoadEdgeMeasurement, speed_active: bool, + dt_s: float) -> tuple[_SideState, bool]: + if not speed_active: + return _SideState(), False + + if measurement.state == RoadEdgeDataState.UNAVAILABLE: + unavailable_timer_s = state.unavailable_timer_s + dt_s + if unavailable_timer_s < UNAVAILABLE_HOLD_S - TIMER_EPSILON_S: + return _SideState(state.blocked, unavailable_timer_s=unavailable_timer_s, + fallback_reported=state.fallback_reported), False + fallback_started = not state.fallback_reported + return _SideState(unavailable_timer_s=unavailable_timer_s, fallback_reported=True), fallback_started + + should_block = bool(measurement.should_block) if measurement.state == RoadEdgeDataState.VALID else False + if should_block == state.blocked: + return _SideState(blocked=state.blocked), False + + if should_block: + block_timer_s = state.block_timer_s + dt_s + if block_timer_s >= BLOCK_DEBOUNCE_S - TIMER_EPSILON_S: + return _SideState(blocked=True), False + return _SideState(block_timer_s=block_timer_s), False + + clear_timer_s = state.clear_timer_s + dt_s + if clear_timer_s >= CLEAR_DEBOUNCE_S - TIMER_EPSILON_S: + return _SideState(), False + return _SideState(blocked=True, clear_timer_s=clear_timer_s), False + + +class LateralEdgeGuard: + def __init__(self, enabled: bool | None = None) -> None: + self._params = Params() if enabled is None else None + self._param_refresh_frame = 0 + self.enabled = self._read_enabled() if enabled is None else enabled + self._active = False + self._left = _SideState() + self._right = _SideState() + self.left_measurement = RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + self.right_measurement = RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + + def _read_enabled(self) -> bool: + try: + return bool(self._params and self._params.get_bool("IQEdgeGuard")) + except Exception: + return False + + def _refresh_enabled(self) -> None: + if self._params is not None and self._param_refresh_frame % PARAM_REFRESH_FRAMES == 0: + self.enabled = self._read_enabled() + self._param_refresh_frame += 1 + + def _reset(self) -> None: + self._left = _SideState() + self._right = _SideState() + self.left_measurement = RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + self.right_measurement = RoadEdgeMeasurement(RoadEdgeDataState.UNAVAILABLE) + + @staticmethod + def _model_side(modeldata: Any, side_index: int) -> tuple[Any | None, Any | None]: + if modeldata is None: + return None, None + try: + edges = modeldata.roadEdges + stds = modeldata.roadEdgeStds + if len(edges) <= side_index or len(stds) <= side_index: + return None, None + return edges[side_index], stds[side_index] + except (AttributeError, TypeError): + return None, None + + @staticmethod + def _lane_line_prob(modeldata: Any, index: int) -> float | None: + if modeldata is None: + return None + try: + probs = modeldata.laneLineProbs + if len(probs) <= index: + return None + value = float(probs[index]) + except (AttributeError, TypeError, IndexError, ValueError): + return None + return value if math.isfinite(value) else None + + @classmethod + def _adjacent_lane_visible(cls, modeldata: Any, side_index: int) -> bool: + prob = cls._lane_line_prob(modeldata, OUTER_LANE_LINE_INDEX[side_index]) + return prob is not None and prob > ADJACENT_LANE_LINE_PROB + + @classmethod + def _measured_lane_width(cls, modeldata: Any) -> float: + left_prob = cls._lane_line_prob(modeldata, EGO_LANE_LINE_INDEX[0]) + right_prob = cls._lane_line_prob(modeldata, EGO_LANE_LINE_INDEX[1]) + if left_prob is None or right_prob is None: + return LANE_CENTER_OFFSET_M + if left_prob <= EGO_LANE_LINE_PROB_MIN or right_prob <= EGO_LANE_LINE_PROB_MIN: + return LANE_CENTER_OFFSET_M + try: + lines = modeldata.laneLines + left_y = float(lines[EGO_LANE_LINE_INDEX[0]].y[0]) + right_y = float(lines[EGO_LANE_LINE_INDEX[1]].y[0]) + except (AttributeError, TypeError, IndexError, ValueError): + return LANE_CENTER_OFFSET_M + width = abs(right_y - left_y) + if not math.isfinite(width): + return LANE_CENTER_OFFSET_M + return min(max(width, MIN_MEASURED_LANE_WIDTH_M), MAX_MEASURED_LANE_WIDTH_M) + + @staticmethod + def _apply_lane_evidence(measurement: RoadEdgeMeasurement, lane_visible: bool) -> RoadEdgeMeasurement: + if lane_visible and measurement.state == RoadEdgeDataState.VALID and measurement.should_block: + return replace(measurement, should_block=False) + return measurement + + def update(self, modeldata: Any, v_ego_mps: float, dt_s: float) -> None: + self._refresh_enabled() + if not self.enabled: + if self._active: + self._reset() + self._active = False + return + if not self._active: + self._reset() + self._active = True + + dt = max(float(dt_s), 0.0) + left_edge, left_std = self._model_side(modeldata, 0) + right_edge, right_std = self._model_side(modeldata, 1) + lane_width_m = self._measured_lane_width(modeldata) + self.left_measurement = self._apply_lane_evidence( + evaluate_road_edge(left_edge, left_std, LaneChangeDirection.left, lane_width_m), + self._adjacent_lane_visible(modeldata, 0)) + self.right_measurement = self._apply_lane_evidence( + evaluate_road_edge(right_edge, right_std, LaneChangeDirection.right, lane_width_m), + self._adjacent_lane_visible(modeldata, 1)) + speed_active = math.isfinite(v_ego_mps) and v_ego_mps >= MIN_ACTIVE_SPEED_MPS + self._left, left_fallback = step_side_guard(self._left, self.left_measurement, speed_active, dt) + self._right, right_fallback = step_side_guard(self._right, self.right_measurement, speed_active, dt) + if left_fallback: + cloudlog.warning(f"lateral edge guard: left road edge unavailable for {UNAVAILABLE_HOLD_S:.2f} s; falling back to not blocking") + if right_fallback: + cloudlog.warning(f"lateral edge guard: right road edge unavailable for {UNAVAILABLE_HOLD_S:.2f} s; falling back to not blocking") + + def block_for_direction(self, direction: int) -> custom.IQLateralEdgeBlock: + if not self.enabled: + return LateralEdgeBlock.none + if direction == LaneChangeDirection.left and self._left.blocked: + return LateralEdgeBlock.left + if direction == LaneChangeDirection.right and self._right.blocked: + return LateralEdgeBlock.right + return LateralEdgeBlock.none diff --git a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/daemon.py b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/daemon.py index 2f1edd563..97327992f 100644 --- a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/daemon.py +++ b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/daemon.py @@ -604,6 +604,7 @@ class InferenceDaemon: driving_msg.drivingModelData.meta.laneChangeState = self._desire_logic.lane_change_state driving_msg.drivingModelData.meta.laneChangeDirection = self._desire_logic.lane_change_direction iq_msg.iqDriveModelData.turnSignalDirection = self._desire_logic.lane_turn_direction + iq_msg.iqDriveModelData.lateralEdgeBlock = self._desire_logic.lateral_edge_block populate_odometry_message( pose_msg, diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so index 61d676510..c58c5de0b 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so new file mode 100755 index 000000000..2313a1810 Binary files /dev/null and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so index cd29790cb..61df1f27b 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so index a5c157008..691d6df9c 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so index 574b8dd24..07f527389 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so differ diff --git a/iqpilot/selfdrive/iqmodeld/tools/egpu_host_mock.py b/iqpilot/selfdrive/iqmodeld/tools/egpu_host_mock.py index b01d7c2a0..3b43dd8e4 100644 --- a/iqpilot/selfdrive/iqmodeld/tools/egpu_host_mock.py +++ b/iqpilot/selfdrive/iqmodeld/tools/egpu_host_mock.py @@ -26,6 +26,10 @@ def activate(arch: str = DEFAULT_ARCH, execute: bool = False) -> None: tree = tinygrad_tree() if tree not in sys.path: sys.path.insert(0, tree) + from test.mockgpu.am import amgpu + + # The mock dock models 512MB VRAM; big-model weights alone exceed that. Must be set before amdriver binds it. + amgpu.VRAM_SIZE = int(os.environ.get("IQ_MOCK_VRAM_GB", "4")) << 30 from tinygrad.runtime.autogen import libc if sys.platform == "darwin": # A Homebrew-LLVM gfx1200 kernel (no s_code_end padding) hung a real dock; ship only container-built artifacts. diff --git a/launch_chffrplus.sh b/launch_chffrplus.sh index f40c2cd2a..05b2a06a4 100755 --- a/launch_chffrplus.sh +++ b/launch_chffrplus.sh @@ -205,7 +205,7 @@ function launch { service_dropin="/run/systemd/system/${service_name}.service.d" service_exec="$(grep '^ExecStart=' "$service_src")" sudo mkdir -p "$service_dropin" - printf '[Service]\nWorkingDirectory=%s\nEnvironment="IQPILOT_SOURCE_ROOT=%s/iqpilot"\nEnvironment="IQPILOT_PROPRIETARY_ROOT=%s/artifacts"\nEnvironment="PYTHONPATH=/usr/libexec/iqpilot/python:%s:%s"\nExecStart=\n%s\n' "$RUNTIME_COMPAT_ROOT" "$DIR" "$DIR" "$VENV_SITE_PACKAGES" "$DIR" "$service_exec" | sudo tee "$service_dropin/iqpilot-packages.conf" >/dev/null + printf '[Service]\nWorkingDirectory=%s\nEnvironment="IQPILOT_SOURCE_ROOT=%s/iqpilot"\nEnvironment="IQPILOT_PROPRIETARY_ROOT=%s/artifacts"\nEnvironment="PYTHONPATH=%s"\nExecStart=\n%s\n' "$RUNTIME_COMPAT_ROOT" "$DIR" "$DIR" "$PYTHONPATH" "$service_exec" | sudo tee "$service_dropin/iqpilot-packages.conf" >/dev/null sudo systemctl daemon-reload if [ -f "$service_lib" ] && grep -q "/usr/libexec/iqpilot/iqpilot_bundle_runner" "$service_lib"; then if [ -f "$service_dst" ]; then @@ -262,15 +262,18 @@ function launch { # start manager cd "$DIR/iqpilot/system/manager" export PWD="$(pwd)" + MANAGER_PYTHON="$DIR/.venv/bin/python3" if [ ! -f $DIR/prebuilt ]; then if pkill -f /tmp/installer 2>/dev/null; then sleep 1; fi - "$DIR/.venv/bin/python3" ./build.py + "$MANAGER_PYTHON" ./build.py for service_name in hephaestusd ble-transportd flockd; do sudo systemctl restart --no-block "${service_name}.service" done + else + MANAGER_PYTHON="/usr/local/venv/bin/python3" fi - "$DIR/.venv/bin/python3" ./manager.py + "$MANAGER_PYTHON" ./manager.py # if broken, keep on screen error while true; do sleep 1; done