Skip to content

Architecture

Antony Kamp edited this page May 5, 2023 · 77 revisions

You can find the diagrams in the repository visual-paradigm-diagrams.

Abstract architecture

Abstract Architecture

The diagram shows the abstract architecture as component diagram.

REST API

The REST API component handles and validates the incoming requests from users or the dashboard.

SUMO

Framework for traffic simulation.

Interaction of components

The interaction between components will be modeled as sequence diagrams.

Start run

PUT _run

Stop run

DELETE _run__id

Get progress of run

GET _run__id

Get results from data science components

GET _component_data-science__id_result_run=run_id

Component interfaces

The component interfaces will be modeled as component diagram.

Interfaces

Concrete architecture

The concrete architecture will be modeled as class diagram. Everybody is responsible to update their own interface-classes with mermaid.

Implementor

The Implementor component contains the functions to execute the requested action. It initializes the Components for the Simulation and works with the TraCICommunicator to start the simulation.

classDiagram
  class IImplementor{
  }
Loading

TraCICommunicator

It calls the DataScience module after the completion of the simulation.

classDiagram
  class ITraCICommunicator {
    +progress: float
    +sumo_running: bool
    -configuration: String
    -components
    -current_tick: int
    -max_tick: int

    +ITraciCommunictor(components: List[IComponent], max_tick: int, sumo_port: int, sumo_configuration: String)
    +add_component(IComponent)
    +run()
  }
Loading

To show the progress of a run, the state or to stop a run, please use the following class methods:

  • TraCICommunicator.progress(process_id: str)
  • TraCICommunicator.stateprocess_id: str)
  • TraCICommunicator.stop(process_id: str)

DataScience

Evaluates the logged data and calculates data.

classDiagram
  class IAnalysisCalculator {
  }
  class IAnalysisResult {
  }
Loading

Logger

Writes logs to the database.

classDiagram
  class ILogCreator {
    +run_id: UUID

    +spawn_train(tick: int, train_id: str)
    +remove_train(tick: int, train_id: str)
    +arrival_train(tick: int, train_id: str, station_id: str)
    +departure_train(tick: int , train_id: str, station_id: str)
    +create_fahrstrasse(tick: int, fahrstrasse: str)
    +remove_fahrstrasse(tick: int, fahrstrasse: str)
    +set_signal(tick: int, signal_id: UUID, state_before: int, state_after: int)
    +train_enter_block_section(tick: int, train_id: str, block_section_id: str, block_section_length: str)
    +train_leave_block_section(tick: int, train_id: str, block_section_id: str, block_section_length: str)
    +inject_platform_blocked_fault(tick: int, platform_blocked_fault_configuration: UUID, affected_element: str)
    +inject_track_blocked_fault(tick: int, track_blocked_fault_configuration: UUID, affected_element: str) 
    +inject_track_speed_limit_fault(tick: int, track_speed_limit_fault_configuration: UUID, affected_element: str, value_before: str, value_after: str)
    +inject_schedule_blocked_fault(tick: int, train_cancelled_fault_configuration: UUID, affected_element: str)
    +inject_train_prio_fault(tick: int, train_prio_fault_configuration: UUID, affected_element: str, value_before: str, value_after: str) 
    +inject_train_speed_fault(tick: int, train_speed_fault_configuration: UUID, affected_element: str, value_before: str, value_after: str)
    +resolve_platform_blocked_fault(tick: int, platform_blocked_fault_configuration: UUID)
    +resolve_track_blocked_fault(tick: int, track_blocked_fault_configuration: UUID)
    +resolve_track_speed_limit_fault(tick: int, track_speed_limit_fault_configuration: UUID)
    +resolve_train_cancelled_fault(tick: int, train_cancelled_fault_configuration: UUID)
    +resolve_train_prio_fault(tick: int, train_prio_fault_configuration: UUID)
    +resolve_train_speed_fault(tick: int, train_speed_fault_configuration: UUID)
    +remove_fault(tick: int, injection_id: int)
  }

  class ILogCollector {
    -get_trains_departure_arrivals(run_id)
    -get_departures_of_train(run_id, train_id)
    -get_arrivals_of_train(run_id, train_id)
    +get_departures_arrivals_of_train(run_id, train_id)
    +get_departures_arrivals_all_trains(run_id)
    -get_trains_block_section(run_id)
    +get_block_section_times_of_train(run_id, train_id)
    +get_block_section_times_all_trains(run_id)
  }
Loading

FaultInjector

Inject faults into the Spawner or Interlocking to test the robustness of the simulation.

classDiagram

  class FaultInjector {
    +faults: list[Fault]
    +add_fault(Fault)
    +next_tick(tick)
  }

