Skip to content

Chore/ndk27 buildtools34#5

Open
dj-death wants to merge 8 commits into
phr00t:masterfrom
dj-death:chore/ndk27-buildtools34
Open

Chore/ndk27 buildtools34#5
dj-death wants to merge 8 commits into
phr00t:masterfrom
dj-death:chore/ndk27-buildtools34

Conversation

@dj-death

Copy link
Copy Markdown

No description provided.

dj-death and others added 8 commits June 17, 2026 13:37
* Auto-detect camera intrinsics to support non-LG Android phones

flowpilot's camera intrinsics (focal length, principal point) and camera
selection were hardcoded for the LG G8, so the model received wrong
geometry on other phones and could even crash when the hardcoded
wide-camera index didn't exist.

- Derive intrinsics from the bound camera's hardware characteristics
  (physical sensor size + focal length in mm) for non-LG devices when no
  manual camerainfo override file is present. Reading characteristics from
  the actually-bound CameraX camera avoids any camera-id mapping guesswork.
- Guard camera selection against out-of-range indices and fall back to the
  default back camera, preventing crashes on phones with fewer cameras.
- Extract the shared intrinsics recompute into Camera.updateIntrinsics()
  so the file loader and auto-detection use the same logic.
- Surface the detected focal length in device settings for verification.

LG devices and any device with a manual camerainfo file keep their
existing known-good behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

* Make runtime-updated camera intrinsics volatile

updateIntrinsics() now runs on the camera/main thread after the model and
UI threads have started (during camera bind, for hardware auto-detection),
whereas previously the intrinsics were only written in onCreate before any
threads started. Without synchronization the reader threads could keep
observing the stale LG-default intrinsics, silently defeating the
auto-detection on non-LG phones.

Mark the mutable intrinsic fields volatile so the model (ModelExecutorF3)
and UI threads reliably observe updates. cam_intrinsics is written last in
updateIntrinsics(), so its volatile write publishes the preceding fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

---------

Co-authored-by: Claude <noreply@anthropic.com>
Add docs covering the runtime camera-intrinsics auto-detection, the
ultrawide and logical multi-camera limitations, and how to fall back to a
manual camerainfo override.


Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

