Files
onepilot/tools/StarPilot/derive_feasible_params.py
T
firestar5683 d0e1db6766 StarPilot
2026-03-22 03:15:05 -05:00

122 lines
5.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""
derive_feasible_params.py
Dynamically parses the OpenPilot/StarPilot codebase to cross-reference logically
registered Param keys with UI string literals. This ensures that no hidden or
dynamically-instantiated UI toggles are missed, outputting a highly accurate "Golden List"
of parameters that can be safely modified by The Pond or other configuration interfaces.
"""
import os
import re
def get_repo_root() -> str:
# Resolves to the root of the StarPilot repository based on this script's location
return os.path.abspath(os.path.join(os.path.dirname(__file__), '../../'))
# Constants
REPO_ROOT = get_repo_root()
PARAMS_CC_PATH = os.path.join(REPO_ROOT, 'common/params.cc')
UI_DIRECTORIES = [
os.path.join(REPO_ROOT, 'selfdrive/ui'),
os.path.join(REPO_ROOT, 'frogpilot/ui')
]
# A curated list of parameters that are known to be strictly readable state metadata
# rather than user-toggled configurations.
KNOWN_READ_ONLY = {
"ApiCache_Device", "ApiCache_DriveStats", "ApiCache_NavDestinations",
"CarMake", "CarModel", "CarModelName", "CarParamsPersistent", "CarVin",
"ClusterOffset", "Compass", "DeveloperSidebarMetric1", "DeveloperSidebarMetric2",
"DeveloperSidebarMetric3", "DeveloperSidebarMetric4", "DeveloperSidebarMetric5",
"DeveloperSidebarMetric6", "DeveloperSidebarMetric7", "DongleId",
"FrogPilotCarParamsPersistent", "FrogPilotDrives", "FrogPilotKilometers",
"FrogPilotMinutes", "GitBranch", "GitCommit", "GitCommitDate", "GitDiff",
"GitRemote", "GithubSshKeys", "GithubUsername", "HardwareSerial", "IMEI",
"InstallDate", "IsRhdDetected", "KonikMinutes", "LastGPSPosition",
"LastMapsUpdate", "LastUpdateTime", "ModelDrivesAndScores", "ModelReleasedDates",
"ModelVersions", "PrimeType", "TermsVersion", "TrainingVersion", "Version",
"openpilotMinutes", "CompletedTrainingVersion"
}
def extract_registered_keys(params_path: str) -> set:
"""Extracts all legally registered parameter keys from common/params.cc"""
registered_keys = set()
try:
with open(params_path, 'r', encoding='utf-8') as f:
content = f.read()
# Isolate the keys `unordered_map` block
keys_block_match = re.search(r'unordered_map<std::string, uint32_t> keys = \{(.*?)\};', content, re.DOTALL)
if not keys_block_match:
print("Error: Could not locate 'keys' map in params.cc")
return registered_keys
# Extract {"KeyName", FLAG} entries
for match in re.finditer(r'\{"([A-Za-z0-9_]+)",\s*([^}]+)\}', keys_block_match.group(1)):
key, flag = match.group(1), match.group(2)
# Remove keys that are strictly internal ephemeral states
if 'CLEAR_ON_MANAGER_START' not in flag:
registered_keys.add(key)
except FileNotFoundError:
print(f"Error: Could not find params source file at {params_path}")
return registered_keys
def extract_ui_string_literals(ui_dirs: list) -> set:
"""Recursively walks UI directories to extract every string literal."""
ui_strings = set()
valid_extensions = ('.cc', '.h', '.cpp', '.hpp', '.qml')
for directory in ui_dirs:
if not os.path.exists(directory):
print(f"Warning: UI directory not found {directory}")
continue
for root, _, files in os.walk(directory):
for file in files:
if file.endswith(valid_extensions):
filepath = os.path.join(root, file)
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
# Extract all "StringLiterals" block
matches = re.findall(r'\"([A-Za-z0-9_]+)\"', f.read())
ui_strings.update(matches)
return ui_strings
def main():
print(f"Starting parameter derivation inside {REPO_ROOT}...")
# 1. Fetch
registered_keys = extract_registered_keys(PARAMS_CC_PATH)
ui_strings = extract_ui_string_literals(UI_DIRECTORIES)
# 2. Intersect
feasible_keys = registered_keys.intersection(ui_strings)
# 3. Filter Read-Only
editable_keys = feasible_keys - KNOWN_READ_ONLY
# 4. Export
output_path = os.path.join(os.path.dirname(__file__), 'feasibleparams.txt')
try:
with open(output_path, 'w', encoding='utf-8') as f:
f.write("Dynamically Derived Feasible Param Candidates (The Golden List)\n")
f.write("===============================================================\n\n")
f.write(f"Total globally registered C++ keys: {len(registered_keys)}\n")
f.write(f"Total explicit UI string references: {len(feasible_keys)}\n")
f.write(f"Total Editable/Toggleable targets: {len(editable_keys)}\n\n")
for key in sorted(list(editable_keys)):
f.write(f"{key}\n")
print(f"Successfully derived {len(editable_keys)} highly feasible parameter targets.")
print(f"Report exported to: {output_path}")
except Exception as e:
print(f"Error writing to output file: {e}")
if __name__ == '__main__':
main()