Züge folgen dem Gleis statt gerader Linien, Mindesthaltezeit 40 s, osmium renumber

- Server schickt pro Zug die Gleispunkte der nächsten 12 s mit Zeitstempel
  (gerade Stücke auf ~3 m vereinfacht); Browser fährt sie ab, Richtung aus
  dem aktuellen Gleisstück
- Halte mit Ankunft = Abfahrt werden für die Animation auf 40 s verlängert
- OSM-IDs durchnummerieren: osmium extract braucht sonst ~4 GB RAM

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X48pE4bzjHej8w9HyZXCjb
This commit is contained in:
Claude
2026-10-22 07:29:00 +02:00
parent d339da5da2
commit 7ece7603a9
5 changed files with 118 additions and 34 deletions
+16 -15
View File
@@ -19,7 +19,7 @@ from . import border, realtime
from .feed import TZ, Feed
log = logging.getLogger("trainpulse")
STEP, STEPS = 2, 5 # Positionen alle 2 s für die nächsten 10 s, damit der Browser Kurven nachfährt
STEP, STEPS = 2, 6 # Gleisverlauf für die nächsten 12 s (Abruf alle 5 s, Berechnung alle 3 s -> Reserve)
WEB = Path(__file__).resolve().parent.parent / "web"
@@ -121,23 +121,24 @@ def positions(src: Source, t: float) -> list:
def compute_positions():
now = time.time()
feats, future = [], [{} for _ in range(STEPS)]
feats = []
for src in list(S.sources.values()):
if not src.feed:
continue
feats += positions(src, now)
for k in range(STEPS):
future[k].update({f"{src.name}/{f['properties']['id']}": f["geometry"]["coordinates"] + [f["properties"]["heading"]]
for f in src.feed.vehicles(now + STEP * (k + 1), src.rt)})
for f in feats:
path = []
for pos in future:
p = pos.get(f["properties"]["id"])
if p is None:
break # Fahrt endet
path.append(p)
f["path"] = path
S.vehicles = json.dumps({"type": "FeatureCollection", "ts": now, "step": STEP, "features": feats},
cur = positions(src, now)
# Distanz entlang der Strecke alle STEP s; daraus der Gleisverlauf, dem der Browser folgt
future = [{f["properties"]["id"]: f["_dist"] for f in src.feed.vehicles(now + STEP * (k + 1), src.rt)}
for k in range(STEPS)] # Schlüssel Betriebstag/Fahrt: Nachtzüge laufen über Mitternacht
for f in cur:
key, dists = f["properties"]["id"].split("/", 1)[1], [f["_dist"]]
for pos in future:
if key not in pos:
break # Fahrt endet
dists.append(pos[key])
f["path"] = src.feed.track(f.pop("_ti"), dists, STEP)
del f["_dist"]
feats += cur
S.vehicles = json.dumps({"type": "FeatureCollection", "ts": now, "features": feats},
separators=(",", ":")).encode()
S.vehicles_gz = gzip.compress(S.vehicles, 5)
S.count, S.computed_at = len(feats), time.time()