This commit is contained in:
Your Name
2024-04-27 13:48:05 -05:00
parent 2fbe9dbea1
commit 931db76fc6
432 changed files with 12973 additions and 3300 deletions

View File

@@ -2,7 +2,6 @@
import os
import subprocess
from pathlib import Path
from typing import List
# NOTE: Do NOT import anything here that needs be built (e.g. params)
from openpilot.common.basedir import BASEDIR
@@ -29,7 +28,7 @@ def build(spinner: Spinner, dirty: bool = False, minimal: bool = False) -> None:
# building with all cores can result in using too
# much memory, so retry with less parallelism
compile_output: List[bytes] = []
compile_output: list[bytes] = []
for n in (nproc, nproc/2, 1):
compile_output.clear()
scons: subprocess.Popen = subprocess.Popen(["scons", f"-j{int(n)}", "--cache-populate", *extra_args], cwd=BASEDIR, env=env, stderr=subprocess.PIPE)

View File

@@ -5,16 +5,15 @@ import signal
import subprocess
import sys
import threading
import time
import traceback
from pathlib import Path
from typing import List, Tuple, Union
from cereal import log
import cereal.messaging as messaging
import openpilot.selfdrive.sentry as sentry
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params, ParamKeyType
from openpilot.common.text_window import TextWindow
from openpilot.common.time import system_time_valid
from openpilot.system.hardware import HARDWARE, PC
from openpilot.selfdrive.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog
from openpilot.selfdrive.manager.process import ensure_running
@@ -25,63 +24,61 @@ from openpilot.system.version import is_dirty, get_commit, get_version, get_orig
get_normalized_origin, terms_version, training_version, \
is_tested_branch, is_release_branch, get_commit_date
from openpilot.selfdrive.frogpilot.functions.frogpilot_functions import DEFAULT_MODEL
from openpilot.selfdrive.frogpilot.controls.lib.frogpilot_functions import FrogPilotFunctions
from openpilot.selfdrive.frogpilot.controls.lib.model_manager import DEFAULT_MODEL, DEFAULT_MODEL_NAME, delete_deprecated_models
def manager_init() -> None:
def frogpilot_boot_functions(frogpilot_functions):
try:
delete_deprecated_models()
while not system_time_valid():
print("Waiting for system time to become valid...")
time.sleep(1)
try:
frogpilot_functions.backup_frogpilot()
except subprocess.CalledProcessError as e:
print(f"Failed to backup FrogPilot. Error: {e}")
return
try:
frogpilot_functions.backup_toggles()
except subprocess.CalledProcessError as e:
print(f"Failed to backup toggles. Error: {e}")
return
except Exception as e:
print(f"An unexpected error occurred: {e}")
def manager_init(frogpilot_functions) -> None:
frogpilot_boot = threading.Thread(target=frogpilot_boot_functions, args=(frogpilot_functions,))
frogpilot_boot.start()
save_bootlog()
params = Params()
params_storage = Params("/persist/comma/params")
params_storage = Params("/persist/params")
params.clear_all(ParamKeyType.CLEAR_ON_MANAGER_START)
params.clear_all(ParamKeyType.CLEAR_ON_ONROAD_TRANSITION)
params.clear_all(ParamKeyType.CLEAR_ON_OFFROAD_TRANSITION)
if is_release_branch():
params.clear_all(ParamKeyType.DEVELOPMENT_ONLY)
############### Remove this after the April 26th update ###############
previous_speed_limit = params.get_float("PreviousSpeedLimit")
if previous_speed_limit >= 50:
params.put_float("PreviousSpeedLimit", previous_speed_limit / 100)
for priority_key in ["SLCPriority", "SLCPriority1", "SLCPriority2", "SLCPriority3"]:
priority_value = params.get(priority_key)
if isinstance(priority_value, int):
params.remove(priority_key)
attributes = ["AggressiveFollow", "StandardFollow", "RelaxedFollow", "AggressiveJerk", "StandardJerk", "RelaxedJerk"]
values = {attr: params.get_float(attr) for attr in attributes}
if any(value > 5 for value in values.values()):
for attr, value in values.items():
params.put_float(attr, value / 10)
if params.get_bool("SilentMode"):
attributes = ["DisengageVolume", "EngageVolume", "PromptVolume", "PromptDistractedVolume", "RefuseVolume", "WarningSoftVolume", "WarningImmediateVolume"]
for attr in attributes:
params.put_float(attr, 0)
params.put_bool("SilentMode", False)
#######################################################################
# Check if the currently selected model still exists
current_model = params.get("Model", encoding='utf-8')
if current_model != DEFAULT_MODEL:
models_folder = os.path.join(BASEDIR, 'selfdrive/modeld/models/models')
model_exists = current_model in [os.path.splitext(file)[0] for file in os.listdir(models_folder)]
if not model_exists:
params.remove("Model")
default_params: List[Tuple[str, Union[str, bytes]]] = [
default_params: list[tuple[str, str | bytes]] = [
("CarParamsPersistent", ""),
("CompletedTrainingVersion", "0"),
("DisengageOnAccelerator", "0"),
("ExperimentalLongitudinalEnabled", "1"),
("GsmMetered", "1"),
("HasAcceptedTerms", "0"),
("IsLdwEnabled", "0"),
("IsMetric", "0"),
("LanguageSetting", "main_en"),
("NavSettingLeftSide", "0"),
("NavSettingTime24h", "0"),
("OpenpilotEnabledToggle", "1"),
("UpdaterAvailableBranches", ""),
("RecordFront", "0"),
("LongitudinalPersonality", str(log.LongitudinalPersonality.standard)),
# Default FrogPilot parameters
@@ -89,15 +86,17 @@ def manager_init() -> None:
("AccelerationProfile", "2"),
("AdjacentPath", "0"),
("AdjacentPathMetrics", "0"),
("AdjustablePersonalities", "1"),
("AggressiveAcceleration", "1"),
("AggressiveFollow", "1.25"),
("AggressiveJerk", "0.5"),
("AlertVolumeControl", "0"),
("AlwaysOnLateral", "1"),
("AlwaysOnLateralMain", "0"),
("AMapKey1", ""),
("AMapKey2", ""),
("AutomaticUpdates", "0"),
("BlindSpotPath", "1"),
("CameraView", "1"),
("CameraView", "2"),
("CarMake", ""),
("CarModel", ""),
("CECurves", "1"),
@@ -106,18 +105,21 @@ def manager_init() -> None:
("CENavigationLead", "1"),
("CENavigationTurns", "1"),
("CESignal", "1"),
("CESlowerLead", "0"),
("CESlowerLead", "1"),
("CESpeed", "0"),
("CESpeedLead", "0"),
("CEStopLights", "1"),
("CEStopLightsLead", "0"),
("Compass", "0"),
("Compass", "1"),
("ConditionalExperimental", "1"),
("CrosstrekTorque", "1"),
("CurveSensitivity", "100"),
("CustomAlerts", "1"),
("CustomColors", "1"),
("CustomCruise", "1"),
("CustomCruiseLong", "5"),
("CustomIcons", "1"),
("CustomPaths", "1"),
("CustomPersonalities", "1"),
("CustomSignals", "1"),
("CustomSounds", "1"),
@@ -125,6 +127,8 @@ def manager_init() -> None:
("CustomUI", "1"),
("CydiaTune", "0"),
("DecelerationProfile", "1"),
("DeveloperUI", "0"),
("DeviceManagement", "1"),
("DeviceShutdown", "9"),
("DisableMTSCSmoothing", "0"),
("DisableOnroadUploads", "0"),
@@ -133,26 +137,22 @@ def manager_init() -> None:
("DisengageVolume", "100"),
("DragonPilotTune", "0"),
("DriverCamera", "0"),
("DriveStats", "1"),
("DynamicPathWidth", "0"),
("EngageVolume", "100"),
("EVTable", "1"),
("ExperimentalModeActivation", "1"),
("ExperimentalModeViaDistance", "0"),
("ExperimentalModeViaLKAS", "0"),
("ExperimentalModeViaScreen", "1"),
("ExperimentalModeViaDistance", "1"),
("ExperimentalModeViaLKAS", "1"),
("ExperimentalModeViaTap", "0"),
("Fahrenheit", "0"),
("FireTheBabysitter", "0"),
("ForceAutoTune", "0"),
("ForceAutoTune", "1"),
("ForceFingerprint", "0"),
("ForceMPHDashboard", "0"),
("FPSCounter", "0"),
("FrogPilotDrives", "0"),
("FrogPilotKilometers", "0"),
("FrogPilotMinutes", "0"),
("FrogsGoMooTune", "1"),
("FullMap", "0"),
("GasRegenCmd", "0"),
("GMapKey", ""),
("GoatScream", "1"),
("GreenLightAlert", "0"),
("HideAlerts", "0"),
@@ -166,46 +166,56 @@ def manager_init() -> None:
("HideUIElements", "0"),
("HigherBitrate", "0"),
("HolidayThemes", "1"),
("IncreaseThermalLimits", "0"),
("LaneChangeTime", "0"),
("LaneDetection", "1"),
("LaneDetectionWidth", "60"),
("LaneLinesWidth", "4"),
("LateralTune", "1"),
("LeadDepartingAlert", "0"),
("LeadDetectionThreshold", "25"),
("LeadDetectionThreshold", "35"),
("LeadInfo", "0"),
("LockDoors", "0"),
("LockDoors", "1"),
("LongitudinalTune", "1"),
("LongPitch", "1"),
("LoudBlindspotAlert", "0"),
("LowerVolt", "1"),
("LowVoltageShutdown", "11.8"),
("kiV1", "0.60"),
("kiV2", "0.45"),
("kiV3", "0.30"),
("kiV4", "0.15"),
("kpV1", "1.50"),
("kpV2", "1.00"),
("kpV3", "0.75"),
("kpV4", "0.50"),
("MapsSelected", ""),
("MapboxPublicKey", ""),
("MapboxSecretKey", ""),
("MapStyle", "0"),
("MTSCAggressiveness", "100"),
("MTSCCurvatureCheck", "0"),
("MTSCLimit", "0"),
("Model", DEFAULT_MODEL),
("ModelName", DEFAULT_MODEL_NAME),
("ModelSelector", "1"),
("ModelUI", "1"),
("MTSCEnabled", "1"),
("MuteOverheated", "0"),
("NavChill", "0"),
("NNFF", "1"),
("NNFFLite", "1"),
("NoLogging", "0"),
("NoUploads", "0"),
("NudgelessLaneChange", "1"),
("NumericalTemp", "0"),
("OfflineMode", "0"),
("OfflineMode", "1"),
("Offset1", "5"),
("Offset2", "5"),
("Offset3", "5"),
("Offset4", "10"),
("OneLaneChange", "1"),
("OnroadDistanceButton", "0"),
("PathEdgeWidth", "20"),
("PathWidth", "61"),
("PauseAOLOnBrake", "0"),
("PauseLateralOnSignal", "0"),
("PedalsOnUI", "1"),
("PersonalitiesViaScreen", "1"),
("PersonalitiesViaWheel", "1"),
("PreferredSchedule", "0"),
("PromptVolume", "100"),
("PromptDistractedVolume", "100"),
@@ -232,21 +242,27 @@ def manager_init() -> None:
("ShowCPU", "0"),
("ShowGPU", "0"),
("ShowIP", "0"),
("ShowJerk", "1"),
("ShowMemoryUsage", "0"),
("ShowSLCOffset", "0"),
("ShowSLCOffset", "1"),
("ShowSLCOffsetUI", "1"),
("ShowStorageLeft", "0"),
("ShowStorageUsed", "0"),
("ShowTuning", "1"),
("Sidebar", "0"),
("SLCConfirmation", "1"),
("SLCConfirmationLower", "1"),
("SLCConfirmationHigher", "1"),
("SLCFallback", "2"),
("SLCLookaheadHigher", "5"),
("SLCLookaheadLower", "5"),
("SLCOverride", "1"),
("SLCPriority1", "Dashboard"),
("SLCPriority2", "Offline Maps"),
("SLCPriority3", "Navigation"),
("SmoothBraking", "1"),
("SmoothBrakingFarLead", "0"),
("SmoothBrakingJerk", "0"),
("SNGHack", "1"),
("SpeedLimitChangedAlert", "1"),
("SpeedLimitController", "1"),
@@ -256,13 +272,17 @@ def manager_init() -> None:
("SteerRatio", "0"),
("StockTune", "0"),
("StoppingDistance", "0"),
("TacoTune", "1"),
("ToyotaDoors", "0"),
("TrafficFollow", "0.5"),
("TrafficJerk", "1"),
("TrafficMode", "0"),
("Tuning", "1"),
("TurnAggressiveness", "100"),
("TurnDesires", "0"),
("UnlimitedLength", "1"),
("UpdateSchedule", "0"),
("UseLateralJerk", "0"),
("UseSI", "0"),
("UnlockDoors", "1"),
("UseSI", "1"),
("UseVienna", "0"),
("VisionTurnControl", "1"),
("WarningSoftVolume", "100"),
@@ -347,23 +367,15 @@ def manager_cleanup() -> None:
cloudlog.info("everything is dead")
def update_frogpilot_params(params, params_memory):
keys = ["DisableOnroadUploads", "FireTheBabysitter", "NoLogging", "NoUploads", "RoadNameUI", "SpeedLimitController"]
for key in keys:
params_memory.put_bool(key, params.get_bool(key))
def manager_thread() -> None:
def manager_thread(frogpilot_functions) -> None:
cloudlog.bind(daemon="manager")
cloudlog.info("manager start")
cloudlog.info({"environ": os.environ})
params = Params()
params_memory = Params("/dev/shm/params")
params_storage = Params("/persist/comma/params")
update_frogpilot_params(params, params_memory)
ignore: List[str] = []
ignore: list[str] = []
if params.get("DongleId", encoding='utf8') in (None, UNREGISTERED_DONGLE_ID):
ignore += ["manage_athenad", "uploader"]
if os.getenv("NOBOARD") is not None:
@@ -374,20 +386,23 @@ def manager_thread() -> None:
pm = messaging.PubMaster(['managerState'])
write_onroad_params(False, params)
ensure_running(managed_processes.values(), False, params=params, params_memory=params_memory, CP=sm['carParams'], not_run=ignore)
ensure_running(managed_processes.values(), False, params=params, CP=sm['carParams'], not_run=ignore)
started_prev = False
while True:
sm.update(1000)
openpilot_crashed = os.path.isfile(os.path.join(sentry.CRASHES_DIR, 'error.txt'))
if openpilot_crashed:
frogpilot_functions.delete_logs()
started = sm['deviceState'].started
if started and not started_prev:
params.clear_all(ParamKeyType.CLEAR_ON_ONROAD_TRANSITION)
# Clear the error log on offroad transition to prevent old errors from hanging around
if os.path.isfile(os.path.join(sentry.CRASHES_DIR, 'error.txt')):
if openpilot_crashed:
os.remove(os.path.join(sentry.CRASHES_DIR, 'error.txt'))
elif not started and started_prev:
@@ -400,9 +415,9 @@ def manager_thread() -> None:
started_prev = started
ensure_running(managed_processes.values(), started, params=params, params_memory=params_memory, CP=sm['carParams'], not_run=ignore)
ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=ignore)
running = ' '.join("%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
running = ' '.join("{}{}\u001b[0m".format("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
for p in managed_processes.values() if p.proc)
print(running)
cloudlog.debug(running)
@@ -414,7 +429,7 @@ def manager_thread() -> None:
# Exit main loop when uninstall/shutdown/reboot is needed
shutdown = False
for param in ("DoUninstall", "DoShutdown", "DoReboot"):
for param in ("DoUninstall", "DoShutdown", "DoReboot", "DoSoftReboot"):
if params.get_bool(param):
shutdown = True
params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}")
@@ -423,55 +438,17 @@ def manager_thread() -> None:
if shutdown:
break
if params_memory.get_bool("FrogPilotTogglesUpdated"):
update_frogpilot_params(params, params_memory)
def backup_openpilot():
# Configure the auto backup generator
backup_dir_path = '/data/backups'
Path(backup_dir_path).mkdir(parents=True, exist_ok=True)
# Sort backups by creation time and only keep the 5 newest auto generated ones
auto_backups = sorted([f for f in os.listdir(backup_dir_path) if f.endswith("_auto")],
key=lambda x: os.path.getmtime(os.path.join(backup_dir_path, x)))
for old_backup in auto_backups:
subprocess.run(['sudo', 'rm', '-rf', os.path.join(backup_dir_path, old_backup)], check=True)
print(f"Deleted oldest backup to maintain limit: {old_backup}")
# Generate the backup folder name from the current git commit and branch name
branch = get_short_branch()
commit = get_commit_date()[12:-16]
backup_folder_name = f"{branch}_{commit}_auto"
# Check if the backup folder already exists
backup_path = os.path.join(backup_dir_path, backup_folder_name)
if os.path.exists(backup_path):
print(f"Backup folder {backup_folder_name} already exists. Skipping backup.")
return
# Create the backup directory and copy openpilot to it
Path(backup_path).mkdir(parents=True, exist_ok=True)
subprocess.run(['sudo', 'cp', '-a', '/data/openpilot/.', backup_path + '/'], check=True)
print(f"Successfully backed up openpilot to {backup_folder_name}.")
def main() -> None:
# Create the long term param storage folder
try:
# Attempt to remount /persist as read-write
subprocess.run(['sudo', 'mount', '-o', 'remount,rw', '/persist'], check=True)
print("Successfully remounted /persist as read-write.")
except subprocess.CalledProcessError as e:
print(f"Failed to remount /persist. Error: {e}")
frogpilot_functions = FrogPilotFunctions()
# Backup the current version of openpilot
try:
backup_thread = threading.Thread(target=backup_openpilot)
backup_thread.start()
frogpilot_functions.setup_frogpilot()
except subprocess.CalledProcessError as e:
print(f"Failed to backup openpilot. Error: {e}")
print(f"Failed to setup FrogPilot. Error: {e}")
return
manager_init()
manager_init(frogpilot_functions)
if os.getenv("PREPAREONLY") is not None:
return
@@ -479,7 +456,7 @@ def main() -> None:
signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(1))
try:
manager_thread()
manager_thread(frogpilot_functions)
except Exception:
traceback.print_exc()
sentry.capture_exception()
@@ -489,10 +466,13 @@ def main() -> None:
params = Params()
if params.get_bool("DoUninstall"):
cloudlog.warning("uninstalling")
HARDWARE.uninstall()
frogpilot_functions.uninstall_frogpilot()
elif params.get_bool("DoReboot"):
cloudlog.warning("reboot")
HARDWARE.reboot()
elif params.get_bool("DoSoftReboot"):
cloudlog.warning("softreboot")
HARDWARE.soft_reboot()
elif params.get_bool("DoShutdown"):
cloudlog.warning("shutdown")
HARDWARE.shutdown()

View File

@@ -4,7 +4,7 @@ import signal
import struct
import time
import subprocess
from typing import Optional, Callable, List, ValuesView
from collections.abc import Callable, ValuesView
from abc import ABC, abstractmethod
from multiprocessing import Process
@@ -47,7 +47,7 @@ def launcher(proc: str, name: str) -> None:
raise
def nativelauncher(pargs: List[str], cwd: str, name: str) -> None:
def nativelauncher(pargs: list[str], cwd: str, name: str) -> None:
os.environ['MANAGER_DAEMON'] = name
# exec the process
@@ -67,12 +67,12 @@ class ManagerProcess(ABC):
daemon = False
sigkill = False
should_run: Callable[[bool, Params, car.CarParams], bool]
proc: Optional[Process] = None
proc: Process | None = None
enabled = True
name = ""
last_watchdog_time = 0
watchdog_max_dt: Optional[int] = None
watchdog_max_dt: int | None = None
watchdog_seen = False
shutting_down = False
@@ -109,7 +109,7 @@ class ManagerProcess(ABC):
else:
self.watchdog_seen = True
def stop(self, retry: bool = True, block: bool = True, sig: Optional[signal.Signals] = None) -> Optional[int]:
def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals = None) -> int | None:
if self.proc is None:
return None
@@ -239,7 +239,7 @@ class DaemonProcess(ManagerProcess):
self.params = None
@staticmethod
def should_run(started, params, params_memory, CP):
def should_run(started, params, CP):
return True
def prepare(self) -> None:
@@ -274,14 +274,14 @@ class DaemonProcess(ManagerProcess):
pass
def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, params_memory=None, CP: car.CarParams=None,
not_run: Optional[List[str]]=None) -> List[ManagerProcess]:
def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None,
not_run: list[str] | None=None) -> list[ManagerProcess]:
if not_run is None:
not_run = []
running = []
for p in procs:
if p.enabled and p.name not in not_run and p.should_run(started, params, params_memory, CP):
if p.enabled and p.name not in not_run and p.should_run(started, params, CP):
running.append(p)
else:
p.stop(block=False)

