hbox-docs/docs/historia/wialon-viajes-hallazgos.md

58 lines
8.4 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.

# HBOX RTK vs CalAmp on RTG ZPMC-20 — Wialon trip discrepancy: root cause, framework, fixes (2026-10-06)
**Context.** ICAVE compares Wialon trips from two devices on the same RTG crane (ZPMC-20): HBOX **H0013** (EinarBoard V5.5, fw 0.6.0, Wialon unit `RT-ZPM-20 (RTK)`) and the legacy CalAmp (`RT-ZPMC-20`). They derive fuel consumption from trips and asked why the two disagree. Data from Jacobo (Drive folder, 5 and 6 Oct 2026): Wialon NMEA message exports of both units, Wialon *Trips* .xlsx of both, and H0013's raw `historial` from htracker. Everything is now in `Drogheda/06-Testing-Validation/wialon-trips/` (raw data per day + `informe_viajes_2026-10-0{5,6}.html` + `analisis_*.json`).
## Bottom line
The complaint as phrased ("more trips from the RTK → more fuel") is the **opposite** of what the data shows. The CalAmp over-reports trips and mileage by **8–18×** because it reports movement while the crane is parked; the HBOX is clean but Wialon's trip-distance threshold discards most real RTG manoeuvres.
| | CalAmp (RT-ZPMC-20) | HBOX H0013 (RTK) | Real crane motion (from the 1 Hz RTK track) |
|---|---|---|---|
| 5-Oct 15:00–17:00 | 1 trip · 1 h 47 min · **3.30 km** | 1 trip · 6 min · 0.19 km | **0.41 km in 8 min** — 6 manoeuvres (12–166 m, 2–5 km/h) |
| 6-Oct 08:00–10:46 | 2 trips · 2 h 40 min · **6.17 km** | 1 trip · 2 min · 0.17 km | **0.35 km in 6 min** — 8 manoeuvres (11–170 m, 2–6 km/h) |
### Evidence
1. **Same Wialon trip-detector settings on both units.** A Wialon-equivalent detector (by GPS speed ≥ 1 km/h, parking ≥ 300 s, min trip distance ≈ 150 m, speed floored to integer km/h as Wialon stores it) reproduces **all four** Wialon Trips reports: RTK boundaries within ±3–5 s, CalAmp within 0–30 s (one 30-s sample). Parameter sweep over 525 combinations: only this family fits all four. So the difference is in the data, not the configuration.
2. **CalAmp false motion.** Per 30-s CalAmp sample, with the RTK as ground truth (0.2 m resolution; H0013 historial matches the Wialon export to 0.07 m, zero lag; Wialon speed = floor(km/h)):
- while the crane is stationary, CalAmp reports 1–5 km/h **33.5 % (5-Oct) / 43.8 % (6-Oct)** of samples;
- its position jumps 6.5 / 10.4 m median (p90 15 / 26 m, max 34 / 140 m) between consecutive messages while parked → **1.67 km / 3.64 km phantom mileage** per window;
- it detects real motion only 70 % / 47 % of the time;
- stationary drift it integrates: 785 / 1152 m/h. Because it rarely strings 300 s of zero speed, Wialon never closes the trip → one all-afternoon trip.
- Wialon's printed CalAmp mileage (3.30 / 5.81 km) is even higher than the path sum of its own exported positions (1.94 / 3.81 km) — Wialon's counter for that unit likely uses the CalAmp odometer parameter; either way it is noise.
3. **HBOX under-reporting is a Wialon threshold, not a device problem.** 93–97 % of samples at 0 km/h, stationary scatter p50 1.9 m / p95 4.9 m (DGPS fix quality 2, 12 sats, HDOP 0.5 — note: *not* RTK fixed/float; corrections issue is separate, see earlier notes). Real RTG moves last 20–120 s and cover 10–170 m; with min distance ≈ 150 m Wialon kept 1 of 6 (5-Oct) and 1 of 8 (6-Oct). The one it kept (15:16–15:22, 166 m) only crossed 150 m thanks to rest-jitter mileage during a 3.8-min pause inside the trip.
4. **HBOX stationary drift** at 1 Hz integrates ~0.33 km/h of path (does not affect Wialon trips, which ignore 0 km/h, but dirties tracks/counters) — fixed by the retranslator motion filter below.
### The map says it in one glance
RTK track = clean line along the container block; CalAmp track = scribble around a parked crane (see the reports).
## What was built — `htracker/trips/` (committed to the repo folder on Leo's Mac, not yet pushed)
Pure-stdlib Python package (openpyxl optional) + 40-line hook in `retranslator.py` + 26-line hook in `web_monitor.py`. Full details, env vars and deploy steps: `04-Source-Code/htracker/CHANGES-2026-10-06-viajes.md`.
- `nmea.py` readers: Wialon NMEA export, htracker `historial_unidades` ring files (unsorted → sorted/deduped), raw NMEA, `.gz`, Wialon Trips `.xlsx` (openpyxl must *not* be in read_only mode — Wialon's xlsx has a bad dimension).
- `detector.py`: `TripParams` + `detect_trips()` (Wialon-equivalent; defaults 1 km/h · 300 s · 150 m); `MotionFilter` (REPOSO/MOVIMIENTO hysteresis: ≥1 km/h × 2 samples or > 8 m from anchor → moving; < 1 km/h × 10 s → rest; at rest forward speed 0 and the anchor position). Hold radius 8 m because a parked F9P in DGPS wanders up to ~5 m over 20 min; 3 m caused 114 spurious transitions.
- `compare.py`: fine-vs-coarse alignment, confusion matrix, phantom mileage, true mileage, trip matching, chart series; `analyze()` builds the whole JSON.
- `report.py`: self-contained HTML (Chart.js + Leaflet CDN, monitor dark theme) — verdict cards, speed timeline with Wialon trips as bands, cumulative km (device path vs real vs Wialon-printed), map, noise histogram, Wialon-vs-recalculated tables, real-manoeuvre list, filter simulation, method. Also the `/trips` monitor page (same renderer, API-fed).
- `store.py`: `trips_positions.db` (SQLite WAL) fed by the retranslator at 1 Hz while moving, 1/10 s at rest (10 s, not 30: at 30 s the rest-jitter mileage disappears and the marginal 166-m Wialon trip would be lost; at 10 s all four Wialon reports still reproduce). ≈ 0.7 MB/unit/day, retention 14 d (~300 MB for 30 units). Writer thread, UDP loop never blocks.
- `gateway.py`: `TripsGateway.process()` hook (store raw fix; if the filter is enabled for the unit, send Wialon a copy with speed 0.00 and the held position). Never raises. Env: `GW_TRIPS_STORE_ENABLED=1` (default on), `GW_MOTION_FILTER_ENABLED=0` (default off), `GW_MOTION_FILTER_UNITS=H0013` for a staged rollout.
- `monitor_routes.py`: `GET /trips`, `GET /api/trips_1hz/units`, `POST /api/trips_1hz` (unit, window, params, optional reference NMEA file + Wialon .xlsx uploads, raw vs sent data). Same auth/unit gates as `/api/track`. Nav links added on dashboard and reports.
- Tests: 22 (`unittest`, real data fixtures 116 KB gzip): Wialon-report reproduction, readers, filter behaviour, store downsampling, gateway, FastAPI routes (skip without fastapi/openpyxl). Green here and on Leo's Mac (3.14; 7 skipped there for missing openpyxl/fastapi). End-to-end with a fake Wialon listener verified `#SD#` packets carry speed 0.00 + held position at rest and pass through unchanged when moving.
- CLI: `python3 -m trips.cli --device … --reference … --wialon-trips-device … --out informe.html --json …`.
Existing `/api/trips` (5-minute `gps_positions.db`) cannot see 20–120 s crane moves; it stays as is.
## Recommendations (in order)
1. **Wialon config for HBOX units:** min speed 1 km/h, parking 120–300 s, **min trip distance 10 m**, min time 0. Turns 1 → 6 and 1 → 8 trips (0.50 / 0.48 km ≈ real). Do *not* apply to the CalAmp (would explode its false trips).
2. **Enable the motion filter on H0013 only** (`GW_MOTION_FILTER_ENABLED=1`, `GW_MOTION_FILTER_UNITS=H0013`), validate 2–3 days with `/trips` ("raw" vs "sent"), then fleet-wide. It cleans tracks/counters; it does not change trip counts under the current 150 m threshold.
3. **Fuel = engine hours, not trip km** for an RTG. Forward ignition (`$PHEV IGN_ON/OFF`, fw 0.5.1+; PA5) as a Wialon IPS `#D#` param `ign` and use "ignition sensor" engine hours (and optionally ignition-based trips). Proposed, not implemented — needs a one-unit bench check that Wialon accepts the `D` packet with params from the current unit type.
4. Do not "match" the HBOX to the CalAmp.
Customer-facing note (es-MX, Leo's voice): `00-Project-Management/client-comms/2026-10-06_Drogheda_Viajes-Wialon-RTK-vs-CalAmp_Nota-ICAVE_v1.0.md`.
## Open points / caveats
- Wialon's detector parameters are inferred from the reports (they fit exactly), not read from the account — confirm in Wialon → unit → Trip detector before changing them.
- H0013 fix quality is 2 (DGPS), never 4/5; the RTK-corrections thread is unchanged by this work.
- The Wialon-printed CalAmp mileage source (odometer param vs GPS) is unverified; irrelevant to the conclusion.
- The `historial` ring covers only ~1 h and is unordered; the new store is the proper source for `/trips`.
- Git: Leo runs `git add trips/ retranslator.py web_monitor.py .gitignore CHANGES-2026-10-06-viajes.md README.md`, commit, `./push-deploy.sh`; then check `journalctl -u htracker` for "TripsStore iniciado".