docs: update elevation docs and changelog for two-button recalculation and DEM fix

This commit is contained in:
Davide Scaini
2026-04-20 21:43:28 +02:00
parent ebac3f50f4
commit 88b24a6274
3 changed files with 94 additions and 48 deletions
+35 -24
View File
@@ -26,37 +26,48 @@ the last committed value. GPS noise is suppressed without losing real climbs.
suppression, barometric vs GPS threshold difference, real climb approximation,
unknown-treated-as-gps invariant
### New feature — DEM-based elevation recalculation from the edit drawer
### New feature — On-demand elevation recalculation from the edit drawer
A new **"Recalculate from terrain map (DEM)"** button in the activity edit
drawer replaces noisy GPS altitude with SRTM terrain data, then re-applies
hysteresis accumulation to compute corrected gain/loss.
Two new buttons in the activity edit drawer fix inaccurate elevation stats
without re-uploading the file:
This is the recommended fix for activities that still show inaccurate
elevation after the hysteresis improvement (e.g. activities recorded before
re-extracting from sources, or uploads where the source file had severe GPS
altitude noise).
**📐 Recalculate (hysteresis)** — re-applies source-aware hysteresis
accumulation to the original recorded elevation. Fast, offline, no network
required. Best for barometric altimeters (Karoo 2, Garmin with
`enhanced_altitude`, Wahoo) that were extracted before the noise-filtering
improvement.
How it works:
1. The server subsamples the activity's 1 Hz GPS track (one point every 10 s)
2. Queries an Open-Elevation-compatible API for terrain elevation
3. Linearly interpolates DEM elevation back to every GPS-valid second
4. Applies 5 m hysteresis to compute the corrected gain and loss
5. Writes the updated `elevation_m` array to the timeseries (chart updates)
6. Patches `elevation_gain_m` / `elevation_loss_m` in the activity JSON and
`index.json` summary
**⛰ Recalculate (DEM)** — replaces GPS altitude with SRTM terrain data, then
re-applies hysteresis. Best for GPS-only devices where the recorded altitude
is noisy.
- **`bincio/extract/dem.py`** (new) — `lookup_elevations()` (batched HTTP POST,
Open-Elevation wire format) + `recalculate_elevation()` (full pipeline above)
- **`POST /api/activity/{id}/recalculate-elevation`** — on both `bincio serve`
(auth-gated, triggers `merge_one` + rebuild) and `bincio edit` (no auth)
DEM pipeline (revised after discovering that a naive 5 m threshold produced
results worse than no correction on some activities):
1. Subsample GPS track to one point per 10 s
2. Query Open-Elevation API in batches of 512
3. Linearly interpolate back to the full 1 Hz series
4. Apply a **45 s sliding median filter** to suppress SRTM tile-boundary
steps (occur every ~7 s at cycling speed; were accumulating through 5 m
threshold and inflating gain by 50 %+)
5. Apply **10 m hysteresis** to the smoothed series
6. Back up original `elevation_m` as `elevation_m_original` in the timeseries
on the first DEM run (never overwrites an existing backup)
- **`bincio/extract/dem.py`** (new) — `lookup_elevations()`,
`recalculate_elevation()` (DEM + median + 10 m hysteresis),
`recalculate_elevation_hysteresis()` (offline, reads `elevation_m_original`
if available, uses 5 m/10 m source-aware threshold)
- **`POST /api/activity/{id}/recalculate-elevation/dem`** and
**`POST /api/activity/{id}/recalculate-elevation/hysteresis`** — on both
`bincio serve` (auth-gated, triggers `merge_one` + rebuild) and
`bincio edit` (no auth)
- **`bincio serve --dem-url URL`** / **`bincio edit --dem-url URL`** — override
the default DEM endpoint (also read from `DEM_URL` env var)
- Default DEM endpoint: **`https://api.open-elevation.com`** — works out of the
box with no configuration
- Default DEM endpoint: **`https://api.open-elevation.com`** — works out of
the box with no configuration
- **`GET /api/me`** response gains `dem_configured: bool`
- **`EditDrawer.svelte`** — button with spinner, shows `↑ Xm ↓ Ym` on success
or an inline error (e.g. if the DEM API is unreachable)
- **`EditDrawer.svelte`** — two side-by-side buttons with individual spinners,
shows `↑ Xm ↓ Ym` on success or inline error
---