8.7 KiB
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) |
| 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 + systemd unit |
| 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) |
| 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) |
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 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):
- Camera shipped in hardware-trigger mode (
TriggerSource=Line0) → produced no frames. Fixed by configuring software trigger explicitly in-session in VimbaCameraSource.cpp (relying on the camera's persisted user set alone did not work). - 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: write0to/sys/devices/.../usb2/2-0:1.0/usb2-port<N>/usb3_lpm_permit, then re-enumerate (the per-devicepower/usb3_hardware_lpm_u*files are read-only). Make persistent via a udev rule matched on idVendor1ab2. - The host xHCI cannot reliably move large single frames. Measured (LPM off, paced ~1 fps): RGB8 full-res 61 MB stalls in 3–5 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_mbto 1000 (persist via kernel cmdline; resets to 16 on reboot).
- USB3 hardware LPM (U1/U2) was enabled on the camera's link (the camera logs
Approach (config-driven, see [Camera] in 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=ONbuild 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 — seecmake/Paho.cmakefor the toolchain-compat shims). - Serial protocol verified live against real firmware (LattePanda, this session):
ENABLE/HOME/SPEEDreach the firmware, theSTtelemetry parses with zero unparsed lines across a full session, and a live--initdrove a clean re-home of both axes toREADY. 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=ONCMake 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 extendImagePipeline::Params::demo_image.
Possible follow-ups (not done)
- Graceful shutdown on SIGINT (currently exit via
exit/Ctrl-D; a pendinggetlinecan 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.) - Reintroduce optional image upload to the ground station, config-driven (the old hardcoded NFS/SMB upload was removed).
gimbal calibpersistence: the fittedcounts_per_deg/zero_countare always applied to the live session (display, manual moves, MQTT heading, and the capture scheduler) and written tologs/calib_*.log. In the TUI, the activity strip then promptsSave … as the new default? (y/n)—ywrites the full per-axis[Motor]map (*_counts_per_deg,*_zero_count,*_min_deg/*_max_deg) intoconfig.ini(persists across restarts),nkeeps 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 nudgemoves 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 / nogimbal dump), nudge requests one and does nothing that press — it never falls back to the configured degree clamps (which, if*_min_deg/*_max_degwere unset, produced absurd ±100000° steps).- Ambient temperature/humidity (SHT41,
IEnvSensor/Sht41EnvSensor/MockEnvSensor) is fully integrated and validated against the physical sensor on the LattePanda — config-gated ([Features] enable_env,[Env]), Sensors panel + expandediview + MQTTEnvtopic wired. It is off by default (enable_env = false), so a config without an[Env]section shows the panel aspending— that status means "no driver constructed", not "sensor unreachable"; an enabled-but-silent sensor readsno fixinstead. Dev machines without the hardware should use--mock-env(impliesenable_env) rather than editing config. [Env] i2c_addrused to be parsed with a decimal-onlystd::stoi, so the0x44form every datasheet andi2cdetectuses silently became address0x00and the sensor never answered. It now accepts decimal or0xhex (getIntAutoBaseinConfig.cpp, covered by a test). Other integer config keys stay decimal-only on purpose, so a leading zero never turns into octal.