Loading

Spawner

Spawns trains and people defined by a schedule, parameters or data from outside.

classDiagram
  class ISpawner {
    +configuration: SpawnerConfiguration
    +next_tick(tick: int)
    +get_schedule(schedule_id: str): Schedule
  }
  class ISpawnerDisruptor {
    +block_schedule(schedule_id: int)
    +unblock_schedule(schedule_id: int)
  }
Loading

Interlocking

classDiagram
    IInterlockingDisruptor --> Route_Controller
    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 Route_Controller{
        + set_spawn_route(start_track: Track, end_track: Track) -> str
        + update_fahrstrasse(train: Train, track: Track)
        + maybe_update_fahrstrasse(train: Train, track: Track)
    }
Loading

TraCIWrapper

Provides utility-functions to edit the simulation.

classDiagram
    ISimulationObject <|-- ISimulationTrain
    ISimulationObject <|-- ISimulationNode
    ISimulationNode <|-- ISimulationSignal
    ISimulationNode <|-- ISimulationSwitch
    ISimulationObject <|-- ISimulationTrack
    ISimulationObject <|-- ISimulationPlatform

    class ISimulationObject {
        +identifier: str
        +updater: ISimulationObjectUpdater
        +update(updates: dict)
        +add_subscription() -> int
        +from_simulation(simulation_object, updater: ISimulationObjectUpdater) -> ISimulationObject
        +add_simulation_connections()
    }

    class ISimulationTrain {
        +current_track: ISimulationTrack
        +priority: int
        +position: tuple[float, float]
        +speed: float
        +max_speed: float
        +route: String
        +timetable: ITimetable
        +new(train_type: String, platform: ISimulationPlatform, timetable: ITimetable)
    }

    class ISimulationSignal {
        +state: Enum[Halt, Go]
    }

    class ISimulationNode {
        +position: tuple[float, float]
    }

    class ISimulationSwitch {
        +state: Enum[Left, Right]
    }

    class ISimulationTrack {
        +blocked: bool
        +speed_limit: float
    }

    class ISimulationPlatform {
        +edge: ISimulationEdge
        +platform_id: String
        +blocked: bool
    }

    class IInfrastructureProvider {
        -simulation: SimulationComponent
        +turn_point(yaramo_point: String, target_orientation: String)
        +set_signal_state(yaramo_signal: String, target_state: String)
        +tds_count_in_callback(callback: Callable)
        +tds_count_out_callback(callback: Callable)

    }

    class ISimulationObjectsUpdater {
        objects: List[ISimulationObject]
        trains: List[ISimulationTrain]
        signals: List[ISimulationSignal]
        switches: List[ISimulationSwitch]
        tracks: List[ISimulationTrack]
        platforms: List[ISimulationPlatform]
        +nextTick(tick: int)
    }
Loading

Database Class Diagram

The following diagram show the database schema.

The classes Track and Platform are not part of the database. You can find the corresponding ids of the platform in an app configuration file and ids of the tracks in the SUMO-XML.

Please keep in mind that m:n relations are implemented as reference table.

