Files
StarPilot/openpilot/starpilot/controllers/runtime.py
T
firestar5683 347397ad38 Add exclusive parked SpacePilot mode and native Big UI
Use the supported Offroad lifecycle with fresh Park, receive-only CAN,
stopped-process and noOutput checks. Add offroad touch/controller play
and the native Big UI five-version-tap entry. Exiting never restores
driving mode automatically within the existing manager session.

Qualified by210 unique focused passing cases, lint/type checks, native
host rendering/input/resource checks and independent lifecycle review.
Actual vehicle lifecycle, hardware inputs and device headroom remain
unqualified; no deployment is part of this change.
2026-10-26 00:01:36 -05:00

63 lines
2.1 KiB
Python

import logging
import time
from openpilot.starpilot.controllers.input import InputReader
from openpilot.starpilot.controllers.owner import ControllerOwner
from openpilot.starpilot.controllers.transport import ControllerService
from openpilot.starpilot.galaxy.settings import LiveContextSource
LOGGER = logging.getLogger(__name__)
class ControllerRuntime:
def __init__(self, params, *, actions, favorites, invoke_favorite, authority=None, reader=None, socket_path=None, input_capture=lambda: None):
self.authority = authority if authority is not None else LiveContextSource(params)
self.reader = reader if reader is not None else InputReader()
self.owner = ControllerOwner(params, parked=self.authority.parked, actions=actions, favorites=favorites,
invoke_favorite=invoke_favorite)
self.service = ControllerService(self.owner, socket_path)
self.input_capture = input_capture
self._closed = False
self._next_warm = 0.0
self._warm_until = time.monotonic() + 2.0
try:
self.service.start()
except (OSError, RuntimeError):
LOGGER.exception('Controller input could not start')
self.close()
def poll(self):
if self._closed:
return
try:
now = time.monotonic()
if now >= self._next_warm:
self.authority.parked()
self._next_warm = now + (0.1 if now < self._warm_until else 1.0)
presses = self.reader.poll(time.monotonic_ns())
self.owner.set_devices(self.reader.devices())
self.owner.tick()
# Process input before configuration so queued presses cannot activate a new binding.
capture = self.input_capture()
for press in presses:
if capture is None:
self.owner.feed(press)
else:
self.owner.feed(press, capture=capture)
self.service.poll()
except Exception:
LOGGER.exception('Controller input stopped')
self.close()
def close(self):
if self._closed:
return
self._closed = True
try:
self.service.close()
finally:
try:
self.reader.close()
finally:
self.authority.close()