Bench mode (--bench flag): - bench_onroad.py publishes fake vehicle state as managed process - manager blocks real car processes (pandad, thermald, controlsd, etc.) - bench_cmd.py for setting params and querying UI state - BLOCKER: UI segfaults (SIGSEGV) when OnroadWindow becomes visible without camera frames — need to make CameraWidget handle missing VisionIPC gracefully before bench drive mode works ClearPilot menu: - Replaced grid launcher with sidebar settings panel (ClearPilotPanel) - Sidebar: Home, Dashcam, Debug - Home panel: Status and System Settings buttons - Debug panel: telemetry logging toggle (ParamControl) - Tap from any view (splash, onroad) opens ClearPilotPanel - Back button returns to splash/onroad Status window: - Live system stats refreshing every 1 second - Storage, RAM, load, IP, WiFi, VPN, GPS, time, telemetry status - Tap anywhere to close, returns to previous view - Honors interactive timeout UI introspection RPC: - ZMQ REP server at ipc:///tmp/clearpilot_ui_rpc - Dumps full widget tree with visibility, geometry, stacked indices - bench_cmd dump queries it, detects crash loops via process uptime - ui_dump.py standalone tool Other: - Telemetry toggle wired to TelemetryEnabled param with disk space guard - Telemetry disabled on every manager start - Blinking red circle on onroad UI when telemetry recording - Fixed showDriverView overriding park/drive transitions every frame - Fixed offroadTransition sidebar visibility race in MainWindow - launch_openpilot.sh: cd to /data/openpilot, --bench flag support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
130 lines
4.3 KiB
Python
130 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
ClearPilot bench onroad simulator.
|
|
|
|
Publishes fake messages to make the UI go onroad and display
|
|
configurable vehicle state. Control values via params in /dev/shm/params:
|
|
|
|
BenchSpeed - vehicle speed in mph (default: 0)
|
|
BenchSpeedLimit - speed limit in mph (default: 0, 0=hidden)
|
|
BenchCruiseSpeed - cruise set speed in mph (default: 0, 0=not set)
|
|
BenchGear - P, D, R, N (default: P)
|
|
BenchEngaged - 0 or 1, cruise engaged (default: 0)
|
|
|
|
Usage:
|
|
su - comma -c "PYTHONPATH=/data/openpilot python3 -m selfdrive.clearpilot.bench_onroad"
|
|
|
|
To stop: Ctrl+C or kill the process. UI returns to offroad.
|
|
"""
|
|
import time
|
|
|
|
import cereal.messaging as messaging
|
|
from cereal import log, car
|
|
from openpilot.common.params import Params
|
|
|
|
MS_PER_MPH = 0.44704
|
|
|
|
|
|
def main():
|
|
params = Params()
|
|
params_mem = Params("/dev/shm/params")
|
|
|
|
# Set defaults
|
|
params_mem.put("BenchSpeed", "0")
|
|
params_mem.put("BenchSpeedLimit", "0")
|
|
params_mem.put("BenchCruiseSpeed", "0")
|
|
params_mem.put("BenchGear", "P")
|
|
params_mem.put("BenchEngaged", "0")
|
|
|
|
pm = messaging.PubMaster([
|
|
"deviceState", "pandaStates", "carState", "controlsState",
|
|
"driverMonitoringState", "liveCalibration",
|
|
])
|
|
|
|
print("Bench onroad simulator started")
|
|
print("Set values in /dev/shm/params/d/Bench*")
|
|
print(" BenchSpeed=0 BenchSpeedLimit=0 BenchCruiseSpeed=0 BenchGear=P BenchEngaged=0")
|
|
|
|
gear_map = {
|
|
"P": car.CarState.GearShifter.park,
|
|
"D": car.CarState.GearShifter.drive,
|
|
"R": car.CarState.GearShifter.reverse,
|
|
"N": car.CarState.GearShifter.neutral,
|
|
}
|
|
|
|
frame = 0
|
|
try:
|
|
while True:
|
|
# Read bench params
|
|
speed_mph = float((params_mem.get("BenchSpeed", encoding="utf-8") or "0").strip())
|
|
speed_limit_mph = float((params_mem.get("BenchSpeedLimit", encoding="utf-8") or "0").strip())
|
|
cruise_mph = float((params_mem.get("BenchCruiseSpeed", encoding="utf-8") or "0").strip())
|
|
gear_str = (params_mem.get("BenchGear", encoding="utf-8") or "P").strip().upper()
|
|
engaged = (params_mem.get("BenchEngaged", encoding="utf-8") or "0").strip() == "1"
|
|
|
|
speed_ms = speed_mph * MS_PER_MPH
|
|
gear = gear_map.get(gear_str, car.CarState.GearShifter.park)
|
|
|
|
# deviceState — 2 Hz
|
|
if frame % 5 == 0:
|
|
dat = messaging.new_message("deviceState")
|
|
dat.deviceState.started = True
|
|
dat.deviceState.freeSpacePercent = 80
|
|
dat.deviceState.memoryUsagePercent = 30
|
|
dat.deviceState.cpuTempC = [40.0] * 3
|
|
dat.deviceState.gpuTempC = [40.0] * 3
|
|
dat.deviceState.cpuUsagePercent = [20] * 8
|
|
dat.deviceState.networkType = log.DeviceState.NetworkType.cell4G
|
|
pm.send("deviceState", dat)
|
|
|
|
# pandaStates — 10 Hz
|
|
if frame % 1 == 0:
|
|
dat = messaging.new_message("pandaStates", 1)
|
|
dat.pandaStates[0].ignitionLine = True
|
|
dat.pandaStates[0].pandaType = log.PandaState.PandaType.tres
|
|
pm.send("pandaStates", dat)
|
|
|
|
# carState — 10 Hz
|
|
dat = messaging.new_message("carState")
|
|
cs = dat.carState
|
|
cs.vEgo = speed_ms
|
|
cs.vEgoCluster = speed_ms
|
|
cs.gearShifter = gear
|
|
cs.standstill = speed_ms < 0.1
|
|
cs.cruiseState.available = True
|
|
cs.cruiseState.enabled = engaged
|
|
cs.cruiseState.speed = cruise_mph * MS_PER_MPH if cruise_mph > 0 else 0
|
|
pm.send("carState", dat)
|
|
|
|
# controlsState — 10 Hz
|
|
dat = messaging.new_message("controlsState")
|
|
ctl = dat.controlsState
|
|
ctl.vCruise = cruise_mph * 1.60934 if cruise_mph > 0 else 255 # km/h or 255=not set
|
|
ctl.vCruiseCluster = ctl.vCruise
|
|
ctl.enabled = engaged
|
|
ctl.active = engaged
|
|
pm.send("controlsState", dat)
|
|
|
|
# driverMonitoringState — low freq
|
|
if frame % 10 == 0:
|
|
dat = messaging.new_message("driverMonitoringState")
|
|
dat.driverMonitoringState.isActiveMode = True
|
|
pm.send("driverMonitoringState", dat)
|
|
|
|
# liveCalibration — low freq
|
|
if frame % 50 == 0:
|
|
dat = messaging.new_message("liveCalibration")
|
|
dat.liveCalibration.calStatus = log.LiveCalibrationData.Status.calibrated
|
|
dat.liveCalibration.rpyCalib = [0.0, 0.0, 0.0]
|
|
pm.send("liveCalibration", dat)
|
|
|
|
frame += 1
|
|
time.sleep(0.1) # 10 Hz base loop
|
|
|
|
except KeyboardInterrupt:
|
|
print("\nBench simulator stopped")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|