Compteur à 0 si la trace ne bouge pas

This commit is contained in:
Alex 2026-09-24 23:41:24 +02:00
parent f08c599113
commit 8e62e2b440
2 changed files with 34 additions and 1 deletions

View File

@ -22,7 +22,7 @@
## Fonctionnalités
- Lecture GPX 1.0 / 1.1 (points `trkpt` horodatés).
- Vitesse issue de l'extension `gpxtpx:speed` (m/s, ex. GeoRide) si présente, sinon calculée à partir des distances et des temps ; lissage léger.
- Vitesse issue de l'extension `gpxtpx:speed` (m/s, ex. GeoRide) si présente, sinon calculée à partir des distances et des temps ; lissage léger. Aux arrêts (trace immobile, moins de 3 km/h en moyenne entre deux points), le compteur retombe à 0, même si le GPS n'a enregistré aucun point pendant la pause.
- Vidéo accélérée à durée fixe (60 s par défaut) : le trajet complet est parcouru du début à la fin.
- Compteur analogique 0-200 km/h (paramétrable), aiguille et vitesse numérique, placé automatiquement dans le coin le moins encombré par la trace ; l'aiguille part de 0 et y revient sur la première et la dernière seconde.
- Villes traversées obtenues par géocodage inverse [Nominatim](https://nominatim.org/) (OpenStreetMap), affichées sur la carte dès le début, avec placement des étiquettes qui évite chevauchements et trace.

View File

@ -43,6 +43,8 @@ CLES_VILLE = ("city", "town", "village", "municipality", "hamlet")
LARGEUR_ZOOM = TAILLE // 2 # largeur du nom de ville zoomé
HAUTEUR_ZOOM_MAX = TAILLE // 4 # limite pour les noms très courts
FONDU_ZOOM = 0.3 # durée des fondus d'apparition/disparition (s de vidéo)
SEUIL_ARRET_KMH = 3 # sous cette vitesse moyenne, un segment est un arrêt
TRANSITION_ARRET = 1.0 # durée (s de trajet) du retour de l'aiguille à 0
BLANC = (255, 255, 255)
GRIS = (170, 170, 170)
@ -115,6 +117,36 @@ def calculer_vitesses(lat, lon, t, v_gpx):
return np.clip(lisse, 0, None)
def annuler_arrets(lat, lon, t, v):
"""Met la vitesse à 0 pendant les arrêts (trace immobile).
Un segment est immobile si sa vitesse moyenne (distance/durée) est sous
SEUIL_ARRET_KMH. Le GPS enregistre souvent peu ou pas de points à
l'arrêt : sans correction, l'aiguille resterait figée sur la vitesse des
points encadrant la pause. Des points à vitesse nulle sont donc insérés
au début et à la fin de chaque segment immobile long.
"""
d = distances_haversine(lat, lon)
dt = np.diff(t)
immobile = d < SEUIL_ARRET_KMH / 3.6 * dt
v = v.copy()
# Point entouré de segments immobiles (ou en bout de trace) : à l'arrêt.
avant = np.concatenate([[True], immobile])
apres = np.concatenate([immobile, [True]])
v[avant & apres] = 0.0
longs = np.flatnonzero(immobile & (dt > 2 * TRANSITION_ARRET))
if len(longs) == 0:
return lat, lon, t, v
t_ajout = np.concatenate([t[longs] + TRANSITION_ARRET, t[longs + 1] - TRANSITION_ARRET])
t2 = np.concatenate([t, t_ajout])
lat2 = np.concatenate([lat, np.interp(t_ajout, t, lat)])
lon2 = np.concatenate([lon, np.interp(t_ajout, t, lon)])
v2 = np.concatenate([v, np.zeros(len(t_ajout))])
ordre = np.argsort(t2, kind="stable")
return lat2[ordre], lon2[ordre], t2[ordre], v2[ordre]
# --------------------------------------------------------------------------
# Villes (Nominatim)
# --------------------------------------------------------------------------
@ -373,6 +405,7 @@ def extraire_morceau(lat, lon, t, vitesse, t0, t1):
def generer_video(args):
lat, lon, t, v_gpx = charger_gpx(args.gpx)
vitesse = calculer_vitesses(lat, lon, t, v_gpx)
lat, lon, t, vitesse = annuler_arrets(lat, lon, t, vitesse)
print(f"{len(lat)} points, durée {t[-1] / 60:.1f} min, vitesse max {vitesse.max():.0f} km/h")
villes = [] if args.sans_villes else trouver_villes(args.gpx, lat, lon)