Skip to content

The aim of this project is to create a real-time visualisation of vienna's metro system using python.

License

Notifications You must be signed in to change notification settings

NxanIT/WienerLinienMonitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Brief summary:

The aim of this project is to build a live map of the full vienna metro system displaying each trains approximate position using a Raspberry Pi. For this on each line the next departures of trains from specified stations is requested, interpolated for all stations, and stored. From this data the state of LEDs (one LED per station and direction) on each line is computed every second. The LEDs are powered via three 16-bit serially connected LED sink drivers and P-channel mosfet transistors, allowing for multiplexing each line and therefore minimizing the number of GPIO pins needed.

Important

The code uploaded here represents the current state of the project, it works but still has it's flaws and will get modifications in the future.

Warning

The program sends GET requests to the the API of WienerLinien. During normal operations these should not occur less than 'min_refresh_intervall' seconds apart (defaultvalue=60, setting it <30 is discouraged). However, changes to the code could potentially bypass this restriction, which could result in your IP address being blocked.

Design specifications:

For the physical representation, I settled on the following specifications:

Name Function Specifications The part I chose
Frame house all electronics 70x50cm from Ikea
Map a map of vienna's metro printed after slight modifications downloadable here
Computer run the program GPIO, WLAN, able to process 36KB of json data at once Raspberry Pi 5
LED control power LEDs multiplexing due to restrictions on # of GPIO pins 3xSTP16CP05MTR and 5 P-channel Mosfets

A more detailed digression:

How this project came to life

My project was inspired by an instagram post made by 'designrulesco' from July 2024, link to the original post is here. Further info on their product webisite where they sell metro-styled maps of cities in the USA, where the stations illuminate whenever a train is departing from them.

My goal was to do just that, but here in Vienna :)

Fortunately WienerLinien, the company operating the Vienna metro provides a real-time API system, through which in particular one can request future departures for each station. No API-key required. Documentation and further informations can be found here: https://www.wienerlinien.at/ogd_realtime/doku/ . In the following I want to give a short introduction on how I used this service to create the 'WienerLinienMonitor'.

Constraints and compromises

The metro system consists currently of 109 stations, with stations served by more than one line counted for each line. A geographical location of all metro stations generated by 'WienerLinien.ipynb'

grafik

Given the fair-use principle of the API (request as little data as possible) and statement that the interval between two requests should not be less than 15 seconds, this presents a challenge of how to continuously retrieve up-to-date data across the entire metro system. During numerous iterations, I followed different strategies, a few of which should be listed below.

  1. It suffices to only rely on data from a few stations (as equidistant spaced as possible) and interpolate the departure times.
  2. The choice of stations that are meassured should reflect the current service of the metro (e.g. if a line is not in service end-to-end, but is divided into two independently operating lines).
  3. If we could assign every station a value for the 'necessity' of update during runtime and dynamically depending on current data, we could only update those.
  4. Stations serving more than one line include more data per requested station, therefore appear to be more valuable.
  5. Only handling one line at a time reduces complexity and difficulty.
  6. Data only reflects where a train is headed to, so lines with more then one terminal station per direction have to be meassured past every intermediate terminal station in order to track the origin station of a train correctly.

Point 3 would be highly desirable if implemented efficiently and correctly, but I consider it to be too prone for 'bias' towards certain stations, giving insufficient data on the rest of the system. Combining Point 1, 4 and 6 was my first strategy, but complexity of handeling the data, in particular the incomplete picture one has in the case where only given departure data of one station for a single line at a time, made it susceptible for errors when matching older data to this new data. Hence for this version I settled with Point 5 additionally to the Points 1, 2 and 6. The current operating state of the metro is computed at the begining of the program. For this a set of stations is given by the value 'initial_meassure' in the file 'Config.ini'. These might need to be changed, if continuos service of any line is interrupted. The program requests departure data from all those stations at once, computing for each line the terminal stations most distant to the station meassured (these are called service intervals) as well as for each line a set of terminal stations (for both directions at a time). The departure data is then discarded, since it is not of use anymore and from the service intervals and terminal stations the to be meassured stations are then determined. A visualisation (printed to 'monitor.log') might look like this:

grafik

Note

Work in progress, significant parts are still missing here.

display modes

Roughly speaking, even numbers correspond to visualisations relying on if the train is currently in the station or not where odd numbers correspond to lighting the stations nearest to each train.

display-mode description
0 - train in station LED is turned on, if calculation shows a train is currently at this station
1 - nearest station For each train tracked, the station closest to it's position is lit up. On the trains terminal/origin station the LED is turned on at train_in_station_time/2 seconds before departure
2 - train in station, blink on departure like display-mode 0, but LED blinks once train is about to depart
3 - nearest station, blink before transition like display-mode 1, but before the nearest station of the train changes, the LED is blinking
4 - train in station, blink on arrival as display-mode 2, but in reverse time
5 - nearest station, blink after transition like display-mode 3, but reverse
6 - train in station, blink on transition imagine display-modes 2 and 4 put together
7 - nearest station, blink on transition similarly display-mode 3 and 5 combined

parameters in 'Config.ini'

section parameter range default description
[DEFAULT]
flag_debug 0 or 1 0 If 1, then program will run in debug_mode, it will use data stored in /debugfiles instead of fetching data from API-requests
debug_time list[int] storing time used when in debug_mode
logging_level 0 or 1 1 Debug-messages show up in monitor.log iff logging_level=0
lines list[str] all lines only lines entered here are tracked
initial_meassure list[str] stations initially meassured to calculate service intervals and terminal stations of trains
[FETCH]
min_refresh_intervall int, >=30 60 no GET request is sent, if last is less than min_refresh_intervall seconds ago
max_refresh_intervall int 180 GET request is sent, if the line not updated for the longest, has not been updated since at least max_refresh_intervall seconds
meass_stations_per_line int 6 # of Stations for which a GET request is sent on each line
url_start str starting sequence of url for GET request
url_inbetween str intermediary sequence in url between stations
[METRO]
train_dep_cutoff_time int -100 train will be discarded, if every departure of it lays back more than train_dep_cutoff_time seconds
max_trains_on_line int 20 maximal # of trains tracked at one time on each line
threshold_time_between_departures int 100 seconds, time deviation permissible for departures meassured at different times to be considered to be the same train. If deviation is less then 2*threshold_time_between_departures and the best match, it will still be counted as a match but a warning is logged.
display_mode int, 0-7 1 see display modes
train_in_station_time int 30 seconds each train is assumed to halt at one station
train_departure_delay_time_offset int 0 seconds added to departuretime of each train. An experimental feature not yet tested
[MONITOR]
flag_monitor_debug 0 or 1 0 If =1, then a window with a matplotlib representation of the data is shown instead of driving LEDs
debug_speed int, >=1 10 Simulated time is multiplied with this factor
frame_rate int 20 # of times the program switches lighting all lines per second
duty_cycle float 0.8 fraction of time the LEDs of one line are powered on per reserved time for lighting one line
blink_half_period float 1 seconds the LED is either ON or OFF if in blinking mode
pin_displaymode int, GPIO compatible 26 pin # for external control of displaymode
pin_monitor_on int, GPIO compatible 19 pin controling turning on the monitor
pin_exit int, GPIO compatible 13 interupt pin shuting down program
pins_line_select list[int], GPIO compatible output pin of line that is set to be displayed, is turned low
pin_sdo int, GPIO compatible 12 serial data out pin
pin_clk int, GPIO compatible 16 serial clock pin
pin_oe_not int, GPIO compatible 20 pin disabling powering the LEDs
pin_le int, GPIO compatible 21 pin latch enable
shift_register_size int 48 size of shift register

About

The aim of this project is to create a real-time visualisation of vienna's metro system using python.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages