Interlocking Component - BP2022-AP1/bp2022-ap1 GitHub Wiki
Architecture
classDiagram
IInterlockingDisruptor --> RouteController
RouteController --> Router
RouteController --> InterlockingConfiguration
RouteController --> Interlocking
Interlocking <--> SumoInfrastructureProvider
RouteController <-- SumoInfrastructureProvider
InfrastructureProvider <|-- SumoInfrastructureProvider
class Interlocking{
+ prepare(yaramo_topoloy)
+ reset()
+ print_state()
+ set_route(yaramo_route)
+ free_route(yaramo_route)
}
class InterlockingConfiguration{
+ dynamicRouting: Boolean
}
class IInterlockingDisruptor {
+ insert_track_blocked(track: Track)
+ insert_track_unblocked(track: Track)
+ insert_platform_blocked(platform: Platform)
+ insert_platform_unblocked(platform: Platform)
+ insert_track_speed_limit_changed(track: Track)
+ insert_train_max_speed_changed(train: Train)
+ insert_train_priority_changed(train: Train)
}
class RouteController{
+ set_spawn_route(start_track: Track, end_track: Track) -> str
+ maybe_set_fahrstrasse(train: Train, track: Track)
+ set_fahrstrasse(train: Train, track: Track)
+ maybe_free_fahrstrasse(track: Track)
- free_fahrstrasse(route: Route)
- get_interlocking_route_for_track(track: Track) -> Route
+ check_all_fahrstrassen_for_failures()
}
class Router{
+ get_route(start_track_segment_id, end_track_segment_id)
}
class InfrastructureProvider{
+ turn_point(yaramo_point, target_orientation)
+ set_signal_state(yaramo_signal, target_state)
+ set_tds_count_in_callback(tds_count_in_callback)
+ tds_count_in(track_segment_id)
+ set_tds_count_out_callback(tds_count_out_callback)
+ tds_count_out(track_segment_id)
}
class SumoInfrastructureProvider{
+ turn_point(yaramo_point, target_orientation)
+ set_signal_state(yaramo_signal, target_state)
+ train_drove_onto_track(train: Train, edge: Edge)
+ train_drove_off_track(edge: Edge):
}
MoSCoW
Must have:
- set fahrstrassen when a train enters a new track_segment
- set fahrstrassen when called (for the first fahrstrasse)
- set fahrstrassen according to schedule (route correctly)
- routing algorithm that avoids deadlocks
Should have:
- make cargo trains have priority over passenger trains
- reevaluate routes when a fault gets inserted
Could have:
- static routing algorithm, that has good performance through precalculating routes or caching
- consider how to realistically set fahrstrassen as a human would do it
Won't have:
- dynamic routing algorithm, that takes into consideration where other trains are driving and how that may affect travel times along different routes
Avoiding Deadlocks
There is a paper by Jörn Pachel, that describes two possible solutions to avoiding deadlocks in a simulation like ours.
Deadlock Avoiding by Dynamic Route Reservation
In this method, trains that want to drive into a section reserve a number of sections for them to drive on according to rules. If a train wants to reserve an already reserved section, it is placed in a reservation queue and may only enter that section once it is in the first place of the queue. The rules are:
- Before a train is authorized to enter a track section, the route into that section must be reserved.
- If a route is reserved that leads into a track section with bidirectional operation other than a station track, the route to leave that section must also be reserved.
- If a track section to be reserved is still reserved for or occupied by another train, the reservation for that section is stacked to the next position.
- If a reservation is put into the stack behind another train, for that train, if not yet the case, the route to leave that section must be reserved.
- If a route to be reserved leads into a track that is reserved for or occupied by an opposing train, i.e. a train that will leave that section by moving into the section the route to be reserved comes from, the reservation of that route fails.
- A reservation comes only into effect if all following reservations that are initiated by that reservation by rules 2 and 4 are possible. If the reservation of a route fails, all reservations previously initiated by rules 2 and 4 fail, too.
There is a proposed rule 7 for more efficiency in the network, that may be used to implement priority of trains:
- If the reservation of successive routes for a train ends in a section where this train is in the first position of the stack, then in all intermediate sections reserved for that train, the reservation can be moved to the first stack position.
This method requires information on the future routing of the trains, as through the interaction rules a reservation until any station in the future of the train could be needed. With a limited queue of reservations, this could be mitigated. Another disadvantage of this system is, that "it seems possible that in very rare situations, a deadlock may occur."
This method seems to fit to our architecture the best, so we will need to evaluate how bad potentially still occurring deadlocks are.
Movement Consequence Analysis
In this method, before any train is allowed to move into a new block section, a complete analysis of the consequences that movement would have is calculated. So-called primary consequences describe necessary preconditions, that need to be given, before a train is allowed to enter a block section. They are:
- trains ahead has cleared the section
- opposing trains have cleared the section
Secondary consequences describe consequences resulting from the movement of the train, regarding the train itself. Those consequences can be, that the train needs to keep moving through some sections of track in order to allow for some opposing train to then enter the track and not be stuck in a deadlock.
Any of those consequences may have consequences of its own. For example, if a train is required to enter a section that is currently blocked by another train, that train will then have to move. That move can cause primary and secondary consequences in itself.
To calculate if all the consequences can be met, a consequence tree has to be constructed and evaluated. I think, that for a big, busy and complex simulation like ours this could become a slow computation. Another constriction of this approach is, that all the routes of the entire trains need to be known before the calculation. This is not something we want, as we only route each train from platform to platform.
Domain questions
- How much distance needs to be between two trains?
- One block section?
- More?
- What needs to be given so that a train can enter a block section?
- How far are Fahrstrassen set?
- fully from platform to platform?
- from signal to signal?
- from switch to switch?
- Are block sections set to free as soon as the train leaves the control area?
- When do trains not run on the right track?