View File

@@ -5,51 +5,53 @@ from openpilot.common.params import Params
from openpilot.system.hardware import PC, TICI
from openpilot.selfdrive.manager.process import PythonProcess, NativeProcess, DaemonProcess
from openpilot.selfdrive.frogpilot.controls.lib.model_manager import RADARLESS_MODELS
RADARLESS = Params().get("Model", encoding='utf-8') in RADARLESS_MODELS
WEBCAM = os.getenv("USE_WEBCAM") is not None
def driverview(started: bool, params: Params, params_memory: Params, CP: car.CarParams) -> bool:
def driverview(started: bool, params: Params, CP: car.CarParams) -> bool:
return started or params.get_bool("IsDriverViewEnabled")
def notcar(started: bool, params: Params, params_memory: Params, CP: car.CarParams) -> bool:
def notcar(started: bool, params: Params, CP: car.CarParams) -> bool:
return started and CP.notCar
def iscar(started: bool, params: Params, params_memory: Params, CP: car.CarParams) -> bool:
def iscar(started: bool, params: Params, CP: car.CarParams) -> bool:
return started and not CP.notCar
def logging(started, params, params_memory, CP: car.CarParams) -> bool:
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, params_memory, CP: car.CarParams) -> bool:
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 started and use_ublox
def qcomgps(started, params, params_memory, CP: car.CarParams) -> bool:
def qcomgps(started, params, CP: car.CarParams) -> bool:
return started and not ublox_available()
def always_run(started, params, params_memory, CP: car.CarParams) -> bool:
def always_run(started, params, CP: car.CarParams) -> bool:
return True
def only_onroad(started: bool, params, params_memory, CP: car.CarParams) -> bool:
def only_onroad(started: bool, params, CP: car.CarParams) -> bool:
return started
def only_offroad(started, params, params_memory, CP: car.CarParams) -> bool:
def only_offroad(started, params, CP: car.CarParams) -> bool:
return not started
# FrogPilot functions
def allow_uploads(started, params, params_memory, CP: car.CarParams) -> bool:
allow_uploads = not (params_memory.get_bool("FireTheBabysitter") and params_memory.get_bool("NoUploads"))
at_home = not started or not params_memory.get_bool("DisableOnroadUploads")
return allow_uploads and at_home
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_logging(started, params, params_memory, CP: car.CarParams) -> bool:
allow_logging = not (params_memory.get_bool("FireTheBabysitter") and params_memory.get_bool("NoLogging"))
return allow_logging and logging(started, params, params_memory, 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"),
@@ -79,16 +81,18 @@ procs = [
PythonProcess("deleter", "system.loggerd.deleter", always_run),
PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(not PC or WEBCAM)),
PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI),
#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),
NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], ublox, enabled=TICI),
PythonProcess("pigeond", "system.sensord.pigeond", ublox, enabled=TICI),
PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI),
PythonProcess("plannerd", "selfdrive.controls.plannerd", only_onroad),
PythonProcess("radard", "selfdrive.controls.radard", only_onroad),
PythonProcess("radard", "selfdrive.controls.radard", only_onroad, enabled=not RADARLESS),
PythonProcess("radardless", "selfdrive.controls.radardless", only_onroad, enabled=RADARLESS),
PythonProcess("thermald", "selfdrive.thermald.thermald", always_run),
PythonProcess("tombstoned", "selfdrive.tombstoned", allow_logging, enabled=not PC),
PythonProcess("updated", "selfdrive.updated", always_run, enabled=not PC),
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),
@@ -99,8 +103,8 @@ procs = [
# FrogPilot processes
PythonProcess("fleet_manager", "selfdrive.frogpilot.fleetmanager.fleet_manager", always_run),
PythonProcess("frogpilot_process", "selfdrive.frogpilot.functions.frogpilot_process", always_run),
PythonProcess("mapd", "selfdrive.frogpilot.functions.mapd", always_run),
PythonProcess("frogpilot_process", "selfdrive.frogpilot.frogpilot_process", always_run),
PythonProcess("mapd", "selfdrive.frogpilot.navigation.mapd", always_run),
]
managed_processes = {p.name: p for p in procs}

View File

View File

@@ -0,0 +1,82 @@
#!/usr/bin/env python3
import os
import pytest
import signal
import time
import unittest
from parameterized import parameterized
from cereal import car
from openpilot.common.params import Params
import openpilot.selfdrive.manager.manager as manager
from openpilot.selfdrive.manager.process import ensure_running
from openpilot.selfdrive.manager.process_config import managed_processes
from openpilot.system.hardware import HARDWARE
os.environ['FAKEUPLOAD'] = "1"
MAX_STARTUP_TIME = 3
BLACKLIST_PROCS = ['manage_athenad', 'pandad', 'pigeond']
@pytest.mark.tici
class TestManager(unittest.TestCase):
def setUp(self):
HARDWARE.set_power_save(False)
# ensure clean CarParams
params = Params()
params.clear_all()
def tearDown(self):
manager.manager_cleanup()
def test_manager_prepare(self):
os.environ['PREPAREONLY'] = '1'
manager.main()
def test_blacklisted_procs(self):
# TODO: ensure there are blacklisted procs until we have a dedicated test
self.assertTrue(len(BLACKLIST_PROCS), "No blacklisted procs to test not_run")
@parameterized.expand([(i,) for i in range(10)])
def test_startup_time(self, index):
start = time.monotonic()
os.environ['PREPAREONLY'] = '1'
manager.main()
t = time.monotonic() - start
assert t < MAX_STARTUP_TIME, f"startup took {t}s, expected <{MAX_STARTUP_TIME}s"
@unittest.skip("this test is flaky the way it's currently written, should be moved to test_onroad")
def test_clean_exit(self):
"""
Ensure all processes exit cleanly when stopped.
"""
HARDWARE.set_power_save(False)
manager.manager_init()
CP = car.CarParams.new_message()
procs = ensure_running(managed_processes.values(), True, Params(), CP, not_run=BLACKLIST_PROCS)
time.sleep(10)
for p in procs:
with self.subTest(proc=p.name):
state = p.get_process_state_msg()
self.assertTrue(state.running, f"{p.name} not running")
exit_code = p.stop(retry=False)
self.assertNotIn(p.name, BLACKLIST_PROCS, f"{p.name} was started")
self.assertTrue(exit_code is not None, f"{p.name} failed to exit")
# TODO: interrupted blocking read exits with 1 in cereal. use a more unique return code
exit_codes = [0, 1]
if p.sigkill:
exit_codes = [-signal.SIGKILL]
self.assertIn(exit_code, exit_codes, f"{p.name} died with {exit_code}")
if __name__ == "__main__":
unittest.main()