classDiagram
    FaultConfiguration <|-- PlatformBlockedFaultConfiguration
    FaultConfiguration <|-- ScheduleBlockedFaultConfiguration
    FaultConfiguration <|-- TrainSpeedFaultConfiguration
    FaultConfiguration <|-- TrackSpeedLimitFaultConfiguration
    FaultConfiguration <|-- TrackBlockedFaultConfiguration
    FaultConfiguration <|-- TrainPrioFaultConfiguration

    LogEntry <|-- TrainSpawnLogEntry
    LogEntry <|-- TrainRemoveLogEntry
    LogEntry <|-- TrainArrivalLogEntry
    LogEntry <|-- TrainDepartureLogEntry
    LogEntry <|-- CreateFahrstrasseLogEntry
    LogEntry <|-- RemoveFahrstrasseLogEntry
    LogEntry <|-- SetSignalLogEntry
    LogEntry <|-- TrainEnterBlockSectionLogEntry
    LogEntry <|-- TrainLeaveBlockSectionLogEntry
    LogEntry <|-- InjectFaultLogEntry
    LogEntry <|-- ResolveFaultLogEntry

    Token "1" -- "0..*" SimulationConfiguration
    SimulationConfiguration "0..*" *-- "0..*" FaultConfiguration
    SimulationConfiguration "0..*" *-- "1" InterlockingConfiguration
    SimulationConfiguration "0..*" *-- "1" SpawnerConfiguration

    SimulationConfiguration "1" -- "0..*" Run
    Run "1" o-- "0..*" LogEntry

    SpawnerConfiguration "0..*" -- "0..*" Schedule
    ScheduleBlockedFaultConfiguration "0..*" -- "1" Schedule

    TrackBlockedFaultConfiguration "0..*" -- "1" Track
    TrackSpeedLimitFaultConfiguration "0..*" -- "1" Track
    PlatformBlockedFaultConfiguration "0..*" -- "1" Platform

    InjectFaultLogEntry "0..*" o-- "0..1" PlatformBlockedFaultConfiguration
    InjectFaultLogEntry "0..*" o-- "0..1" TrackBlockedFaultConfiguration
    InjectFaultLogEntry "0..*" o-- "0..1" TrackSpeedLimitFaultConfiguration
    InjectFaultLogEntry "0..*" o-- "0..1" ScheduleBlockedFaultConfiguration
    InjectFaultLogEntry "0..*" o-- "0..1" TrainPrioFaultConfiguration
    InjectFaultLogEntry "0..*" o-- "0..1" TrainSpeedFaultConfiguration

    class SimulationConfiguration {
        + id: UUID
        + description: String
    }

    class Token {
        + id: UUID
        + permission: String
        + name: String
        + hashedToken: String
    }

    class Run {
       + id: UUID
    }

    class LogEntry {
        + timestamp: DateTime
        + tick: int
        + message: str
    }

    class TrainSpawnLogEntry {
        + train_id: str
    }

    class TrainRemoveLogEntry {
        + train_id: str
    }

    class TrainArrivalLogEntry {
        + train_id: str
        + station_id: str
    }

    class TrainDepartureLogEntry {
        + train_id: str
        + station_id: str
    }

    class CreateFahrstrasseLogEntry {
        + fahrstrasse: str
    }

    class RemoveFahrstrasseLogEntry {
        + fahrstrasse: str
    }

    class SetSignalLogEntry {
        + signal_id: str
        + state_before: int
        + state_after: int
    }

    class TrainEnterBlockSectionLogEntry {
        + train_id: str
        + block_section_id: str
        + block_section_length: float
    }

    class TrainLeaveBlockSectionLogEntry {
        + train_id: str
        + block_section_id: str
        + block_section_length: float
    }

    class InjectFaultLogEntry {
        + affected_element: str
        + value_before: str
        + value_after: str
    }

    class ResolveFaultLogEntry {

    }

    class FaultConfiguration {
        +start_tick: int
        +end_tick: int
        +description: str

    }

    class PlatformBlockedFaultConfiguration {
        +affected_element_id: str
    }

    class ScheduleBlockedFaultConfiguration {
        +affected_element_id: str
    }

    class TrainSpeedFaultConfiguration {
        +affected_element_id: str
    }

    class TrackSpeedLimitFaultConfiguration {
        +affected_element_id: str
    }

    class TrackBlockedFaultConfiguration {
        +affected_element_id: str
    }

    class TrainPrioFaultConfiguration {
        +affected_element_id: str
        +new_prio: int
    }

    class ScheduleConfiguration {
        +schedule_type: str
        +strategy_type: str
        +strategy_start_tick: int
        +startegy_end_tick
        +train_schedule_train_type: str
        +regular_strategy_frequency: int
        +random_strategy_trains_per_1000_ticks: float
        +random_strategy_seed: int
        +demand_strategy_power_station: str
        +demand_strategy_scaling_factor: float
        +demand_strategy_start_datetime: datetime
    }

    ScheduleConfigurationXSimulationPlatform "1" o-- "1" ScheduleConfiguration

    class ScheduleConfigurationXSimulationPlatform {
        +index: int
        +simulation_platform_id: str
    }

    SpawnerConfiguration "m" o-- "n" ScheduleConfiguration

    class SpawnerConfiguration {

    }

    class SmardApiIndex {
        timestamp: datetime
    }

    class SmardApiEntry {
        timestamp: datetime
        value: float
    }

    SmardApiEntry "" *-- "1" SmardApiIndex : index

    class InterlockingConfiguration {
        + dynamicRouting: Boolean
    }

    class Track {

    }

    class Platform {

    }
    
Loading

Class types

Configuration class

A configuration class contains information to initialize the functionality class. It inherits from the BaseModel in order to be saved to the database.

Pass an object of the configuration class the the according functionality class during the initialization.

Please keep the OpenAPI3 definition, postman collections and the database class diagram in sync with the configuration class. Ask Antony, if you need help.

Functionality class

Interface to interact with as TraCICommunicator. Pass an object of the configuration class the the according functionality class during the initialization.

Interaction between classes

The following diagram shows a rough overview over the interaction between configuration classes (in this example SpawnerConfiguration and functionality classes (in this case the component Spawner contains the class).

Initializing component

Clone this wiki locally