Files
StarPilot/selfdrive/frogpilot/controls/lib/frogpilot_functions.py
T
FrogAi 9dcf86fdb6 Controls - Model Management
Manage openpilot's driving models.
2024-07-31 21:43:26 -07:00

207 lines
7.3 KiB
Python

import datetime
import filecmp
import glob
import http.client
import numpy as np
import os
import shutil
import socket
import subprocess
import sys
import threading
import time
import urllib.error
import urllib.request
from openpilot.common.basedir import BASEDIR
from openpilot.common.numpy_fast import clip, interp, mean
from openpilot.common.params_pyx import Params, ParamKeyType, UnknownKeyName
from openpilot.common.time import system_time_valid
from openpilot.system.hardware import HARDWARE
MODELS_PATH = "/data/models"
def delete_file(file):
try:
os.remove(file)
print(f"Deleted file: {file}")
except FileNotFoundError:
print(f"File not found: {file}")
except Exception as e:
print(f"An error occurred: {e}")
def is_url_pingable(url, timeout=5):
try:
urllib.request.urlopen(url, timeout=timeout)
return True
except (http.client.IncompleteRead, http.client.RemoteDisconnected, socket.gaierror, socket.timeout, urllib.error.HTTPError, urllib.error.URLError):
return False
def update_frogpilot_toggles():
def update_params():
params_memory = Params("/dev/shm/params")
params_memory.put_bool("FrogPilotTogglesUpdated", True)
time.sleep(1)
params_memory.put_bool("FrogPilotTogglesUpdated", False)
threading.Thread(target=update_params).start()
def run_cmd(cmd, success_msg, fail_msg):
try:
subprocess.check_call(cmd)
print(success_msg)
except subprocess.CalledProcessError as e:
print(f"{fail_msg}: {e}")
except Exception as e:
print(f"Unexpected error occurred: {e}")
def calculate_lane_width(lane, current_lane, road_edge):
current_x, current_y = np.array(current_lane.x), np.array(current_lane.y)
lane_y_interp = interp(current_x, np.array(lane.x), np.array(lane.y))
road_edge_y_interp = interp(current_x, np.array(road_edge.x), np.array(road_edge.y))
distance_to_lane = np.mean(abs(current_y - lane_y_interp))
distance_to_road_edge = np.mean(abs(current_y - road_edge_y_interp))
return float(min(distance_to_lane, distance_to_road_edge))
# Credit goes to Pfeiferj!
def calculate_road_curvature(modelData, v_ego):
orientation_rate = np.abs(modelData.orientationRate.z)
velocity = modelData.velocity.x
max_pred_lat_acc = np.amax(orientation_rate * velocity)
return abs(float(max(max_pred_lat_acc / v_ego**2, sys.float_info.min)))
def backup_directory(backup, destination, success_msg, fail_msg):
os.makedirs(destination, exist_ok=True)
try:
run_cmd(['sudo', 'cp', '-a', os.path.join(backup, '.'), destination], success_msg, fail_msg)
except OSError as e:
if e.errno == 28:
print("Not enough space to perform the backup.")
else:
print(f"Failed to backup due to unexpected error: {e}")
def cleanup_backups(directory, limit):
backups = sorted(glob.glob(os.path.join(directory, "*_auto")), key=os.path.getmtime, reverse=True)
for old_backup in backups[limit:]:
subprocess.run(['sudo', 'rm', '-rf', old_backup], check=True)
print(f"Deleted oldest backup: {os.path.basename(old_backup)}")
def backup_frogpilot(build_metadata):
backup_path = "/data/backups"
cleanup_backups(backup_path, 4)
branch = build_metadata.channel
commit = build_metadata.openpilot.git_commit_date[12:-16]
backup_dir = f"{backup_path}/{branch}_{commit}_auto"
backup_directory(BASEDIR, backup_dir, f"Successfully backed up FrogPilot to {backup_dir}.", f"Failed to backup FrogPilot to {backup_dir}.")
def backup_toggles(params, params_storage):
for key in params.all_keys():
if params.get_key_type(key) & ParamKeyType.FROGPILOT_STORAGE:
value = params.get(key)
if value is not None:
params_storage.put(key, value)
backup_path = "/data/toggle_backups"
cleanup_backups(backup_path, 9)
backup_dir = f"{backup_path}/{datetime.datetime.now().strftime('%Y-%m-%d_%I-%M%p').lower()}_auto"
backup_directory("/data/params/d", backup_dir, f"Successfully backed up toggles to {backup_dir}.", f"Failed to backup toggles to {backup_dir}.")
def convert_params(params, params_storage):
def convert_param(key, action_func):
try:
if params_storage.check_key(key) and params_storage.get_bool(key):
action_func()
except UnknownKeyName:
pass
version = 8
try:
if params_storage.check_key("ParamConversionVersion") and params_storage.get_int("ParamConversionVersion") == version:
print("Params already converted, moving on.")
return
except UnknownKeyName:
pass
print("Converting params...")
convert_param("ModelSelector", lambda: params.put_nonblocking("ModelManagement", "True"))
convert_param("DragonPilotTune", lambda: params.put_nonblocking("FrogsGoMooTune", "True"))
print("Params successfully converted!")
params_storage.put_int_nonblocking("ParamConversionVersion", version)
def frogpilot_boot_functions(build_metadata, params, params_storage):
convert_params(params, params_storage)
while not system_time_valid():
print("Waiting for system time to become valid...")
time.sleep(1)
try:
backup_frogpilot(build_metadata)
backup_toggles(params, params_storage)
except subprocess.CalledProcessError as e:
print(f"Backup failed: {e}")
def setup_frogpilot(build_metadata):
remount_persist = ['sudo', 'mount', '-o', 'remount,rw', '/persist']
run_cmd(remount_persist, "Successfully remounted /persist as read-write.", "Failed to remount /persist.")
os.makedirs("/persist/params", exist_ok=True)
os.makedirs(MODELS_PATH, exist_ok=True)
remount_root = ['sudo', 'mount', '-o', 'remount,rw', '/']
run_cmd(remount_root, "File system remounted as read-write.", "Failed to remount file system.")
frogpilot_boot_logo = f'{BASEDIR}/selfdrive/frogpilot/assets/other_images/frogpilot_boot_logo.png'
frogpilot_boot_logo_jpg = f'{BASEDIR}/selfdrive/frogpilot/assets/other_images/frogpilot_boot_logo.jpg'
boot_logo_location = '/usr/comma/bg.jpg'
boot_logo_save_location = f'{BASEDIR}/selfdrive/frogpilot/assets/other_images/original_bg.jpg'
if not os.path.exists(boot_logo_save_location):
shutil.copy(boot_logo_location, boot_logo_save_location)
print("Successfully saved original_bg.jpg.")
if filecmp.cmp(boot_logo_save_location, frogpilot_boot_logo_jpg, shallow=False):
os.remove(boot_logo_save_location)
if not filecmp.cmp(frogpilot_boot_logo, boot_logo_location, shallow=False):
run_cmd(['sudo', 'cp', frogpilot_boot_logo, boot_logo_location], "Successfully replaced bg.jpg with frogpilot_boot_logo.png.", "Failed to replace boot logo.")
if build_metadata.channel == "FrogPilot-Development":
subprocess.run(["sudo", "python3", "/persist/frogsgomoo.py"], check=True)
def uninstall_frogpilot():
boot_logo_location = '/usr/comma/bg.jpg'
boot_logo_restore_location = f'{BASEDIR}/selfdrive/frogpilot/assets/other_images/original_bg.jpg'
copy_cmd = ['sudo', 'cp', boot_logo_restore_location, boot_logo_location]
run_cmd(copy_cmd, "Successfully restored the original boot logo.", "Failed to restore the original boot logo.")
HARDWARE.uninstall()
class MovingAverageCalculator:
def __init__(self):
self.reset_data()
def add_data(self, value):
if len(self.data) == 5:
self.total -= self.data.pop(0)
self.data.append(value)
self.total += value
def get_moving_average(self):
if len(self.data) == 0:
return None
return self.total / len(self.data)
def reset_data(self):
self.data = []
self.total = 0