~derf
dark mode

Hi!

This is the personal homepage of Daniel Friesel / derf (depending on context and nickname availability). Every now and then, I write software and take pictures, which you can find here.

Projects

Web Applications

CLI Software

Travel::Routing::DE::VRR v2.20
Interface to EFA-based itinerary services
> efa Essen Martinstr Düsseldorf Hbf
14:34 ab  Essen Martinstr.: Bstg. 1      Straßenbahn 108      Essen Altenessen Bf Schleife
14:38 an  Essen Hauptbahnhof: Bstg. 1

14:47 ab  Essen Hauptbahnhof: 2          R-Bahn RE11 (RRX)    Düsseldorf Hbf
15:24 an  Düsseldorf Hbf: 10
Travel::Status::DE::DBWagenreihung v0.06
Interface to Deutsche Bahn Wagon Order API
> db-wagenreihung 'Essen Hbf' 723
▏      G       ▕▏    F    ▕▏    E     ▕▏   D    ▕▏    C    ▕▏    B    ▕▏             A             ▕
     >  39   38    37   36   35   33   32   31    29   28   27   26   25    23   22   21 >
Travel::Status::DE::DeutscheBahn v3.01
Interface to HAFAS-based arrival/departure monitors
> hafas-m 'Messegelände, Leipzig'
14:32    STR   16  Lößnig, Leipzig
14:40    STR   16  Sportforum Süd, Leipzig
14:43    ALT   86  S-Bahnhof Messe, Leipzig
14:47    STR   16  Lößnig, Leipzig
> db-iris 'Dortmund Hbf'
14:38 +16  IC 2027     Passau Hbf            11
14:39      ABR RE11    Kassel-Wilhelmshöhe   8
14:41      RE 57       Winterberg(Westf)     2
└────      RE 57       Brilon Wald           2
14:41      S 5         Hagen Hbf             5
14:42      S 2         Dortmund Hbf          6
14:45 +1   RE 1        Aachen Hbf            16
> ura-m Talbot
14:49:41  52    Aachen Bushof
15:04:47  11    Lichtenbusch
15:05:00  52    Eschweiler Bushof
15:18:00  1     Aachen Bushof
15:19:56  11    Hoengen Markt
15:35:00  1     Schevenhütte
Travel::Status::DE::VRR v1.20
Interface to EFA-based departure monitors
> efa-m Dortmund 'Universität S'
08:32  +1  02  445    Dortmund Am Kai
08:35      3   HB1    Dortmund Technologiezentrum
08:36      3   HB1    Dortmund Eichlinghofen H-Bahn
08:38      02  447    Dortmund Bandelstraße
08:39      2   S1     Dortmund Hbf
08:40      01  447    Dortmund Hacheney
> ct a mutt
mutt: retrieving package
Cloning into 'mutt'...
[..]
created   .muttrc         -> /home/derf/packages/mutt/etc/muttrc
> ekgping ccc.de
__________^________^__________^________^______

Firmware and Hardware

Blinkencat
RGB moodlight mod
TODO!
MicroMoody
I²C moodlight
TODO!
VUSB-I²C v0.02
USB ↔ I²C adapter
TODO!
zlib-deflate-nostdlib
embedded decompression library
TODO!

Unmaintained

I am no longer working on these projects. Some are nearly feature-complete, others never left the early prototype stage.

App::Raps2 v0.54
CLI password safe
App::Slackeria v0.12
Project status overview

News

Travel-Status-DE-IRIS-1.58.tar.gz (signature)

  • Result->has_realtime: Fix cancellations not being reported as realtime
  • db-iris: Annotate arrival/departure times which should have realtime data, but don't, with a question mark.

Travel-Status-DE-IRIS-1.57.tar.gz (signature)

  • Result: Add arrival_has_realtime, departure_has_realtime, has_realtime accessors
  • Result->delay_messages: Leave out superseded messages (right now, the only case is "Defekt am Zug" -> "Behobener Defekt am Zug")
  • Stations: Add swiss and austrian stations reachable from Waldshut and Lindau

Travel-Status-DE-IRIS-1.56.tar.gz (signature)

  • Update IRIS station list. Adds support for lots of Albtal-Verkehrs-Gesellschaft stations around Karlsruhe
  • Update some delay/qos messages ahead of a DB-wide change planned for October 2021

Travel-Status-DE-IRIS-1.55.tar.gz (signature)

  • Fix transfer trains getting lost when requested from a related station. Notable offender: "Berlin Südkreuz" lacked S 41 / S42 (ring line from Südkreuz (S) to Südkreuz (S) with transfer to/from the next/previous incarnation), as it referenced "Berlin Südkreuz (S)". "Berlin Südkreuz (S)" itself worked fine.

Setting PULSE_SERVER forwards the entire system audio to a remote (tcp) network sink. A more fine-granular solution (with control on stream- instead of system level) is almost as easy, thanks to module-tunnel-sink:

pacmd load-module module-tunnel-sink server=192.168.0.195

Now you can select the remote sink for individual streams (or turn it into the default / fallback one) and, for instance, have two different videos play back on two different remote sinks while your messenger's notification sounds remain local.

Wer DBF aus einem fahrenden Zug heraus aufruft, kann seit heute nur per GPS-Position Informationen zu diesem Zug erhalten – zumindest in den meisten Fällen und mit ein paar Einschränkungen. Ich möchte hier das Konzept dahinter erläutern.

Da über GTFS derzeit nur Solldaten zur Verfügung stehen und das HAFAS Zugradar lediglich nach beliebigen Fahrten im Umkreis sucht, ohne dabei konkrete Strecken zu berücksichtigen, greift die DBF-Implementierung nicht darauf zurück.

Stattdessen hat sie als einzige API-Abhängigkeit die Ankunfts-/Abfahrtstafel für Bahnhöfe und berechnet alles weitere selbst. Auch bei Abschaltung des HAFAS Zugradars bleibt sie funktionsfähig.

Abbildung von Positionen auf Nachbarstationen

Kern der Lokalisierung ist eine Datenbank, die Deutschland in ca. 200m × 300m große Rechtecke einteilt¹. Für jedes Rechteck, das mindestens eine Bahnstrecke enthält, listet sie alle Bahnhöfe auf, die von einem diese Bahnstrecke passierenden Zug planmäßig als nächstes angefahren werden. Eine Position auf dem Tunnel durch den Teutoburger Wald bei Lengerich enthält beispielsweise unter anderem

  • Lengerich (Westf) und Natrup-Hagen (RB66),
  • Münster (Westf) Hbf und Osnabrück Hbf (IC/ICE Linien 30 und 31) sowie
  • Essen Hbf und Hamburg Hbf (IC-Verbindung Hamburg – Ruhrgebiet ohne Unterwegshalte).

Die Datenbank beruht derzeit überwiegend auf dem von NVBW bereitgestellten SPNV GTFS-Liniennetzplan. Dieser enthält erfreulicherweise auch RE- und RB-Linien außerhalb von Baden-Württembeg. Erweitert wird sie mit einer (leider unfreien und unvollständigen) Menge an IC/ICE- und S-Bahn-Verbindungen. Für Hinweise zu weiteren offenen Datenquellen mit Liniennetzangaben bin ich dankbar.

Bestimmung von Zugkandidaten

Auf Basis einer GPS-Position werden zunächst die Nachbarstationen aus der Datenbank geholt und dann die Ankünfte der nächsten zwei Stunden an jeder Station abgefragt. Dieser Vorgang kann bei einer großen Menge an Stationen einige Sekunden dauern, da die Abfragen nicht parallel stattfinden. Zwar wäre die dadurch ausgelöste zusätzliche Last verglichen mit den restlichen (durch Menschen verursachten) HAFAS-Anfragen noch nicht einmal messbar, zu viele parallele Anfragen von einer einzigen IP dürften aber dennoch nicht gerne gesehen werden.

Für jede Zugfahrt sind Soll- und Ist-Zeit der Ankunft an der angefragten Station sowie die Namen und Soll-Abfahrtszeiten aller vorherigen Stationen bekannt. Züge, die an mehreren der angefragten Stationen verkehren, sind mehrfach vorhanden und werden zu einer einzigen Zugfahrt vereinigt. Nun geht es daran, für jeden Zug abzuschätzen, ob er sich gerade an der angefragten Position befinden könnte oder nicht.

Da die Datenbank mit Paaren von Stationen gefüttert wird, fliegt zunächst jeder Zug raus, der nur eine der angefragten Stationen passiert. Bei solchen Zügen ist sehr wahrscheinlich, dass sie die gesuchte Position auf ihrer Strecke nicht passieren. Anschließend wird für jeden Zug mit Hilfe der (bekannten) Verspätung an der angefragten Station die (unbekannte) verspätung an den vorherigen Unterwegshalten geschätzt und anhand dieser Echtzeitdaten bestimmt, zwischen welchen beiden Unterwegshalten er sich gerade befindet. Ebenso wird für jedes Paar von Unterwegshalten die Entfernung zwischen der angefragten Position und der Luftlinie zwischen den Halten bestimmt.

Jetzt fliegen alle Züge, deren aktuelle geschätzte Position sich nicht zwischen dem Paar von Unterwegshalten mit der kürzesten Entfernung zur angefragten Position befindet. Denn diese sind gerade sehr wahrscheinlich nicht auf dem richtigen Streckenabschnitt. Ebenso werden Züge verworfen, die sich noch an der Startstation befinden und nicht innerhalb der nächsten fünf Minuten losfahren. Eine S-Bahn, die erst in einer Stunde losfährt, ist wohl kaum gerade auf einer Bahnstrecke unterwegs oder auch nur einstiegsbereit am Bahnsteig.

Für die verbleibenden Züge wird die aktuelle Position auf der Luftlinie zwischen ihren Halten geschätzt. Dabei gehe ich von konstanter Geschwindigkeit aus, da ich keine Beschleunigungsprofile oder Streckengeschwindigkeiten kenne. Anschließend werden die Züge sortiert nach der Entfernung zur gesuchten Position aufgelistet.

Genauere Positionsabschätzung

Mit Verwendung des tatsächlichen Linienverlaufs einer Fahrt anstelle der Luftlinie zwischen Unterwegshalten ließe sich die Position noch viel genauer abschätzen und insbesondere bestimmen, ob die Route eines Zuges überhaupt die gesuchte Position enthält – wenn nicht, kann er direkt verworfen werden, auch wenn er nur wenige km neben der gesuchten Position auf einer anderen Bahnstrecke entlangfährt.

Diese Verbesserung ist derzeit nicht implementiert, da das die Menge notwendiger API-Anfragen nochmals erhöhen würde und ich zunächst testen möchte, ob die Ergebnisse mit linearer (Luftlinien-)Interpolation bereits hinreichend nützlich sind. Außerdem kommt es regelmäßig vor, dass das HAFAS die Linie selbst falsch einschätzt und z.B. einen ICE auf einer nicht elektrisierten Nebenbahn (statt der einige km entfernt verlaufenden, aber insgesamt längeren, elektrisierten Hauptbahn) platziert.

Ebenso wäre es auf Dauer interessant, anstelle der Entfernung zur Position die Zeit bis zum Erreichen (oder seit dem Erreichen) der Position als Gütemaß zu verwenden. S-Bahnen und ICE sind ja durchaus unterschiedlich schnell unterwegs. Das steht noch auf der Todo-Liste.

Quelltext

Die Implementierung ist noch ein wenig frickelig und undokumentiert, aber selbstverständlich auf GitHub verfügbar: derf/geolocation-to-train.

Fußnoten

¹ Der Einfachheit halber werden auf drei Nachkommastellen gerundete GPS-Koordinaten genutzt. Das resultierende Gitternetz ist unseren Breitengeraden nicht quadratisch.

Travel-Status-DE-VRR-1.20.tar.gz (signature)

  • efa-m, EFA: Accept "stopID" stop type
  • EFA: Add proximity_search (useProxFootSearch) option

Travel-Status-DE-VRR-1.19.tar.gz (signature)

  • Result: Add ->train_no accessor

Travel-Routing-DE-VRR-2.20.tar.gz (signature)

  • EFA/Route/Part: Add occupancy accessor
  • efa: Show expected occupancy, if available

Travel-Status-DE-VRR-1.18.tar.gz (signature)

  • EFA: "place" is now optional
  • Result: Add ->occupancy accessor
  • efa-m: The "place" argument is now optional
  • efa-m: Show expected vehicle occupancy, if available

Travel-Status-DE-DBWagenreihung-0.06.tar.gz (signature)

  • DBWagenreihung: Add train_descriptions accessor
  • Wagon: Add train_subtype accessor

Travel-Status-DE-IRIS-1.54.tar.gz (signature)

  • Add stations DKP, DRBS, DSBG, KWHD, NCBD, TENS, XLHW

Travel-Status-DE-DBWagenreihung-0.04.tar.gz (signature)

  • Distinguish between IC2 KISS / IC2 Twindexx and ICE T 411 / ICE T 415

Travel-Status-DE-DBWagenreihung-0.05.tar.gz (signature)

  • Distinguish between ICE 3 403 series 1/2 and ICE T 411 series 1/2

Travel-Status-DE-IRIS-1.53.tar.gz (signature)

  • import station name changes and station removals from Winterfahrplan 2021

Travel-Status-DE-IRIS-1.52.tar.gz (signature)

  • get_station_by_name: Fix crash (unhandled exception) when the station name is an invalid regular expression

Travel-Status-DE-IRIS-1.51.tar.gz (signature)

  • Add BER airport stations
  • Rename Schönefeld airport to BER Terminal 5

Travel-Status-DE-IRIS-1.50.tar.gz (signature)

  • Add station Brunnen(Oberbay)
  • Incorporate station name and eva number changes from DB IRIS (affects nine stations)
  • Add geocoordinates to 17 stations previously lacking those

Travel-Status-DE-IRIS-1.48.tar.gz (signature)

  • Add stations Neuruppin Seedamm (temporary, teardown expected Dec 2020), Amriswil, and Baar(CH)