Merge pull request #12 from railtoolkit/development

Development
development
Max Kannenberg 2022-05-17 11:29:44 +02:00 committed by GitHub
commit f09a5cac9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 2545 additions and 3926 deletions

59
.github/workflows/CI.yml vendored Normal file
View File

@ -0,0 +1,59 @@
name: CI
on:
push:
branches:
- main
tags: '*'
pull_request:
concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version:
- '1.6'
- '1.7'
- 'nightly'
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
# - x86
- x64
# - aarch64
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: '1'
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-docdeploy@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
- run: |
julia --project=docs -e '
using Documenter: DocMeta, doctest
using TrainRuns
DocMeta.setdocmeta!(TrainRuns, :DocTestSetup, :(using TrainRuns); recursive=true)
doctest(TrainRuns)'

16
.github/workflows/CompatHelper.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: CompatHelper
on:
schedule:
- cron: 0 0 * * *
workflow_dispatch:
jobs:
CompatHelper:
runs-on: ubuntu-latest
steps:
- name: Pkg.add("CompatHelper")
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}
run: julia -e 'using CompatHelper; CompatHelper.main()'

15
.github/workflows/TagBot.yml vendored Normal file
View File

@ -0,0 +1,15 @@
name: TagBot
on:
issue_comment:
types:
- created
workflow_dispatch:
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}

14
.github/workflows/register.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: Register Package
on:
workflow_dispatch:
inputs:
version:
description: Version to register or component to bump
required: true
jobs:
register:
runs-on: ubuntu-latest
steps:
- uses: julia-actions/RegisterAction@latest
with:
token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -9,6 +9,36 @@ Categories: Added, Changed, Deprecated, Removed, Fixed, and Security.
## [Unreleased]
### Added
* dependency JSONSchema
* validation of YAML input via JSON schema
### Changed
* renamed TrainRun into TrainRuns
* replaced settings::Dict with type Settings as struct
* replaced path::Dict with type Path as struct
* replaced train::Dict with type Train as struct
* restructured examples/ and data/ in docs/ and test/
* modified test to work with Julia Testsets and with simplier naming of input files
* renamed Validate.jl into types.jl
* renamed TrainRunCalc.jl into calc.jl
* moved trainrun function from calc.jl to TrainRun.jl
* moved createDataPoint() from behavior.jl to types.jl
* moved createBehaviorSection() from behavior.jl to types.jl
* moved createMovingSection() from characteristics.jl to types.jl
* moved createCharacteristicSection() from characteristics.jl to types.jl
* changed title of include files from upper case to lower case
* changed seperation of submodules into a single module with file include
* updated test files to railtoolkit/schema (2022.05)
### Removed
* dependency Plots and CSV
* AdditionalOutput.jl
* EnergySaving.jl
* test/testEnums.jl
* import.jl
* export.jl
* settings for CSV export
## Version [0.8] 2022-01-20
@ -142,18 +172,18 @@ Modules and variables were renamed.
Proof of concept and master thesis submission.
[Unreleased]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.8...master
[0.8]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.7...v0.8
[0.7]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.6.2...v0.7
[0.6.2]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.6.1...v0.6.2
[0.6.1]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.6...v0.6.1
[0.6]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.5.3...v0.6
[0.5.3]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.5.2...v0.5.3
[0.5.2]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.5...v0.5.1
[0.5]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.4.1...v0.5
[0.4.1]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.4...v0.4.1
[0.4]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.3...v0.4
[0.3]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.2...v0.3
[0.2]: https://github.com/railtoolkit/TrainRun.jl/compare/v0.1...v0.2
[0.1]: https://github.com/railtoolkit/TrainRun.jl/releases/tag/v0.1
[Unreleased]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.8...main
[0.8]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.7...v0.8
[0.7]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.6.2...v0.7
[0.6.2]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.6.1...v0.6.2
[0.6.1]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.6...v0.6.1
[0.6]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.5.3...v0.6
[0.5.3]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.5.2...v0.5.3
[0.5.2]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.5...v0.5.1
[0.5]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.4.1...v0.5
[0.4.1]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.4...v0.4.1
[0.4]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.3...v0.4
[0.3]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.2...v0.3
[0.2]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.1...v0.2
[0.1]: https://github.com/railtoolkit/TrainRuns.jl/releases/tag/v0.1

View File

@ -3,7 +3,7 @@
# Visit https://bit.ly/cffinit to generate yours today!
---
cff-version: 1.2.0
title: TrainRun.jl
title: TrainRuns.jl
message: 'If you use this software, please cite it using these metadata.'
type: software
authors:
@ -22,12 +22,12 @@ identifiers:
- type: doi
value: 10.5281/zenodo.6448564
description: Current version
url: 'https://www.railtoolkit.org/projects/TrainRun.jl/'
repository: 'https://github.com/railtoolkit/TrainRun.jl'
url: 'https://www.railtoolkit.org/projects/TrainRuns.jl/'
repository: 'https://github.com/railtoolkit/TrainRuns.jl'
abstract: >-
TrainRun.jl is a step towards open science and open data in railway engineering.
TrainRuns.jl is a step towards open science and open data in railway engineering.
Its modular design offers the possibility to serve as a basis for future
optimization and development. TrainRun.jl is suitable for qualitative
optimization and development. TrainRuns.jl is suitable for qualitative
calculations to compare different trains, and it is publicly available, and we
invite others to collaborate.
keywords:

View File

@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
reported by contacting the project team at railtoolkit@ownx.net. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.

View File

@ -5,7 +5,83 @@ email, or any other method with the owners of this repository before making a ch
Please note we have a code of conduct, please follow it in all your interactions with the project.
# Pull Request Process
## Julia Development Environment
* add your changes to the CHANGELOG.md under [Unreleased]
* TODO!
Link your local git repository to Julia:
```console
$ ln -s ~/path/to/TrainRuns.jl ~/.julia/dev/TrainRuns
```
Have a look how to develop Julia packages: https://github.com/ShozenD/julia-pkg-dev
You might want to use `Revise.jl` as well:
```julia
Pkg.add("Revise")
```
and then just load with `using Revise` (preferably by putting it in the `~/.julia/config/startup.jl` file).
You can overide the standard TrainRuns package with the local development branch (see linking above) with:
```julia
julia> # use the ] key
(@v1.x) pkg> develop TrainRuns
(@v1.x) pkg> # use backspace
julia> using TrainRuns # local development branch will be loaded
```
If you want to add a dependency use:
```julia
julia> # use the ] key
(@v1.x) pkg> activate TrainRuns
(TrainRuns) pkg>
```
## Files in TrainRuns
| file | concern |
| --------------- | ------------------------------ |
| TrainRuns.jl | main file and function |
| types.jl | special TrainRuns types |
| constructors.jl | type constructors |
| formulary.jl | formulars from literature |
| output.jl | transformation into DataFrames |
## Reporting Issues
* It's always good to start with a quick search for an existing issue to post on,
or related issues for context, before opening a new issue
* Including minimal examples is greatly appreciated
* If it's a bug, or unexpected behaviour, reproducing on the latest development version
(`Pkg.add(name="TrainRuns", rev="main")`) is a good gut check and can streamline the process,
along with including the first two lines of output from `versioninfo()`
## Style Guidelines
TODO
## Git Recommendations For Pull Requests
* Avoid working from the `main` branch of your fork, creating a new branch will make it
easier if TrainRuns.jl `main` branch changes and you need to update your pull request;
* All PRs and issues should be opened against the `main` branch not against the current release;
* Run tests of your code before sending any commit to GitHub. Only push changes when
the tests of the change are passing locally. In particular note that it is not a problem
if you send several commits in one push command to GitHub as CI will be run only once then;
* If any conflicts arise due to changes in TrainRuns.jl `main` branch, prefer updating your pull
request branch with `git rebase` (rather than `git merge`), since the latter will introduce a merge
commit that might confuse GitHub when displaying the diff of your PR, which makes your changes more
difficult to review. Alternatively use conflict resolution tool available at GitHub;
* Please try to use descriptive commit messages to simplify the review process;
* Using `git add -p` or `git add -i` can be useful to avoid accidently committing unrelated changes;
* Maintainers get notified of all changes made on GitHub. However, what is useful is writing a short
message after a sequence of changes is made summarizing what has changed and that the PR is ready
for a review;
* When linking to specific lines of code in discussion of an issue or pull request, hit the `y` key
while viewing code on GitHub to reload the page with a URL that includes the specific commit that
you're viewing. That way any lines of code that you refer to will still be correct in the future, even
if additional commits are pushed to the branch you are reviewing;
* Please make sure you follow the code formatting guidelines when submitting a PR;
Also preferably do not modify parts of code that you are not editing as this makes
reviewing the PR harder (it is better to open a separate maintenance PR
if e.g. code layout can be improved);
* If a PR is not finished yet and should not be reviewed yet then it should be opened as DRAFT
(in this way maintainers will know that they can ignore such PR until it is made non-draft or the author
asks for a review).

View File

@ -1,6 +1,6 @@
ISC License (ISC)
Copyright 2021 Max Kannenberg
Copyright 2022 Max Kannenberg, Martin Scheidt
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice

View File

@ -1,12 +1,24 @@
name = "TrainRun"
name = "TrainRuns"
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
authors = ["Max Kannenberg"]
authors = ["Max Kannenberg", "Martin Scheidt", "contributors"]
version = "0.8.0"
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
JSONSchema = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
[compat]
DataFrames = "^1"
JSONSchema = "^1"
YAML = "^0"
julia = "^1.6"
[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[targets]
test = ["Test"]

View File

@ -1,40 +1,43 @@
# TrainRun
# TrainRuns
[![License: ISC](https://img.shields.io/badge/license-ISC-green.svg)](https://opensource.org/licenses/ISC) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6448563.svg)](https://doi.org/10.5281/zenodo.6448563)
[![License: ISC](https://img.shields.io/badge/license-ISC-green.svg)](https://opensource.org/licenses/ISC) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6448563.svg)](https://doi.org/10.5281/zenodo.6448563) [![Build Status](https://github.com/railtoolkit/TrainRuns.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/railtoolkit/TrainRuns.jl/actions/workflows/CI.yml?query=branch%3Amain)
------------
# About
TrainRun.jl is a step towards open science and open data in railway engineering. Its modular design offers the possibility to serve as a basis for future optimization and development. TrainRun.jl is suitable for qualitative calculations to compare different trains, and it is publicly available, and we invite others to collaborate.
TrainRuns.jl is a step towards open science and open data in railway engineering. Its modular design offers the possibility to serve as a basis for future optimization and development. TrainRuns.jl is suitable for qualitative calculations to compare different trains, and it is publicly available, and we invite others to collaborate.
------------
# Installation
The required julia packages are
- YAML.jl
- Dates.jl
- DataFrames.jl
- CSV.jl
- Plots.jl
Use the package manager provided by julia:
```julia
julia> # use the ] key
(@v1.x) pkg> add TrainRuns
(@v1.x) pkg> # use backspace
julia> using TrainRuns
```
Review the settings.yaml file for your appropriate settings.
The required julia packages are
- YAML.jl
- JSONSchema.jl
- DataFrames.jl
------------
# Minimal working example
```julia
include("../src/TrainRun.jl")
using .TrainRun
using TrainRuns
train_directory = "data/trains/train_freight_V90withOreConsist.yaml"
running_path_directory = "data/paths/path_1_10km_nConst_vConst.yaml"
settings_directory = "data/settings.yaml"
(train, running_path, settings) = importYamlFiles(train_directory, running_path_directory, setting_directory)
train = Train("test/data/trains/freight.yaml")
path = Path("test/data/paths/const.yaml")
train_run = trainRun(train, running_path, settings)
runtime = trainrun(train, path)
println("The train needs $runtime seconds for the running path.")
```
------------
@ -47,11 +50,11 @@ This work was supervised by South Westphalia University of Applied Sciences and
# License
[![Open Source Initiative Approved License logo](https://opensource.org/files/OSIApproved_100X125.png "Open Source Initiative Approved License logo")](https://opensource.org)
[![Open Source Initiative Approved License logo](https://opensource.org/files/OSIApproved_100X125.png "Open Source Initiative Approved License logo")](https://opensource.org)
ISC License (ISC)
Copyright 2021 Max Kannenberg
Copyright 2022 Max Kannenberg, Martin Scheidt
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

View File

@ -1,9 +0,0 @@
%YAML 1.2
---
path:
name: "10 km, no gradient, 160 km/h"
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
- [0, 160, 0]
- [10000, 160, 0]

View File

@ -1,19 +0,0 @@
%YAML 1.2
---
path:
name: "10 km, different gradient, 160 km/h"
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
- [0, 160, 0]
- [1000, 160, 1]
- [2000, 160, 2]
- [3000, 160, 5]
- [4000, 160, -3]
- [5000, 160, 5]
- [6000, 160, -10]
- [7000, 160, 15]
- [8000, 160, -10]
- [8500, 160, 20]
- [9000, 160, 0]
- [10000, 160, 0]

View File

@ -1,17 +0,0 @@
%YAML 1.2
---
path:
name: "10 km, no gradient, different speed limits"
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
- [0, 160, 0.0]
- [3000, 60, 0.0]
- [4000, 160, 0.0]
- [5000, 60, 0.0]
- [6000, 160, 0.0]
- [6500, 60, 0.0]
- [6700, 65, 0.0]
- [6800, 70, 0.0]
- [7000, 120.00, 0]
- [10000, 160.00, 0.0]

View File

@ -1,354 +0,0 @@
%YAML 1.2
---
path:
name: "'infra_Ostsachsen': track id='tr_80.6212_2' name='DG-DN' -> spp_5"
# source: https://www.railml.org/en/user/exampledata.html -> "Real world railway examples from professional tools" -> "East Saxony railway network by FBS" -> "Ostsachsen_V220.railml" -> 'infra_Ostsachsen': track id='tr_80.6212_2' name='DG-DN' -> spp_5
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
- [0.0, 40, 0]
- [318.0, 40, 2]
- [399.0, 40, -3]
- [500.0, 40, 0]
- [579.0, 40, 1]
- [784.0, 40, 5.3]
- [868.0, 40, 20]
- [1082.0, 40, 16.1]
- [1287.0, 40, 18.1]
- [1800.0, 110, 18.1]
- [2242.0, 110, 15.4]
- [3295.0, 110, 11]
- [3880.0, 110, 11.1]
- [4680.0, 45, 11.1]
- [4686.0, 90, 11.1]
- [6122.0, 90, 0]
- [6487.0, 90, 1.5]
- [6588.0, 70, 1.5]
- [6589.0, 70, 2.4]
- [6608.0, 130, 2.4]
- [6723.0, 150, 1.3]
- [6928.0, 160, 1.3]
- [7030.0, 160, 7.5]
- [7300.0, 160, 8]
- [7552.0, 160, 5]
- [7675.0, 160, 6.7]
- [7800.0, 160, 7.4]
- [7920.0, 160, 7]
- [8020.0, 140, 7]
- [8100.0, 140, 6.3]
- [8168.0, 140, 7.4]
- [8226.0, 140, 8.4]
- [8300.0, 140, 7.4]
- [8381.0, 150, 7.4]
- [8600.0, 150, 7.8]
- [8900.0, 150, 6.7]
- [9100.0, 150, 7.8]
- [9600.0, 150, 8]
- [9845.0, 150, 7.3]
- [10005.0, 160, 7.3]
- [10600.0, 160, 6]
- [10748.0, 160, 7.3]
- [11100.0, 160, 4.5]
- [11280.0, 160, 3.6]
- [11450.0, 160, 7.2]
- [11800.0, 160, 6.8]
- [12100.0, 160, 7.3]
- [12590.0, 160, 7.6]
- [13100.0, 160, 7.3]
- [13500.0, 160, 7.1]
- [13800.0, 160, 7.3]
- [14138.0, 150, 7.3]
- [14330.0, 150, 0.3]
- [14640.0, 150, -1.8]
- [14764.0, 160, -2.8]
- [15000.0, 160, -3.3]
- [15500.0, 160, -0.9]
- [16000.0, 160, 0]
- [16470.0, 160, 1.2]
- [16572.0, 160, 2.2]
- [16700.0, 160, 3.8]
- [16949.0, 160, 3.5]
- [17086.0, 160, 3.2]
- [17232.0, 160, 1.3]
- [17339.0, 160, 4.5]
- [17406.0, 160, 3.4]
- [17727.0, 150, 3.4]
- [17807.0, 150, 4.6]
- [18049.0, 150, 3]
- [18210.0, 140, 3]
- [18300.0, 140, 4.6]
- [18680.0, 140, 3.2]
- [18761.0, 150, 3.2]
- [19047.0, 150, 5.1]
- [19305.0, 150, 3]
- [19406.0, 160, 3]
- [19414.0, 160, -0.3]
- [19900.0, 160, 3]
- [20150.0, 160, 1.8]
- [20470.0, 160, -4]
- [20940.0, 160, -3.6]
- [21150.0, 160, -1.5]
- [21390.0, 160, 0]
- [21702.0, 160, 1.5]
- [22188.0, 150, 1.5]
- [22294.0, 150, 1.8]
- [22383.0, 160, 1.8]
- [22500.0, 160, 2.6]
- [22900.0, 160, 4.6]
- [23542.0, 160, 0.2]
- [23736.0, 160, 0.9]
- [24124.0, 160, 7]
- [24918.0, 160, 7.6]
- [25100.0, 150, 7.1]
- [25580.0, 150, 7.4]
- [25708.0, 160, 7.4]
- [25810.0, 160, 7.1]
- [26040.0, 160, 3.2]
- [26330.0, 160, 1.8]
- [26593.0, 160, 2.1]
- [27020.0, 160, 3.5]
- [27195.0, 160, 5.8]
- [27253.0, 160, 1.1]
- [27310.0, 160, 3.5]
- [27595.0, 160, 3.4]
- [28530.0, 160, 4.6]
- [29115.0, 160, 0]
- [29700.0, 160, -5.2]
- [30055.0, 120, -4.3]
- [30301.0, 120, -6.2]
- [30487.0, 160, -6.2]
- [30537.0, 160, -4.8]
- [31130.0, 160, -0.3]
- [31293.0, 160, 3.7]
- [31400.0, 160, 2.9]
- [31640.0, 160, 4.1]
- [31795.0, 120, 4.1]
- [32010.0, 120, 3.2]
- [32138.0, 130, 3.2]
- [32365.0, 130, -4]
- [33000.0, 130, 6.1]
- [33426.0, 160, 6.1]
- [33907.0, 160, 7.1]
- [34220.0, 160, 8.4]
- [34300.0, 160, 7.9]
- [34440.0, 160, 7.1]
- [34610.0, 160, 4.4]
- [35000.0, 160, 5.6]
- [35173.0, 150, 5.6]
- [35400.0, 150, -0.2]
- [35597.0, 160, -0.2]
- [35900.0, 160, 0]
- [36700.0, 160, 3.9]
- [36938.0, 160, 0]
- [37700.0, 160, -0.3]
- [37978.0, 150, -5.6]
- [38063.0, 150, -1.9]
- [38141.0, 150, -3.1]
- [38210.0, 150, 0]
- [38406.0, 150, -7]
- [38900.0, 150, -7.5]
- [39200.0, 150, -8.7]
- [39298.0, 150, -6.4]
- [39476.0, 150, -7.2]
- [40400.0, 150, -6.9]
- [40676.0, 130, -6.9]
- [41000.0, 130, -7.3]
- [41406.0, 130, -7.5]
- [41571.0, 160, -7.3]
- [41816.0, 160, -6.8]
- [41923.0, 160, -7.1]
- [42139.0, 160, -1.3]
- [42343.0, 160, -2.4]
- [42432.0, 150, -2.4]
- [42952.0, 160, -2.4]
- [43000.0, 160, -4.6]
- [43264.0, 160, -2.5]
- [43388.0, 160, -0.6]
- [43700.0, 160, 0.8]
- [44030.0, 160, 2.7]
- [44430.0, 160, 0]
- [44708.0, 160, -7.2]
- [45477.0, 160, -7.8]
- [45890.0, 160, -1]
- [46562.0, 160, -1.6]
- [47000.0, 160, -6.9]
- [47500.0, 160, -7.7]
- [47800.0, 160, -6.8]
- [48700.0, 160, -4.3]
- [49218.0, 160, -5.3]
- [49514.0, 160, -2.5]
- [50000.0, 160, -2.2]
- [51150.0, 160, -5.7]
- [51406.0, 160, -6.3]
- [51710.0, 150, -5.8]
- [52000.0, 150, -6.7]
- [52215.0, 150, -6.1]
- [53213.0, 150, -6.8]
- [53567.0, 150, -5.6]
- [53943.0, 150, -6.5]
- [54129.0, 140, -6.5]
- [54212.0, 140, -10.5]
- [54247.0, 140, -5.4]
- [54326.0, 140, -6.1]
- [54450.0, 140, -6.5]
- [54482.0, 120, -6.5]
- [54550.0, 120, -6.2]
- [54855.0, 140, -6.2]
- [55307.0, 140, -0.3]
- [55651.0, 140, -1.2]
- [55788.0, 140, 0]
- [55918.0, 100, 0]
- [56433.0, 150, 0]
- [56560.0, 150, -2.1]
- [56624.0, 150, -6.7]
- [57012.0, 150, 1.3]
- [57260.0, 150, 6.6]
- [57800.0, 150, 5.3]
- [57987.0, 150, 0]
- [57990.0, 150, 7.6]
- [58321.0, 150, 6.4]
- [59090.0, 150, 6.9]
- [59468.0, 150, 9.2]
- [59600.0, 150, 0.2]
- [60683.0, 150, 4.1]
- [61156.0, 150, 2.3]
- [61181.0, 130, 2.3]
- [61325.0, 130, 0]
- [61605.0, 130, 7.3]
- [62108.0, 150, 7.3]
- [62246.0, 150, 6.6]
- [62279.0, 150, 5.1]
- [62454.0, 150, 0.9]
- [62777.0, 150, 5.5]
- [63802.0, 150, 4.6]
- [64344.0, 150, 0.2]
- [64932.0, 150, -0.6]
- [65100.0, 150, 0]
- [65690.0, 150, 1.8]
- [65878.0, 150, 2.5]
- [66266.0, 150, -1]
- [66339.0, 150, 6.3]
- [66448.0, 160, 6.3]
- [66587.0, 160, 0]
- [66856.0, 160, 3.2]
- [67480.0, 160, 3.6]
- [67697.0, 160, 2.2]
- [67800.0, 160, 6]
- [67851.0, 130, 6]
- [68027.0, 130, 2.7]
- [68172.0, 130, 0.6]
- [68328.0, 130, 2.5]
- [68357.0, 130, 0]
- [68479.0, 130, 7.1]
- [68783.0, 130, 7.4]
- [69056.0, 150, 7.4]
- [69500.0, 150, 6.8]
- [69741.0, 160, 6.8]
- [69900.0, 160, 6.6]
- [70757.0, 160, 3.6]
- [71384.0, 160, 6]
- [71568.0, 160, 7.1]
- [71800.0, 160, 7.4]
- [72100.0, 160, 7.3]
- [73919.0, 150, 7.3]
- [74317.0, 140, 7.3]
- [74448.0, 140, 1.5]
- [74590.0, 140, -1.5]
- [74620.0, 140, -5]
- [74950.0, 140, -4.3]
- [75100.0, 140, -1.8]
- [75154.0, 130, -1.8]
- [75260.0, 130, -6.2]
- [75873.0, 130, -5.6]
- [76062.0, 100, -5.6]
- [76100.0, 100, -6.4]
- [76350.0, 100, -5.7]
- [76476.0, 100, -7]
- [76600.0, 100, -6.4]
- [76601.0, 90, -6.4]
- [76726.0, 90, -6.2]
- [77256.0, 90, -2.1]
- [77285.0, 80, -2.1]
- [77299.0, 80, -14]
- [77331.0, 80, -1.6]
- [77379.0, 90, -1.6]
- [77425.0, 110, -1.6]
- [77455.0, 110, -4.9]
- [77498.0, 110, 0]
- [77505.0, 160, 0]
- [77555.0, 160, -5.6]
- [77662.0, 160, 0]
- [78085.0, 160, -4]
- [78223.0, 160, -6.8]
- [78337.0, 130, -6.8]
- [78856.0, 130, -6.6]
- [78875.0, 130, -7.2]
- [79345.0, 150, -7.2]
- [79600.0, 150, -6.5]
- [79792.0, 150, -0.2]
- [80537.0, 150, -5.2]
- [81300.0, 150, -4.8]
- [81634.0, 110, -4.8]
- [81943.0, 110, -5.4]
- [82166.0, 110, 0]
- [82408.0, 110, 4.8]
- [82790.0, 110, 5.9]
- [83137.0, 120, 5.9]
- [83300.0, 120, 0]
- [83519.0, 150, 0]
- [83597.0, 150, -7.8]
- [83827.0, 150, -8.1]
- [84150.0, 150, -7.2]
- [84391.0, 150, 0]
- [84966.0, 150, -4]
- [85529.0, 130, -2.3]
- [85589.0, 130, -4]
- [86081.0, 130, 0]
- [86514.0, 130, 7.8]
- [86577.0, 120, 7.8]
- [87554.0, 90, 7.8]
- [87690.0, 90, 7.9]
- [87842.0, 90, 1.7]
- [88007.0, 110, 1.7]
- [88100.0, 110, 3.4]
- [88260.0, 110, 5.3]
- [88376.0, 160, 5.3]
- [88450.0, 160, 6.7]
- [89050.0, 160, 7.4]
- [89350.0, 160, -7.1]
- [90365.0, 160, 0]
- [90700.0, 160, -7.3]
- [92000.0, 160, -7.9]
- [92166.0, 160, -4]
- [92460.0, 160, -5.4]
- [93330.0, 160, 0]
- [93901.0, 160, 0.7]
- [94156.0, 160, 5.2]
- [94440.0, 160, -2.8]
- [94530.0, 160, -0.8]
- [94630.0, 160, -6.8]
- [94830.0, 160, -4.4]
- [95090.0, 160, -4.6]
- [95500.0, 160, -4.8]
- [96500.0, 160, -4.4]
- [96700.0, 160, -5.6]
- [97000.0, 160, -4.6]
- [97590.0, 160, 0]
- [97858.0, 120, 0]
- [98224.0, 120, -1.5]
- [98264.0, 120, 0]
- [98577.0, 120, 7.5]
- [98738.0, 120, 0]
- [99055.0, 130, 0]
- [99427.0, 130, -2]
- [99610.0, 130, -3.1]
- [99906.0, 120, -3.1]
- [99980.0, 120, -1.3]
- [100190.0, 120, -6.8]
- [100832.0, 120, -7.2]
- [100980.0, 120, -8.1]
- [101100.0, 120, -7.4]
- [101245.0, 120, -6.3]
- [101332.0, 100, -6.3]
- [101365.0, 100, -2.4]
- [101551.0, 110, -2.4]
- [101800.0, 110, 0]

View File

@ -1,12 +0,0 @@
%YAML 1.2
---
settings:
# settings for the simulation
massModel: "homogeneous strip" # model type of train mass "mass point" or "homogeneous strip"
stepVariable: "s in m" # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize: 10 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime: true # operation mode "minimum running time"
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
csvDirectory: "~/Desktop/TrainRun"

View File

@ -1,12 +0,0 @@
%YAML 1.2
---
settings:
# settings for the simulation
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
stepVariable: "s in m" # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize: 10 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime: true # operation mode "minimum running time"
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
csvDirectory: "~/Desktop/TrainRun"

View File

@ -1,12 +0,0 @@
%YAML 1.2
---
settings:
# settings for the simulation
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
stepVariable: "s in m" # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize: 10 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime: true # operation mode "minimum running time"
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
typeOfOutput: "CSV" # output as "julia dictionary" or as "CSV"
detailOfOutput: "running time" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
csvDirectory: "~/Desktop/TrainRun"

View File

@ -1,12 +0,0 @@
%YAML 1.2
---
settings:
# settings for the simulation
massModel: "homogeneous strip" # model type of train mass "mass point" or "homogeneous strip"
stepVariable: "t in s" # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize: 3.0 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime: true # operation mode "minimum running time"
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
csvDirectory: "~/Desktop/TrainRun"

View File

@ -1,12 +0,0 @@
%YAML 1.2
---
settings:
# settings for the simulation
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
stepVariable: "t in s" # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize: 3.0 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime: true # operation mode "minimum running time"
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
csvDirectory: "~/Desktop/TrainRun"

View File

@ -1,12 +0,0 @@
%YAML 1.2
---
settings:
# settings for the simulation
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
stepVariable: "v in m/s" # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize: 0.1 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime: true # operation mode "minimum running time"
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
csvDirectory: "~/Desktop/TrainRun"

View File

@ -1,112 +0,0 @@
%YAML 1.2
---
train:
name: "V 90 with 10 ore wagons of type Facs 124" # (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90 and https://dybas.de/dybas/gw/gw_f_1/g124.html)
length: 205.3 # in m (source: FBS: DB 290 with 10x Facs124)
m_td: 80000 # mass on driving axles of the traction unit in kg (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
m_tc: 0 # mass on carrying axles of the traction unit in kg (no carrying axles; source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
m_w: 850000 # mass of the consist (set of wagons) in kg (source: FBS: 10x Facs124)
rotationMassFactor_train:
rotationMassFactor_t: 1.09 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit)
rotationMassFactor_w: 1.03 # (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 13 for "Güterwagenzug beladen" -> 1.03 to 1.04)
powerType: diesel # diesel or electric (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
type: freight # "freight" or "passenger" (source: https://dybas.de/dybas/gw/gw_f_1/g124.html)
v_limit: # in m/s
v_limit_kmh: 80 # in km/h (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
a_braking: -0.4124 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 290 with with 10x Facs124)
# coefficients for the vehicle resistance
# for the traction unit (F_Rt=f_Rtd0*m_td*g+f_Rtc0*m_tc*g+F_Rt2*((v+Δv_t)/v00)^2)
f_Rtd0: 2.2 # coefficient for basic resistance due to the traction units driving axles (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "4-achsige Diesellokomot." -> 2.2 ‰ to 3.5 ‰)
f_Rtc0: 0 # coefficient for basic resistance due to the traction units carring axles (in ‰) (source: no carrying axles; source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
F_Rt2: 7500 # coefficient for air resistance of the traction units (in N) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "MittelfUhrerstand" -> 5000 N to 10000 N)
# for the consist (set of wagons) (F_Rw=m_w*g*(f_Rw0+f_Rw1*v/v00+f_Rw2*((v+Δv_w)/v00)^2))
f_Rw0: 1.4 # coefficient for the consists basic resistance (in ‰) (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for "roller bearings")
f_Rw1: 0 # coefficient for the consists resistance to rolling (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 -> no f_Rw1 for freight consists)
f_Rw2: 3.9 # coefficient fo the consistsr air resistance (in ‰) (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for "full train loads of coal or ore" modified for the used formula)
# tractive effort as pairs of speed and tractive effort
F_T_pairs: # [v in m/s, F_T in N]
F_T_pairs_kmh: # [v in km/h, F_T in N] (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 290 with with 10x Facs124)
- [0.0, 186940]
- [1.0, 186940]
- [2.0, 182310]
- [3.0, 177680]
- [4.0, 173050]
- [5.0, 168420]
- [6.0, 163790]
- [7.0, 159160]
- [8.0, 154530]
- [9.0, 149240]
- [10.0, 144120]
- [11.0, 139150]
- [12.0, 134340]
- [13.0, 129690]
- [14.0, 125200]
- [15.0, 120860]
- [16.0, 116680]
- [17.0, 112660]
- [18.0, 108790]
- [19.0, 105080]
- [20.0, 101530]
- [21.0, 98120]
- [22.0, 94840]
- [23.0, 91700]
- [24.0, 88700]
- [25.0, 85840]
- [26.0, 83110]
- [27.0, 80520]
- [28.0, 78070]
- [29.0, 75750]
- [30.0, 73580]
- [31.0, 71600]
- [32.0, 69660]
- [33.0, 67770]
- [34.0, 65930]
- [35.0, 64130]
- [36.0, 62380]
- [37.0, 60670]
- [38.0, 59010]
- [39.0, 57400]
- [40.0, 55830]
- [41.0, 54300]
- [42.0, 52820]
- [43.0, 51390]
- [44.0, 50000]
- [45.0, 48660]
- [46.0, 48080]
- [47.0, 47220]
- [48.0, 46380]
- [49.0, 45550]
- [50.0, 44730]
- [51.0, 43930]
- [52.0, 43140]
- [53.0, 42370]
- [54.0, 41610]
- [55.0, 40870]
- [56.0, 40140]
- [57.0, 39430]
- [58.0, 38730]
- [59.0, 38040]
- [60.0, 37370]
- [61.0, 36720]
- [62.0, 36070]
- [63.0, 35450]
- [64.0, 34830]
- [65.0, 34230]
- [66.0, 33650]
- [67.0, 33080]
- [68.0, 32520]
- [69.0, 31980]
- [70.0, 31450]
- [71.0, 30940]
- [72.0, 30440]
- [73.0, 29960]
- [74.0, 29490]
- [75.0, 29030]
- [76.0, 28590]
- [77.0, 28170]
- [78.0, 27760]
- [79.0, 27360]
- [80.0, 26980]

View File

@ -1,192 +0,0 @@
%YAML 1.2
---
train:
name: "Intercity 2 (Traxx P160 AC2 + double deck coaches)" # (source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario#Intercity_2 and https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
length: 152 # in m (source: FBS: DB146.5 with 1x DApza687.2, 3x DBpza668.2, 1x DBpbzfa668.2)
m_td: 84000 # mass on driving axles of the traction unit in kg (source: FBS: DB146.5)
m_tc: 0 # mass on carrying axles of the traction unit in kg (no carrying axles; source: FBS: DB146.5)
m_w: 309000 # mass of the consist (set of wagons) in kg (source: FBS: 1x DApza687.2, 3x DBpza668.2, 1x DBpbzfa668.2)
rotationMassFactor_train:
rotationMassFactor_t: 1.09 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit)
rotationMassFactor_w: 1.06 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for freight wagons)
powerType: electric # diesel or electric (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn)#Gemeinsame_Merkmale)
type: passenger # "freight" or "passenger" (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
v_limit: # in m/s
v_limit_kmh: 160 # in km/h (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn)#Gemeinsame_Merkmale)
a_braking: -0.3507 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB146.5 with 1x DApza687.2, 3x DBpza668.2, 1x DBpbzfa668.2)
# coefficients for the vehicle resistance
# for the traction unit (F_Rt=f_Rtd0*m_td*g+f_Rtc0*m_tc*g+F_Rt2*((v+Δv_t)/v00)^2)
f_Rtd0: 2.5 # coefficient for basic resistance due to the traction units driving axles (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "Hochgeschwindigkeitslok."" -> 2.0 ‰ to 3.0 ‰)
f_Rtc0: 0 # coefficient for basic resistance due to the traction units carring axles (in ‰) (source: no carrying axles; source: FBS: DB146.5)
F_Rt2: 5000 # coefficient for air resistance of the traction units (in N) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "4-achsig, eckige Kopfform"with "Stromabnehmer" -> 5000 N to 6000 N)
# for the consist (set of wagons) (F_Rw=m_w*g*(f_Rw0+f_Rw1*v/v00+f_Rw2*((v+Δv_w)/v00)^2))
f_Rw0: 2.0 # coefficient for the consists basic resistance (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge")
f_Rw1: 0.715 # coefficient for the consists resistance to rolling (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge")
f_Rw2: 3.64 # coefficient fo the consistsr air resistance (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge")
# tractive effort as pairs of speed and tractive effort
F_T_pairs: # [v in m/s, F_T in N]
F_T_pairs_kmh: # [v in km/h, F_T in N] (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB146.5 with 1x DApza687.2, 3x DBpza668.2, 1x DBpbzfa668.2)
- [0.0, 300000]
- [1.0, 300000]
- [2.0, 300000]
- [3.0, 300000]
- [4.0, 300000]
- [5.0, 300000]
- [6.0, 300000]
- [7.0, 300000]
- [8.0, 300000]
- [9.0, 300000]
- [10.0, 300000]
- [11.0, 300000]
- [12.0, 300000]
- [13.0, 300000]
- [14.0, 300000]
- [15.0, 300000]
- [16.0, 300000]
- [17.0, 300000]
- [18.0, 300000]
- [19.0, 300000]
- [20.0, 300000]
- [21.0, 300000]
- [22.0, 300000]
- [23.0, 300000]
- [24.0, 300000]
- [25.0, 300000]
- [26.0, 300000]
- [27.0, 300000]
- [28.0, 300000]
- [29.0, 300000]
- [30.0, 300000]
- [31.0, 300000]
- [32.0, 300000]
- [33.0, 300000]
- [34.0, 300000]
- [35.0, 300000]
- [36.0, 300000]
- [37.0, 300000]
- [38.0, 300000]
- [39.0, 300000]
- [40.0, 300000]
- [41.0, 300000]
- [42.0, 300000]
- [43.0, 300000]
- [44.0, 300000]
- [45.0, 300000]
- [46.0, 300000]
- [47.0, 300000]
- [48.0, 300000]
- [49.0, 300000]
- [50.0, 300000]
- [51.0, 300000]
- [52.0, 300000]
- [53.0, 300000]
- [54.0, 300000]
- [55.0, 300000]
- [56.0, 300000]
- [57.0, 300000]
- [58.0, 300000]
- [59.0, 300000]
- [60.0, 300000]
- [61.0, 300000]
- [62.0, 300000]
- [63.0, 300000]
- [64.0, 300000]
- [65.0, 300000]
- [66.0, 300000]
- [67.0, 297760]
- [68.0, 293380]
- [69.0, 289130]
- [70.0, 285000]
- [71.0, 280990]
- [72.0, 277080]
- [73.0, 273290]
- [74.0, 269590]
- [75.0, 266000]
- [76.0, 262500]
- [77.0, 259090]
- [78.0, 255770]
- [79.0, 252530]
- [80.0, 249380]
- [81.0, 246300]
- [82.0, 243290]
- [83.0, 240360]
- [84.0, 237500]
- [85.0, 234710]
- [86.0, 231980]
- [87.0, 229310]
- [88.0, 226700]
- [89.0, 224160]
- [90.0, 221670]
- [91.0, 219230]
- [92.0, 216850]
- [93.0, 214520]
- [94.0, 212230]
- [95.0, 210000]
- [96.0, 207810]
- [97.0, 205670]
- [98.0, 203570]
- [99.0, 201520]
- [100.0, 199500]
- [101.0, 197520]
- [102.0, 195590]
- [103.0, 193690]
- [104.0, 191830]
- [105.0, 190000]
- [106.0, 188210]
- [107.0, 186450]
- [108.0, 184720]
- [109.0, 183030]
- [110.0, 181360]
- [111.0, 179730]
- [112.0, 178130]
- [113.0, 176550]
- [114.0, 175000]
- [115.0, 173480]
- [116.0, 171980]
- [117.0, 170510]
- [118.0, 169070]
- [119.0, 167650]
- [120.0, 166250]
- [121.0, 164880]
- [122.0, 163520]
- [123.0, 162200]
- [124.0, 160890]
- [125.0, 159600]
- [126.0, 158330]
- [127.0, 157090]
- [128.0, 155860]
- [129.0, 154650]
- [130.0, 153460]
- [131.0, 152290]
- [132.0, 151140]
- [133.0, 150000]
- [134.0, 148880]
- [135.0, 147780]
- [136.0, 146690]
- [137.0, 145620]
- [138.0, 144570]
- [139.0, 143530]
- [140.0, 142500]
- [141.0, 141490]
- [142.0, 140490]
- [143.0, 139510]
- [144.0, 138540]
- [145.0, 137590]
- [146.0, 136640]
- [147.0, 135710]
- [148.0, 134800]
- [149.0, 133890]
- [150.0, 133000]
- [151.0, 132120]
- [152.0, 131250]
- [153.0, 130390]
- [154.0, 129550]
- [155.0, 128710]
- [156.0, 127880]
- [157.0, 127070]
- [158.0, 126270]
- [159.0, 125470]
- [160.0, 124690]

View File

@ -1,152 +0,0 @@
%YAML 1.2
---
train:
name: "Siemens Desiro Classic" # (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
length: 41.7 # in m (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
m_td: 52800 # mass on driving axles of the traction unit in kg (source: FBS: DB 642; proportionately to the number of axles: 4 to 2, see: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
m_tc: 35200 # mass on carrying axles of the traction unit in kg (source: FBS: DB 642; proportionately to the number of axles: 4 to 2, see: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
m_w: 0 # mass of the consist (set of wagons) in kg (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic -> no separate wagons)
rotationMassFactor_train: 1.08 # (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 13 for "Zug, überschlägliche Berechnung")
rotationMassFactor_t:
rotationMassFactor_w:
powerType: diesel # diesel or electric (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
type: passenger # "freight" or "passenger" (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
v_limit: # in m/s
v_limit_kmh: 120 # in km/h (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
a_braking: -0.4253 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 642)
# coefficients for the vehicle resistance
# for the traction unit (F_Rt=f_Rtd0*m_td*g+f_Rtc0*m_tc*g+F_Rt2*((v+Δv_t)/v00)^2)
f_Rtd0: 3.0 # coefficient for basic resistance due to the traction units driving axles (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "f_WL0" -> 2.5 ‰ to 3.5 ‰)
f_Rtc0: 1.4 # coefficient for basic resistance due to the traction units carring axles (in ‰) (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "f_WW0" -> 1.2 ‰ to 1.6 ‰)
F_Rt2: 2600 # coefficient for air resistance of the traction units (in N) (source: the closest parameters are used: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "Fzg. vierachsig, abgerundeter Kopf" plus "Sektion bei Mehrteiligkeit" -> 2200 N + 400 N)
# for the consist (set of wagons) (F_Rw=m_w*g*(f_Rw0+f_Rw1*v/v00+f_Rw2*((v+Δv_w)/v00)^2))
f_Rw0: # coefficient for basic resistance of the set of wagons (in ‰) (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic -> no separate wagons)
f_Rw1: # coefficient for resistance to rolling of the set of wagons (in ‰) (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic -> no separate wagons)
f_Rw2: # coefficient for air resistance of the set of wagons (in ‰) (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic -> no separate wagons)
# tractive effort as pairs of speed and tractive effort
F_T_pairs: # [v in m/s, F_T in N]
F_T_pairs_kmh: # [v in km/h, F_T in N] (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 642)
- [0.0, 94400]
- [1.0, 94400]
- [2.0, 92800]
- [3.0, 91200]
- [4.0, 89600]
- [5.0, 88000]
- [6.0, 86400]
- [7.0, 84800]
- [8.0, 83200]
- [9.0, 81600]
- [10.0, 80000]
- [11.0, 78160]
- [12.0, 76290]
- [13.0, 74420]
- [14.0, 72550]
- [15.0, 70680]
- [16.0, 68810]
- [17.0, 66940]
- [18.0, 65070]
- [19.0, 63200]
- [20.0, 61330]
- [21.0, 59460]
- [22.0, 57590]
- [23.0, 55720]
- [24.0, 53850]
- [25.0, 51980]
- [26.0, 50110]
- [27.0, 48240]
- [28.0, 46370]
- [29.0, 44500]
- [30.0, 42630]
- [31.0, 40760]
- [32.0, 38890]
- [33.0, 38110]
- [34.0, 37330]
- [35.0, 36550]
- [36.0, 35770]
- [37.0, 35600]
- [38.0, 35600]
- [39.0, 35600]
- [40.0, 35600]
- [41.0, 35600]
- [42.0, 35600]
- [43.0, 35550]
- [44.0, 35280]
- [45.0, 35010]
- [46.0, 34740]
- [47.0, 34280]
- [48.0, 33560]
- [49.0, 32880]
- [50.0, 32220]
- [51.0, 31590]
- [52.0, 26300]
- [53.0, 26300]
- [54.0, 26300]
- [55.0, 26300]
- [56.0, 26300]
- [57.0, 25990]
- [58.0, 25840]
- [59.0, 25690]
- [60.0, 25540]
- [61.0, 25390]
- [62.0, 25240]
- [63.0, 25090]
- [64.0, 25140]
- [65.0, 24760]
- [66.0, 24380]
- [67.0, 24020]
- [68.0, 23660]
- [69.0, 23320]
- [70.0, 22990]
- [71.0, 19400]
- [72.0, 19400]
- [73.0, 19400]
- [74.0, 19400]
- [75.0, 19400]
- [76.0, 19400]
- [77.0, 19400]
- [78.0, 19400]
- [79.0, 19400]
- [80.0, 19400]
- [81.0, 19440]
- [82.0, 19310]
- [83.0, 19180]
- [84.0, 19050]
- [85.0, 18920]
- [86.0, 18670]
- [87.0, 18460]
- [88.0, 18250]
- [89.0, 15360]
- [90.0, 15310]
- [91.0, 15260]
- [92.0, 15210]
- [93.0, 15160]
- [94.0, 15110]
- [95.0, 15060]
- [96.0, 15010]
- [97.0, 14960]
- [98.0, 14910]
- [99.0, 14860]
- [100.0, 14810]
- [101.0, 14760]
- [102.0, 14710]
- [103.0, 14660]
- [104.0, 14610]
- [105.0, 14560]
- [106.0, 14510]
- [107.0, 14460]
- [108.0, 14410]
- [109.0, 14360]
- [110.0, 14310]
- [111.0, 14460]
- [112.0, 14340]
- [113.0, 14210]
- [114.0, 14080]
- [115.0, 13960]
- [116.0, 13840]
- [117.0, 13720]
- [118.0, 13610]
- [119.0, 13490]
- [120.0, 13380]

10
docs/DEFAULT.yaml Normal file
View File

@ -0,0 +1,10 @@
%YAML 1.2
---
settings:
# default settings for the calculation
massModel: "mass_point" # type of train model used: "mass_point" or "homogeneous_strip"
stepVariable: "distance" # variable of the linear multistep method: "distance", "time" or "velocity"
stepSize: 20 # step size, unit depends on stepVariable - distance in meter, time in seconds and velocity in meter/second.
approxLevel: 3 # value for approximation; used when rounding or interating
outputDetail: "running_time" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
outputFormat: "dataframe" # output as "dataframe" or as "dict"

3
docs/Project.toml Normal file
View File

@ -0,0 +1,3 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
TrainRuns = "e4541106-d44c-4e00-b50b-ecdf479fcf92"

View File

@ -0,0 +1,32 @@
#!/usr/bin/env julia
import TrainRuns
paths=[]
push!(paths, importFromYaml(:path, "data/paths/path_1_10km_nConst_vConst.yaml"))
push!(paths, importFromYaml(:path, "data/paths/path_2_10km_nVar_vConst.yaml"))
push!(paths, importFromYaml(:path, "data/paths/path_3_10km_nConst_vVar.yaml"))
push!(paths, importFromYaml(:path, "data/paths/path_4_real_Germany_EastSaxony_DG-DN.yaml"))
settings=[]
push!(settings, importFromYaml(:settings, "data/settings/settings_distanceStep_massPoint.yaml"))
trains=[]
push!(trains, importFromYaml(:train, "data/trains/train_freight_V90withOreConsist.yaml"))
push!(trains, importFromYaml(:train, "data/trains/train_passenger_SiemensDesiroClassic.yaml"))
push!(trains, importFromYaml(:train, "data/trains/train_passenger_IC2.yaml"))
for path in paths
# println(" - - - - - - - - -")
# println("path: ", path[:name])
for train in trains
# println("train: ", train[:name])
for settings in settings
resultsDict = trainrun(train, path, settings)
if haskey(settings, :outputFormat) && settings[:outputFormat] == "CSV"
exportToCsv(resultsDict, settings)
sleep(2)
end
end
end
end

View File

@ -0,0 +1,10 @@
#!/usr/bin/env julia
using TrainRuns
train = Train("test/data/trains/freight.yaml")
path = Path("test/data/paths/const.yaml")
runtime = trainrun(train, path)
println("The train needs $runtime seconds for the running path.")

24
docs/make.jl Normal file
View File

@ -0,0 +1,24 @@
using TrainRuns
using Documenter
DocMeta.setdocmeta!(TrainRuns, :DocTestSetup, :(using TrainRuns); recursive=true)
makedocs(;
modules=[TrainRuns],
authors="Max Kannenberg, Martin Scheidt, and contributors",
repo="https://github.com/railtoolkit/TrainRuns.jl/blob/{commit}{path}#{line}",
sitename="TrainRuns.jl",
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", "false") == "true",
canonical="https://railtoolkit.github.io/TrainRuns.jl",
assets=String[],
),
pages=[
"Home" => "index.md",
],
)
deploydocs(;
repo="github.com/railtoolkit/TrainRuns.jl",
devbranch="development",
)

14
docs/src/index.md Normal file
View File

@ -0,0 +1,14 @@
```@meta
CurrentModule = TrainRuns
```
# TrainRuns
Documentation for [TrainRuns](https://github.com/railtoolkit/TrainRuns.jl).
```@index
```
```@autodocs
Modules = [TrainRuns]
```

View File

@ -1,44 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.0
# __author__ = "Max Kannenberg"
# __copyright__ = "2021"
# __license__ = "ISC"
include("../src/TrainRun.jl")
using .TrainRun
allPaths=[]
push!(allPaths, importFromYaml(:path, "data/paths/path_1_10km_nConst_vConst.yaml"))
push!(allPaths, importFromYaml(:path, "data/paths/path_2_10km_nVar_vConst.yaml"))
push!(allPaths, importFromYaml(:path, "data/paths/path_3_10km_nConst_vVar.yaml"))
push!(allPaths, importFromYaml(:path, "data/paths/path_4_real_Germany_EastSaxony_DG-DN.yaml"))
allSettings=[]
push!(allSettings, importFromYaml(:settings, "data/settings/settings_distanceStep_massPoint.yaml"))
allTrains=[]
push!(allTrains, importFromYaml(:train, "data/trains/train_freight_V90withOreConsist.yaml"))
push!(allTrains, importFromYaml(:train, "data/trains/train_passenger_SiemensDesiroClassic.yaml"))
push!(allTrains, importFromYaml(:train, "data/trains/train_passenger_IC2.yaml"))
for path in allPaths
# println(" - - - - - - - - -")
# println("path: ", path[:name])
for train in allTrains
# println("train: ", train[:name])
for settings in allSettings
resultsDict = trainRun(train, path, settings)
if haskey(settings, :typeOfOutput) && settings[:typeOfOutput] == "CSV"
exportToCsv(resultsDict, settings)
sleep(2)
end
# println("")
end
end
# println("")
end
# println("")
# println("________________________")
# println("")

View File

@ -1,19 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.0
# __author__ = "Max Kannenberg"
# __copyright__ = "2021"
# __license__ = "ISC"
include("../src/TrainRun.jl")
using .TrainRun
train_directory = "data/trains/train_freight_V90withOreConsist.yaml"
running_path_directory = "data/paths/path_1_10km_nConst_vConst.yaml"
setting_directory = "data/settings/settings_distanceStep_massPoint_runningTime.yaml"
(train, running_path, settings) = importYamlFiles(train_directory, running_path_directory, setting_directory)
runtime = trainRun(train, running_path, settings)
exportToCsv(runtime, settings)
println("The V 90 with 10 ore wagons needs $runtime seconds for 10 km with no gradient.")

View File

@ -1,210 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Max Kannenberg"
# __copyright__ = "2020-2022"
# __license__ = "ISC"
# INFO: AdditionalOutput should not be used because it is not completed yet. It was used to show first results during development.
# TODO: It has to be optimized so that the created plots and printed information is clear and understandable.
module AdditionalOutput
using Plots
export plotResults, plotDrivingCourse, printImportantValues, printSectionInformation
function plotResults(output::Dict)
opModeMinTime = output[:settings][:operationModeMinimumRunningTime]
opModeMinEnergy = output[:settings][:operationModeMinimumEnergyConsumption]
if opModeMinTime == true && opModeMinEnergy == true
plotDrivingCourse(output[:drivingCourseMinimumRunningTime], output[:drivingCourseMinimumEnergyConsumption])
elseif opModeMinTime == true
plotDrivingCourse(output[:drivingCourseMinimumRunningTime])
elseif opModeMinEnergy == true
plotDrivingCourse(output[:drivingCourseMinimumEnergyConsumption])
else
output[:settings][:detailOfOutput] == "everything" && println("No Output was demanded. So no plot is created.")
end
return true
end #function plotResults
function plotResults(drivingCourse::Vector{Dict})
plotDrivingCourse(drivingCourse)
return true
end #function plotResults
function plotResults(singleValue::AbstractFloat)
println("Not able to plot the single value ",singleValue)
return false
end #function plotResults
function plotDrivingCourse(drivingCourse::Vector{Dict})
a=[]
E=[]
s=[]
t=[]
v=[]
for i in 1:length(drivingCourse)
push!(a, drivingCourse[i][:a])
push!(E, drivingCourse[i][:E])
push!(s, drivingCourse[i][:s])
push!(t, drivingCourse[i][:t])
push!(v, drivingCourse[i][:v])
end #for
# p1=plot([s], [v], title = "v in m/s", label = ["v"], xlabel = "s in m")
p1=plot([s/1000], [v*3.6], title = "v in km/h", label = ["v"], xlabel = "s in km")
# p2=plot([t], [v], title = "v in m/s", label = ["v"], xlabel = "t in s")
p2=plot([t/60], [v*3.6], title = "v in km/h", label = ["v"], xlabel = "t in min")
# p3=plot([s], [t], title = "t in s", label = ["t"], xlabel = "s in m")
# p4=plot([t], [s], title = "s in m", label = ["s"], xlabel = "t in s")
#p5=plot([s], [E], title = "E in Ws", label = ["E"], xlabel = "s in m")
p5=plot([s/1000], [E], title = "E in Ws", label = ["E"], xlabel = "s in km")
#p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s")
p6=plot([t/60], [E], title = "E in Ws", label = ["E"], xlabel = "t in min")
all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false)
#=
# p5=plot([s], [E], title = "E in Ws", label = ["E"], xlabel = "s in m")
# p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s")
all=plot(p1, p2, layout = (1, 2), legend = false)=#
# all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
display(all)
println("Plots for different variables have been created.")
end #function plotDrivingCourse
function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{Dict},drivingCourseMinimumEnergyConsumption::Vector{Dict})
a_minTime=[]
E_minTime=[]
s_minTime=[]
t_minTime=[]
v_minTime=[]
for i in 1:length(drivingCourseMinimumRunningTime)
push!(a_minTime, drivingCourseMinimumRunningTime[i][:a])
push!(E_minTime, drivingCourseMinimumRunningTime[i][:E])
push!(s_minTime, drivingCourseMinimumRunningTime[i][:s])
push!(t_minTime, drivingCourseMinimumRunningTime[i][:t])
push!(v_minTime, drivingCourseMinimumRunningTime[i][:v])
end #for
a_minEnergy=[]
E_minEnergy=[]
s_minEnergy=[]
t_minEnergy=[]
v_minEnergy=[]
for i in 1:length(drivingCourseMinimumEnergyConsumption)
push!(a_minEnergy, drivingCourseMinimumEnergyConsumption[i][:a])
push!(E_minEnergy, drivingCourseMinimumEnergyConsumption[i][:E])
push!(s_minEnergy, drivingCourseMinimumEnergyConsumption[i][:s])
push!(t_minEnergy, drivingCourseMinimumEnergyConsumption[i][:t])
push!(v_minEnergy, drivingCourseMinimumEnergyConsumption[i][:v])
end #for
p1=plot([s_minTime,s_minEnergy],
[v_minTime,v_minEnergy],
title = "v in m/s",
label = ["v for t_min" "v for E_min"],
xlabel = "s in m")# lw = 3)
p2=plot([t_minTime,t_minEnergy],
[v_minTime,v_minEnergy],
title = "v in m/s",
label = ["v for t_min" "v for E_min"],
xlabel = "t in s")
# p3=plot([s_minTime,s_minEnergy],
# [t_minTime,t_minEnergy],
# title = "t in s",
# label = ["t for t_min" "t for E_min"],
# xlabel = "s in m")
# p4=plot([t_minTime,t_minEnergy],
# [s_minTime,s_minEnergy],
# title = "s in m",
# label = ["s for t_min" "s for E_min"],
# xlabel = "t in s")
p5=plot([s_minTime,s_minEnergy],
[E_minTime,E_minEnergy],
title = "E in Ws",
label = ["E for t_min" "E for E_min"],
xlabel = "s in m")
p6=plot([t_minTime,t_minEnergy],
[E_minTime,E_minEnergy],
title = "E in Ws",
label = ["E for t_min" "E for E_min"],
xlabel = "t in s")
# all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false)
display(all)
println("Plots for different variables have been created.")
end #function plotDrivingCourse
function printImportantValues(dataPoints::Vector{Dict})
println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh")
for i in 1:length(dataPoints)
println(dataPoints[i][:i],". ",dataPoints[i][:behavior]," ",dataPoints[i][:s]," ",dataPoints[i][:v]*3.6," ",dataPoints[i][:t]/60," ",dataPoints[i][:a]," ",dataPoints[i][:F_R]/1000," ",dataPoints[i][:F_T]/1000," ",dataPoints[i][:E]/3600/1000)
end #for
println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh")
end #function printImportantValues
function printSectionInformation(movingSection::Dict)
CSs::Vector{Dict} = movingSection[:characteristicSections]
println("MS with length=", movingSection[:length]," with t=", movingSection[:t])
#allBSs=[:breakFree, :clearing, :accelerating, :clearing2, :accelerating2, :clearing3, :accelerating3, :cruising, :downhillBraking, :diminishing, :coasting, :braking, :standstill]
for csId in 1:length(CSs)
println("CS ",csId," with length=", CSs[csId][:length]," with t=", CSs[csId][:t])
# for bs in 1: length(allBSs)
# if haskey(CSs[csId][:behaviorSections], allBSs[bs])
# println("BS ",allBSs[bs], " with s_entry=", CSs[csId][:behaviorSections][allBSs[bs]][:s_entry], " and length=",CSs[csId][:behaviorSections][allBSs[bs]][:length]) # and t=", CSs[csId][:behaviorSections][allBSs[bs]][:t])
# # for point in 1:length(CSs[csId][:behaviorSections][allBSs[bs]][:dataPoints])
# # println(CSs[csId][:behaviorSections][allBSs[bs]][:dataPoints][point])
# # end
# end #if
# end #for
tempBSs = collect(keys(CSs[csId][:behaviorSections]))
while length(tempBSs) > 0
currentBS = :default
for bs in 1: length(tempBSs)
if currentBS == :default
currentBS = tempBSs[bs]
else
if CSs[csId][:behaviorSections][currentBS][:s_entry] > CSs[csId][:behaviorSections][tempBSs[bs]][:s_entry]
currentBS = tempBSs[bs]
end
end
end #for
println("BS ",currentBS, " with s_entry=", CSs[csId][:behaviorSections][currentBS][:s_entry], " and length=",CSs[csId][:behaviorSections][currentBS][:length]) # and t=", CSs[csId][:behaviorSections][currentBS][:t])
# for point in 1:length(CSs[csId][:behaviorSections][currentBS][:dataPoints])
# println(CSs[csId][:behaviorSections][currentBS][:dataPoints][point])
# end
newTempBSs = []
for bs in 1: length(tempBSs)
if currentBS != tempBSs[bs]
push!(newTempBSs, tempBSs[bs])
end #if
end #for
tempBSs = newTempBSs
end #while
end #for
end #function printSectionInformation
end # module AdditionalOutput

File diff suppressed because it is too large Load Diff

View File

@ -1,220 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Max Kannenberg"
# __copyright__ = "2020-2022"
# __license__ = "ISC"
module Export
using CSV, DataFrames, Dates
export exportToCsv
function exportToCsv(runningTime::AbstractFloat, settings::Dict)
createCsvFile(runningTime, settings)
return true
end
function exportToCsv(dataPointsToExport::Vector{Dict}, settings::Dict)
createCsvFile(dataPointsToExport, settings)
return true
end
function exportToCsv(output::Dict)
if output[:settings][:typeOfOutput] == "CSV"
pathName = output[:path][:name]
trainName = output[:train][:name]
if output[:settings][:operationModeMinimumRunningTime] == true
operationMode = "minimum running time"
if output[:settings][:detailOfOutput] == "points of interest"
dataPointsToExport = output[:pointsOfInterestMinimumRunningTime]
else
dataPointsToExport = output[:drivingCourseMinimumRunningTime]
end
createCsvFile(dataPointsToExport, operationMode, pathName, trainName, output[:settings])
end
if output[:settings][:operationModeMinimumEnergyConsumption] == true
operationMode = "minimum energy consumption"
if output[:settings][:detailOfOutput] == "points of interest"
dataPointsToExport = output[:pointsOfInterestMinimumEnergyConsumption]
else
dataPointsToExport = output[:drivingCourseMinimumEnergyConsumption]
end
createCsvFile(dataPointsToExport, operationMode, pathName, trainName, output[:settings])
end
return true
end
return false
end #function exportToCsv
function createCsvFile(runningTime::AbstractFloat, settings::Dict)
# create DataFrame with running time information
df = DataFrame(column1=["t (in s)", runningTime])
# save DataFrame as a CSV-file at csvDirectory
date = Dates.now()
dateString = Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath = settings[:csvDirectory]*"/"*dateString*"_RunningTime.csv"
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created at ",csvFilePath)
return true
end #function createCsvFile
function createCsvFile(dataPointsToExport::Vector{Dict}, settings::Dict)
detailOfOutput = settings[:detailOfOutput]
header = ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]
columnSymbols = [:i, :behavior, :Δs, :s, :Δt, :t, :Δv, :v, :F_T, :F_R, :R_path, :R_train, :R_traction, :R_wagons, :ΔW, :W, :ΔE, :E, :a]
allColumns = Array{Any,1}[]
for column in 1:length(header)
currentColumn = Any[]
push!(currentColumn, header[column])
for point in dataPointsToExport
push!(currentColumn, point[columnSymbols[column]])
end
push!(allColumns, currentColumn)
end # for
# combine the columns in a data frame and saving it as a CSV-file at csvDirectory
if detailOfOutput == "driving course" || detailOfOutput == "points of interest"
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18], c19=allColumns[19])
else
println("")
end
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_DataPoints.csv"
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created at ",csvFilePath)
return true
end #function createCsvFile
function createCsvFile(dataPointsToExport::Vector{Dict}, operationMode::String, pathName::String, trainName::String, settings::Dict)
detailOfOutput = settings[:detailOfOutput]
massModel = settings[:massModel]
stepVariable = settings[:stepVariable]
stepSize = string(settings[:stepSize])
# create accumulated data block
accumulatedData = Array{Any, 1}[]
push!(accumulatedData, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to accumulatedData
for point in dataPointsToExport
row = [point[:i], point[:behavior], point[:Δs], point[:s], point[:Δt], point[:t], point[:Δv], point[:v], point[:F_T], point[:F_R], point[:R_path], point[:R_train], point[:R_traction], point[:R_wagons], point[:ΔW], point[:W], point[:ΔE], point[:E], point[:a]]
push!(accumulatedData, row) # push row to accumulatedData
end
#create information block
allColumns=Array{Any,1}[]
push!(allColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
push!(allColumns, [pathName, trainName, operationMode, massModel, stepVariable, stepSize, ""])
for column in 3:length(accumulatedData[1])
push!(allColumns, ["", "", "", "", "", "", ""])
end # for
# add driving data to the array
header = accumulatedData[1]
for column in 1:length(accumulatedData[1])
push!(allColumns[column], header[column])
for row in accumulatedData[2:end]
push!(allColumns[column], row[column])
end
end # for
# combine the columns in a data frame and saving it as a CSV-file at csvDirectory
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18], c19=allColumns[19])
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
if operationMode == "minimum running time"
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumRunningTime.csv"
elseif operationMode == "minimum energy consumption"
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumEnergyConsumption.csv"
else
# should not be possible
end
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for ",operationMode," at ",csvFilePath)
return true
end #function createCsvFile
#=
function createCsvFile(movingSection::Dict, dataPointsToExport::Vector{Dict}, operationMode::String, pathName::String, trainName::String, settings::Dict)
detailOfOutput = settings[:detailOfOutput]
massModel = settings[:massModel]
stepVariable = settings[:stepVariable]
stepSize = string(settings[:stepSize])
# create accumulated data block
accumulatedData = Array{Any, 1}[]
if detailOfOutput == "minimal"
push!(accumulatedData, ["s (in m)", "t (in s)","E (in Ws)"]) # push header to accumulatedData
row = [movingSection[:length], movingSection[:t], movingSection[:E]]
push!(accumulatedData, row) # push row to accumulatedData
elseif detailOfOutput == "driving course" || detailOfOutput == "points of interest"
push!(accumulatedData, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to accumulatedData
for point in dataPointsToExport
row = [point[:i], point[:behavior], point[:Δs], point[:s], point[:Δt], point[:t], point[:Δv], point[:v], point[:F_T], point[:F_R], point[:R_path], point[:R_train], point[:R_traction], point[:R_wagons], point[:ΔW], point[:W], point[:ΔE], point[:E], point[:a]]
push!(accumulatedData, row) # push row to accumulatedData
end
end
#create information block
allColumns=Array{Any,1}[]
push!(allColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
push!(allColumns, [pathName, trainName, operationMode, massModel, stepVariable, stepSize, ""])
for column in 3:length(accumulatedData[1])
push!(allColumns, ["", "", "", "", "", "", ""])
end # for
# add driving data to the array
header = accumulatedData[1]
for column in 1:length(accumulatedData[1])
push!(allColumns[column], header[column])
for row in accumulatedData[2:end]
push!(allColumns[column], row[column])
end
end # for
# combine the columns in a data frame and saving it as a CSV-file at csvDirectory
if detailOfOutput == "minimal"
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif detailOfOutput=="driving course" || detailOfOutput == "points of interest"
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18], c19=allColumns[19])
end
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
if operationMode == "minimum running time"
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumRunningTime.csv"
elseif operationMode == "minimum energy consumption"
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumEnergyConsumption.csv"
else
# should not be possible
end
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for ",operationMode," at ",csvFilePath)
return true
end #function createCsvFile
=#
end #module Export

View File

@ -1,44 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Max Kannenberg"
# __copyright__ = "2020-2022"
# __license__ = "ISC"
module Import
import YAML
export importYamlFiles, importFromYaml
"""
Read the input information from YAML files for train, path and settings, save it in different dictionaries and return them.
"""
function importYamlFiles(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
train = importFromYaml(:train, trainDirectory)
path = importFromYaml(:path, pathDirectory)
settings = importFromYaml(:settings, settingsDirectory)
return (train, path, settings)
end #function importYamlFiles
"""
Read the train information from a YAML file, save it in a Dict and return it.
"""
function importFromYaml(dataType::Symbol, directory::String)
dataSet = String(dataType)
data = YAML.load(open(directory))
if collect(keys(data))[1] != dataSet
error("ERROR at reading the ", dataSet, " yaml file: The data set is called ", collect(keys(data))[1]," and not ", dataSet, ".")
end
dataKeys = collect(keys(data[dataSet]))
dataKeys = collect(keys(data[dataSet]))
dataValues = collect(values(data[dataSet]))
dictionary = Dict()
for number in 1:length(dataKeys)
merge!(dictionary, Dict(Symbol(dataKeys[number]) => dataValues[number]))
end
return dictionary
end # function importFromYaml
end # module Input

View File

@ -1,55 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Max Kannenberg"
# __copyright__ = "2020-2022"
# __license__ = "ISC"
module TrainRun
# include main module TrainRunCalc
include("./TrainRunCalc.jl")
# include additional modules
include("./Import.jl")
include("./Export.jl")
# include additional modules that are not recommended to use in this state
include("./AdditionalOutput.jl")
include("./EnergySaving.jl")
# use main module TrainRunCalc
using .TrainRunCalc
# use additional modules
using .Import
using .Export
# use additional modules that are not recommended to use in this state
using .AdditionalOutput
using .EnergySaving
# main function
export trainRun,
# import functions
importYamlFiles, importFromYaml,
# functions for saving energy that are not recommended to use in this state
addOperationModeEnergySaving!,
# export functions
exportToCsv,
# functions for visualising results that are not recommended to use in this state
plotResults, plotDrivingCourse, printImportantValues, printSectionInformation
# approximationLevel = 6 # value for approximation to intersections
# TODO: define it here and give it to each function? (Behavior, EnergySaving, ..)
"""
TODO: Package description
"""
end # module TrainRun

64
src/TrainRuns.jl Normal file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Max Kannenberg, Martin Scheidt"
# __copyright__ = "2020-2022"
# __license__ = "ISC"
__precompile__(true)
module TrainRuns
## loading standard library packages
using UUIDs, Dates, Statistics
## loading external packages
using YAML, JSONSchema, DataFrames
export
## Interface
trainrun, Train, Path, Settings
## global variables
global g = 9.80665 # acceleration due to gravity (in m/s^2)
global μ = 0.2 # friction as constant, todo: implement as function
global Δv_air = 15.0/3.6 # coefficient for velocitiy difference between train and outdoor air (in m/s)
## include package files
include("types.jl")
include("constructors.jl")
include("formulary.jl")
include("calc.jl")
include("characteristics.jl")
include("behavior.jl")
include("output.jl")
## main function
"""
trainrun(train::Train, path::Path, settings::Settings)
Calculate the running time of a `train` on a `path`.
The `settings` provides the choice of models for the calculation.
`settings` can be omitted. If so, a default is used.
The running time will be return in seconds.
# Examples
```julia-repl
julia> trainrun(train, path)
xxx.xx # in seconds
```
"""
function trainrun(train::Train, path::Path, settings=Settings()::Settings)
# prepare the input data
movingSection = determineCharacteristics(path, train, settings)
settings.outputDetail == :everything && println("The moving section has been prepared.")
# calculate the train run for oparation mode "minimum running time"
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
settings.outputDetail == :everything && println("The driving course for the shortest running time has been calculated.")
# accumulate data and create an output dictionary
output = createOutput(train, settings, path, movingSection, drivingCourse)
return output
end # function trainrun
end # module TrainRuns

View File

@ -1,757 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Max Kannenberg"
# __copyright__ = "2022"
# __license__ = "ISC"
# TODO: 2022-04-07: if EnergySaving should be used. The train type has do be defined and checked
module Validate
export checkAndSetInput!
approximationLevel = 6 # value for approximation to intersections TODO further explanation
"""
Read the input information from YAML files for train, path and settings, save it in different dictionaries and return them.
"""
function checkAndSetInput!(train::Dict, path::Dict, settings::Dict)
checkAndSetTrain!(train)
checkAndSetPath!(path)
checkAndSetSettings!(settings)
if settings[:detailOfOutput] == "points of interest" && !haskey(path, :pointsOfInterest)
settings[:detailOfOutput] = "driving course"
println("INFO at checking the input for settings and path: settings[:detailOfOutput] is 'points of interest' but the path does not have a list for pointsOfInterest. Therefore the detailOfOut is changed to 'driving course'.")
end
return (train, path, settings)
end #function checkAndSetInput!
"""
Read the train information from a YAML file, save it in a train Dict and return it.
"""
function checkAndSetTrain!(train::Dict)
# check train information from input dictionary
checkAndSetString!(train, "train", :name, "") # train's name
# add train's identifier if not existing
if !(haskey(train, :id) && train[:id]!=nothing)
merge!(train, Dict(:id =>1))
end
checkAndSetString!(train, "train", :type, "passenger", ["passenger", "freight"]) # train type "passenger" or "freight"
checkAndSetPositiveNumberWithDifferentNames!(train, "train", :length, :l_train, "m", 20.0) # total length (in m)
# TODO: or just use: checkAndSetPositiveNumber!(train, "train", :length, "m", 20.0)
checkAndSetSpeedLimit!(train) # train's speed limit (in m/s)
checkAndSetBrakingAcceleration!(train) # a_braking
checkAndSetPositiveNumber!(train, "train", :m_td, "kg", 80000) # mass on the traction unit's driving axles (in kg)
checkAndSetPositiveNumber!(train, "train", :m_tc, "kg", 0.0) # mass on the traction unit's carrying axles (in kg)
checkAndSetSum!(train, "train", :m_t, :m_td, :m_tc) # mass of the traction unit (in kg)
checkAndSetPositiveNumber!(train, "train", :m_w, "kg", 0.0) # mass of the set of wagons (consist) (in kg)
checkAndSetSum!(train, "train", :m_train, :m_t, :m_w) # total mass (in kg)
if train[:m_train] <= 0.0
error("ERROR at checking the input for the train: The train's mass has to be higher than 0.0 kg.")
end
checkAndSetRotationMassFactors!(train)
checkAndSetTractiveEffortVelocityPairs!(train) # pairs of velocity and tractive effort
# coefficients for the vehicle resistance of the traction unit
checkAndSetRealNumber!(train, "train", :Δv_t, "m/s", 15.0/3.6) # coefficient for velocitiy difference between traction unit and outdoor air (in m/s)
checkAndSetPositiveNumber!(train, "train", :f_Rtd0, "", 0.0) # coefficient for basic resistance due to the traction units driving axles (in ‰)
checkAndSetPositiveNumber!(train, "train", :f_Rtc0, "", 0.0) # coefficient for basic resistance due to the traction units carring axles (in ‰)
checkAndSetPositiveNumber!(train, "train", :F_Rt2, "N", 0.0) # coefficient for air resistance of the traction units (in N)
# coefficients for the vehicle resistance of the set of wagons (consist)
checkAndSetRealNumber!(train, "train", :Δv_w, "m/s", getDefault_Δv_w(train[:type])) # coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s)
checkAndSetPositiveNumber!(train, "train", :f_Rw0, "", 0.0) # coefficient for basic resistance of the set of wagons (consist) (in ‰)
checkAndSetPositiveNumber!(train, "train", :f_Rw1, "", 0.0) # coefficient for the consists resistance to rolling (in ‰)
checkAndSetPositiveNumber!(train, "train", :f_Rw2, "", 0.0) # coefficient fo the consistsr air resistance (in ‰)
# inform the user about keys of the input dictionary that are not used in this tool
usedKeys = [:name, :id, :type,
:length, :l_train, :v_limit, :v_limit_kmh, :a_braking,
:m_train, :m_t, :m_td, :m_tc, :m_w,
:ξ_train, :ξ_t, :ξ_w, :rotationMassFactor_train, :rotationMassFactor_t, :rotationMassFactor_w,
:tractiveEffortVelocityPairs, :F_T_pairs, :F_T_pairs_kmh,
:f_Rtd0, :f_Rtc0, :F_Rt2, :Δv_t,
:f_Rw0, :f_Rw1, :f_Rw2, :Δv_w]
informAboutUnusedKeys(collect(keys(train)), usedKeys::Vector{Symbol}, "train")
return train
end #function checkAndSetTrain!
function checkAndSetPath!(path::Dict)
# check path information from input dictionary
checkAndSetString!(path, "path", :name, "")
# TODO checkId ? path[:id] # path identifier
checkAndSetSections!(path)
checkAndSetPOIs!(path)
# inform the user about keys of the input dictionary that are not used in this tool
usedKeys = [:name,
:sections, :sectionStarts, :sectionStarts_kmh,
:pointsOfInterest]
informAboutUnusedKeys(collect(keys(path)), usedKeys::Vector{Symbol}, "path")
return path
end # function checkAndSetPath!
## settings for the calculation
function checkAndSetSettings!(settings::Dict)
# check settings information from input dictionary
checkAndSetString!(settings, "settings", :massModel, "mass point", ["mass point", "homogeneous strip"]) # model type of the train's mass "mass point" or "homogeneous strip"
checkAndSetString!(settings, "settings", :stepVariable, "s in m", ["s in m", "t in s", "v in m/s"]) # step variable of the step method "s in m", "t in s" or "v in m/s"
checkAndSetPositiveNumber!(settings, "settings", :stepSize, "("*settings[:stepVariable]*")", getDefaultStepSize(settings[:stepVariable])) # step size (unit depends on stepVariable: s in m, t in s and v in m/s)
checkAndSetBool!(settings, "settings", :operationModeMinimumRunningTime, true) # operation mode "minimum running time"
checkAndSetBool!(settings, "settings", :operationModeMinimumEnergyConsumption, false) # operation mode "minimum energy consumption"
checkAndSetString!(settings, "settings", :typeOfOutput, "julia dictionary", ["julia dictionary", "CSV"]) # output as "julia dictionary" or as "CSV"
if settings[:typeOfOutput] == "CSV"
checkAndSetString!(settings, "settings", :csvDirectory, "~/Desktop/TrainRun")
# TODO use correct default directory
# TODO: it could be checked if the path is existing on the pc
end # if
checkAndSetString!(settings, "settings", :detailOfOutput, "running time", ["running time", "points of interest", "driving course", "everything"]) # should the output be only the value of the "running time", or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
# inform the user about keys of the input dictionary that are not used in this tool
usedKeys = [:massModel, :stepVariable, :stepSize,
:operationModeMinimumRunningTime, :operationModeMinimumEnergyConsumption,
:typeOfOutput, :detailOfOutput]
if settings[:typeOfOutput] == "CSV"
push!(usedKeys, :csvDirectory)
end
informAboutUnusedKeys(collect(keys(settings)), usedKeys::Vector{Symbol}, "settings")
return settings
end # function checkAndSetSettings!
function checkAndSetBool!(dictionary::Dict, dictionaryType::String, key::Symbol, defaultValue::Bool)
if haskey(dictionary,key) && dictionary[key]!=nothing
if typeof(dictionary[key]) != Bool
error("ERROR at checking the input for the ",dictionaryType,": The value of the key ",String(key)," is not correct. The value has to be of type Bool.")
end
else
merge!(dictionary, Dict(key => defaultValue))
defaultValue && println("INFO at checking the input for the ",dictionaryType,": The key ",String(key)," or its value is missing. Therefore ",String(key),"=",dictionary[key]," is assumed and used.")
end
return dictionary
end #function checkAndSetBool!
function checkAndSetPositiveNumber!(dictionary::Dict, dictionaryType::String, key::Symbol, unit::String, default::Real)
if haskey(dictionary,key) && dictionary[key]!=nothing
if typeof(dictionary[key]) <: Real && dictionary[key] >= 0.0
else
error("ERROR at checking the input for the ",dictionaryType,": The value of ",String(key)," is no real floating point number >=0.0.")
end
else
merge!(dictionary, Dict(key => default))
println("INFO at checking the input for the ",dictionaryType,": The key ",String(key)," is missing. Therefore ",String(key),"=",default," ",unit," will be assumed and used." )
end
return dictionary
end #function checkAndSetPositiveNumber!
# first method without a default value
function checkAndSetPositiveNumberWithDifferentNames!(dictionary::Dict, dictionaryType::String, mainKey::Symbol, alternativeKey::Symbol, unit::String)
mainKey_temp = -1.0
alternativeKey_temp = -1.0
if haskey(dictionary, mainKey) && dictionary[mainKey]!=nothing
if typeof(dictionary[mainKey]) <: Real && dictionary[mainKey] >= 0.0
mainKey_temp = dictionary[mainKey]
else
error("ERROR at checking the input for the ",dictionaryType,": The value of ",mainKey," is no real floating point number >=0.0.")
end
end
if haskey(dictionary, alternativeKey) && dictionary[alternativeKey]!=nothing
if typeof(dictionary[alternativeKey]) <: Real && dictionary[alternativeKey] >= 0.0
alternativeKey_temp = dictionary[alternativeKey]
else
error("ERROR at checking the input for the ",dictionaryType,": The value of ",alternativeKey," is no real floating point number >=0.0.")
end
else
delete!(dictionary, alternativeKey)
end
if mainKey_temp >= 0.0 && alternativeKey_temp >= 0.0
difference = abs(mainKey_temp - alternativeKey_temp)
if difference > 1/(10^approximationLevel) # TODO or use difference > 0.0 ?
delete!(dictionary, alternativeKey)
println("WARNING at checking the input for the ",dictionaryType,": The values of ",mainKey," and ",alternativeKey," differ by ",difference," ",unit,". The value ",String(mainKey),"=",default," ",unit," is used." )
end
elseif mainKey_temp >= 0.0
# do nothing
elseif alternativeKey_temp >= 0.0
merge!(dictionary, Dict(mainKey => alternativeKey_temp))
else
# do nothing
end
return dictionary
end #function checkAndSetPositiveNumberWithDifferentNames!
# second method with a default value
function checkAndSetPositiveNumberWithDifferentNames!(dictionary::Dict, dictionaryType::String, mainKey::Symbol, alternativeKey::Symbol, unit::String, default::Real)
mainKey_temp = -1.0
alternativeKey_temp = -1.0
if haskey(dictionary, mainKey) && dictionary[mainKey]!=nothing
if typeof(dictionary[mainKey]) <: Real && dictionary[mainKey] >= 0.0
mainKey_temp = dictionary[mainKey]
else
error("ERROR at checking the input for the ",dictionaryType,": The value of ",mainKey," is no real floating point number >=0.0.")
end
end
if haskey(dictionary, alternativeKey) && dictionary[alternativeKey]!=nothing
if typeof(dictionary[alternativeKey]) <: Real && dictionary[alternativeKey] >= 0.0
alternativeKey_temp = dictionary[alternativeKey]
else
error("ERROR at checking the input for the ",dictionaryType,": The value of ",alternativeKey," is no real floating point number >=0.0.")
end
else
delete!(dictionary, alternativeKey)
end
if mainKey_temp >= 0.0 && alternativeKey_temp >= 0.0
difference = abs(mainKey_temp - alternativeKey_temp)
if difference > 1/(10^approximationLevel) # TODO or use difference > 0.0 ?
delete!(dictionary, alternativeKey)
println("WARNING at checking the input for the ",dictionaryType,": The values of ",mainKey," and ",alternativeKey," differ by ",difference," ",unit,". The value ",String(mainKey),"=",default," ",unit," is used." )
end
elseif mainKey_temp >= 0.0
# do nothing
elseif alternativeKey_temp >= 0.0
merge!(dictionary, Dict(mainKey => alternativeKey_temp))
else
# set a default value
merge!(dictionary, Dict(mainKey, default))
println("INFO at checking the input for the ",dictionaryType,": The key ",mainKey," or its value is missing. Therefore the value ",String(mainKey),"=",default," ",unit," is used." )
end
return dictionary
end #function checkAndSetPositiveNumberWithDifferentNames!
function checkAndSetRealNumber!(dictionary::Dict, dictionaryType::String, key::Symbol, unit::String, default::Real)
if haskey(dictionary,key) && dictionary[key]!=nothing
if typeof(dictionary[key]) <: Real
else
error("ERROR at checking the input for the ",dictionaryType,": The value of ",String(key)," is no real number.")
end
else
merge!(dictionary, Dict(key => default))
println("INFO at checking the input for the ",dictionaryType,": The key ",String(key)," is missing. Therefore ",String(key),"=",default," ",unit," will be assumed and used." )
end
return dictionary
end #function checkAndSetRealNumber!
function checkAndSetSum!(dictionary::Dict, dictionaryType::String, sum::Symbol, summand1::Symbol, summand2::Symbol)
if haskey(dictionary,sum) && dictionary[sum]!=nothing
if typeof(dictionary[sum]) <: Real && dictionary[sum] >= 0.0
difference = abs(dictionary[sum] - (dictionary[summand1]+dictionary[summand2]))
if difference > 1/(10^approximationLevel)
error("ERROR at checking the input for the ",dictionaryType,": The value of ",String(sum)," is not exactly the sum of ",String(summand1)," and ",String(summand2),". It differs by ",difference,".")
end
else
error("ERROR at checking the input for the ",dictionaryType,": The value of ",String(sum)," is no real floating point number >=0.0.")
end
else
merge!(dictionary, Dict(sum => dictionary[summand1]+dictionary[summand2]))
println("INFO at checking the input for the ",dictionaryType,": The key ",String(sum)," is missing. Therefore ",String(sum)," = ",String(summand1)," + ",String(summand2)," = ",dictionary[sum]," was calculated and will be used." )
end
return dictionary
end #function checkAndSetSum!
function checkAndSetString!(dictionary::Dict, dictionaryType::String, key::Symbol, defaultValue::String, validValues::Vector{String})
# TODO change checkAndAddString! to checkAndAddSymbol! ?
if haskey(dictionary,key) && dictionary[key]!=nothing
value = dictionary[key]
if typeof(value) == String
for validValue in validValues
if value == validValue
return dictionary
end
end
end
error("ERROR at checking the input for the ",dictionaryType,": The value of ",String(key)," is wrong. It has to be one of the following String values: ", validValues)
else
println("INFO at checking the input for the ",dictionaryType,": The key ",String(key)," is missing. It has to be one of the following String values: ", validValues,". For this calculation the default value '",defaultValue,"' will be used.")
merge!(dictionary, Dict(key => defaultValue))
end
return dictionary
end #function checkAndSetString!
# second method of function checkAndSetString! without validValues
function checkAndSetString!(dictionary::Dict, dictionaryType::String, key::Symbol, defaultValue::String)
if haskey(dictionary,key) && dictionary[key]!=nothing
value = dictionary[key]
if typeof(value) == String
return dictionary
end
error("ERROR at checking the input for the ",dictionaryType,": The value of ",String(key)," is wrong. It has to be of type String.")
else
println("INFO at checking the input for the ",dictionaryType,": The key ",String(key)," is missing. For this calculation the default value '",defaultValue,"' will be used.")
merge!(dictionary, Dict(key => defaultValue))
end
return dictionary
end #function checkAndSetString!
function checkAndSetSpeedLimit!(train::Dict)
v_limit_temp = 0.0
v_limit_kmh_temp = 0.0
if haskey(train, :v_limit) && train[:v_limit]!=nothing
if typeof(train[:v_limit]) <: Real && train[:v_limit] >= 0.0
v_limit_temp = train[:v_limit]
else
error("ERROR at checking the input for the train: The value of v_limit is no real floating point number >=0.0.")
end
end
if haskey(train, :v_limit_kmh) && train[:v_limit_kmh]!=nothing
if typeof(train[:v_limit_kmh]) <: Real && train[:v_limit_kmh] >= 0.0
v_limit_kmh_temp = train[:v_limit_kmh]
else
error("ERROR at checking the input for the train: The value of v_limit_kmh is no real floating point number >=0.0.")
end
else
delete!(train, :v_limit_kmh)
end
if v_limit_temp > 0.0 && v_limit_kmh_temp > 0.0
difference = abs(v_limit_temp - v_limit_kmh_temp/3.6)
if difference > 1/(10^approximationLevel) # TODO or use difference > 0.0 ?
delete!(train, :v_limit_kmh)
println("WARNING at checking the input for the train: The values of v_limit and v_limit_kmh differ by ",difference," m/s. The value v_limit=",v_limit_temp," m/s is used." )
end
elseif v_limit_temp > 0.0
# do nothing
elseif v_limit_kmh_temp > 0.0
merge!(train, Dict(:v_limit => v_limit_kmh_temp/3.6))
else
# set a default value
merge!(train, Dict(:v_limit, 1000.0/3.6)) # set speed limit to 1000 km/h
println("INFO at checking the input for the train: There is no value for the trains speed limit (v_limit or v_limit_kmh). The value v_limit=1000 km/h =",train[:v_limit]," m/s is used." )
end
return train
end #function checkAndSetSpeedLimit!
function checkAndSetBrakingAcceleration!(train::Dict)
if haskey(train, :a_braking) && train[:a_braking]!=nothing
if typeof(train[:a_braking]) <: Real
if train[:a_braking] > 0.0
train[:a_braking] =-train[:a_braking]
println("INFO at checking the input for the train: The value for a_braking is >0.0. The braking acceleration has to be <0.0. Therefore a_braking=",train[:a_braking]," m/s^2 is used." )
elseif train[:a_braking] == 0.0
error("ERROR at checking the input for the train: The value for a_braking is 0.0. The braking acceleration has to be <0.0.")
end
else
error("ERROR at checking the input for the train: The value for a_braking is no real floating point number <0.0.")
end
else
# set a default value depending on the train type
if train[:type] == "freight"
a_braking = -0.225
elseif train[:type] == "passenger"
a_braking = -0.375
#elseif train[:type] == "passengerSuburban"
# a_braking = -0.525
# TODO: add suburban trains to train type?
end
merge!(train, Dict(:a_braking => a_braking))
println("INFO at checking the input for the train: The key for a_braking is missing. Because of the train type ",train[:type]," a_braking=",a_braking," m/s^2 will be assumed and used." )
end
return train
end #function checkAndSetBrakingAcceleration!
function checkAndSetRotationMassFactors!(train::Dict)
checkAndSetPositiveNumberWithDifferentNames!(train, "train", :ξ_train, :rotationMassFactor_train, "")
checkAndSetPositiveNumberWithDifferentNames!(train, "train", :ξ_t, :rotationMassFactor_t, "")
checkAndSetPositiveNumberWithDifferentNames!(train, "train", :ξ_w, :rotationMassFactor_w, "")
if haskey(train, :ξ_train) && train[:ξ_train]!=nothing
if train[:ξ_train]>0.0
if haskey(train, :ξ_t) && train[:ξ_t]!=nothing && train[:ξ_t]>0.0 && (train[:m_w]==0.0 || (haskey(train, :ξ_w) && train[:ξ_w]!=nothing))
# TODO: is && train[:ξ_t]>0.0 necessary here?
difference = abs(train[:ξ_train] - (train[:ξ_t]*train[:m_t] + train[:ξ_w]*train[:m_w])/train[:m_train])
if difference > 1/(10^approximationLevel)
error("ERROR at checking the input for the train: The value of ξ_train is not exactly ξ_train=(ξ_t*m_t + ξ_w*m_w)/m_train. It differs by ",difference,".")
end
end
else
error("ERROR at checking the input for the train: The value of :ξ_train is no real floating point number >0.0.")
end
else
checkAndSetPositiveNumber!(train, "train", :ξ_t, "", 1.09)
if train[:m_w]>0.0
default_ξ_w = 1.06
else
default_ξ_w = 0.0
end
checkAndSetPositiveNumber!(train, "train", :ξ_w, "", default_ξ_w)
ξ_train=(train[:ξ_t]*train[:m_t] + train[:ξ_w]*train[:m_w])/train[:m_train] # rotation mass factor of the whole train (without unit)
if ξ_train <= 0.0
error("ERROR at checking the input for the train: The train's rotations mass factor has to be higher than 0.0 kg.")
end
merge!(train, Dict(:ξ_train => ξ_train))
end
return train
end #function checkAndSetRotationMassFactors!
function checkAndSetTractiveEffortVelocityPairs!(train::Dict) # pairs of velocity and tractive effort
if haskey(train,:tractiveEffortVelocityPairs) && train[:tractiveEffortVelocityPairs]!=nothing
pairs = train[:tractiveEffortVelocityPairs]
velocityMultiplier = 1.0
if (haskey(train,:F_T_pairs) && train[:F_T_pairs]!=nothing) && (haskey(train,:F_T_pairs_kmh) && train[:F_T_pairs_kmh]!=nothing)
println("WARNING at checking the input for the train: There are values for tractiveEffortVelocityPairs, F_T_pairs and F_T_pairs_kmh. The values for tractiveEffortVelocityPairs are used." )
elseif haskey(train,:F_T_pairs) && train[:F_T_pairs]!=nothing
println("WARNING at checking the input for the train: There are values for tractiveEffortVelocityPairs and F_T_pairs. The values for tractiveEffortVelocityPairs are used." )
elseif haskey(train,:F_T_pairs_kmh) && train[:F_T_pairs_kmh]!=nothing
println("WARNING at checking the input for the train: There are values for tractiveEffortVelocityPairs and F_T_pairs_kmh. The values for tractiveEffortVelocityPairs are used." )
end
elseif haskey(train,:F_T_pairs) && train[:F_T_pairs]!=nothing
pairs = train[:F_T_pairs]
velocityMultiplier = 1.0
if haskey(train,:F_T_pairs_kmh) && train[:F_T_pairs_kmh]!=nothing
println("WARNING at checking the input for the train: There are values for F_T_pairs and F_T_pairs_kmh. The values for F_T_pairs are used." )
end
elseif haskey(train,:F_T_pairs_kmh) && train[:F_T_pairs_kmh]!=nothing
velocityMultiplier = 1000/3600
pairs=[]
for row in 1:length(train[:F_T_pairs_kmh])
push!(pairs, [train[:F_T_pairs_kmh][row][1]*velocityMultiplier, train[:F_T_pairs_kmh][row][2]])
end # for
else
error("ERROR at checking the input for the train: There has to be the key tractiveEffortVelocityPairs filled with a list of pairs of velocity and tractive effort.")
end # if
# check if the elements of the array have the correct type
errorDetected=false
for row in 1:length(pairs)
if typeof(pairs[row][1]) <: Real && pairs[row][1]>=0.0
else
errorDetected=true
println("ERROR at checking the input for the train: The speed value of train[:tractiveEffortVelocityPairs] in row ", row ," is no real floating point number >=0.0.")
end
if typeof(pairs[row][2]) <: Real && pairs[row][2]>=0.0
else
errorDetected=true
println("ERROR at checking the input for the train: The tractive effort value of train[:tractiveEffortVelocityPairs] in row ", row ," is no real floating point number >=0.0.")
end
if row>=2 && pairs[row][1] <= pairs[row-1][1]
errorDetected=true
println("ERROR at checking the input for the train: The speed value of train[:tractiveEffortVelocityPairs] in row ", row ," (v=",pairs[row][1]," m/s) is not higher than the speed value in the previous row (v=",pairs[row-1][1]," m/s).")
end
end # for
if errorDetected
error("ERROR at checking the input for the train: Only real floating point number >=0.0 are allowed for speed and tractive effort. The speed values have to be listed from low to high.")
end
# create tractiveEffortVelocityPairs
if pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first known value is used
newPairs=[]
push!(newPairs, [0.0, pairs[1][2]])
println("INFO at checking the input for the train: The tractive effort for v=0.0 m/s is missing. Therefore the first given value F_T(v=",pairs[1][1]," m/s)=",pairs[1][2]," N will be used." )
for row in 1:length(pairs)
push!(newPairs, [pairs[row][1], pairs[row][2]])
end # for
merge!(train, Dict(:tractiveEffortVelocityPairs => newPairs))
else
merge!(train, Dict(:tractiveEffortVelocityPairs => pairs))
end
if length(pairs[1])>2
println("INFO according the train dictionary: Only the first two columns of train[:tractiveEffortVelocityPairs] are used in this tool.")
end
return train
end #function checkAndSetTractiveEffortVelocityPairs!
function getDefault_Δv_w(type::String) # coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s)
if type == "passenger"
# TODO if different passenger or freight trains are posiible, use: if startswith(type, "passenger"). exanples: passengerLocomotivehauled and passengerMotorCoachTrain
Δv_w=15.0/3.6
elseif type == "freight"
Δv_w=0.0
end # if
return Δv_w
end #function getDefault_Δv_w!
function checkAndSetSections!(path::Dict)
# check the section information
if haskey(path,:sections) && path[:sections]!=nothing
# TODO: check typeof(path[:sections]) == Dict
if (haskey(path, :sectionStarts) && path[:sectionStarts]!=nothing) && (haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing)
println("WARNING at checking the input for the path: There are values for sections, sectionStarts and sectionStarts_kmh. The dictionary sections is used." )
elseif haskey(path,:sectionStarts) && path[:sectionStarts]!=nothing
println("WARNING at checking the input for the path: There are values for sections and sectionStarts. The dictionary sections is used." )
elseif haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
println("WARNING at checking the input for the path: There are values for sections and sectionStarts_kmh. The dictionary sections is used." )
end
elseif haskey(path,:sectionStarts) && path[:sectionStarts]!=nothing
# TODO: check typeof(path[:sections]) == Array
createSections!(path, :sectionStarts)
if haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
println("WARNING at checking the input for the path: There are values for sectionStarts and sectionStarts_kmh. The array sectionStarts is used." )
end
elseif haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
# TODO: check typeof(path[:sections]) == Array
createSections!(path, :sectionStarts_kmh)
else
error("ERROR at checking the input for the path: The Symbol :sections is missing. It has to be added with a list of sections. Each has to be a dictionary with the keys :s_tart, :s_end, :v_limit and :f_Rp.")
section = Dict(:s_start => 0.0,
:s_end => 15.0,
:v_limit => 1000.0/3.6,
:f_Rp => 0.0)
merge!(path, Dict(:sections => [section]))
return path
end
sections = path[:sections]
checkedSections = []
increasing = false
decreasing = false
#TODO: throw error for each issue or collect the issues and use the Bool errorDetected like in createSections?
# check values for section==1
checkAndSetRealNumber!(sections[1], "path[:sections][1]", :s_start, "m", 0.0) # first point of the section (in m)
checkAndSetRealNumber!(sections[1], "path[:sections][1]", :s_end, "m", 0.0) # first point of the next section (in m)
checkAndSetPositiveNumber!(sections[1], "path[:sections][1]", :v_limit, "m/s", 1000.0/3.6) # paths speed limt (in m/s)
checkAndSetRealNumber!(sections[1], "path[:sections][1]", :f_Rp, "", 0.0) # specific path resistance of the section (in ‰)
push!(checkedSections, sections[1])
if sections[1][:s_start] < sections[1][:s_end]
increasing = true
elseif sections[1][:s_start] > sections[1][:s_end]
decreasing = true
else
pop!(checkedSections)
println("WARNING at checking the input for the path: The first section of :sections has the same position for starting and end point. The section will be deleted and not used in the tool.")
end
for sectionNr in 2:length(sections)
checkAndSetRealNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :s_start, "m", sections[sectionNr-1][:s_end]) # first point of the section (in m)
# TODO how to define default values? which has to be checked and defined fist? s_end-1 and s_start need each other as default values
#if sectionNr < length(sections) && haskey(sections[sectionNr], :s_start) && sections[sectionNr][:s_start]!=nothing && typeof(sections[sectionNr][:s_start]) <: Real
# defaultEnd = sections[sectionNr+1][:s_start]
#end
defaultEnd = sections[sectionNr][:s_start] # so the default value for s_end creates a sections of lenght=0.0 #TODO should be changed!
checkAndSetRealNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :s_end, "m", defaultEnd) # first point of the next section (in m)
checkAndSetPositiveNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :v_limit, "m/s", 1000.0/3.6) # paths speed limt (in m/s)
checkAndSetRealNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :f_Rp, "", 0.0) # specific path resistance of the section (in ‰)
push!(checkedSections, sections[sectionNr])
# compare the section's start and end position
if sections[sectionNr][:s_start] < sections[sectionNr][:s_end]
increasing = true
elseif sections[sectionNr][:s_start] > sections[sectionNr][:s_end]
decreasing = true
else
pop!(checkedSections)
println("INFO at checking the input for the path: The ",sectionNr,". section of :sections has the same position for starting and end point. The section will be deleted and not used in the tool.")
end
if increasing && decreasing
error("ERROR at checking the input for the path: The positions of the :sections are not increasing/decreasing consistently. The direction in the ",sectionNr,". section differs from the previous.")
end
if length(checkedSections)>1 && sections[sectionNr][:s_start] != checkedSections[end-1][:s_end]
error("ERROR at checking the input for the path[:sections]: The starting position of the ",section,". section (s=",sections[sectionNr][:s_start]," m) does not euqal the last position of the previous section(s=",checkedSections[end-1][:s_end]," m). The sections have to be sequential.")
# TODO: maybe if there is a gab create a new section and only if there a jumps in the wrong direction throw an error?
end
end #for
return path
end #function checkAndSetSections!
function createSections!(path::Dict, key::Symbol)
# read the section starting positions and corresponding information
if key == :sectionStarts
sectionStartsArray = path[:sectionStarts]
conversionFactor = 1.0 # conversion factor between the units m/s and m/s
if haskey(path,:sectionStarts) && path[:sectionStarts_kmh]!=nothing
println("WARNING at checking the input for the path: There are values for sectionStarts and sectionStarts_kmh. The values for sectionStarts are used." )
end
elseif key == :sectionStarts_kmh
sectionStartsArray = path[:sectionStarts_kmh]
conversionFactor = 1/3.6 # conversion factor between the units km/h and m/s
else
error("ERROR at checking the input for the path: The keyword sectionStarts or sectionStarts_kmh is missing. The sections can not be created without them.")
end # if
# check if the array is correct and if elements of the array have the correct type and valid values
errorDetected = false
if length(sectionStartsArray)<2
error("ERROR at checking the input for the path: The keyword ",key," needs at least two rows for two points each with the three columns [s, v_limit, f_Rp].")
end
for row in 1:length(sectionStartsArray)
if length(sectionStartsArray[row])>=3
if length(sectionStartsArray[row])>3
println("INFO at checking the input for the path: Only the first three columns of sectionStartsArray are used in this tool.")
end
else
error("ERROR at checking the input for the path: The keyword ",key," needs to be filled with the three columns [s, v_limit, f_Rp].")
end
if !(typeof(sectionStartsArray[row][1]) <: Real)
errorDetected=true
println("ERROR at checking the input for the path: The position value (column 1) of ",key," in row ", row ," is no real floating point number.")
end
if !(typeof(sectionStartsArray[row][2]) <: Real && sectionStartsArray[row][2] >= 0.0)
errorDetected=true
println("ERROR at checking the input for the path: The speed limit (column 2) of ",key," in row ", row ," is no real floating point number >=0.0.")
end
if !(typeof(sectionStartsArray[row][3]) <: Real)
errorDetected=true
println("ERROR at checking the input for the path: The tractive effort value (column 3) of ",key," in row ", row ," is no real floating point number.")
end
end # for
if errorDetected
error("ERROR at checking the input for the path: The values of ",key," have to be corrected.")
end
sections = []
for row in 2:length(sectionStartsArray)
s_start = sectionStartsArray[row-1][1] # first point of the section (in m)
s_end = sectionStartsArray[row][1] # first point of the next section (in m)
v_limit = sectionStartsArray[row-1][2]*conversionFactor # paths speed limt (in m/s)
f_Rp = sectionStartsArray[row-1][3] # specific path resistance of the section (in ‰)
section = Dict(:s_start => s_start,
:s_end => s_end,
:v_limit => v_limit,
:f_Rp => f_Rp)
push!(sections, section)
end # for
# s_start in first entry defines the path's beginning
# s_end in last entry defines the path's ending
merge!(path, Dict(:sections => sections))
return path
end #function createSections!
function checkAndSetPOIs!(path::Dict)
# read the section starting positions and corresponding information
if haskey(path, :pointsOfInterest)
if path[:pointsOfInterest] != nothing
pointsOfInterest = path[:pointsOfInterest]
sortingNeeded = false
errorDetected = false
for element in 1:length(pointsOfInterest)
if typeof(pointsOfInterest[element]) <: Real
if element > 1
if pointsOfInterest[element] < pointsOfInterest[element-1]
sortingNeeded = true
println("INFO at checking the input for the path: The point of interest in element ", element ," (",pointsOfInterest[element]," m) has to be higher than the value of the previous element (",pointsOfInterest[element-1]," m). The points of interest will be sorted.")
end
end
else
errorDetected = true
println("ERROR at checking the input for the path: The point of interest in element ", element ," is no real floating point number.")
end
end # for
if errorDetected
error("ERROR at checking the input for the path: The values of pointsOfInterest have to be corrected.")
end
if sortingNeeded == true
sort!(pointsOfInterest)
end
copiedPOIs = []
for element in 1:length(pointsOfInterest)
if element == 1
push!(copiedPOIs, pointsOfInterest[element])
elseif element > 1 && pointsOfInterest[element] > pointsOfInterest[element-1]
push!(copiedPOIs, pointsOfInterest[element])
end
end # for
path[:pointsOfInterest] = copiedPOIs
else
println("INFO at checking the input for the path: The key pointsOfInterest exists but without values.")
delete!(path, :pointsOfInterest)
end
end
return path
end #function checkAndSetPOIs!
function getDefaultStepSize(stepVariable::String)
if stepVariable == "s in m"
return 10.0
elseif stepVariable == "t in s"
return 3.0
elseif stepVariable == "v in m/s"
return 0.1
#else
# error("ERROR at getting a default step size. The step variable ",stepVariable," can not be used.")
end
end #function getDefaultStepSize
#function informAboutUnusedKeys(dictionary::Dict, dictionaryType::String) # inform the user which Symbols of the input dictionary are not used in this tool
function informAboutUnusedKeys(allKeys::AbstractVector, usedKeys::Vector{Symbol}, dictionaryType::String) # inform the user which Symbols of the input dictionary are not used in this tool
unusedKeys = []
# find unused keys in allKeys
for key in allKeys
used = false
for usedKey in usedKeys
if key == usedKey
used = true
break
end
end
if !used
push!(unusedKeys, key)
end
end
if length(unusedKeys)>0
println("INFO at checking the input for the ",dictionaryType,": The following Keywords are not used in this tool:")
for key in unusedKeys
println(" - ",key)
end
end
end #function informAboutUnusedKeys
end # module Validate

File diff suppressed because it is too large Load Diff

View File

@ -5,83 +5,20 @@
# __copyright__ = "2020-2022"
# __license__ = "ISC"
module TrainRunCalc
# include modules of TrainRunCalc
include("./Validate.jl")
include("./Characteristics.jl")
include("./Behavior.jl")
include("./Output.jl")
# use modules of TrainRunCalc
using .Validate
using .Characteristics
using .Behavior
using .Output
# export main function
export trainRun
approximationLevel = 6 # value for approximation to intersections and precisely calculated digits
# TODO: define it here and give it to each function? (Behavior, ...)
# Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
"""
trainRun(train::Dict, path::Dict, settings::Dict)
Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding dictionaries `train`, `path`, `settings`.
# Examples
```julia-repl
julia> trainRun(trainDict, pathDict, settingsDict)
todo !!!
```
"""
function trainRun(trainInput::Dict, pathInput::Dict, settingsInput::Dict)
# copy Input data for not changing them
# TODO: or should they be changed? normally it would only make it "better" except for settings[:detailOfOutput] == "points of interest" && !haskey(path, :pointsOfInterest)
train = copy(trainInput)
path = copy(pathInput)
settings = copy(settingsInput)
# check the input data
(train, path, settings) = checkAndSetInput!(train, path, settings)
settings[:detailOfOutput] == "everything" && println("The input has been checked.")
# prepare the input data
movingSection = determineCharacteristics(path, train, settings)
settings[:detailOfOutput] == "everything" && println("The moving section has been prepared.")
# calculate the train run for oparation mode "minimum running time"
if settings[:operationModeMinimumRunningTime] || settings[:operationModeMinimumEnergyConsumption]
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
settings[:detailOfOutput] == "everything" && println("The driving course for the shortest running time has been calculated.")
# accumulate data and create an output dictionary
output = createOutput(train, settings, path, movingSection, drivingCourse)
# 30/31 old: output = createOutputDict(train, settings, path, movingSection, drivingCourse)
else
output = nothing
# 30/31 old: output = Dict()
end #if
return output
end # function trainRun
# Calculate the running time of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
# calculate a train run focussing on using the minimum possible running time
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, train::Train)
CSs::Vector{Dict} = movingSection[:characteristicSections]
if settings[:massModel] == "homogeneous strip" && settings[:stepVariable] == "v in m/s"
if settings.massModel == :homogeneous_strip && settings.stepVariable == speed
println("WARNING: ! ! ! TrainRun.jl doesn't work reliably for the mass model homogeneous strip with step size v in m/s. The calculation time can be extremely high when calcutlating paths with steep gradients ! ! !")
end
startingPoint=createDataPoint()
startingPoint[:i]=1
startingPoint[:s]=CSs[1][:s_entry]
calculateForces!(startingPoint, CSs, 1, "default", train, settings[:massModel]) # traction effort and resisting forces (in N)
calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N)
drivingCourse::Vector{Dict} = [startingPoint] # List of data points
for csId in 1:length(CSs)
@ -95,8 +32,8 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end
# determine the different flags for switching between the states for creatinge moving phases
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel]) # tractive effort and resisting forces (in N)
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking)
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) # tractive effort and resisting forces (in N)
previousSpeedLimitReached = false
stateFlags = Dict(:endOfCSReached => drivingCourse[end][:s] > CS[:s_exit],
@ -122,17 +59,17 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached]
# cruise only one step
if settings[:stepVariable] =="s in m"
s_cruising = settings[:stepSize]
elseif settings[:stepVariable] =="t in s"
s_cruising = calc_Δs_with_Δt(settings[:stepSize], drivingCourse[end][:a], drivingCourse[end][:v])
elseif settings[:stepVariable] =="v in m/s"
s_cruising = train[:length]/(10.0) # TODO which step size should be used?
if settings.stepVariable == :distance
s_cruising = settings.stepSize
elseif settings.stepVariable == time
s_cruising = calc_Δs_with_Δt(settings.stepSize, drivingCourse[end][:a], drivingCourse[end][:v])
elseif settings.stepVariable == velocity
s_cruising = train.length/(10.0) # TODO which step size should be used?
end
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising")
elseif drivingCourse[end][:F_R] < 0 && stateFlags[:speedLimitReached]
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking)
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
if s_cruising > 0.0
@ -142,7 +79,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] || stateFlags[:speedLimitReached]
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking)
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
if s_cruising > 0.0 # TODO: define a minimum cruising length?
@ -186,5 +123,3 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
return (movingSection, drivingCourse)
end #function calculateMinimumRunningTime
end # module TrainRunCalc

View File

@ -5,94 +5,16 @@
# __copyright__ = "2020-2022"
# __license__ = "ISC"
module Characteristics
include("./Behavior.jl")
using .Behavior
export determineCharacteristics
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior
function determineCharacteristics(path::Dict, train::Dict, settings::Dict)
movingSection = createMovingSection(path, train[:v_limit])
movingSection = secureBrakingBehavior!(movingSection, train[:a_braking])
function determineCharacteristics(path::Path, train::Train, settings::Settings)
movingSection = createMovingSection(path, train.v_limit, train.length)
movingSection = secureBrakingBehavior!(movingSection, train.a_braking)
movingSection = secureAcceleratingBehavior!(movingSection, settings, train)
#movingSection = secureCruisingBehavior!(movingSection, settings, train)
return movingSection
end #function determineCharacteristics
## create a moving section containing characteristic sections
function createMovingSection(path::Dict, v_trainLimit::Real)
# this function creates and returns a moving section dependent on the paths attributes
s_entry = path[:sections][1][:s_start] # first position (in m)
s_exit = path[:sections][end][:s_end] # last position (in m)
pathLength = s_exit - s_entry # total length (in m)
CSs=Vector{Dict}()
s_csStart=s_entry
csId=1
for row in 2:length(path[:sections])
previousSection = path[:sections][row-1]
currentSection = path[:sections][row]
speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit)
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
if speedLimitIsDifferent || pathResistanceIsDifferent
# 03/09 old: if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), path))
s_csStart = currentSection[:s_start]
csId = csId+1
end #if
end #for
push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][end], min(path[:sections][end][:v_limit], v_trainLimit), path))
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore
:length => pathLength, # total length (in m)
:s_entry => s_entry, # first position (in m)
:s_exit => s_exit, # last position (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:characteristicSections => CSs) # list of containing characteristic sections
return movingSection
end #function createMovingSection
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
function createCharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, path::Dict)
# Create and return a characteristic section dependent on the paths attributes
characteristicSection= Dict(:id => id, # identifier
:s_entry => s_entry, # first position (in m)
:s_exit => section[:s_end], # last position (in m)
:length => section[:s_end] -s_entry, # total length (in m)
:r_path => section[:f_Rp], # path resistance (in ‰)
:behaviorSections => Dict(), # list of containing behavior sections
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_limit => v_limit, # speed limit (in m/s)
# initializing :v_entry, :v_peak and :v_exit with :v_limit
:v_peak => v_limit, # maximum reachable speed (in m/s)
:v_entry => v_limit, # maximum entry speed (in m/s)
:v_exit => v_limit) # maximum exit speed (in m/s)
# list of positions of every point of interest (POI) in this charateristic section for which data points should be calculated
s_exit = characteristicSection[:s_exit]
pointsOfInterest = Vector{Real}()
if haskey(path, :pointsOfInterest)
for POI in path[:pointsOfInterest]
if s_entry < POI && POI < s_exit
push!(pointsOfInterest, POI)
end
end
end
push!(pointsOfInterest, s_exit) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
return characteristicSection
end #function createCharacteristicSection
## define the intersection velocities between the characterisitc sections to secure braking behavior
function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
@ -123,7 +45,7 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
end #function secureBrakingBehavior!
## define the intersection velocities between the characterisitc sections to secure accelerating behavior
function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train::Dict)
function secureAcceleratingBehavior!(movingSection::Dict, settings::Settings, train::Train)
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
CSs = movingSection[:characteristicSections]
@ -136,7 +58,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train:
CS[:v_entry] = min(CS[:v_entry], previousCSv_exit)
startingPoint[:s] = CS[:s_entry]
startingPoint[:v] = CS[:v_entry]
calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings[:massModel]) # traction effort and resisting forces (in N)
calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings.massModel) # traction effort and resisting forces (in N)
acceleratingCourse::Vector{Dict} = [startingPoint] # List of data points
if CS[:v_entry] < CS[:v_peak]
@ -160,7 +82,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train:
(CS, acceleratingCourse, stateFlags) = addClearingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function is needed in case the train is not allowed to accelerate because of a previous speed limit
end
else
if settings[:massModel] == "mass point" || acceleratingCourse[end][:s] > CS[:s_entry] + train[:length]
if settings.massModel == :mass_point || acceleratingCourse[end][:s] > CS[:s_entry] + train.length
break
else
(CS, acceleratingCourse, stateFlags) = addDiminishingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function is needed in case the resisitng forces are higher than the maximum possible tractive effort
@ -190,7 +112,7 @@ end #function secureAcceleratingBehavior!
#=
## define the intersection velocities between the characterisitc sections to secure cruising behavior
function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dict)
function secureCruisingBehavior!(movingSection::Dict, settings::Settings, train::Train)
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak
CSs = movingSection[:characteristicSections]
@ -225,7 +147,7 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
(CS, cruisingCourse, stateFlags) = addCruisingSection!(CS, cruisingCourse, stateFlags, s_cruising, settings, train, CSs, "downhillBraking")
end
else
if settings[:massModel] == "mass point" || cruisingCourse[end][:s] > CS[:s_entry] + train[:length]
if settings.massModel == :mass_point || cruisingCourse[end][:s] > CS[:s_entry] + train.length
break
else
(CS, cruisingCourse, stateFlags) = addDiminishingSection!(CS, cruisingCourse, stateFlags, settings, train, CSs) # this function is needed in case the resisitng forces are higher than the maximum possible tractive effort
@ -246,4 +168,3 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
return movingSection
end #function secureCruisingBehavior!
=#
end #module Characteristics

741
src/constructors.jl Normal file
View File

@ -0,0 +1,741 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Martin Scheidt, Max Kannenberg"
# __copyright__ = "2022"
# __license__ = "ISC"
"""
Settings(file)
Settings is a datastruture for calculation context.
The function Settings() will create a set of settings for the train run calculation.
`file` is optinal may be used to load settings in the YAML format.
# Example
```jldoctest
julia> my_settings = Settings() # will generate default settings
Settings(mass_point, :distance, 20, 3, running_time, :dataframe)
```
"""
function Settings(file="DEFAULT")
## default values
massModel = :mass_point
stepVariable = :distance
stepSize = 20
approxLevel = 3
outputDetail = :running_time
outputFormat = :dataframe
## load from file
if file != "DEFAULT"
## JSON schema for YAML-file validation
schema = Schema("""{
"properties": {
"massModel": {
"description": "type of train model",
"type": "string",
"enum": [ "mass_point", "homogeneous_strip" ]
},
"stepVariable": {
"description": "variable of the linear multistep method",
"type": "string",
"enum": [ "distance", "time", "velocity" ]
},
"stepSize": {
"description": "step size acording to stepVariable",
"type": "number",
"exclusiveMinimum": 0
},
"outputDetail": {
"description": "Selecting the detail of the result",
"type": "string",
"enum": [ "running_time", "points_of_interest", "driving_course", "everything" ]
},
"outputFormat": {
"description": "Output format",
"type": "string",
"enum": [ "dataframe", "dict" ]
}
}
}""")
settings = YAML.load(open(file))["settings"]
## validate the loaded file
try
validate(schema, settings)
catch err
println("Could not load settings file '$file'.\n Format is not recognized - using default as fall back.")
settings = Dict()
end
## set the variables in "settings"
haskey(settings, "massModel") ? massModel = Symbol(settings["massModel"]) : nothing
haskey(settings, "stepVariable") ? stepVariable = Symbol(settings["stepVariable"]) : nothing
haskey(settings, "stepSize") ? stepSize = settings["stepSize"] : nothing
haskey(settings, "approxLevel") ? approxLevel = settings["approxLevel"] : nothing
haskey(settings, "outputDetail") ? outputDetail = Symbol(settings["outputDetail"]) : nothing
haskey(settings, "outputFormat") ? outputFormat = Symbol(settings["outputFormat"]) : nothing
end
Settings(massModel, stepVariable, stepSize, approxLevel, outputDetail, outputFormat)
end #function Settings() # outer constructor
"""
Path(file, type = :YAML)
Path is a datastruture for calculation context.
The function Path() will create a running path for the train.
Supported formats are: railtoolkit/schema (2022.05)
# Example
```jldoctest
julia> my_path = Path("file.yaml") # will generate a path from a YAML file.
Path(variables)
```
"""
function Path(file, type = :YAML)
## default values
name = ""
id = ""
uuid = UUIDs.uuid4()
poi = []
sections = []
## process flags
POI_PRESENT = false
## load from file
if type == :YAML
data = YAML.load(open(file))
if data["schema"] != "https://railtoolkit.org/schema/running-path.json"
error("Could not load path file '$file'.\n
YAML format is not recognized.
Currently supported: railtoolkit/schema/running-path (2022.05)")
end
if data["schema_version"] != "2022.05"
error("Could not load path file '$file'.\n
YAML format is not recognized.
Currently supported: railtoolkit/schema/running-path (2022.05)")
end
## JSON schema for YAML-file validation
railtoolkit_schema = Schema("""{
"required": [ "schema", "schema_version", "paths" ],
"properties": {
"schema": {
"description": "Identifier of the schema",
"enum": [ "https://railtoolkit.org/schema/running-path.json" ]
},
"schema_version": {
"description": "Version of the schema",
"type": "string",
"pattern": "[2-9][0-9][0-9][0-9].[0-1][0-9]"
},
"paths": {
"type": "array",
"minItems": 1,
"items": {
"required": [ "name", "id", "characteristic_sections" ],
"type": "object",
"properties": {
"characteristic_sections": {
"description": "",
"type": "array",
"minItems": 2,
"uniqueItems": true,
"items": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"description": "",
"prefixItems": [
{
"description": "milage in meter",
"type": "number"
},
{
"description": "speed in kilometers per hour",
"type": "number",
"exclusiveMinimum": 0
},
{
"description": "resistance in permil",
"type": "number"
}
]
}
},
"id": {
"description": "Identifier of the path",
"type": "string"
},
"name": {
"description": "Name of the path",
"type": "string"
},
"points_of_interest": {
"description": "",
"type": "array",
"uniqueItems": true,
"items": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"description": "",
"prefixItems": [
{ "type": "number" },
{ "type": "string" },
{ "enum": [ "front", "rear" ] }
]
}
},
"UUID": {
"description": "The unique identifier for a path",
"type": "string",
"format": "uuid"
}
}
}
}
}
}""")
paths = data["paths"]
try
validate(railtoolkit_schema, paths)
catch err
error("Could not load path file '$file'.\n
YAML format is not recognized.
Currently supported: railtoolkit/schema/running-path (2022.05)")
end
if length(paths) > 1
println("WARNING: the loaded file contains more than one path. Using only the first!")
end
path = paths[1]
## set the variables in "path"
# required
name = path["name"]
id = path["id"]
tmp_sec = path["characteristic_sections"]
# optional
haskey(path, "UUID") ? uuid = parse(UUID, path["UUID"] ) : nothing
haskey(path, "points_of_interest") ? POI_PRESENT = true : nothing
haskey(path, "points_of_interest") ? tmp_points = path["points_of_interest"] : nothing
else
error("Unknown file type '$type'")
end #if type
## process characteristic sections
sort!(tmp_sec, by = x -> x[1])
for row in 2:length(tmp_sec)
s_start = tmp_sec[row-1][1] # first point of the section (in m)
s_end = tmp_sec[row][1] # first point of the next section (in m)
v_limit = tmp_sec[row-1][2]/3.6 # paths speed limt (in m/s)
f_Rp = tmp_sec[row-1][3] # specific path resistance of the section (in ‰)
section = Dict(:s_start => s_start,
:s_end => s_end,
:v_limit => v_limit,
:f_Rp => f_Rp)
push!(sections, section)
end #for row
# s_start in first entry defines the path's beginning
# s_end in last entry defines the path's ending
## process points of interest
if POI_PRESENT
sort!(tmp_points, by = x -> x[1])
for elem in tmp_points
station = elem[1] # first point of the section (in m)
label = elem[2] # paths speed limt (in m/s)
measure = elem[3] # specific path resistance of the section (in ‰)
point = Dict(:station => station,
:label => label,
:measure => measure)
push!(poi, point)
end #for elem
end #if !isempty(points)
Path(name, id, uuid, poi, sections)
end #function Path() # outer constructor
"""
Train(file, type = :YAML)
Train is a datastruture for calculation context.
The function Train() will create a train to use in calculations.
Supported formats for the YAML files are: railtoolkit/schema (2022.05)
# Example
```jldoctest
julia> my_train = Train("file.yaml") # will generate a train from a YAML file.
Train(variables)
```
"""
function Train(file, type = :YAML)
## default values
name = "" #
id = "" #
uuid = UUIDs.uuid4() #
length = 0 # in meter
m_train_full = 0 # in kilogram
m_train_empty = 0 # in kilogram
m_loco = 0 # in kilogram
m_td = 0 # in kilogram
m_tc = 0 # in kilogram
m_car_full = 0 # in kilogram
m_car_empty = 0 # in kilogram
ξ_train = 1.08 # rotation mass factor, source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 13 for "Zug, überschlägliche Berechnung"
ξ_loco = 1.09 # rotation mass factor
ξ_cars = 1.06 # rotation mass factor
transportType = :freight # "freight" or "passenger" for resistance calculation
v_limit = 140 # in m/s (default 504 km/h)
a_braking = 0 # in m/s^2, todo: implement as function
f_Rtd0 = 0 # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0 = 0 # coefficient for basic resistance due to the traction units carring axles (in ‰)
F_Rt2 = 3000 # coefficient for air resistance of the traction units (in N)
f_Rw0 = 0 # coefficient for the consists basic resistance (in ‰)
f_Rw1 = 0 # coefficient for the consists resistance to rolling (in ‰)
f_Rw2 = 0 # coefficient fo the consistsr air resistance (in ‰)
F_v_pairs = [] # [v in m/s, F_T in N]
## load from file
if type == :YAML
data = YAML.load(open(file))
if data["schema"] != "https://railtoolkit.org/schema/rolling-stock.json"
error("Could not load path file '$file'.\n
YAML format is not recognized.
Currently supported: railtoolkit/schema/rolling-stock (2022.05)")
end
if data["schema_version"] != "2022.05"
error("Could not load path file '$file'.\n
YAML format is not recognized.
Currently supported: railtoolkit/schema/rolling-stock (2022.05)")
end
## JSON schema for YAML-file validation
railtoolkit_schema = Schema("""{
"required": [ "schema", "schema_version" ],
"anyOf": [
{"required": [ "trains" ] },
{"required": [ "vehicles" ] }
],
"properties": {
"schema": {
"description": "Identifier of the schema",
"enum": [ "https://railtoolkit.org/schema/rolling-stock.json" ]
},
"schema_version": {
"description": "Version of the schema",
"type": "string",
"pattern": "[2-9][0-9][0-9][0-9].[0-1][0-9]"
},
"trains": {
"type": "array",
"minItems": 1,
"items": {
"required": [ "name", "id", "formation" ],
"type": "object",
"properties": {
"id": {
"description": "Identifier of the train",
"type": "string"
},
"name": {
"description": "Name of the train",
"type": "string"
},
"UUID": {
"description": "The unique identifier for a train",
"type": "string",
"format": "uuid"
},
"formation": {
"description": "Collection of vehicles that form the train",
"type": "array",
"minItems": 1,
"uniqueItems": false,
"items": {
"type": "string"
}
}
}
}
},
"vehicles": {
"type": "array",
"minItems": 1,
"items": {
"required": [ "name", "id", "vehicle_type", "length", "mass" ],
"type": "object",
"properties": {
"air_resistance": {
"description": "coefficient for air resistance in permil",
"type": "number",
"exclusiveMinimum": 0
},
"base_resistance": {
"description": "coefficient for basic resistance in permil",
"type": "number",
"exclusiveMinimum": 0
},
"id": {
"description": "Identifier of the vehicle",
"type": "string"
},
"length": {
"description": "The length of the vehicle in meter",
"type": "number",
"exclusiveMinimum": 0
},
"load_limit": {
"description": "The maximum permitted load of the vehicle in metric ton",
"type": "number",
"exclusiveMinimum": 0
},
"mass_traction": {
"description": "The mass on the powered axles of the vehicle in metric ton",
"type": "number",
"exclusiveMinimum": 0
},
"mass": {
"description": "The empty mass of the vehicle in metric ton",
"type": "number",
"exclusiveMinimum": 0
},
"name": {
"description": "Name of the vehicle",
"type": "string"
},
"picture": {
"description": "A URI with a picture for humans",
"type": "string",
"format": "uri"
},
"power_type": {
"description": "Type of propulsion",
"enum": [ "diesel", "electric", "steam" ]
},
"rolling_resistance": {
"description": "coefficient for resistance of rolling axles in permil",
"type": "number",
"exclusiveMinimum": 0
},
"rotation_mass": {
"description": "Factor for rotating mass; >= 1",
"type": "number",
"minimum": 1
},
"speed_limit": {
"description": "Maximum permitted speed in kilometers per hour",
"type": "number",
"exclusiveMinimum": 0
},
"tractive_effort": {
"description": "Tractive effort as pairs of speed in kilometers per hour and tractive force in newton",
"type": "array",
"minItems": 3,
"uniqueItems": true,
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"uniqueItems": true,
"items": {
"type": "number",
"minimum": 0
}
}
},
"UUID": {
"description": "The unique identifier for a vehicle",
"type": "string",
"format": "uuid"
},
"vehicle_type": {
"description": "Type of vehicle",
"enum": [ "traction unit", "freight", "passenger", "multiple unit" ]
}
}
}
}
}
}""")
try
validate(railtoolkit_schema, data)
catch err
error("Could not load path file '$file'.\n
YAML format is not recognized.
Currently supported: railtoolkit/schema/rolling-stock (2022.05)")
end
else
error("Unknown file type '$type'")
end #if type
trains = data["trains"]
Base.length(trains) > 1 ? println("WARNING: the loaded file contains more than one train. Using only the first!") : nothing
Base.length(trains) == 0 ? error("No train present in file '$file'") : nothing
train = trains[1]
used_vehicles = unique(train["formation"])
included_vehicles = []
for vehicle in data["vehicles"]
push!(included_vehicles,vehicle["id"])
end
## test if all vehicles of the formation are avilable
for vehicle in used_vehicles
vehicle included_vehicles ? error("'$vehicle' is not present in '$file'") : nothing
end
## gather the count of vehicles and usage in the formation
vehicles = NamedTuple[]
for vehicle in data["vehicles"]
if vehicle["id"] in used_vehicles
n = count(==(vehicle["id"]),train["formation"])
type = vehicle["vehicle_type"]
type == "traction unit" || type == "multiple unit" ? propulsion = true : propulsion = false
type == "passenger" || type == "multiple unit" ? transportType = :passenger : nothing
push!(vehicles, (data=vehicle, n=n, propulsion=propulsion) )
end
end
## set the variables in "train"
name = train["name"]
id = train["id"]
haskey(train, "UUID") ? uuid = parse(UUID, train["UUID"] ) : nothing
transportType == :freight ? a_braking = -0.225 : a_braking = -0.375 # set a default a_braking value depending on the train type
## set the variables for all vehicles
for vehicle in vehicles
length += vehicle.data["length"] * vehicle.n
m_train_full += vehicle.data["mass"] * vehicle.n * 1000 # in kg
m_train_empty += vehicle.data["mass"] * vehicle.n * 1000 # in kg
haskey(vehicle.data, "load_limit") ?
m_train_full += vehicle.data["load_limit"] * vehicle.n * 1000 : # in kg
nothing
haskey(vehicle.data, "speed_limit") ?
v_limit > vehicle.data["speed_limit"]/3.6 ? v_limit = vehicle.data["speed_limit"]/3.6 : nothing :
nothing
end
## divide vehicles in propulsion and non-propulsion
loco = []
for i in 1:Base.length(vehicles)
if vehicles[i].propulsion
push!(loco, vehicles[i])
deleteat!(vehicles, i)
end
end
Base.length(loco) > 1 ? println("WARNING: the loaded file contains more than one traction unit or multiple unit. Using only the first!") : nothing
loco[1].n > 1 ? println("WARNING: the loaded file contains more than one traction unit or multiple unit. Using only one!") : nothing
Base.length(loco) == 0 ? error("No traction unit or multiple unit present in file '$file'") : nothing
loco = loco[1].data
cars = vehicles
## set the variables for locos
m_loco= loco["mass"] * 1000
haskey(loco, "a_braking") ? a_braking = loco["a_braking"] : nothing
haskey(loco, "base_resistance") ? f_Rtd0 = loco["base_resistance"] : nothing
haskey(loco, "rolling_resistance") ? f_Rtc0 = loco["rolling_resistance"] : nothing
haskey(loco, "air_resistance") ? F_Rt2 = loco["air_resistance"] * g * m_loco : nothing
haskey(loco, "mass_traction") ? m_td = loco["mass_traction"] * 1000 : m_td = m_t
haskey(loco, "rotation_mass") ? ξ_loco = loco["rotation_mass"] : nothing
m_tc = m_loco- m_td
haskey(loco, "tractive_effort") ? F_v_pairs = loco["tractive_effort"] : F_v_pairs = [ [0.0, m_td * g * μ],[v_limit*3.6, m_td * g * μ] ]
F_v_pairs = reduce(hcat,F_v_pairs)' # convert to matrix
F_v_pairs[:,1] ./= 3.6 # convert km/h to m/s
F_v_pairs = tuple.(eachcol(F_v_pairs)...) # convert each row to tuples
## set the variables for cars
if !isempty(cars)
resis_base = []
resis_roll = []
resis_air = []
rotMassFac = []
for car in cars
haskey(car.data, "base_resistance") ?
append!(resis_base,repeat([car.data["base_resistance"]],car.n)) :
append!(resis_base,repeat([f_Rw0],car.n))
haskey(car.data, "rolling_resistance") ?
append!(resis_roll,repeat([car.data["rolling_resistance"]],car.n)) :
append!(resis_roll,repeat([f_Rw1],car.n))
haskey(car.data, "air_resistance") ?
append!(resis_air,repeat([car.data["air_resistance"]],car.n)) :
append!(resis_air, repeat([f_Rw2],car.n))
haskey(car.data, "rotation_mass") ?
append!(rotMassFac,repeat([(car.data["rotation_mass"],car.data["mass"])],car.n)) :
append!(rotMassFac,repeat([(ξ_cars ,car.data["mass"])],car.n))
m_car_empty += car.data["mass"] * car.n * 1000 # in kg
m_car_full += car.data["mass"] * car.n * 1000 # in kg
haskey(car.data, "load_limit") ?
m_car_full += car.data["load_limit"] * car.n * 1000 : # in kg
nothing
end
f_Rw0 = Statistics.mean(resis_base)
f_Rw1 = Statistics.mean(resis_roll)
f_Rw2 = Statistics.mean(resis_air)
carRotMass = 0
for elem in rotMassFac
carRotMass += elem[1]*elem[2] * 1000 # in kg
end
ξ_cars = carRotMass/m_car_empty
ξ_train = (ξ_loco * m_loco+ carRotMass)/m_train_empty
else
ξ_cars = 0
ξ_train = ξ_loco
end
Train(
name, id, uuid, length,
m_train_full, m_td, m_tc, m_car_full,
ξ_train, ξ_loco, ξ_cars,
transportType, v_limit,
a_braking,
f_Rtd0, f_Rtc0, F_Rt2, f_Rw0, f_Rw1, f_Rw2,
F_v_pairs
)
end #function Train() # outer constructor
## create a moving section containing characteristic sections
function createMovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real)
# this function creates and returns a moving section dependent on the paths attributes
s_entry = path.sections[1][:s_start] # first position (in m)
s_exit = path.sections[end][:s_end] # last position (in m)
pathLength = s_exit - s_entry # total length (in m)
CSs=Vector{Dict}()
s_csStart=s_entry
csId=1
for row in 2:length(path.sections)
previousSection = path.sections[row-1]
currentSection = path.sections[row]
speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit)
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
if speedLimitIsDifferent || pathResistanceIsDifferent
# 03/09 old: if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, path))
s_csStart = currentSection[:s_start]
csId = csId+1
end #if
end #for
push!(CSs, createCharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, path))
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore
:length => pathLength, # total length (in m)
:s_entry => s_entry, # first position (in m)
:s_exit => s_exit, # last position (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:characteristicSections => CSs) # list of containing characteristic sections
return movingSection
end #function createMovingSection
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
function createCharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, path::Path)
# Create and return a characteristic section dependent on the paths attributes
characteristicSection= Dict(:id => id, # identifier
:s_entry => s_entry, # first position (in m)
:s_exit => section[:s_end], # last position (in m)
:length => section[:s_end] -s_entry, # total length (in m)
:r_path => section[:f_Rp], # path resistance (in ‰)
:behaviorSections => Dict(), # list of containing behavior sections
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_limit => v_limit, # speed limit (in m/s)
# initializing :v_entry, :v_peak and :v_exit with :v_limit
:v_peak => v_limit, # maximum reachable speed (in m/s)
:v_entry => v_limit, # maximum entry speed (in m/s)
:v_exit => v_limit) # maximum exit speed (in m/s)
# list of positions of every point of interest (POI) in this charateristic section for which data points should be calculated
s_exit = characteristicSection[:s_exit]
##TODO: use a tuple with naming
pointsOfInterest = Tuple[]
# pointsOfInterest = Real[]
if !isempty(path.poi)
for POI in path.poi
s_poi = POI[:station]
if POI[:measure] == "rear"
s_poi -= s_trainLength
end
if s_entry < s_poi && s_poi < s_exit
push!(pointsOfInterest, (s_poi, POI[:label]) )
# push!(pointsOfInterest, s_poi )
end
end
end
push!(pointsOfInterest, (s_exit,"")) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
# push!(pointsOfInterest, s_exit) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
return characteristicSection
end #function createCharacteristicSection
"""
a DataPoint is the smallest element of the driving course. One step of the step approach is between two data points
"""
function createDataPoint()
dataPoint = Dict(
:i => 0, # identifier and counter variable of the driving course
:behavior => "", # type of behavior section the data point is part of - see createBehaviorSection()
# a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
:s => 0.0, # position (in m)
:Δs => 0.0, # step size (in m)
:t => 0.0, # point in time (in s)
:Δt => 0.0, # step size (in s)
:v => 0.0, # velocity (in m/s)
:Δv => 0.0, # step size (in m/s)
:a => 0.0, # acceleration (in m/s^2)
:W => 0.0, # mechanical work (in Ws)
:ΔW => 0.0, # mechanical work in this step (in Ws)
:E => 0.0, # energy consumption (in Ws)
:ΔE => 0.0, # energy consumption in this step (in Ws)
:F_T => 0.0, # tractive effort (in N)
:F_R => 0.0, # resisting force (in N)
:R_path => 0.0, # path resistance (in N)
:R_train => 0.0, # train resistance (in N)
:R_traction => 0.0, # traction unit resistance (in N)
:R_wagons => 0.0, # set of wagons resistance (in N)
:label => "" # a label for importend points
)
return dataPoint
end #function createDataPoint
"""
BehaviorSection() TODO!
"""
function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
BS= Dict(
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "downhillBraking", "diminishing", "coasting", "braking" or "standstill"
:length => 0.0, # total length (in m)
:s_entry => s_entry, # first position (in m)
:s_exit => 0.0, # last position (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_entry => v_entry, # entry speed (in m/s)
:v_exit => 0.0, # exit speed (in m/s)
:dataPoints => [startingPoint] # list of identifiers of the containing data points starting with the initial point
)
return BS
end #function createBehaviorSection

View File

@ -5,8 +5,6 @@
# __copyright__ = "2022"
# __license__ = "ISC"
module Formulary
#########################
## literature the driving dynamics equations are based on:
##
@ -21,17 +19,6 @@ module Formulary
## isbn = {978-3-777-10462-1},
## publisher = {Eurailpress DVV Media Group},
## }
## @article{Jaekel:2014,
## author = {Jaekel, Birgit and Albrecht, Thomas},
## year = {2014},
## title = {Comparative analysis of algorithms and models for train running simulation},
## journal = {Journal of Rail Transport Planning \& Management},
## doi = {10.1016/j.jrtpm.2014.06.002},
## volume = {4},
## number = {1-2},
## pages = {14--27},
## publisher = {Elsevier},
## }
## @Book{Wende:2003,
## author = {Wende, Dietrich},
## date = {2003},
@ -41,24 +28,8 @@ module Formulary
## }
#########################
# export resisting forces and acceleration
export calcTractionUnitResistance, calcWagonsResistance, calcForceFromCoefficient, calcAcceleration,
# export step sizes in different units
calc_Δs_with_Δt, calc_Δs_with_Δv,
calc_Δt_with_Δs, calc_Δt_with_Δv, calc_Δt_with_constant_v,
calc_Δv_with_Δs, calc_Δv_with_Δt,
calc_ΔW, calc_ΔE,
# export braking information
calcBrakingDistance, calcBrakingStartVelocity, calcBrakingAcceleration
approxLevel = 6
v00 = 100/3.6 # velocity factor (in m/s)
g = 9.81 # acceleration due to gravity (in m/s^2) # TODO: should more digits of g be used? g=9,80665 m/s^2
approximationLevel = 6 # value for approximation to intersections TODO further explanation (e.g. approximationLevel = 3 -> with stepSize 10 m the approximation will be calculated accurate on 10 mm ; 1s -> 1 ms; 1 km/h -> 3.6 mm/s)
# TODO: necessary here?
## calculate forces
@ -71,7 +42,7 @@ Calculate the vehicle resistance for the traction unit of the `train` dependend
...
# Arguments
- `v::AbstractFloat`: the current velocity in m/s.
- `train::Dict`: ? ? ?
- `train::Train`: ? ? ?
...
# Examples
@ -80,36 +51,34 @@ julia> calcTractionUnitResistance(30.0, ? ? ?)
? ? ?
```
"""
function calcTractionUnitResistance(v::AbstractFloat, train::Dict)
function calcTractionUnitResistance(v::AbstractFloat, train::Train)
# equation is based on [Wende:2003, page 151]
f_Rtd0 = train[:f_Rtd0] # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0 = train[:f_Rtc0] # coefficient for basic resistance due to the traction units carring axles (in ‰)
F_Rt2 = train[:F_Rt2] # coefficient for air resistance of the traction units (in N)
m_td = train[:m_td] # mass on the traction unit's driving axles (in kg)
m_tc = train[:m_tc] # mass on the traction unit's carrying axles (in kg)
Δv_t = train[:Δv_t] # coefficient for velocitiy difference between traction unit and outdoor air (in m/s)
f_Rtd0 = train.f_Rtd0 # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0 = train.f_Rtc0 # coefficient for basic resistance due to the traction units carring axles (in ‰)
F_Rt2 = train.F_Rt2 # coefficient for air resistance of the traction units (in N)
m_td = train.m_td # mass on the traction unit's driving axles (in kg)
m_tc = train.m_tc # mass on the traction unit's carrying axles (in kg)
F_R_tractionUnit = f_Rtd0/1000 * m_td * g + f_Rtc0/1000 * m_tc * g + F_Rt2 * ((v + Δv_t) /v00)^2 # vehicle resistance of the traction unit (in N) # /1000 because of the unit ‰
# TODO: use calcForceFromCoefficient? F_R_tractionUnit = calcForceFromCoefficient(f_Rtd0, m_td) + calcForceFromCoefficient(f_Rtc0, m_tc) + F_Rt2 * ((v + Δv_t) /v00)^2 # vehicle resistance of the traction unit (in N)
F_R_tractionUnit = f_Rtd0/1000 * m_td * g + f_Rtc0/1000 * m_tc * g + F_Rt2 * ((v + Δv_air) /v00)^2 # vehicle resistance of the traction unit (in N) # /1000 because of the unit ‰
# TODO: use calcForceFromCoefficient? F_R_tractionUnit = calcForceFromCoefficient(f_Rtd0, m_td) + calcForceFromCoefficient(f_Rtc0, m_tc) + F_Rt2 * ((v + Δv_air) /v00)^2 # vehicle resistance of the traction unit (in N)
return F_R_tractionUnit
#TODO: same variable name like in the rest of the tool? return R_traction
#TODO: just one line? return train[:f_Rtd0]/1000*train[:m_td]*g+train[:f_Rtc0]/1000*train[:m_tc]*g+train[:F_Rt2]*((v+train[:Δv_t])/v00)^2 # /1000 because of the unit ‰
#TODO: just one line? return train.f_Rtd0/1000*train.m_td*g+train.f_Rtc0/1000*train.m_tc*g+train.F_Rt2*((v+train.Δv_air)/v00)^2 # /1000 because of the unit ‰
end #function calcTractionUnitResistance
"""
TODO
calculate and return the wagons vehicle resistance dependend on the velocity
"""
function calcWagonsResistance(v::AbstractFloat, train::Dict)
function calcWagonsResistance(v::AbstractFloat, train::Train)
# equation is based on a combination of the equations of Strahl and Sauthoff [Wende:2003, page 153] with more detailled factors (Lehmann, page 135)
f_Rw0 = train[:f_Rw0] # coefficient for basic resistance of the set of wagons (consist) (in ‰)
f_Rw1 = train[:f_Rw1] # coefficient for the consists resistance to rolling (in ‰)
f_Rw2 = train[:f_Rw2] # coefficient fo the consistsr air resistance (in ‰)
m_w = train[:m_w] # mass of the set of wagons (consist) (in kg)
Δv_w = train[:Δv_w] # coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s)
f_Rw0 = train.f_Rw0 # coefficient for basic resistance of the set of wagons (consist) (in ‰)
f_Rw1 = train.f_Rw1 # coefficient for the consists resistance to rolling (in ‰)
f_Rw2 = train.f_Rw2 # coefficient fo the consistsr air resistance (in ‰)
m_w = train.m_w # mass of the set of wagons (consist) (in kg)
F_R_wagons = m_w *g *(f_Rw0/1000 + f_Rw1/1000 *v /v00 + f_Rw2/1000 * ((v + Δv_w) /v00)^2) # vehicle resistance of the wagons (in N) # /1000 because of the unit ‰
# TODO: use calcForceFromCoefficient? F_R_wagons = calcForceFromCoefficient(f_Rw0, m_w) + calcForceFromCoefficient(f_Rw1, m_w) *v /v00 + calcForceFromCoefficient(f_Rw2, m_w) * ((v + Δv_w) /v00)^2 # vehicle resistance of the wagons (in N)
F_R_wagons = m_w *g *(f_Rw0/1000 + f_Rw1/1000 *v /v00 + f_Rw2/1000 * ((v + Δv_air) /v00)^2) # vehicle resistance of the wagons (in N) # /1000 because of the unit ‰
# TODO: use calcForceFromCoefficient? F_R_wagons = calcForceFromCoefficient(f_Rw0, m_w) + calcForceFromCoefficient(f_Rw1, m_w) *v /v00 + calcForceFromCoefficient(f_Rw2, m_w) * ((v + Δv_air) /v00)^2 # vehicle resistance of the wagons (in N)
return F_R_wagons
end #function calcWagonsResistance
@ -213,8 +182,8 @@ function calc_ΔW(F_T_prev::Real, Δs::Real)
end #function calc_ΔW
function calc_ΔE(ΔW::Real)
# simplified equation is based on [Jaekel:2014, page 6]
# simplified equation
# TODO!
# ΔW: mechanical work in this step (in Ws)
ΔE = ΔW # energy consumption in this step (in Ws)
return ΔE
@ -228,8 +197,8 @@ function calcBrakingDistance(v_start::Real, v_end::Real, a_braking::Real)
# a_braking: constant braking acceleration (in m/s^2)
s_braking = (v_end^2 - v_start^2) /2 /a_braking # braking distance (in m)
# TODO: also possible: calc_Δs_with_Δv(v_end-v_start, a_braking, v_start)
# return max(0.0, ceil(s_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
return max(0.0, ceil(s_braking, digits=approximationLevel +1)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
# return max(0.0, ceil(s_braking, digits=approxLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
return max(0.0, ceil(s_braking, digits=approxLevel +1)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
end #function calcBrakingDistance
function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real)
@ -239,8 +208,8 @@ function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real)
# a_braking: constant braking acceleration (in m/s^2)
# s_braking: braking distance (in Ws)
v_start = sqrt(v_end^2 - 2*a_braking *s_braking) # braking start velocity (in m/s)
# return floor(v_start, digits=approximationLevel)
return floor(v_start, digits=approximationLevel +1)
# return floor(v_start, digits=approxLevel)
return floor(v_start, digits=approxLevel +1)
end #function calcBrakingStartVelocity
function calcBrakingAcceleration(v_start::Real, v_end::Real, s_braking::Real)
@ -252,5 +221,3 @@ function calcBrakingAcceleration(v_start::Real, v_end::Real, s_braking::Real)
a_braking = (v_end^2 - v_start^2) /2 /s_braking # constant braking acceleration (in m/s^2)
return a_braking
end #function calcBrakingAcceleration
end #module Formulary

View File

@ -5,22 +5,22 @@
# __copyright__ = "2020-2022"
# __license__ = "ISC"
module Output
export createOutput
function createOutput(train::Dict, settings::Dict, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
if settings[:detailOfOutput] == "running time"
function createOutput(train::Train, settings::Settings, path::Path, movingSection::Dict, drivingCourse::Vector{Dict})
if settings.outputDetail == :running_time
output = movingSection[:t] # TODO: or use drivingCourse[end][:t]
elseif settings[:detailOfOutput] == "points of interest"
elseif settings.outputDetail == :points_of_interest
# add points of interest
if haskey(path, :pointsOfInterest)
output = Vector{Dict}()
if !isempty(path.poi)
# for elem in 1:length(driving_course)
# end
output = Dict[]
POI = 1
i = 1
while POI <= length(path[:pointsOfInterest]) && i <= drivingCourse[end][:i]
if path[:pointsOfInterest][POI] == drivingCourse[i][:s]
while POI <= length(path.poi) && i <= drivingCourse[end][:i]
if path.poi[POI][:station] == drivingCourse[i][:s]
push!(output, drivingCourse[i])
POI = POI+1
end
@ -28,10 +28,10 @@ function createOutput(train::Dict, settings::Dict, path::Dict, movingSection::Di
end
end
elseif settings[:detailOfOutput] == "driving course"
elseif settings.outputDetail == :driving_course
output = drivingCourse
elseif settings[:detailOfOutput] == "everything"
elseif settings.outputDetail == :everything
output = Dict{Symbol,Any}()
merge!(output, Dict(:train => train, :path => path, :settings => settings))
@ -46,12 +46,12 @@ function createOutput(train::Dict, settings::Dict, path::Dict, movingSection::Di
end
# add points of interest
if haskey(path, :pointsOfInterest)
if !isempty(path.poi)
pointsOfInterest = Vector{Dict}()
POI = 1
i = 1
while POI <= length(path[:pointsOfInterest]) && i <= drivingCourse[end][:i]
if path[:pointsOfInterest][POI] == drivingCourse[i][:s]
while POI <= length(path.poi) && i <= drivingCourse[end][:i]
if path.poi[POI] == drivingCourse[i][:s]
push!(pointsOfInterest, drivingCourse[i])
POI = POI+1
end
@ -71,7 +71,7 @@ function createOutput(train::Dict, settings::Dict, path::Dict, movingSection::Di
end
#=
function createOutputDict(train::Dict, settings::Dict, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
function createOutputDict(train::Train, settings::Settings, path::Path, movingSection::Dict, drivingCourse::Vector{Dict})
outputDict = Dict{Symbol,Any}()
merge!(outputDict, Dict(:train => train, :path => path, :settings => settings))
@ -86,12 +86,12 @@ function createOutputDict(train::Dict, settings::Dict, path::Dict, movingSection
end
# add points of interest
if haskey(path, :pointsOfInterest)
if !isempty(path.poi)
pointsOfInterest = Vector{Dict}()
POI = 1
i = 1
while POI <= length(path[:pointsOfInterest]) && i <= drivingCourse[end][:i]
if path[:pointsOfInterest][POI] == drivingCourse[i][:s]
while POI <= length(path.poi) && i <= drivingCourse[end][:i]
if path.poi[POI] == drivingCourse[i][:s]
push!(pointsOfInterest, drivingCourse[i])
POI = POI+1
end
@ -108,5 +108,3 @@ function createOutputDict(train::Dict, settings::Dict, path::Dict, movingSection
return outputDict
end # function createOutputDict
=#
end # module Output

61
src/types.jl Normal file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.2
# __author__ = "Martin Scheidt, Max Kannenberg"
# __copyright__ = "2022"
# __license__ = "ISC"
struct Settings
massModel::Symbol # model type of train mass ":mass_point" or ":homogeneous_strip".
stepVariable::Symbol # variable of the linear multistep method: ":distance", ":time" or ":velocity".
stepSize::Real # step size, unit depends on stepVariable - :distance in meter, time in seconds and velocity in meter/second.
approxLevel::Int # value for approximation; used when rounding or interating.
outputDetail::Symbol # single Float() ":running_time", Array() of ":points_of_interest",
# complete Array() ":driving_course", or Dict() ":everything".
outputFormat::Symbol # output as ":dataframe" or as ":dict".
end #struct Settings
struct Path
name::String # a name or description of the path
id::String # a short string as identifier
uuid::UUID # a unique identifier
poi::Vector # a vector of triples with points along the path
sections::Vector # a vector of the characteristic sections
end #struct Path
struct Train
name::String # a name or description of the train
id::String # a short string as identifier
uuid::UUID # a unique identifier
length::Real # train length in meter
m_train_full::Real # mass of the full loaded train in kilogram
m_td::Real # mass on driving axles of the traction unit in kilogram
m_tc::Real # mass on the traction unit's carrying axles in kilogram
m_w::Real # mass of the set of wagons/cars/consist in kilogram
ξ_train::Real # rotation mass factor
ξ_loco::Real # rotation mass factor
ξ_cars::Real # rotation mass factor
transportType::Symbol # ":freight" or ":passenger" for resistance calculation
v_limit::Real # in m/s
a_braking::Real # in m/s^2
# coefficients for the vehicle resistance
# for the traction unit (F_Rt=f_Rtd0*m_td*g+f_Rtc0*m_tc*g+F_Rt2*((v+Δv_air)/v00)^2)
f_Rtd0::Real # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0::Real # coefficient for basic resistance due to the traction units carring axles (in ‰)
F_Rt2::Real # coefficient for air resistance of the traction units (in N)
# for the consist (set of wagons) (F_Rw=m_w*g*(f_Rw0+f_Rw1*v/v00+f_Rw2*((v+Δv_air)/v00)^2))
f_Rw0::Real # coefficient for the consists basic resistance (in ‰)
f_Rw1::Real # coefficient for the consists resistance to rolling (in ‰)
f_Rw2::Real # coefficient fo the consistsr air resistance (in ‰)
# tractive effort as pairs of speed and tractive effort
tractiveEffort::Vector{Tuple{Real, Real}} # [v in m/s, F_T in N]
end #struct Train

View File

@ -0,0 +1,21 @@
%YAML 1.2
---
schema: https://railtoolkit.org/schema/running-path.json
schema_version: "2022.05"
paths:
- name: "10 km, no gradient, 160 km/h"
id: const
UUID: 23ff336e-9b9a-4535-bdb6-9db488b10945
points_of_interest:
# [ station in m, name, front or rear ]
- [ 999.00, point_1, front ]
- [ 2000.00, point_2, front ]
- [ 3333.30, point_3, rear ]
- [ 5000.00, point_4, front ]
- [ 7777.00, point_5, front ]
- [ 9000.00, point_6, front ]
- [ 9500.95, point_7, front ]
characteristic_sections:
# [ station in m, speed limit in km/h, resistance in ‰ ]
- [ 0.0, 160, 0.00 ]
- [ 10000.0, 160, 0.00 ]

View File

@ -0,0 +1,362 @@
%YAML 1.2
---
schema: https://railtoolkit.org/schema/running-path.json
schema_version: "2022.05"
paths:
- name: "'infra_Ostsachsen': track id='tr_80.6212_2' name='DG-DN' -> spp_5"
id: realworld
UUID: 2b31a0c5-85bc-4721-b7e0-66f9df95f7b6
# source: https://www.railml.org/en/user/exampledata.html
# -> "Real world railway examples from professional tools"
# -> "East Saxony railway network by FBS"
# -> "Ostsachsen_V220.railml"
# -> 'infra_Ostsachsen': track id='tr_80.6212_2' name='DG-DN' -> spp_5
characteristic_sections:
# [ s in m, v_limit in km/h, f_Rp in ‰ ]
- [ 0.0, 40, 0.0 ]
- [ 318.0, 40, 2.0 ]
- [ 399.0, 40, -3.0 ]
- [ 500.0, 40, 0.0 ]
- [ 579.0, 40, 1.0 ]
- [ 784.0, 40, 5.3 ]
- [ 868.0, 40, 20.0 ]
- [ 1082.0, 40, 16.1 ]
- [ 1287.0, 40, 18.1 ]
- [ 1800.0, 110, 18.1 ]
- [ 2242.0, 110, 15.4 ]
- [ 3295.0, 110, 11.0 ]
- [ 3880.0, 110, 11.1 ]
- [ 4680.0, 45, 11.1 ]
- [ 4686.0, 90, 11.1 ]
- [ 6122.0, 90, 0.0 ]
- [ 6487.0, 90, 1.5 ]
- [ 6588.0, 70, 1.5 ]
- [ 6589.0, 70, 2.4 ]
- [ 6608.0, 130, 2.4 ]
- [ 6723.0, 150, 1.3 ]
- [ 6928.0, 160, 1.3 ]
- [ 7030.0, 160, 7.5 ]
- [ 7300.0, 160, 8.0 ]
- [ 7552.0, 160, 5.0 ]
- [ 7675.0, 160, 6.7 ]
- [ 7800.0, 160, 7.4 ]
- [ 7920.0, 160, 7.0 ]
- [ 8020.0, 140, 7.0 ]
- [ 8100.0, 140, 6.3 ]
- [ 8168.0, 140, 7.4 ]
- [ 8226.0, 140, 8.4 ]
- [ 8300.0, 140, 7.4 ]
- [ 8381.0, 150, 7.4 ]
- [ 8600.0, 150, 7.8 ]
- [ 8900.0, 150, 6.7 ]
- [ 9100.0, 150, 7.8 ]
- [ 9600.0, 150, 8.0 ]
- [ 9845.0, 150, 7.3 ]
- [ 10005.0, 160, 7.3 ]
- [ 10600.0, 160, 6.0 ]
- [ 10748.0, 160, 7.3 ]
- [ 11100.0, 160, 4.5 ]
- [ 11280.0, 160, 3.6 ]
- [ 11450.0, 160, 7.2 ]
- [ 11800.0, 160, 6.8 ]
- [ 12100.0, 160, 7.3 ]
- [ 12590.0, 160, 7.6 ]
- [ 13100.0, 160, 7.3 ]
- [ 13500.0, 160, 7.1 ]
- [ 13800.0, 160, 7.3 ]
- [ 14138.0, 150, 7.3 ]
- [ 14330.0, 150, 0.3 ]
- [ 14640.0, 150, -1.8 ]
- [ 14764.0, 160, -2.8 ]
- [ 15000.0, 160, -3.3 ]
- [ 15500.0, 160, -0.9 ]
- [ 16000.0, 160, 0.0 ]
- [ 16470.0, 160, 1.2 ]
- [ 16572.0, 160, 2.2 ]
- [ 16700.0, 160, 3.8 ]
- [ 16949.0, 160, 3.5 ]
- [ 17086.0, 160, 3.2 ]
- [ 17232.0, 160, 1.3 ]
- [ 17339.0, 160, 4.5 ]
- [ 17406.0, 160, 3.4 ]
- [ 17727.0, 150, 3.4 ]
- [ 17807.0, 150, 4.6 ]
- [ 18049.0, 150, 3.0 ]
- [ 18210.0, 140, 3.0 ]
- [ 18300.0, 140, 4.6 ]
- [ 18680.0, 140, 3.2 ]
- [ 18761.0, 150, 3.2 ]
- [ 19047.0, 150, 5.1 ]
- [ 19305.0, 150, 3.0 ]
- [ 19406.0, 160, 3.0 ]
- [ 19414.0, 160, -0.3 ]
- [ 19900.0, 160, 3.0 ]
- [ 20150.0, 160, 1.8 ]
- [ 20470.0, 160, -4.0 ]
- [ 20940.0, 160, -3.6 ]
- [ 21150.0, 160, -1.5 ]
- [ 21390.0, 160, 0.0 ]
- [ 21702.0, 160, 1.5 ]
- [ 22188.0, 150, 1.5 ]
- [ 22294.0, 150, 1.8 ]
- [ 22383.0, 160, 1.8 ]
- [ 22500.0, 160, 2.6 ]
- [ 22900.0, 160, 4.6 ]
- [ 23542.0, 160, 0.2 ]
- [ 23736.0, 160, 0.9 ]
- [ 24124.0, 160, 7.0 ]
- [ 24918.0, 160, 7.6 ]
- [ 25100.0, 150, 7.1 ]
- [ 25580.0, 150, 7.4 ]
- [ 25708.0, 160, 7.4 ]
- [ 25810.0, 160, 7.1 ]
- [ 26040.0, 160, 3.2 ]
- [ 26330.0, 160, 1.8 ]
- [ 26593.0, 160, 2.1 ]
- [ 27020.0, 160, 3.5 ]
- [ 27195.0, 160, 5.8 ]
- [ 27253.0, 160, 1.1 ]
- [ 27310.0, 160, 3.5 ]
- [ 27595.0, 160, 3.4 ]
- [ 28530.0, 160, 4.6 ]
- [ 29115.0, 160, 0.0 ]
- [ 29700.0, 160, -5.2 ]
- [ 30055.0, 120, -4.3 ]
- [ 30301.0, 120, -6.2 ]
- [ 30487.0, 160, -6.2 ]
- [ 30537.0, 160, -4.8 ]
- [ 31130.0, 160, -0.3 ]
- [ 31293.0, 160, 3.7 ]
- [ 31400.0, 160, 2.9 ]
- [ 31640.0, 160, 4.1 ]
- [ 31795.0, 120, 4.1 ]
- [ 32010.0, 120, 3.2 ]
- [ 32138.0, 130, 3.2 ]
- [ 32365.0, 130, -4.0 ]
- [ 33000.0, 130, 6.1 ]
- [ 33426.0, 160, 6.1 ]
- [ 33907.0, 160, 7.1 ]
- [ 34220.0, 160, 8.4 ]
- [ 34300.0, 160, 7.9 ]
- [ 34440.0, 160, 7.1 ]
- [ 34610.0, 160, 4.4 ]
- [ 35000.0, 160, 5.6 ]
- [ 35173.0, 150, 5.6 ]
- [ 35400.0, 150, -0.2 ]
- [ 35597.0, 160, -0.2 ]
- [ 35900.0, 160, 0.0 ]
- [ 36700.0, 160, 3.9 ]
- [ 36938.0, 160, 0.0 ]
- [ 37700.0, 160, -0.3 ]
- [ 37978.0, 150, -5.6 ]
- [ 38063.0, 150, -1.9 ]
- [ 38141.0, 150, -3.1 ]
- [ 38210.0, 150, 0.0 ]
- [ 38406.0, 150, -7.0 ]
- [ 38900.0, 150, -7.5 ]
- [ 39200.0, 150, -8.7 ]
- [ 39298.0, 150, -6.4 ]
- [ 39476.0, 150, -7.2 ]
- [ 40400.0, 150, -6.9 ]
- [ 40676.0, 130, -6.9 ]
- [ 41000.0, 130, -7.3 ]
- [ 41406.0, 130, -7.5 ]
- [ 41571.0, 160, -7.3 ]
- [ 41816.0, 160, -6.8 ]
- [ 41923.0, 160, -7.1 ]
- [ 42139.0, 160, -1.3 ]
- [ 42343.0, 160, -2.4 ]
- [ 42432.0, 150, -2.4 ]
- [ 42952.0, 160, -2.4 ]
- [ 43000.0, 160, -4.6 ]
- [ 43264.0, 160, -2.5 ]
- [ 43388.0, 160, -0.6 ]
- [ 43700.0, 160, 0.8 ]
- [ 44030.0, 160, 2.7 ]
- [ 44430.0, 160, 0.0 ]
- [ 44708.0, 160, -7.2 ]
- [ 45477.0, 160, -7.8 ]
- [ 45890.0, 160, -1.0 ]
- [ 46562.0, 160, -1.6 ]
- [ 47000.0, 160, -6.9 ]
- [ 47500.0, 160, -7.7 ]
- [ 47800.0, 160, -6.8 ]
- [ 48700.0, 160, -4.3 ]
- [ 49218.0, 160, -5.3 ]
- [ 49514.0, 160, -2.5 ]
- [ 50000.0, 160, -2.2 ]
- [ 51150.0, 160, -5.7 ]
- [ 51406.0, 160, -6.3 ]
- [ 51710.0, 150, -5.8 ]
- [ 52000.0, 150, -6.7 ]
- [ 52215.0, 150, -6.1 ]
- [ 53213.0, 150, -6.8 ]
- [ 53567.0, 150, -5.6 ]
- [ 53943.0, 150, -6.5 ]
- [ 54129.0, 140, -6.5 ]
- [ 54212.0, 140, -10.5 ]
- [ 54247.0, 140, -5.4 ]
- [ 54326.0, 140, -6.1 ]
- [ 54450.0, 140, -6.5 ]
- [ 54482.0, 120, -6.5 ]
- [ 54550.0, 120, -6.2 ]
- [ 54855.0, 140, -6.2 ]
- [ 55307.0, 140, -0.3 ]
- [ 55651.0, 140, -1.2 ]
- [ 55788.0, 140, 0.0 ]
- [ 55918.0, 100, 0.0 ]
- [ 56433.0, 150, 0.0 ]
- [ 56560.0, 150, -2.1 ]
- [ 56624.0, 150, -6.7 ]
- [ 57012.0, 150, 1.3 ]
- [ 57260.0, 150, 6.6 ]
- [ 57800.0, 150, 5.3 ]
- [ 57987.0, 150, 0.0 ]
- [ 57990.0, 150, 7.6 ]
- [ 58321.0, 150, 6.4 ]
- [ 59090.0, 150, 6.9 ]
- [ 59468.0, 150, 9.2 ]
- [ 59600.0, 150, 0.2 ]
- [ 60683.0, 150, 4.1 ]
- [ 61156.0, 150, 2.3 ]
- [ 61181.0, 130, 2.3 ]
- [ 61325.0, 130, 0.0 ]
- [ 61605.0, 130, 7.3 ]
- [ 62108.0, 150, 7.3 ]
- [ 62246.0, 150, 6.6 ]
- [ 62279.0, 150, 5.1 ]
- [ 62454.0, 150, 0.9 ]
- [ 62777.0, 150, 5.5 ]
- [ 63802.0, 150, 4.6 ]
- [ 64344.0, 150, 0.2 ]
- [ 64932.0, 150, -0.6 ]
- [ 65100.0, 150, 0.0 ]
- [ 65690.0, 150, 1.8 ]
- [ 65878.0, 150, 2.5 ]
- [ 66266.0, 150, -1.0 ]
- [ 66339.0, 150, 6.3 ]
- [ 66448.0, 160, 6.3 ]
- [ 66587.0, 160, 0.0 ]
- [ 66856.0, 160, 3.2 ]
- [ 67480.0, 160, 3.6 ]
- [ 67697.0, 160, 2.2 ]
- [ 67800.0, 160, 6.0 ]
- [ 67851.0, 130, 6.0 ]
- [ 68027.0, 130, 2.7 ]
- [ 68172.0, 130, 0.6 ]
- [ 68328.0, 130, 2.5 ]
- [ 68357.0, 130, 0.0 ]
- [ 68479.0, 130, 7.1 ]
- [ 68783.0, 130, 7.4 ]
- [ 69056.0, 150, 7.4 ]
- [ 69500.0, 150, 6.8 ]
- [ 69741.0, 160, 6.8 ]
- [ 69900.0, 160, 6.6 ]
- [ 70757.0, 160, 3.6 ]
- [ 71384.0, 160, 6.0 ]
- [ 71568.0, 160, 7.1 ]
- [ 71800.0, 160, 7.4 ]
- [ 72100.0, 160, 7.3 ]
- [ 73919.0, 150, 7.3 ]
- [ 74317.0, 140, 7.3 ]
- [ 74448.0, 140, 1.5 ]
- [ 74590.0, 140, -1.5 ]
- [ 74620.0, 140, -5.0 ]
- [ 74950.0, 140, -4.3 ]
- [ 75100.0, 140, -1.8 ]
- [ 75154.0, 130, -1.8 ]
- [ 75260.0, 130, -6.2 ]
- [ 75873.0, 130, -5.6 ]
- [ 76062.0, 100, -5.6 ]
- [ 76100.0, 100, -6.4 ]
- [ 76350.0, 100, -5.7 ]
- [ 76476.0, 100, -7.0 ]
- [ 76600.0, 100, -6.4 ]
- [ 76601.0, 90, -6.4 ]
- [ 76726.0, 90, -6.2 ]
- [ 77256.0, 90, -2.1 ]
- [ 77285.0, 80, -2.1 ]
- [ 77299.0, 80, -14.0 ]
- [ 77331.0, 80, -1.6 ]
- [ 77379.0, 90, -1.6 ]
- [ 77425.0, 110, -1.6 ]
- [ 77455.0, 110, -4.9 ]
- [ 77498.0, 110, 0.0 ]
- [ 77505.0, 160, 0.0 ]
- [ 77555.0, 160, -5.6 ]
- [ 77662.0, 160, 0.0 ]
- [ 78085.0, 160, -4.0 ]
- [ 78223.0, 160, -6.8 ]
- [ 78337.0, 130, -6.8 ]
- [ 78856.0, 130, -6.6 ]
- [ 78875.0, 130, -7.2 ]
- [ 79345.0, 150, -7.2 ]
- [ 79600.0, 150, -6.5 ]
- [ 79792.0, 150, -0.2 ]
- [ 80537.0, 150, -5.2 ]
- [ 81300.0, 150, -4.8 ]
- [ 81634.0, 110, -4.8 ]
- [ 81943.0, 110, -5.4 ]
- [ 82166.0, 110, 0.0 ]
- [ 82408.0, 110, 4.8 ]
- [ 82790.0, 110, 5.9 ]
- [ 83137.0, 120, 5.9 ]
- [ 83300.0, 120, 0.0 ]
- [ 83519.0, 150, 0.0 ]
- [ 83597.0, 150, -7.8 ]
- [ 83827.0, 150, -8.1 ]
- [ 84150.0, 150, -7.2 ]
- [ 84391.0, 150, 0.0 ]
- [ 84966.0, 150, -4.0 ]
- [ 85529.0, 130, -2.3 ]
- [ 85589.0, 130, -4.0 ]
- [ 86081.0, 130, 0.0 ]
- [ 86514.0, 130, 7.8 ]
- [ 86577.0, 120, 7.8 ]
- [ 87554.0, 90, 7.8 ]
- [ 87690.0, 90, 7.9 ]
- [ 87842.0, 90, 1.7 ]
- [ 88007.0, 110, 1.7 ]
- [ 88100.0, 110, 3.4 ]
- [ 88260.0, 110, 5.3 ]
- [ 88376.0, 160, 5.3 ]
- [ 88450.0, 160, 6.7 ]
- [ 89050.0, 160, 7.4 ]
- [ 89350.0, 160, -7.1 ]
- [ 90365.0, 160, 0.0 ]
- [ 90700.0, 160, -7.3 ]
- [ 92000.0, 160, -7.9 ]
- [ 92166.0, 160, -4.0 ]
- [ 92460.0, 160, -5.4 ]
- [ 93330.0, 160, 0.0 ]
- [ 93901.0, 160, 0.7 ]
- [ 94156.0, 160, 5.2 ]
- [ 94440.0, 160, -2.8 ]
- [ 94530.0, 160, -0.8 ]
- [ 94630.0, 160, -6.8 ]
- [ 94830.0, 160, -4.4 ]
- [ 95090.0, 160, -4.6 ]
- [ 95500.0, 160, -4.8 ]
- [ 96500.0, 160, -4.4 ]
- [ 96700.0, 160, -5.6 ]
- [ 97000.0, 160, -4.6 ]
- [ 97590.0, 160, 0.0 ]
- [ 97858.0, 120, 0.0 ]
- [ 98224.0, 120, -1.5 ]
- [ 98264.0, 120, 0.0 ]
- [ 98577.0, 120, 7.5 ]
- [ 98738.0, 120, 0.0 ]
- [ 99055.0, 130, 0.0 ]
- [ 99427.0, 130, -2.0 ]
- [ 99610.0, 130, -3.1 ]
- [ 99906.0, 120, -3.1 ]
- [ 99980.0, 120, -1.3 ]
- [100190.0, 120, -6.8 ]
- [100832.0, 120, -7.2 ]
- [100980.0, 120, -8.1 ]
- [101100.0, 120, -7.4 ]
- [101245.0, 120, -6.3 ]
- [101332.0, 100, -6.3 ]
- [101365.0, 100, -2.4 ]
- [101551.0, 110, -2.4 ]
- [101800.0, 110, 0.0 ]

View File

@ -0,0 +1,29 @@
%YAML 1.2
---
schema: https://railtoolkit.org/schema/running-path.json
schema_version: "2022.05"
paths:
- name: "10 km, different gradient, 160 km/h"
id: slope
UUID: ffd243a9-0223-4210-8c7d-e6c90fde70d3
points_of_interest:
# [ station in m, name, front or rear ]
- [ 850.00, view_point_1, front ]
- [ 1000.00, distant_signal_1, front ]
- [ 2000.00, main_signal_1, front ]
- [ 9000.00, main_signal_3, front ]
- [ 9050.00, clearing_point_1, rear ]
characteristic_sections:
# [ station in m, speed limit in km/h, resistance in ‰ ]
- [ 0.0, 160, 0.00 ]
- [ 1000.0, 160, 1.00 ]
- [ 2000.0, 160, 2.00 ]
- [ 3000.0, 160, 5.00 ]
- [ 4000.0, 160, -3.00 ]
- [ 5000.0, 160, 5.00 ]
- [ 6000.0, 160, -10.00 ]
- [ 7000.0, 160, 15.00 ]
- [ 8000.0, 160, -10.00 ]
- [ 8500.0, 160, 20.00 ]
- [ 9000.0, 160, 0.00 ]
- [ 10000.0, 160, 0.00 ]

View File

@ -0,0 +1,29 @@
%YAML 1.2
---
schema: https://railtoolkit.org/schema/running-path.json
schema_version: "2022.05"
paths:
- name: "10 km, no gradient, different speed limits"
id: speed
UUID: 401b8ce7-fa75-4576-8a4a-43be2eb55e50
points_of_interest:
# [ station in m, name, front or rear ]
- [ 999.00, point_1, front ]
- [ 2000.00, point_2, front ]
- [ 3333.30, point_3, rear ]
- [ 5000.00, point_4, front ]
- [ 7777.00, point_5, front ]
- [ 9000.00, point_6, front ]
- [ 9500.95, point_7, front ]
characteristic_sections:
# [ station in m, speed limit in km/h, resistance in ‰ ]
- [ 0.0, 160, 0.00 ]
- [ 3000.0, 60, 0.00 ]
- [ 4000.0, 160, 0.00 ]
- [ 5000.0, 60, 0.00 ]
- [ 6000.0, 160, 0.00 ]
- [ 6500.0, 60, 0.00 ]
- [ 6700.0, 65, 0.00 ]
- [ 6800.0, 70, 0.00 ]
- [ 7000.0, 120, 0.00 ]
- [ 10000.0, 160, 0.00 ]

View File

@ -0,0 +1,4 @@
%YAML 1.2
---
settings:
outputDetail: "driving_course" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"

View File

@ -0,0 +1,4 @@
%YAML 1.2
---
settings:
outputDetail: "everything" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"

View File

@ -0,0 +1,4 @@
%YAML 1.2
---
settings:
outputDetail: "points_of_interest" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"

View File

@ -0,0 +1,4 @@
%YAML 1.2
---
settings:
massModel: "homogeneous_strip" # type of train model used: "mass_point" or "homogeneous_strip"

View File

@ -0,0 +1,4 @@
%YAML 1.2
---
settings:
stepVariable: "time" # variable of the linear multistep method: "distance", "time" or "velocity"

View File

@ -0,0 +1,5 @@
%YAML 1.2
---
settings:
stepVariable: "time" # variable of the linear multistep method: "distance", "time" or "velocity"
massModel: "homogeneous_strip" # type of train model used: "mass_point" or "homogeneous_strip"

View File

@ -0,0 +1,5 @@
%YAML 1.2
---
settings:
stepVariable: "velocity" # variable of the linear multistep method: "distance", "time" or "velocity"
stepSize: 0.1 # step size, unit depends on stepVariable - position in meter, time in seconds and velocity in meter/second

View File

@ -0,0 +1,123 @@
%YAML 1.2
---
schema: https://railtoolkit.org/schema/rolling-stock.json
schema_version: "2022.05"
trains:
- name: "V 90 with 10 ore wagons of type Facs 124" # (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90 and https://dybas.de/dybas/gw/gw_f_1/g124.html)
id: Fr100
formation: [DB_V90,Facs124,Facs124,Facs124,Facs124,Facs124,Facs124,Facs124,Facs124,Facs124,Facs124]
vehicles:
- name: "Facs 124" # source: https://dybas.de/dybas/gw/gw_f_1/g124.html
id: Facs124
UUID: 30abe88d-5be7-4c9c-b6a2-61c6b0e9f9bc
picture: https://dybas.de/dybas/gw/gw_f_1/image/124_0042.jpg
vehicle_type: freight # "freight", "passenger", "traction unit" or "multiple unit"
length: 19.04 # source: https://dybas.de/dybas/gw/gw_f_1/g124.html
mass: 25.00 # source: https://dybas.de/dybas/gw/gw_f_1/g124.html
load_limit: 59.0 # source: https://dybas.de/dybas/gw/gw_f_1/g124.html
speed_limit: 100 # source: https://dybas.de/dybas/gw/gw_f_1/g124.html
rotation_mass: 1.03 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 13 for "Güterwagenzug beladen" -> 1.03 to 1.04)
base_resistance: 1.4 # source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for "roller bearings")
air_resistance: 3.9 # source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for "full train loads of coal or ore" modified for the used formula
- name: "DB V90" # source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90
id: DB_V90
UUID: 48b99596-98b2-40c8-b31a-3f9266013803
picture: https://commons.wikimedia.org/wiki/File:DB_294_-_594_side_view.jpg
vehicle_type: traction unit # "freight", "passenger", "traction unit" or "multiple unit"
power_type: diesel # "diesel", "electric", or "steam"
length: 14.32 # source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90
mass: 80 # source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90
mass_traction: 80 # in t # mass on driving axles of the traction unit
speed_limit: 80 # in km/h
rotation_mass: 1.09 # source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit
base_resistance: 2.2 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "4-achsige Diesellokomot." -> 2.2 ‰ to 3.5 ‰
air_resistance: 0.01 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "MittelfUhrerstand" -> 5000 N to 10000 N; modified for the used formula
tractive_effort:
- [0.0, 186940]
- [1.0, 186940]
- [2.0, 182310]
- [3.0, 177680]
- [4.0, 173050]
- [5.0, 168420]
- [6.0, 163790]
- [7.0, 159160]
- [8.0, 154530]
- [9.0, 149240]
- [10.0, 144120]
- [11.0, 139150]
- [12.0, 134340]
- [13.0, 129690]
- [14.0, 125200]
- [15.0, 120860]
- [16.0, 116680]
- [17.0, 112660]
- [18.0, 108790]
- [19.0, 105080]
- [20.0, 101530]
- [21.0, 98120]
- [22.0, 94840]
- [23.0, 91700]
- [24.0, 88700]
- [25.0, 85840]
- [26.0, 83110]
- [27.0, 80520]
- [28.0, 78070]
- [29.0, 75750]
- [30.0, 73580]
- [31.0, 71600]
- [32.0, 69660]
- [33.0, 67770]
- [34.0, 65930]
- [35.0, 64130]
- [36.0, 62380]
- [37.0, 60670]
- [38.0, 59010]
- [39.0, 57400]
- [40.0, 55830]
- [41.0, 54300]
- [42.0, 52820]
- [43.0, 51390]
- [44.0, 50000]
- [45.0, 48660]
- [46.0, 48080]
- [47.0, 47220]
- [48.0, 46380]
- [49.0, 45550]
- [50.0, 44730]
- [51.0, 43930]
- [52.0, 43140]
- [53.0, 42370]
- [54.0, 41610]
- [55.0, 40870]
- [56.0, 40140]
- [57.0, 39430]
- [58.0, 38730]
- [59.0, 38040]
- [60.0, 37370]
- [61.0, 36720]
- [62.0, 36070]
- [63.0, 35450]
- [64.0, 34830]
- [65.0, 34230]
- [66.0, 33650]
- [67.0, 33080]
- [68.0, 32520]
- [69.0, 31980]
- [70.0, 31450]
- [71.0, 30940]
- [72.0, 30440]
- [73.0, 29960]
- [74.0, 29490]
- [75.0, 29030]
- [76.0, 28590]
- [77.0, 28170]
- [78.0, 27760]
- [79.0, 27360]
- [80.0, 26980]

153
test/data/trains/local.yaml Normal file
View File

@ -0,0 +1,153 @@
%YAML 1.2
---
schema: https://railtoolkit.org/schema/rolling-stock.json
schema_version: "2022.05"
trains:
- name: Regional Train
id: RB50-1
formation: [DB_BR_642]
vehicles:
- name: Siemens Desiro Classic # source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic
id: DB_BR_642
UUID: c915c80d-c63d-490b-879f-c481e4b62b55
picture: https://commons.wikimedia.org/wiki/File:Liesel_28-11-10_642_055-8_im_Bahnhof_Scharfenstein.JPG
power_type: diesel # source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic
vehicle_type: multiple unit # source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic
length: 41.7 # source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic
mass: 68.0 # source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic
load_limit: 20.0 # source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic
mass_traction: 45.333 # proportionately to the number of axles: 4 to 2, see: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
speed_limit: 120 # source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic
a_braking: -0.4253 #
# coefficients for the vehicle resistance
rotation_mass: 1.08 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 13 for "Zug, überschlägliche Berechnung"
base_resistance: 3.0 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "f_WL0" -> 2.5 ‰ to 3.5 ‰
rolling_resistance: 1.4 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "f_WW0" -> 1.2 ‰ to 1.6 ‰
air_resistance: 0.0039 # source: the closest parameters are used: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "Fzg. vierachsig, abgerundeter Kopf" plus "Sektion bei Mehrteiligkeit" -> 2200 N + 400 N
# tractive effort as pairs of speed and tractive effort
tractive_effort:
- [0.0, 94400]
- [1.0, 94400]
- [2.0, 92800]
- [3.0, 91200]
- [4.0, 89600]
- [5.0, 88000]
- [6.0, 86400]
- [7.0, 84800]
- [8.0, 83200]
- [9.0, 81600]
- [10.0, 80000]
- [11.0, 78160]
- [12.0, 76290]
- [13.0, 74420]
- [14.0, 72550]
- [15.0, 70680]
- [16.0, 68810]
- [17.0, 66940]
- [18.0, 65070]
- [19.0, 63200]
- [20.0, 61330]
- [21.0, 59460]
- [22.0, 57590]
- [23.0, 55720]
- [24.0, 53850]
- [25.0, 51980]
- [26.0, 50110]
- [27.0, 48240]
- [28.0, 46370]
- [29.0, 44500]
- [30.0, 42630]
- [31.0, 40760]
- [32.0, 38890]
- [33.0, 38110]
- [34.0, 37330]
- [35.0, 36550]
- [36.0, 35770]
- [37.0, 35600]
- [38.0, 35600]
- [39.0, 35600]
- [40.0, 35600]
- [41.0, 35600]
- [42.0, 35600]
- [43.0, 35550]
- [44.0, 35280]
- [45.0, 35010]
- [46.0, 34740]
- [47.0, 34280]
- [48.0, 33560]
- [49.0, 32880]
- [50.0, 32220]
- [51.0, 31590]
- [52.0, 26300]
- [53.0, 26300]
- [54.0, 26300]
- [55.0, 26300]
- [56.0, 26300]
- [57.0, 25990]
- [58.0, 25840]
- [59.0, 25690]
- [60.0, 25540]
- [61.0, 25390]
- [62.0, 25240]
- [63.0, 25090]
- [64.0, 25140]
- [65.0, 24760]
- [66.0, 24380]
- [67.0, 24020]
- [68.0, 23660]
- [69.0, 23320]
- [70.0, 22990]
- [71.0, 19400]
- [72.0, 19400]
- [73.0, 19400]
- [74.0, 19400]
- [75.0, 19400]
- [76.0, 19400]
- [77.0, 19400]
- [78.0, 19400]
- [79.0, 19400]
- [80.0, 19400]
- [81.0, 19440]
- [82.0, 19310]
- [83.0, 19180]
- [84.0, 19050]
- [85.0, 18920]
- [86.0, 18670]
- [87.0, 18460]
- [88.0, 18250]
- [89.0, 15360]
- [90.0, 15310]
- [91.0, 15260]
- [92.0, 15210]
- [93.0, 15160]
- [94.0, 15110]
- [95.0, 15060]
- [96.0, 15010]
- [97.0, 14960]
- [98.0, 14910]
- [99.0, 14860]
- [100.0, 14810]
- [101.0, 14760]
- [102.0, 14710]
- [103.0, 14660]
- [104.0, 14610]
- [105.0, 14560]
- [106.0, 14510]
- [107.0, 14460]
- [108.0, 14410]
- [109.0, 14360]
- [110.0, 14310]
- [111.0, 14460]
- [112.0, 14340]
- [113.0, 14210]
- [114.0, 14080]
- [115.0, 13960]
- [116.0, 13840]
- [117.0, 13720]
- [118.0, 13610]
- [119.0, 13490]
- [120.0, 13380]

View File

@ -0,0 +1,220 @@
%YAML 1.2
---
schema: https://railtoolkit.org/schema/rolling-stock.json
schema_version: "2022.05"
trains:
- name: "Intercity 2 (Traxx P160 AC2 + double deck coaches)" # (source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario#Intercity_2 and https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
id: IC1011
formation: [Bombardier_Traxx_2_P160,DABpza68,DABpza68,DABpza68,DABpza68,DABpza668]
vehicles:
- name: "DBpbzfa 668.2" # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
id: DABpza668
UUID: a186ea2c-daeb-429b-8254-89e0d6700519
picture: https://commons.wikimedia.org/wiki/File:Bombardier_IC_Doppelstocksteuerwagen_Innotrans_2014.JPG
vehicle_type: passenger # "freight", "passenger", "traction unit" or "multiple unit"
length: 27.27 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
mass: 58.00 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
load_limit: 20.0 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
speed_limit: 160 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
rotation_mass: 1.06 # source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for freight wagons
base_resistance: 2.0 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge"
rolling_resistance: 0.715 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge"
air_resistance: 3.64 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge"
- name: "DApza 687.2 and DBpza 682.2" # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
id: DABpza68
UUID: 45e83b27-7952-4f34-ad8d-1affcacfe6f2
picture: https://commons.wikimedia.org/wiki/File:D-DB_50_80_26-81_456-8_DBpza_682.2_Bremen_Hbf_14.11.2015.jpg
vehicle_type: passenger # "freight", "passenger", "traction unit" or "multiple unit"
length: 26.8 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
mass: 50.00 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
load_limit: 20.0 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
speed_limit: 160 # source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario
rotation_mass: 1.06 # source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for freight wagons
base_resistance: 2.0 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge"
rolling_resistance: 0.715 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge"
air_resistance: 3.64 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 153 for "Doppelstockgliederzüge"
- name: "Bombardier Traxx 2 (P160)" # source: https://en.wikipedia.org/wiki/Bombardier_TRAXX#TRAXX_P160_AC2
id: Bombardier_Traxx_2_P160
UUID: bc62a03e-9ec9-41f2-913c-6b315e86cc61
picture: https://commons.wikimedia.org/wiki/File:146_560-8_(Flickr_26502799445).jpg
vehicle_type: traction unit # "freight", "passenger", "traction unit" or "multiple unit"
power_type: electric # "diesel", "electric", or "steam"
length: 18.9 # source: https://de.wikipedia.org/wiki/Bombardier_Traxx#P160_AC2
mass: 85 # source: https://de.wikipedia.org/wiki/Bombardier_Traxx#P160_AC2
mass_traction: 85 # in t # mass on driving axles of the traction unit
speed_limit: 160 # in km/h
rotation_mass: 1.09 # source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit
base_resistance: 2.5 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "4-achsige Diesellokomot." -> 2.2 ‰ to 3.5 ‰
air_resistance: 0.006 # source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 151 for "4-achsig, eckige Kopfform" with "Stromabnehmer" -> 5000 N to 6000 N; modified for the used formula
tractive_effort:
- [0.0, 300000]
- [1.0, 300000]
- [2.0, 300000]
- [3.0, 300000]
- [4.0, 300000]
- [5.0, 300000]
- [6.0, 300000]
- [7.0, 300000]
- [8.0, 300000]
- [9.0, 300000]
- [10.0, 300000]
- [11.0, 300000]
- [12.0, 300000]
- [13.0, 300000]
- [14.0, 300000]
- [15.0, 300000]
- [16.0, 300000]
- [17.0, 300000]
- [18.0, 300000]
- [19.0, 300000]
- [20.0, 300000]
- [21.0, 300000]
- [22.0, 300000]
- [23.0, 300000]
- [24.0, 300000]
- [25.0, 300000]
- [26.0, 300000]
- [27.0, 300000]
- [28.0, 300000]
- [29.0, 300000]
- [30.0, 300000]
- [31.0, 300000]
- [32.0, 300000]
- [33.0, 300000]
- [34.0, 300000]
- [35.0, 300000]
- [36.0, 300000]
- [37.0, 300000]
- [38.0, 300000]
- [39.0, 300000]
- [40.0, 300000]
- [41.0, 300000]
- [42.0, 300000]
- [43.0, 300000]
- [44.0, 300000]
- [45.0, 300000]
- [46.0, 300000]
- [47.0, 300000]
- [48.0, 300000]
- [49.0, 300000]
- [50.0, 300000]
- [51.0, 300000]
- [52.0, 300000]
- [53.0, 300000]
- [54.0, 300000]
- [55.0, 300000]
- [56.0, 300000]
- [57.0, 300000]
- [58.0, 300000]
- [59.0, 300000]
- [60.0, 300000]
- [61.0, 300000]
- [62.0, 300000]
- [63.0, 300000]
- [64.0, 300000]
- [65.0, 300000]
- [66.0, 300000]
- [67.0, 297760]
- [68.0, 293380]
- [69.0, 289130]
- [70.0, 285000]
- [71.0, 280990]
- [72.0, 277080]
- [73.0, 273290]
- [74.0, 269590]
- [75.0, 266000]
- [76.0, 262500]
- [77.0, 259090]
- [78.0, 255770]
- [79.0, 252530]
- [80.0, 249380]
- [81.0, 246300]
- [82.0, 243290]
- [83.0, 240360]
- [84.0, 237500]
- [85.0, 234710]
- [86.0, 231980]
- [87.0, 229310]
- [88.0, 226700]
- [89.0, 224160]
- [90.0, 221670]
- [91.0, 219230]
- [92.0, 216850]
- [93.0, 214520]
- [94.0, 212230]
- [95.0, 210000]
- [96.0, 207810]
- [97.0, 205670]
- [98.0, 203570]
- [99.0, 201520]
- [100.0, 199500]
- [101.0, 197520]
- [102.0, 195590]
- [103.0, 193690]
- [104.0, 191830]
- [105.0, 190000]
- [106.0, 188210]
- [107.0, 186450]
- [108.0, 184720]
- [109.0, 183030]
- [110.0, 181360]
- [111.0, 179730]
- [112.0, 178130]
- [113.0, 176550]
- [114.0, 175000]
- [115.0, 173480]
- [116.0, 171980]
- [117.0, 170510]
- [118.0, 169070]
- [119.0, 167650]
- [120.0, 166250]
- [121.0, 164880]
- [122.0, 163520]
- [123.0, 162200]
- [124.0, 160890]
- [125.0, 159600]
- [126.0, 158330]
- [127.0, 157090]
- [128.0, 155860]
- [129.0, 154650]
- [130.0, 153460]
- [131.0, 152290]
- [132.0, 151140]
- [133.0, 150000]
- [134.0, 148880]
- [135.0, 147780]
- [136.0, 146690]
- [137.0, 145620]
- [138.0, 144570]
- [139.0, 143530]
- [140.0, 142500]
- [141.0, 141490]
- [142.0, 140490]
- [143.0, 139510]
- [144.0, 138540]
- [145.0, 137590]
- [146.0, 136640]
- [147.0, 135710]
- [148.0, 134800]
- [149.0, 133890]
- [150.0, 133000]
- [151.0, 132120]
- [152.0, 131250]
- [153.0, 130390]
- [154.0, 129550]
- [155.0, 128710]
- [156.0, 127880]
- [157.0, 127070]
- [158.0, 126270]
- [159.0, 125470]
- [160.0, 124690]

View File

@ -1,40 +1,88 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.0
# __author__ = "Max Kannenberg"
# __author__ = "Max Kannenberg, Martin Scheidt"
# __copyright__ = "2021"
# __license__ = "ISC"
using TrainRun, Test
using TrainRuns, Test
allPaths=[]
push!(allPaths, importYamlFile(:path, "data/paths/path_1_10km_nConst_vConst.yaml"))
push!(allPaths, importYamlFile(:path, "data/paths/path_2_10km_nVar_vConst.yaml"))
push!(allPaths, importYamlFile(:path, "data/paths/path_3_10km_nConst_vVar.yaml"))
push!(allPaths, importYamlFile(:path, "data/paths/path_4_real_Germany_EastSaxony_DG-DN.yaml"))
trains = Dict()
paths = Dict()
settings = Dict()
@testset "load data" begin
allSettings=[]
push!(allSettings, importYamlFile(:settings, "data/settings.yaml"))
println("testing load train data")
push!(trains, :freight => @time Train("data/trains/freight.yaml"))
push!(trains, :local => @time Train("data/trains/local.yaml"))
push!(trains, :longdistance => @time Train("data/trains/longdistance.yaml"))
allTrains=[]
push!(allTrains, importYamlFile(:train, "data/trains/train_freight_V90withOreConsist.yaml"))
push!(allTrains, importYamlFile(:train, "data/trains/train_passenger_SiemensDesiroClassic.yaml"))
push!(allTrains, importYamlFile(:train, "data/trains/train_passenger_IC2.yaml"))
println("testing load path data")
push!(paths, :const => @time Path("data/paths/const.yaml"))
push!(paths, :slope => @time Path("data/paths/slope.yaml"))
push!(paths, :speed => @time Path("data/paths/speed.yaml"))
push!(paths, :realworld => @time Path("data/paths/realworld.yaml"))
for path in allPaths
for train in allTrains
for settings in allSettings
testDict=trainRun(train, path, settings)
exportToCsv(testDict)
sleep(2)
println("testing load settings data")
push!(settings, "default" => @time Settings())
push!(settings, "poi" => @time Settings("data/settings/points_of_interest.yaml"))
push!(settings, "drivingcourse" => @time Settings("data/settings/driving_course.yaml"))
push!(settings, "everything" => @time Settings("data/settings/everything.yaml"))
push!(settings, "strip" => @time Settings("data/settings/strip.yaml"))
push!(settings, "time" => @time Settings("data/settings/time.yaml"))
push!(settings, "timestrip" => @time Settings("data/settings/time_strip.yaml"))
push!(settings, "velocity" => @time Settings("data/settings/velocity.yaml"))
@test typeof(first(paths)[2]) == Path
@test typeof(first(settings)[2]) == Settings
# TODO:
# compare result to test data set
end
end
end
println("test finished")
# TODO:
# print test results
println("====================")
tests = Base.Iterators.product(trains,paths)
## routine to generate the anticipated Dict()
# anticipated = Dict()
# for test in tests
# println(test[1][1],"-",test[2][1])
# result = @time trainrun(test[1][2],test[2][2])
# push!(anticipated, Symbol(String(test[1][1]) * "_" * String(test[2][1])) => result )
# end
anticipated = Dict(
:default => Dict(
:longdistance_speed => 499.96109564970516,
:freight_slope => 831.4768274141168,
:local_slope => 396.99313307033276,
:longdistance_const => 328.83479381353095,
:freight_realworld => 8971.50124080998,
:longdistance_slope => 329.22915822053164,
:freight_const => 727.7969403041934,
:longdistance_realworld => 2900.1198723158523,
:local_speed => 524.3948201513945,
:local_realworld => 3443.917823618831,
:freight_speed => 733.2610572579886,
:local_const => 392.7234008268302
)
)
@testset "function trainrun()" begin
@testset "Default settings" begin
for test in tests
test_name = String(test[1][1]) * "_" * String(test[2][1])
println("testing $test_name")
@time result = trainrun(test[1][2],test[2][2])
expected = anticipated[:default][Symbol(test_name)]
# compare result to test data set
@test isapprox(result, expected, rtol=0.01)
println("--------------------")
end
end
println("====================")
end

View File

@ -1,24 +0,0 @@
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __julia-version__ = 1.7.0
# __author__ = "Martin Scheidt"
# __copyright__ = "2021"
# __license__ = "ISC"
include("../src/types.jl")
include("../src/Validate.jl")
using .Input
using YAML, Test
@enum trainType passenger=1 freight=2 motorCoachTrain=3
@test Input.getEnum("passenger", trainType) == passenger::trainType
@test Input.getEnum("freight", trainType) == freight::trainType
@test Input.getEnum("motorCoachTrain", trainType) == motorCoachTrain::trainType
data = YAML.load(open("data/trains/train_passenger_IC2.yaml"))
@test Input.getEnum(data["train"]["trainType"], trainType) == passenger::trainType
data = YAML.load(open("data/trains/train_freight_V90withOreConsist.yaml"))
@test Input.getEnum(data["train"]["trainType"], trainType) == freight::trainType