5d18ad1e72
When the car is in park (ignition still on), pause everything that
isn't strictly needed and keep controlsd in a minimal-cycle keepalive
mode so the car's steering ECU keeps seeing the LFA/LKAS CAN-FD
messages and stays in tester mode (no steering fault on shift to drive).
controlsd:
- Detects park gear, writes ParkMode to /dev/shm/params.
- park_mode_tick(): publishes a do-nothing CarControl through
self.card (CarController.update unconditionally appends the
steering messages every cycle, which is the actual heartbeat).
Still runs clearpilot_state_control so the LFA/debug button +
ScreenDisplayMode keep working in park.
- After park→drive, stay in keepalive-tick mode until SubMaster
reports all services healthy (an 8s hard cap as safety net).
Avoids the burst of commIssue alerts that would otherwise fire
while modeld/plannerd/paramsd/torqued/dmonitoringd/calibrationd/
frogpilot_process spin back up from cold.
manager / process_config:
- New gating helpers _park_mode(), only_onroad_active,
driverview_active, always_run_unless_parked.
- Re-gated to only_onroad_active: modeld, sensord, soundd, locationd,
calibrationd, torqued, paramsd, plannerd, radard, speed_logicd.
- Re-gated to driverview_active: dmonitoringmodeld, dmonitoringd.
- frogpilot_process → always_run_unless_parked (preserves offroad
behavior, only pauses when ignition+parked).
- controlsd stays plain only_onroad — it's the writer + heartbeat.
- ParkMode registered in params.cc, defaulted to "0" in manager_init.
thermald + fan_controller (broken-tree rule, ported):
- thermald subscribes to carState; passes standstill, is_parked,
cruise_engaged into fan_controller.update.
- New fan range rules:
parked → 0-100% (no floor, full cooling)
cruise on → 30-100%
standstill → 10-100%
moving → 30-100%
ignition off → 0-30% (existing)
dashcamd: already park-aware via gear-driven trip lifecycle — no
change needed.
Verified: build clean. Launched on bench: park mode kicks in on
startup (gearShifter=unknown initially → eventually park),
modeld/plannerd/paramsd/torqued/calibrationd/frogpilot_process
correctly disappear from the manager process list, gpsd/dashcamd/
ui/controlsd/pandad stay alive, ParkMode=1 in /dev/shm/params.
140 lines
7.4 KiB
Python
Executable File
140 lines
7.4 KiB
Python
Executable File
import os
|
|
|
|
from cereal import car
|
|
from openpilot.common.params import Params
|
|
from openpilot.system.hardware import PC, TICI
|
|
from openpilot.selfdrive.manager.process import PythonProcess, NativeProcess, DaemonProcess
|
|
|
|
|
|
WEBCAM = os.getenv("USE_WEBCAM") is not None
|
|
|
|
def driverview(started: bool, params: Params, CP: car.CarParams) -> bool:
|
|
return started or params.get_bool("IsDriverViewEnabled")
|
|
|
|
def notcar(started: bool, params: Params, CP: car.CarParams) -> bool:
|
|
return started and CP.notCar
|
|
|
|
def iscar(started: bool, params: Params, CP: car.CarParams) -> bool:
|
|
return started and not CP.notCar
|
|
|
|
def logging(started, params, CP: car.CarParams) -> bool:
|
|
run = (not CP.notCar) or not params.get_bool("DisableLogging")
|
|
return started and run
|
|
|
|
def ublox_available() -> bool:
|
|
return os.path.exists('/dev/ttyHS0') and not os.path.exists('/persist/comma/use-quectel-gps')
|
|
|
|
def ublox(started, params, CP: car.CarParams) -> bool:
|
|
use_ublox = ublox_available()
|
|
if use_ublox != params.get_bool("UbloxAvailable"):
|
|
params.put_bool("UbloxAvailable", use_ublox)
|
|
return use_ublox
|
|
|
|
def qcomgps(started, params, CP: car.CarParams) -> bool:
|
|
return not ublox_available()
|
|
|
|
def always_run(started, params, CP: car.CarParams) -> bool:
|
|
return True
|
|
|
|
def only_onroad(started: bool, params, CP: car.CarParams) -> bool:
|
|
return started
|
|
|
|
# CLEARPILOT: park-mode gating. controlsd writes ParkMode to /dev/shm/params
|
|
# when the car is parked (ignition still on). Manager's ensure_running loop
|
|
# reads these gates every tick and stops/starts processes naturally as the
|
|
# flag flips. controlsd itself stays on plain `started` (it's the one
|
|
# writing the flag and emitting the steering keepalive to the car's ECU).
|
|
def _park_mode() -> bool:
|
|
return Params("/dev/shm/params").get_bool("ParkMode")
|
|
|
|
def only_onroad_active(started: bool, params, CP: car.CarParams) -> bool:
|
|
return started and not _park_mode()
|
|
|
|
def driverview_active(started: bool, params, CP: car.CarParams) -> bool:
|
|
return driverview(started, params, CP) and not _park_mode()
|
|
|
|
def always_run_unless_parked(started, params, CP: car.CarParams) -> bool:
|
|
# Same as always_run, but pauses while ignition is on and the car is parked.
|
|
# Preserves offroad behavior; only changes the started+parked case.
|
|
return not (started and _park_mode())
|
|
|
|
def only_offroad(started, params, CP: car.CarParams) -> bool:
|
|
return not started
|
|
|
|
# FrogPilot functions
|
|
def allow_logging(started, params, CP: car.CarParams) -> bool:
|
|
allow_logging = not (params.get_bool("DeviceManagement") and params.get_bool("NoLogging"))
|
|
return allow_logging and logging(started, params, CP)
|
|
|
|
def allow_uploads(started, params, CP: car.CarParams) -> bool:
|
|
allow_uploads = not (params.get_bool("DeviceManagement") and params.get_bool("NoUploads"))
|
|
return allow_uploads
|
|
|
|
procs = [
|
|
DaemonProcess("manage_athenad", "selfdrive.athena.manage_athenad", "AthenadPid"),
|
|
|
|
# CLEARPILOT: camerad runs always (was driverview) so dashcamd can record
|
|
# the moment ignition+drive-gear arrives without waiting for camera startup.
|
|
NativeProcess("camerad", "system/camerad", ["./camerad"], always_run),
|
|
NativeProcess("logcatd", "system/logcatd", ["./logcatd"], allow_logging),
|
|
NativeProcess("proclogd", "system/proclogd", ["./proclogd"], allow_logging),
|
|
PythonProcess("logmessaged", "system.logmessaged", allow_logging),
|
|
PythonProcess("micd", "system.micd", iscar),
|
|
PythonProcess("timed", "system.timed", always_run, enabled=not PC),
|
|
|
|
PythonProcess("dmonitoringmodeld", "selfdrive.modeld.dmonitoringmodeld", driverview_active, enabled=(not PC or WEBCAM)),
|
|
# CLEARPILOT: disabled segment + camera logging — no rlog/qlog or .hevc
|
|
# files written to /data/media/0/realdata. We don't use comma's upload/
|
|
# replay pipeline. Keep deleter running for any leftover cleanup.
|
|
# NativeProcess("encoderd", "system/loggerd", ["./encoderd"], allow_logging),
|
|
# NativeProcess("stream_encoderd", "system/loggerd", ["./encoderd", "--stream"], notcar),
|
|
# NativeProcess("loggerd", "system/loggerd", ["./loggerd"], allow_logging),
|
|
NativeProcess("modeld", "selfdrive/modeld", ["./modeld"], only_onroad_active),
|
|
#NativeProcess("mapsd", "selfdrive/navd", ["./mapsd"], only_onroad),
|
|
#PythonProcess("navmodeld", "selfdrive.modeld.navmodeld", only_onroad),
|
|
NativeProcess("sensord", "system/sensord", ["./sensord"], only_onroad_active, enabled=not PC),
|
|
NativeProcess("ui", "selfdrive/ui", ["./ui"], always_run, watchdog_max_dt=(5 if not PC else None), always_watchdog=only_offroad),
|
|
PythonProcess("soundd", "selfdrive.ui.soundd", only_onroad_active),
|
|
NativeProcess("locationd", "selfdrive/locationd", ["./locationd"], only_onroad_active),
|
|
NativeProcess("boardd", "selfdrive/boardd", ["./boardd"], always_run, enabled=False),
|
|
PythonProcess("calibrationd", "selfdrive.locationd.calibrationd", only_onroad_active),
|
|
PythonProcess("torqued", "selfdrive.locationd.torqued", only_onroad_active),
|
|
PythonProcess("controlsd", "selfdrive.controls.controlsd", only_onroad),
|
|
PythonProcess("deleter", "system.loggerd.deleter", always_run),
|
|
PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview_active, enabled=(not PC or WEBCAM)),
|
|
# PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI), # Fixme
|
|
# CLEARPILOT: replacement for qcomgpsd (whose diag interface is broken on this device).
|
|
# Uses Quectel modem AT commands via mmcli. Self-driving does NOT consume this; locationd
|
|
# is patched to skip gpsLocation. Used only for system clock + UI speed + dashcam metadata.
|
|
PythonProcess("gpsd", "system.clearpilot.gpsd", qcomgps, enabled=TICI),
|
|
# CLEARPILOT: speed/cruise overlay daemon. Reads gpsLocation + carState, writes display
|
|
# params for the onroad UI; asserts ClearpilotPlayDing on speed-limit warning transitions.
|
|
PythonProcess("speed_logicd", "selfdrive.clearpilot.speed_logicd", only_onroad_active),
|
|
# CLEARPILOT: dashcam — VisionIPC frames → OMX H.264 → 3-min MP4 segments + SRT
|
|
# GPS subtitles in /data/media/0/videos/. Manages its own trip lifecycle.
|
|
NativeProcess("dashcamd", "selfdrive/clearpilot", ["./dashcamd"], always_run),
|
|
# PythonProcess("ugpsd", "system.ugpsd", only_onroad, enabled=TICI),
|
|
#PythonProcess("navd", "selfdrive.navd.navd", only_onroad),
|
|
PythonProcess("pandad", "selfdrive.boardd.pandad", always_run),
|
|
PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad_active),
|
|
NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], ublox, enabled=TICI),
|
|
PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI),
|
|
PythonProcess("plannerd", "selfdrive.controls.plannerd", only_onroad_active),
|
|
PythonProcess("radard", "selfdrive.controls.radard", only_onroad_active),
|
|
PythonProcess("thermald", "selfdrive.thermald.thermald", always_run),
|
|
PythonProcess("tombstoned", "selfdrive.tombstoned", always_run, enabled=not PC),
|
|
# PythonProcess("updated", "selfdrive.updated.updated", always_run, enabled=not PC),
|
|
# PythonProcess("uploader", "system.loggerd.uploader", allow_uploads),
|
|
PythonProcess("statsd", "selfdrive.statsd", allow_logging),
|
|
|
|
# debug procs
|
|
NativeProcess("bridge", "cereal/messaging", ["./bridge"], notcar),
|
|
PythonProcess("webrtcd", "system.webrtc.webrtcd", notcar),
|
|
PythonProcess("webjoystick", "tools.bodyteleop.web", notcar),
|
|
|
|
# FrogPilot processes
|
|
PythonProcess("fleet_manager", "selfdrive.frogpilot.fleetmanager.fleet_manager", always_run),
|
|
PythonProcess("frogpilot_process", "selfdrive.frogpilot.frogpilot_process", always_run_unless_parked),
|
|
]
|
|
|
|
managed_processes = {p.name: p for p in procs} |