port C++ UI from broken: ready/splash, ClearPilot menu, onroad widgets, nightrider

Wholesale port of the 10 UI files (main.cc, ui.{cc,h}, onroad.{cc,h},
home.{cc,h}, window.{cc,h}, ready.{cc,h}, SConscript). sidebar.{cc,h}
unchanged.

Brings in:
- splash/ready screen rendered via Qt directly (replaces stock home)
- ready page shown when started but gear=park
- ClearPilot offroad menu (Home/Dashcam/Debug panels) replacing stock
- onroad UI: speed widget reading ClearpilotSpeedDisplay (gpsLocation
  via speed_logicd), speed-limit widget, cruise-vs-limit warning sign
- nightrider mode: camera suppressed, lane lines/path drawn as 2px
  outlines only (ScreenDisplayMode 1 or 4)
- screen power: ScreenDisplayMode 3 forces setAwake(false)
- ignition off blanks screen immediately (tap still wakes)
- Qt-based RPC widget-tree dump server at ipc:///tmp/clearpilot_ui_rpc
- crash handler in main.cc with stack trace

Deviation from broken (3 sites): no_lat_lane_change is read from
paramsMemory (controlsd writes it there in baseline) instead of broken's
custom cereal field frogpilotCarControl.noLatLaneChange. Keeps the
existing self-driving wiring intact.

SConscript drops screenrecorder.cc from qt_src (broken did the same;
omx_encoder.cc still built for dashcamd's future link).

Build clean. UI hasn't been launched yet — that comes after the
controlsd button-handler commit lands.

Translation .ts files are auto-regenerated by Qt's lupdate; included.
This commit is contained in:
2026-05-03 23:03:42 -05:00
parent 41c154014a
commit b5a0b3221c
23 changed files with 1302 additions and 292 deletions
+18 -4
View File
@@ -93,6 +93,9 @@ void update_model(UIState *s,
if (plan_position.getX().size() < model.getPosition().getX().size()) {
plan_position = model.getPosition();
}
// CLEARPILOT: guard against empty model data (bench mode, no modeld running)
if (plan_position.getX().size() == 0) return;
float max_distance = scene.unlimited_road_ui_length ? *(plan_position.getX().end() - 1) :
std::clamp(*(plan_position.getX().end() - 1),
MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE);
@@ -115,8 +118,11 @@ void update_model(UIState *s,
}
// update path
// CLEARPILOT: read from paramsMemory; controlsd writes "no_lat_lane_change"
// there. (Broken used a custom cereal field; we keep the param-based wiring.)
bool no_lat_lane_change = paramsMemory.getBool("no_lat_lane_change");
float path;
if (paramsMemory.getBool("no_lat_lane_change")) {
if (no_lat_lane_change) {
path = (float)LANE_CHANGE_NO_LAT_PATH_WIDTH / 20; // Release: better calc for EU users
} else {
path = (float)CENTER_LANE_WIDTH / 20; // Release: better calc for EU users
@@ -391,6 +397,7 @@ void ui_update_frogpilot_params(UIState *s) {
scene.screen_brightness = screen_management ? params.getInt("ScreenBrightness") : 101;
scene.screen_brightness_onroad = screen_management ? params.getInt("ScreenBrightnessOnroad") : 101;
scene.screen_recorder = screen_management && params.getBool("ScreenRecorder");
scene.screen_recorder_debug = params.getBool("ScreenRecorderDebug");
scene.screen_timeout = screen_management ? params.getInt("ScreenTimeout") : 120;
scene.screen_timeout_onroad = screen_management ? params.getInt("ScreenTimeoutOnroad") : 10;
scene.standby_mode = screen_management && params.getBool("StandbyMode");
@@ -435,9 +442,10 @@ void UIState::updateStatus() {
UIState::UIState(QObject *parent) : QObject(parent) {
sm = std::make_unique<SubMaster, const std::initializer_list<const char *>>({
"modelV2", "controlsState", "liveCalibration", "radarState", "deviceState",
"pandaStates", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "driverStateV2",
"pandaStates", "peripheralState", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "driverStateV2",
"wideRoadCameraState", "managerState", "uiPlan", "liveTorqueParameters",
"frogpilotCarControl", "frogpilotDeviceState", "frogpilotPlan",
"gpsLocation",
});
Params params;
@@ -551,7 +559,10 @@ void Device::updateWakefulness(const UIState &s) {
}
if (ignition_state_changed) {
if (ignition_on && s.scene.screen_brightness_onroad == 0 && !s.scene.standby_mode) {
if (!ignition_on) {
// CLEARPILOT: ignition on→off blanks the screen immediately (tap still wakes).
resetInteractiveTimeout(0, 0);
} else if (s.scene.screen_brightness_onroad == 0 && !s.scene.standby_mode) {
resetInteractiveTimeout(0, 0);
} else {
resetInteractiveTimeout(s.scene.screen_timeout, s.scene.screen_timeout_onroad);
@@ -560,7 +571,10 @@ void Device::updateWakefulness(const UIState &s) {
emit interactiveTimeout();
}
if (s.scene.screen_brightness_onroad != 0) {
// CLEARPILOT: ScreenDisplayMode 3 = screen off — override awake state
if (paramsMemory.getInt("ScreenDisplayMode") == 3) {
setAwake(false);
} else if (s.scene.screen_brightness_onroad != 0) {
setAwake(s.scene.ignition || interactive_timeout > 0);
} else {
setAwake(interactive_timeout > 0);