Rueckblick misst auf Meter, Streckenwahl gemeinsam (2026.9.1.14)

Der erste Wurf (2026.9.1.12) verwarf jedes Importfenster mit distanz == 0. Zu
grob: seit der GNSS-Verfeinerung messen wir Meter, und eine Fahrt von 400
Metern steht im CAN-Wert als Null. Der Eigentuemer hat es auf den Punkt
gebracht - "0,0 moechte ich nicht, ab 0,1 schon".

Der Rueckblick liest jetzt ebenfalls den GNSS-Zaehler und entscheidet auf eine
Nachkommastelle.

Dabei stand die Toleranzlogik kurz doppelt im Code - in screening.py und in
historienimport.py. Genau die Doppelung, die dieses Projekt bei
UNPLAUSIBLE_KMH und MINDESTDAUER_S schon einmal teuer bezahlt hat. Sie liegt
jetzt gemeinsam in verlauf.py:

  strecke_waehlen(grob, fein) - die feine Zahl gilt, solange sie in der
  Rundungsunschaerfe des Ankers liegt, oder wenn es keinen Anker gibt.

  ist_gefahren(distanz) - ab 0,1 km ja. Eine unbekannte Strecke gilt als
  gefahren; nur die gemessene Null ist ein Nein.

VERIFIZIERT: 13 Faelle gegen beide Funktionen, darunter die zwei echten
Fahrten, die 400-Meter-Fahrt, die 100-Meter-Untergrenze, 40 Meter, fehlender
Anker, fehlender GNSS-Wert, gedrifteter Zaehler und beide Seiten der Grenze.
Import live: 1 Fenster uebersprungen, null 0-km-Fahrten im Bestand. Livepfad
live: vier alte Fahrten korrekt abgelehnt.

NICHT live gezeigt: ein Fenster mit 0,1-0,9 km, das der Import nun behaelt -
der Recorder enthaelt kein geschlossenes Fenster dieser Groesse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 18:47:51 +02:00
parent be95b40d79
commit 09c7461892
7 changed files with 136 additions and 26 deletions
@@ -283,6 +283,46 @@ def route_aus_verlauf(
GNSS_TOLERANZ_KM = 1.0
def strecke_waehlen(
grob: float | None, fein: float | None
) -> tuple[float | None, bool]:
"""Welche der beiden Streckenangaben gilt - und wurde die feine genommen?
`grob` ist die Differenz der Fahrzeug-Kilometerstände: der Anker. Er ist
der Tacho, er driftet nicht, und er ist die Zahl im Cockpit - aber er löst
nur ganze Kilometer auf. `fein` ist die Strecke aus dem GNSS-Zähler des
Geräts: metergenau, dafür anfällig für fehlenden Empfang und Drift.
Die feine gilt, solange sie innerhalb der Rundungsunschärfe des Ankers
liegt (GNSS_TOLERANZ_KM) - oder wenn es gar keinen Anker gibt, denn dann
ist irgendeine Messung besser als keine. Liegt sie darüber, hat der Anker
recht: dann fehlte Empfang oder der Zähler ist gedriftet.
Gemeinsam für Livepfad (screening.py) und Rückblick (historienimport.py) -
dieselbe Regel wie bei UNPLAUSIBLE_KMH und MINDESTDAUER_S: beide Wege
dürfen dieselbe Fahrt nie unterschiedlich bewerten."""
if fein is None:
return grob, False
if grob is None or abs(fein - grob) <= GNSS_TOLERANZ_KM:
return fein, True
return grob, False
def ist_gefahren(distanz: float | None) -> bool:
"""Hat sich das Fahrzeug bewegt?
Auf eine Nachkommastelle gerundet: ab 0,1 km ist es eine Fahrt, darunter
nicht (Ansage des Eigentümers, 01.09.2026). Unter 50 Metern zeigt die
Oberfläche ohnehin \"0,0 km\" an, und der Eintrag sähe aus wie die
Nullfahrten, die aus dem Bestand geräumt wurden.
Eine UNBEKANNTE Strecke gilt als gefahren: liegt weder Kilometerstand noch
GNSS-Zähler vor, wissen wir es nicht - und eine Fahrt zu verwerfen, die man
nicht gemessen hat, wäre schlechter als eine ohne Streckenangabe zu
behalten. Nur die gemessene Null ist ein Nein."""
return distanz is None or round(distanz, 1) != 0
def strecke_aus_zaehler(punkte: list[Verlaufspunkt]) -> float | None:
"""Gefahrene Strecke aus einem laufenden Kilometerzaehler des Geraets.