fwt_software/docs/known-issues.md

102 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Known Issues — Status
This tracks the reproduction blockers and robustness issues identified in the original code and what the
refactor did about them.
## Resolved
| # | Original issue | Resolution |
|---|----------------|------------|
| 1 | Hardcoded config path (`/home/ggs/...`) | Config search order: `--config``$FGC_CONFIG``./config.ini` → exe dir → XDG ([src/core/Paths.cpp](../src/core/Paths.cpp)) |
| 2 | Hardcoded image output path | `[Paths] output_dir` with `~`/`$ENV` expansion + sensible default |
| 3 | Startup scripts with `~/projects/...` | Replaced by path-independent [scripts/run.sh](../scripts/run.sh) + [systemd unit](../scripts/fire-gimbal-control.service) |
| 4 | Vimba X required to build | `WITH_VIMBA` CMake option (default ON); `OFF` builds a mock-only binary |
| 5 | No hardware path; exits if MQTT down | Mock implementations + runtime toggles; MQTT failure now logs and continues |
| 8 | Plaintext MQTT credentials | `$FGC_MQTT_USER`/`$FGC_MQTT_PW` env override; `config.ini` gitignored |
| 9 | MQTT busy-wait (`while(running);`) | Gone — Paho async client + `set_automatic_reconnect`; no spin thread |
| 10 | `parser()` missing return | Old parser removed; `parseTelemetryLine` returns `std::optional` cleanly |
| 11 | Fragile Boost.Spirit command grammar | Replaced by `parseCommand` whitespace tokenizer ([src/core/CommandParser.cpp](../src/core/CommandParser.cpp)) |
| 12 | Two divergent `config.ini` files | Single committed `config/config.example.ini`; real configs gitignored |
| 6 | Telemetry field order: humidity before temperature | **Obsolete** — migrated to the current firmware's `ST` protocol (encoder counts, no environmental fields); humidity/temp/fan are gone |
| 7 | Trigger fires while `is_moving == 1` (not when stopped) | **Fixed** by the protocol migration — capture is now move → **settle** → trigger; the camera fires only once both axes report standstill at the target ([CaptureScheduler.cpp](../src/core/CaptureScheduler.cpp)) |
Also added along the way: a leveled logger, typed/validated config, an SDK-independent core library, and a
doctest unit-test suite (`ctest`).
## Open / needs hardware confirmation
| # | Issue | Status |
|---|-------|--------|
| 13 | `[Motor]` degrees↔counts calibration | The `config.example.ini` values are **placeholders**. Calibrate `*_counts_per_deg` / `*_zero_count` against real `xenc` readings after homing on the rig. |
| 14 | Capture sweep untested on hardware | Homing was verified live (see below), but the `MOVE → settle → trigger` sweep was **not** run with `--start`. `kSettleTolCounts` (600) and the per-interval timing in [CaptureScheduler.cpp](../src/core/CaptureScheduler.cpp) still need tuning against observed `ST` behaviour, alongside #13. |
## Camera acquisition (USB3) — root cause + approach
Real-camera capture (Alvium 1800 U-2040c, Sony IMX541, 20.4 MP) was brought up on the LattePanda this
session. Two problems were root-caused (both **host/USB3-side**, reproduced in Allied Vision's own
`vmbpy` — the camera keeps acquiring while the host stops receiving; **no kernel errors**):
1. **Camera shipped in hardware-trigger mode** (`TriggerSource=Line0`) → produced no frames. Fixed by
configuring **software trigger** explicitly in-session in [VimbaCameraSource.cpp](../src/camera/VimbaCameraSource.cpp)
(relying on the camera's persisted user set alone did not work).
2. **Acquisition stall** — frame delivery stops after a few frames:
- **USB3 hardware LPM (U1/U2) was enabled** on the camera's link (the camera logs
`Enable of device-initiated U2 failed`) → silent bulk-transfer stalls under load. Disable per-port:
write `0` to `/sys/devices/.../usb2/2-0:1.0/usb2-port<N>/usb3_lpm_permit`, then re-enumerate
(the per-device `power/usb3_hardware_lpm_u*` files are read-only). **Make persistent** via a udev
rule matched on idVendor `1ab2`.
- **The host xHCI cannot reliably move large single frames.** Measured (LPM off, paced ~1 fps): RGB8
full-res **61 MB stalls in 35 frames**; **≤ ~20 MB frames sustain when *paced*** (BayerRG8 full-res
20 MB → 21 frames/20 s; 3.8 MB → 41/20 s). Freerun at max rate stalls even for medium frames.
- Also raise `usbcore.usbfs_memory_mb` to 1000 (persist via kernel cmdline; resets to 16 on reboot).
**Approach (config-driven, see `[Camera]` in [configuration.md](configuration.md)):** RGB8 + **2×2 binning**
(~5 MP, ~15 MB) keeps de-Bayering **and** white balance on-camera (the on-camera pipeline applies white
balance before de-Bayering); a **paced low-rate stream** keeps on-camera auto-exposure/gain/white-balance
converged to the changing outdoor light, and the scheduler saves one frame per waypoint. `DeviceLinkThroughputLimit`
is kept conservative (~250 MB/s; ≥450 caused incomplete frames). Full 20 MP is possible via BayerRG8
(20 MB) + a host de-Bayer step if reduced resolution proves insufficient.
**Status:** the `[Camera]` config schema, near-lossless JPEG XL, and unit tests are in place. Still to do
on the rig: wire the in-session imaging config + paced acquisition in `VimbaCameraSource`, add the udev/boot
persistence for LPM + usbfs, and verify a full sweep captures white-balanced frames with no stall.
## Verification caveats
- **Full build verified on the LattePanda**: a `WITH_VIMBA=ON WITH_MQTT=ON` build compiles and links on the
device (real Vimba X SDK + Paho fetched). The MQTT wrapper also builds on the dev box (GCC 16 / CMake 4 — see
`cmake/Paho.cmake` for the toolchain-compat shims).
- **Serial protocol verified live against real firmware** (LattePanda, this session): `ENABLE`/`HOME`/`SPEED`
reach the firmware, the `ST` telemetry parses with zero unparsed lines across a full session, and a live
`--init` drove a clean re-home of both axes to `READY`. **Still unverified on hardware:** the capture sweep
(#14) and real-camera (Vimba) frame capture — earlier tests used `--mock-camera`.
- **Makefile parity** is moot: the Makefile was removed in favour of CMake, and the full
`WITH_VIMBA=ON WITH_MQTT=ON` CMake build now runs on the device.
- **Demo mode** copies `bin/x64/Release/test_smoke.jxl`, resolved relative to the working directory. Run from a
directory where that path exists, or extend `ImagePipeline::Params::demo_image`.
## Possible follow-ups (not done)
- Graceful shutdown on SIGINT (currently exit via `exit`/Ctrl-D; a pending `getline` can delay shutdown).
- Make the camera index→label map fully config-driven. (JPEG XL distance/effort and the on-camera imaging
settings are now config-driven under `[Camera]` — see [configuration.md](configuration.md).)
- Reintroduce optional image upload to the ground station, config-driven (the old hardcoded NFS/SMB upload was
removed).
- **`gimbal calib` persistence**: the fitted `counts_per_deg`/`zero_count` are always applied to the live
session (display, manual moves, MQTT heading, **and** the capture scheduler) and written to
`logs/calib_*.log`. In the **TUI**, the activity strip then prompts `Save … as the new default? (y/n)`
`y` writes the full per-axis `[Motor]` map (`*_counts_per_deg`, `*_zero_count`,
`*_min_deg`/`*_max_deg`) into `config.ini` (persists across restarts), `n` keeps them
session-only. In the **headless** console there is no prompt, so calibration stays session-only there;
copy the logged values into `[Motor]` by hand to keep them.
- **`gimbal nudge`** moves a fixed fraction of the **homed** endstop-to-endstop travel (from the
firmware dump), so it is independent of the degrees↔counts calibration. If no dump has been captured
yet (not homed / no `gimbal dump`), nudge requests one and does nothing that press — it never falls
back to the configured degree clamps (which, if `*_min_deg`/`*_max_deg` were unset, produced absurd
±100000° steps).
- Ambient temperature/humidity (SHT41, `IEnvSensor`/`Sht41EnvSensor`/`MockEnvSensor`) is
integrated in software — config-gated (`[Features] enable_env`/`mock_env`, `[Env]`), Sensors
panel + MQTT `Env` topic wired — but defaults to `mock_env = true` in the checked-in example
config. Bus/address bring-up and validation against the physical sensor on the LattePanda's I2C
bus is still pending; flip `mock_env = false` on the deployed `config.ini` once confirmed.