Co-authored-by: Claude <noreply@anthropic.com>
…ller (#3)

Port the road-roll (bank angle) and steering-angle-offset compensation
from upstream openpilot's torque lateral controller. flowpilot's
LatControlTorque was passing roll=0.0 and ignoring params.angleOffsetDeg
when computing the measured curvature, and used the raw desired lateral
acceleration as feedforward.

The PID and INDI lateral controllers in this same tree already use
params.roll and params.angleOffsetDeg (latcontrol_pid.py, latcontrol_indi.py);
this brings the torque controller in line and improves steering on banked
roads and on cars with a steering-angle sensor offset.

- measured curvature now uses (steeringAngleDeg - angleOffsetDeg) and the
  estimated road roll, in both the steering-angle and llk branches
- feedforward is now gravity/roll-adjusted:
  desired_lateral_accel - roll * ACCELERATION_DUE_TO_GRAVITY

Safe no-op when roll is 0 (paramsd bounds/zeroes invalid roll) and the
angle offset is ~0, i.e. the current effective behavior.


Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

Co-authored-by: Claude <noreply@anthropic.com>
Document a portability map for porting upstream openpilot control-stack
improvements into flowpilot, based on an audit of selfdrive/controls/lib.

Captures what is portable (roll/angle-offset compensation in the torque
controller, already in its own PR), what is intentionally customized in
flowpilot and must not be reverted to upstream (gutted longcontrol state
machine, bespoke VCruiseHelper cruise logic), and what requires the
post-0.8.x model/planner/opendbc contract and is therefore a large
migration rather than a port. Also notes a latent divide-by-zero candidate
in the torque controller's non-steering-angle branch.


Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

Co-authored-by: Claude <noreply@anthropic.com>
Adds optional support for a Bluetooth ELM327 OBD-II adapter (e.g. "HH OBD
Advanced") as a DIAGNOSTIC-ONLY device. An ELM327 cannot replace a comma
device / panda for driving: it cannot read the control CAN buses at the
required rate and cannot transmit steering/gas/brake frames. So this mode is
strictly read-only and never enters the control path, and openpilot
engagement is hard-disabled while it is active, with a prominent UI warning.

- ELM327Manager (android): Bluetooth RFCOMM connection + ELM327 AT handshake
  + OBD-II PID polling (speed 010D, RPM 010C, coolant 0105, throttle 0111)
  and stored DTC read (mode 03 / 0101). Publishes read-only values to a shared
  OBDData holder; never touches sendcan.
- OBDData (common): thread-safe snapshot shared between the android writer and
  the UI reader (avoids a circular module dependency).
- OBDDiagnosticScreen (ui): live readouts + an unmissable warning that driving
  features are disabled in this mode. Reachable from Settings -> Device.
- SettingsScreen: "Use ELM327 OBD (Diagnostic Only)" toggle (param UseELM327)
  and an "OPEN" button for the diagnostics screen.
- controlsd.py: hard safety gate - UseELM327 forces read_only (noOutput safety
  model), so the car is never controlled in this mode.
- params.cc: register the UseELM327 key. Manifest: add Bluetooth permissions;
  AndroidLauncher requests BLUETOOTH_CONNECT and starts the manager when enabled.

Not buildable/testable in CI (no Android SDK); the Bluetooth transport and UI
need verification on a phone + adapter. Opened as draft.


Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

Co-authored-by: Claude <noreply@anthropic.com>
#6)

When only the ELM327 (diagnostic-only) device is present, openpilot cannot
control the car. This adds spoken audio notifications so the human driver
still gets openpilot's guidance instead of silent inaction.

- HardwareManager.announce(text): text-to-speech hook (no-op default).
- AndroidHardwareManager: implements announce() via Android TextToSpeech
  (lazy init, US locale).
- OnRoadScreen (advisory mode = UseELM327):
  * Speaks a debounced "Vehicle ahead, slow down" cue when the camera model
    is confident about a close lead (uses modelV2 leads, always available
    without a panda, plus the ELM327 speed). Conservative thresholds.
  * Speaks openpilot's own alert text (e.g. "Brake!", "Take Control") aloud
    when an audible alert fires, reusing the existing tuned alert vocabulary.

This never touches the control path; it is purely advisory audio gated to
ELM327 mode. Thresholds and which messages are live in ELM327-only mode
need on-road verification, so this is a draft.


Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

Co-authored-by: Claude <noreply@anthropic.com>
Follow-up to the ELM327 advisory audio feature: extend the spoken cues with
the lateral actions openpilot would take, derived from the camera model
(available without a panda).

- Lane departure: announces "Lane departure, drifting left/right" when a
  high-confidence ego lane line gets within LANE_DEPARTURE_DIST_M, active
  only above ~30 km/h (like a normal LDW).
- Curve ahead: announces "Curve ahead on the left/right" when the model's
  predicted heading change a couple seconds out exceeds CURVE_YAW_RAD.

runAdvisory() is split into runLeadAdvisory/runLaneDepartureAdvisory/
runCurveAdvisory, each debounced. Thresholds are conservative, named
constants for easy on-road tuning.

Note: a lane-CHANGE cue is intentionally not added - lane changes are driven
by the turn-signal/blinker state, which comes over CAN and is unavailable
with only an ELM327, so such a cue could never fire in this mode.

Still advisory-only; never touches the control path. Not buildable in CI;
thresholds need on-road tuning.


Claude-Session: https://claude.ai/code/session_01Dyfhmdw8DYmFkydZxddoNY

Co-authored-by: Claude <noreply@anthropic.com>
The pinned NDK 21.1.6352462 and AGP-default build-tools 30.x are not
available on modern SDK installs. Bump ndkVersion to 27.1.12297006 and
pin buildToolsVersion 34.0.0 so the debug APK builds against the
currently-shipping SDK toolchain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant