docs: update CLAUDE.md for display modes, dashcam trips, ClearPilot menu

Document 5-state display mode system with auto day/night switching,
nightrider rendering, and button behavior. Update dashcam section for
trip directories, 2500kbps bitrate, SRT subtitles, graceful shutdown.
Update offroad UI section for new ClearPilot menu panels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 06:52:42 +00:00
parent 5b91dac33e
commit bb561ded75

115
CLAUDE.md
View File

@@ -228,12 +228,14 @@ A single `session.log` in each session directory records major events:
- **Codec**: H.264 AVC (hardware accelerated via `OMX.qcom.video.encoder.avc`) - **Codec**: H.264 AVC (hardware accelerated via `OMX.qcom.video.encoder.avc`)
- **Resolution**: 1928x1208 (full camera resolution, no downscaling) - **Resolution**: 1928x1208 (full camera resolution, no downscaling)
- **Bitrate**: 4 Mbps - **Bitrate**: 2500 kbps
- **Container**: MP4 (remuxed via libavformat) - **Container**: MP4 (remuxed via libavformat) + SRT subtitle sidecar
- **Segment length**: 3 minutes per file - **Segment length**: 3 minutes per file
- **Save path**: `/data/media/0/videos/YYYYMMDD-HHMMSS.mp4` - **Save path**: `/data/media/0/videos/YYYYMMDD-HHMMSS/YYYYMMDD-HHMMSS.mp4` (trip directories)
- **Standstill timeout**: suspends recording after 10 minutes of standstill, resumes when car moves - **GPS subtitles**: companion `.srt` file per segment with 1Hz entries (speed MPH, lat/lon, UTC timestamp)
- **Storage**: ~90 MB per 3-minute segment, ~43 hours of footage in 78 GB free space - **Trip lifecycle**: starts recording on launch with 10-min idle timer; car in drive cancels timer; park/off restarts timer; ignition cycle = new trip
- **Graceful shutdown**: thermald sets `DashcamShutdown` param, dashcamd closes segment and acks within 15s
- **Storage**: ~56 MB per 3-minute segment at 2500 kbps
- **Storage device**: WDC SDINDDH4-128G UFS 2.1 — automotive grade, ~384 TB write endurance, no concern for continuous writes - **Storage device**: WDC SDINDDH4-128G UFS 2.1 — automotive grade, ~384 TB write endurance, no concern for continuous writes
### Key Differences from Old Screen Recorder ### Key Differences from Old Screen Recorder
@@ -254,13 +256,13 @@ A single `session.log` in each session directory records major events:
| `selfdrive/clearpilot/SConscript` | Build config for dashcamd | | `selfdrive/clearpilot/SConscript` | Build config for dashcamd |
| `selfdrive/frogpilot/screenrecorder/omx_encoder.cc` | OMX encoder (added `encode_frame_nv12` method) | | `selfdrive/frogpilot/screenrecorder/omx_encoder.cc` | OMX encoder (added `encode_frame_nv12` method) |
| `selfdrive/frogpilot/screenrecorder/omx_encoder.h` | Encoder header | | `selfdrive/frogpilot/screenrecorder/omx_encoder.h` | Encoder header |
| `selfdrive/manager/process_config.py` | dashcamd registered as NativeProcess, encoderd disabled | | `selfdrive/manager/process_config.py` | dashcamd registered as NativeProcess, camerad always_run, encoderd disabled |
| `system/loggerd/deleter.py` | Storage rotation (9 GB threshold, oldest videos deleted first) | | `system/loggerd/deleter.py` | Trip-aware storage rotation (oldest trip first, then segments within active trip) |
### Params ### Params
- `DashcamDebug` — when `"1"`, dashcamd runs even without car connected (for bench testing) - `DashcamDebug` — when `"1"`, dashcamd runs even without car connected (for bench testing)
- `IsDriverViewEnabled` — must be `"1"` to start camerad on bench (no car ignition) - `DashcamShutdown` — set by thermald before power-off, dashcamd acks by clearing it
## Standstill Power Saving ## Standstill Power Saving
@@ -279,63 +281,88 @@ When `carState.standstill` is true:
| `selfdrive/thermald/fan_controller.py` | Standstill-aware fan clamps | | `selfdrive/thermald/fan_controller.py` | Standstill-aware fan clamps |
| `selfdrive/thermald/thermald.py` | Passes standstill to fan controller via carState | | `selfdrive/thermald/thermald.py` | Passes standstill to fan controller via carState |
## Debug Function Button (LFA/LKAS Steering Wheel Button) ## Display Modes (LFA/LKAS Debug Button)
The Hyundai Tucson's LFA (Lane Following Assist) steering wheel button is repurposed as a general-purpose UI control button. It has no driving function in ClearPilot since lateral control is disabled. The Hyundai Tucson's LFA steering wheel button cycles through 5 display modes via `ScreenDisplayMode` param (`/dev/shm/params`, CLEAR_ON_MANAGER_START, default 0).
### Display States
| State | Name | Display | Camera | Path Drawing |
|-------|------|---------|--------|-------------|
| 0 | auto-normal | on | yes | filled (normal) |
| 1 | auto-nightrider | on | black | 2px outline only |
| 2 | normal (manual) | on | yes | filled (normal) |
| 3 | screen off | GPIO off | n/a | n/a |
| 4 | nightrider (manual) | on | black | 2px outline only |
### Auto Day/Night Switching
- `gpsd.py` computes `is_daylight(lat, lon, utc_dt)` using NOAA solar position algorithm
- First calculation immediately on GPS fix + valid clock, then every 30 seconds
- State 0 + sunset → auto-switch to 1; State 1 + sunrise → auto-switch to 0
- States 2/3/4 are never touched by auto logic
- `IsDaylight` param written to `/dev/shm/params` for reference
### Button Behavior
**Onroad (car in drive gear):** 0→4, 1→2, 2→3, 3→4, 4→2 (never back to auto via button)
**Not in drive (parked/off):** any except 3 → 3 (screen off), state 3 → 0 (auto-normal)
### Nightrider Mode
- Camera feed suppressed (OpenGL clears to black instead of rendering camera texture)
- All HUD elements (speed, alerts, telemetry indicator) still visible
- Path/lane polygons drawn as 2px outlines only (no gradient fill)
- Lane lines, road edges, blind spot paths, adjacent paths all use outline rendering
### Signal Chain ### Signal Chain
``` ```
Steering wheel LFA button press Steering wheel LFA button press
-> CAN-FD message: cruise_btns_msg_canfd["LFA_BTN"] -> CAN-FD: cruise_btns_msg_canfd["LFA_BTN"]
[selfdrive/car/hyundai/carstate.py:332-339] -> Edge detection → ButtonEvent(type=FrogPilotButtonType.lkas)
-> Edge detection: lkas_enabled vs lkas_previously_enabled -> controlsd.clearpilot_state_control()
-> create_button_events() -> ButtonEvent(type=FrogPilotButtonType.lkas) -> Reads ScreenDisplayMode, applies transition table based on driving_gear
[selfdrive/car/hyundai/interface.py:168] -> Writes new ScreenDisplayMode to /dev/shm/params
-> controlsd.update_clearpilot_events(CS) -> UI reads ScreenDisplayMode in paintEvent() (for camera/nightrider)
[selfdrive/controls/controlsd.py:1235-1239] and drawHud() (for display power on/off)
-> events.add(EventName.clpDebug)
-> controlsd.clearpilot_state_control(CC, CS)
[selfdrive/controls/controlsd.py:1241-1258]
-> Toggles ScreenDisaplayMode param (0=on, 1=off) in /dev/shm/params
-> UI reads ScreenDisaplayMode in drawHud()
[selfdrive/ui/qt/onroad.cc:390-403]
-> mode=1 and no alert: Hardware::set_display_power(false)
-> mode=0 or alert visible: Hardware::set_display_power(true)
``` ```
### Current Behavior
- Each press toggles the display on/off instantly (debug alert suppressed)
- `ScreenDisaplayMode` is in-memory params (`/dev/shm/params`), resets on reboot
- `max_display_mode = 1` — currently only two states (on/off); can be extended for future modes
### Key Files ### Key Files
| File | Role | | File | Role |
|------|------| |------|------|
| `selfdrive/car/hyundai/carstate.py` | Reads LFA_BTN from CAN-FD | | `selfdrive/controls/controlsd.py` | Button state machine, writes ScreenDisplayMode |
| `selfdrive/car/hyundai/interface.py` | Creates ButtonEvent with FrogPilotButtonType.lkas | | `selfdrive/ui/qt/onroad.cc` | Nightrider rendering, display power control |
| `selfdrive/controls/controlsd.py` | Fires clpDebug event, toggles ScreenDisaplayMode | | `selfdrive/ui/qt/home.cc` | Display power for park/splash state |
| `selfdrive/controls/lib/events.py` | clpDebug event definition (alert suppressed) | | `system/clearpilot/gpsd.py` | Sunset/sunrise calc, auto day/night transitions |
| `selfdrive/ui/qt/onroad.cc` | Reads ScreenDisaplayMode, controls display power | | `selfdrive/clearpilot/bench_cmd.py` | `debugbutton` command simulates button press |
## Screen Timeout / Display Power ## Screen Timeout / Display Power
Display power is managed by `Device::updateWakefulness()` in `selfdrive/ui/ui.cc`. Display power is managed by `Device::updateWakefulness()` in `selfdrive/ui/ui.cc`.
- **Ignition off (offroad)**: screen blanks after `ScreenTimeout` seconds (default 120) of no touch. Tapping wakes it. - **Ignition off (offroad)**: screen blanks after `ScreenTimeout` seconds (default 120) of no touch. Tapping wakes it.
- **Ignition on (onroad)**: screen stays on unconditionally — `setAwake(s.scene.ignition || interactive_timeout > 0)` means ignition=true always keeps the screen awake. The FrogPilot `ScreenTimeoutOnroad` param (default 10s) has no effect because ignition being true short-circuits the timeout check. - **Ignition on (onroad)**: screen stays on unconditionally — ignition=true short-circuits the timeout check.
- **Debug button (LFA)**: the only way to turn off the screen while driving. Toggles `ScreenDisaplayMode` param which is checked in `drawHud()` (onroad) and `updateState()` (park splash). Independent of the timeout system. - **Debug button (LFA)**: cycles through display modes including screen off (state 3). Only state 3 calls `Hardware::set_display_power(false)`.
## Offroad UI ## Offroad UI (ClearPilot Menu)
The offroad home screen (`selfdrive/ui/qt/home.cc`) was replaced with a clean grid launcher. Stock FrogPilot widgets (date, version, update/alert notifications) were removed. The offroad home screen (`selfdrive/ui/qt/home.cc`) is a sidebar settings panel replacing the stock home screen. The original system settings are no longer accessible — the ClearPilot menu is the only settings interface.
- **Settings button**: opens the original comma/FrogPilot settings (backdoor to all original settings) ### Panels
- **Dashcam button**: placeholder for future dashcam footage viewer
- Tapping the splash screen (ReadyWindow) goes directly to the grid launcher (no sidebar) - **General**: Status window, Reset Calibration, Shutdown Timer, Reboot/Soft Reboot/Power Off
- Sidebar with metrics (TEMP, VEHICLE, CONNECT) is hidden but still accessible via settings path - **Network**: WiFi management, tethering, roaming, hidden networks (APN settings removed)
- **Dashcam**: placeholder for future dashcam footage viewer
- **Debug**: Telemetry logging toggle
### Navigation
- Tapping the splash screen (ReadyWindow) opens the ClearPilot menu
- "← Back" button returns to splash or onroad view
- Sidebar with stock metrics (TEMP, VEHICLE, CONNECT) is hidden
## Device: comma 3x ## Device: comma 3x