master thesis submission

pull/1/head v0.1
Max Kannenberg 2021-10-13 16:49:42 +02:00
commit 6f3a391ab0
23 changed files with 4278 additions and 0 deletions

51
.gitignore vendored Normal file
View File

@ -0,0 +1,51 @@
# Files generated by invoking Julia with --code-coverage
*.jl.cov
*.jl.*.cov
# Files generated by invoking Julia with --track-allocation
*.jl.mem
# System-specific files and directories generated by the BinaryProvider and BinDeps packages
# They contain absolute paths specific to the host computer, and so should not be committed
deps/deps.jl
deps/build.log
deps/downloads/
deps/usr/
deps/src/
# Build artifacts for creating documentation generated by the Documenter package
docs/build/
docs/site/
# File generated by Pkg, the package manager, based on a corresponding Project.toml
# It records a fixed state of all packages used by the project. As such, it should not be
# committed for packages, but should be committed for applications that require a static
# environment.
Manifest.toml
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

15
LICENSE Normal file
View File

@ -0,0 +1,15 @@
ISC License (ISC)
Copyright 2021 Max Kannenberg
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.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

12
Project.toml Normal file
View File

@ -0,0 +1,12 @@
name = "RailwayDrivingDynamics"
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
authors = ["Max Kannenberg"]
version = "0.1.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"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"

48
README.md Normal file
View File

@ -0,0 +1,48 @@
# RailwayDrivingDynamics
------------
# Installation
The required julia packages are
- YAML.jl
- Dates.jl
- DataFrames.jl
- CSV.jl
- Plots.jl
Review the settings.yaml file for your appropriate settings.
------------
# Minimal working example
See folder examples.
------------
# History
## Version 0.1
Proof of concept and master thesis submission.
------------
# Acknowledgement
This work was supervides by South Westphalia University of Applied Sciences and Technical University Braunschweig.
------------
# License
[![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
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.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

0
TODO.md Normal file
View File

View File

@ -0,0 +1,7 @@
---
path:
name: "10 km, no gradient, 160 km/h"
sectionStarts: # with path speed limt (in m/s)
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, n in ‰]
- [0, 160, 0]
- [10000, 160, 0]

View File

@ -0,0 +1,17 @@
---
path:
name: "10 km, different gradient, 160 km/h"
sectionStarts: # with path speed limt (in m/s)
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, n 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

@ -0,0 +1,15 @@
---
path:
name: "10 km, no gradient, different speed limits"
sectionStarts: # with path speed limt (in m/s)
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, n 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

@ -0,0 +1,354 @@
---
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)
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, n 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.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]

11
data/settings.yaml Normal file
View File

@ -0,0 +1,11 @@
---
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: true # operation mode "minimum energy consumption"
typeOfOutput: "CSV" # output as "julia dictionary" or as "CSV"
detailOfOutput: "driving course" # should the output be "reduced" or "driving course"?
csvFolderPath: "~/Desktop/RailwayDrivingDynamics"

View File

@ -0,0 +1,111 @@
---
vehicle:
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)
l_union: 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_union:
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)
vehicleType: freight # "freight" or "passenger" or "motor coach train" (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

@ -0,0 +1,191 @@
---
vehicle:
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))
l_union: 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_union:
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)
vehicleType: passenger # "freight" or "passenger" or "motor coach train" (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

@ -0,0 +1,151 @@
---
vehicle:
name: "Siemens Desiro Classic" # (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
l_union: 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_union: 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)
vehicleType: motor coach train # "freight" or "passenger" or "motor coach train" (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 to 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]

View File

@ -0,0 +1,34 @@
include("../src/RailwayDrivingDynamics.jl")
using .RailwayDrivingDynamics
# println("")
# println("________________________")
# println("")
allPaths=["../data/paths/path_1_10km_nConst_vConst.yaml" , "../data/paths/path_2_10km_nVar_vConst.yaml", "../data/paths/path_3_10km_nConst_vVar.yaml", "../data/paths/path_4_real_Ostsachsen_DG-DN_spp_5.yaml"]
settingsFilePath="../data/settings.yaml"
for pathFilePath in allPaths
# println("")
# println(" - - - - - - - - -")
# println("path: ", pathFilePath)
vehicleFilePath="../data/vehicles/vehicle_passenger_intercity.yaml"
testDict1=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
sleep(2)
vehicleFilePath="../data/vehicles/vehicle_passenger_suburban.yaml"
testDict2=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
sleep(2)
vehicleFilePath="../data/vehicles/vehicle_freight.yaml"
testDict3=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
# println("")
# println("")
# println("")
# println("")
end

View File

@ -0,0 +1,64 @@
module RailwayDrivingDynamics
include("./types.jl")
include("./RailwayDrivingDynamicsInput.jl")
include("./RailwayDrivingDynamicsPreparation.jl")
include("./RailwayDrivingDynamicsOperationModes.jl")
include("./RailwayDrivingDynamicsOutput.jl")
using .types
using .RailwayDrivingDynamicsInput
using .RailwayDrivingDynamicsPreparation
using .RailwayDrivingDynamicsOperationModes
using .RailwayDrivingDynamicsOutput
export calculateDrivingDynamics
function calculateDrivingDynamics(vehicleFilePath::String, pathFilePath::String, settingsFilePath::String)
# main function for calculating the driving dynamics
println("")
println("")
println("")
# input
(vehicle, path, settings)=readInput(vehicleFilePath, pathFilePath, settingsFilePath)
println("The input has been saved.")
# preparing the input data
movingSection=preparateSections(path, vehicle, settings)
println("The moving section has been preparated.")
if settings.operationModeMinimumRunningTime==true || settings.operationModeMinimumEnergyConsumption==true
(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=simulateMinimumRunningTime!(movingSection, settings, vehicle)
# println("t_total=", drivingCourseMinimumRunningTime[end].t)
# printSectionInformation(movingSectionMinimumRunningTime)
println("The driving course for the shortest running time has been calculated.")
end #if
# oparation mode "minimum energy consumption"
if settings.operationModeMinimumEnergyConsumption==true
(movingSectionMinimumEnergyConsumption, drivingCourseMinimumEnergyConsumption)=simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime, settings, vehicle)
# printSectionInformation(movingSectionMinimumEnergyConsumption)
println("The driving course for the energy consumption has been calculated.")
end #if
#output
if settings.operationModeMinimumRunningTime==true && settings.operationModeMinimumEnergyConsumption==true
plotDrivingCourse(drivingCourseMinimumRunningTime, drivingCourseMinimumEnergyConsumption)
return createOutput(settings, path.name, vehicle.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
elseif settings.operationModeMinimumRunningTime==true
plotDrivingCourse(drivingCourseMinimumRunningTime)
return createOutput(settings, path.name, vehicle.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
elseif settings.operationModeMinimumEnergyConsumption==true
plotDrivingCourse(drivingCourseMinimumEnergyConsumption)
return createOutput(settings, path.name, vehicle.name, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
else
println("No Output was demanded. So no output is created.")
return Dict()
end
end # function calculateDrivingDynamics
end # module RailwayDrivingDynamics

View File

@ -0,0 +1,281 @@
module RailwayDrivingDynamicsEnergySaving
using ..types
using ..RailwayDrivingDynamicsMovingPhases
export calculateRecoveryTime, increaseCostingSection, decreaseMaximumVelocity, combineEnergySavingMethods
function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, vehicle::Vehicle)
# function for calculating the recovery time that can be used for energy saving
if vehicle.vehicleType=="motor coach train"
if s_MS<= 30000
c_s=0.0
else s_MS> 30000
c_s=0.0006
end # if s_MS
if vehicle.v_limit<=140/3.6 # unit is m/s
c_t=0.03
elseif vehicle.v_limit<=160/3.6 # unit is m/s
c_t=0.04
elseif vehicle.v_limit<=200/3.6 # unit is m/s
c_t=0.05
elseif vehicle.v_limit<=250/3.6 # unit is m/s
c_t=0.06
else # vehicle.v_limit>120/3.6 # unit is m/s
c_t=0.07
end # if vehicle.v_limit
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
elseif vehicle.vehicleType=="freight" && vehicle.v_limit<=120/3.6 # unit is m/s
t_recovery1=s_MS*0.0006 +t_MS*0.03
t_recovery2=s_MS*0.0018 +t_MS*0.0
t_recovery3=s_MS*0.0 +t_MS*0.04
t_recovery=max(t_recovery1, t_recovery2, t_recovery3)
return t_recovery
else # vehicle.vehicleType=="passenger" || (vehicle.vehicleType=="freight" && vehicle.v_limit>120/3.6) # unit is m/s
if s_MS<= 30000
c_s=0.0
else s_MS> 30000
c_s=0.0009
end # if s_MS
if vehicle.v_limit<=140/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
c_t=0.03
elseif vehicle.m_union<=500000 # unit is kg
c_t=0.04
elseif vehicle.m_union<=700000 # unit is kg
c_t=0.04
else # vehicle.m_union>700000 # unit is kg
c_t=0.05
end # if vehicle.m_union
elseif vehicle.v_limit<=160/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
c_t=0.03
elseif vehicle.m_union<=500000 # unit is kg
c_t=0.04
else # vehicle.m_union>500000 # unit is kg
c_t=0.0
end # if vehicle.m_union
elseif vehicle.v_limit<=200/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
c_t=0.04
elseif vehicle.m_union<=500000 # unit is kg
c_t=0.05
else # vehicle.m_union>500000 # unit is kg
c_t=0.06
end # if vehicle.m_union
else # vehicle.v_limit>200/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
c_t=0.05
elseif vehicle.m_union<=500000 # unit is kg
c_t=0.06
else # vehicle.m_union>500000 # unit is kg
c_t=0.07
end # if vehicle.m_union
end # if vehicle.v_limit
c_tMin=s_MS/t_MS*0.0012
c_t=max(c_t, c_tMin)
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
end # if vehicle.vehicleType
end #function calculateRecoveryTime
function increaseCostingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "braking")
cruisingReduction=settings.stepSize
while cruisingReduction>=settings.stepSize/100
while cruisingReduction>=settings.stepSize/100 # will be done once and repeated twice with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_end) -> see below at the end of the while loop
# creating a drivingCourse for the characteristic section
energySavingStartId=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).waypoints[1]
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
drivingCourseModified=[Waypoint(drivingCourse[1])]
for i in 2:energySavingStartId
push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving
end
# calculating the new length of the cruising section
if settings.stepVariable=="s in m" # distance step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction
elseif settings.stepVariable=="t in s" # time step method
t_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).t_total-cruisingReduction
s_cruising=t_cruising*drivingCourseModified[end].v
elseif settings.stepVariable=="v in m/s" # velocity step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction*10 # TODO: or better: *100 ?
end #if
s_cruising=max(0.0, s_cruising)
# copying csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "starting")
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("starting"=>startingSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "starting", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "starting", BehaviorSection()).t_total
end
if haskey(csOriginal.behaviorSections, "cruisingBeforeAcceleration") # this section is needed before acceleration if the mass strip model is used and if the vehicle wants to accelerate to a velocity higher than the limit in the other CS where parts of the union are still located
cruisingBeforeAccelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("cruisingBeforeAcceleration"=>cruisingBeforeAccelerationSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).t_total
end
if haskey(csOriginal.behaviorSections, "acceleration")
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total
end
# calculating the new and now shorter cruising section
if s_cruising>0.0
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, vehicle, allCSs, "cruising")
end
(csModified, drivingCourseModified)=addCoastingPhaseWithIntersection!(csModified, drivingCourseModified, settings, vehicle, allCSs)
if drivingCourseModified[end].v<csModified.v_exit || drivingCourseModified[end].s>csModified.s_end
# the vehicle reaches v_exit before reaching s_end. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section)
cruisingReduction=cruisingReduction/10
else
break
end
end # while cruisingReduction
if drivingCourseModified[end].v>csModified.v_exit
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, vehicle, allCSs)
elseif drivingCourseModified[end].v==csModified.v_exit && drivingCourseModified[end].s<csModified.s_end
# v_exit is already reached. Now cruising till the end of the CS
s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, vehicle, allCSs, "cruisingAfterCoasting")
end
if t_recoveryAvailable<(csModified.t_total-csOriginal.t_total) || drivingCourseModified[end].v!=csModified.v_exit || drivingCourseModified[end].s!=csModified.s_end # time loss is to high and the CS has to be calculated again with larger cruising section (so with a smaller reduction of the cruising section) or v_exit or s_end are not reached excatly
cruisingReduction=cruisingReduction/10
else
return (csModified, drivingCourseModified, true)
end
end #while
# there is no energy saving modification for this CS with the available recovery time
return (CharacteristicSection(), [], false)
else
# there is no energy saving modification for this CS because a cruising section AND a braking section are needed to be transformed into a coasting section
return (CharacteristicSection(), [], false)
end
end # function increaseCostingSection
# method 2 with shortening the acceleration by stepsize
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && csOriginal.v_reach>csOriginal.v_entry && csOriginal.v_reach>csOriginal.v_exit
# instead of calculating the new final velocity of the acceleration phase with the step sizes for the different step variables, the velocity of the point before the last will be the new v_reach
# because it it easier at the moment (TODO)
lastIdOfOldAccelerationSection=get(csOriginal.behaviorSections, "acceleration", BehaviorSection()).waypoints[end]
accelerationReduction=drivingCourse[lastIdOfOldAccelerationSection].Δv # with step size it would be accelerationReduction=settings.stepSize
while accelerationReduction>=drivingCourse[lastIdOfOldAccelerationSection].Δv/100 # will be done once and repeated twice with smaller accelerationReduction unless t_recoveryAvailable>=(csModified.t_total-csOriginal.t_total) && 0.0<(csModified.t_total-csOriginal.t_total) -> see below at the end of the while loop
# copying csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "starting")
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("starting"=>startingSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "starting", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "starting", BehaviorSection()).t_total
end
# creating a drivingCourse for the characteristic section
energySavingStartId=get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", get(csOriginal.behaviorSections, "acceleration", BehaviorSection())).waypoints[1]
drivingCourseModified=Vector{Waypoint}()
for i in 1:energySavingStartId
push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving
end
csModified.v_reach=max(csModified.v_entry, csModified.v_exit, csOriginal.v_reach-accelerationReduction)
# calculation of the new and now shorter acceleration section
if drivingCourseModified[end].v<csModified.v_reach
(csModified, drivingCourseModified)=addAccelerationPhase!(csModified, drivingCourseModified, settings, vehicle, allCSs)
end #if
# TODO: instead of copying the drivingCourse till the start of acceleration and calculating the acceleration again till the point before the last it would be possible to copy the drivingCouse until this point. Then it would not be necessary to calculate the accelerationPhase again. But then it is difficult to reduce accelerationReduction.
s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_reach^2)/2/vehicle.a_braking, digits=10)) # ceil is used to be sure that the vehicle stops at s_end in spite of rounding errors
s_cruising=csModified.s_end-drivingCourseModified[end].s-s_braking
if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, vehicle, allCSs, "cruising")
end #if
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/vehicle.a_braking, digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified.v_exit
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, vehicle, allCSs)
elseif drivingCourseModified[end].s<csModified.s_end
if (csModified.s_end-drivingCourseModified[end].s)>0.001
println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_reach.")
println(" Therefore s=",drivingCourseModified[end].s," will be set s_end=",csModified.s_end," because the difference is only ",csModified.s_end-drivingCourseModified[end].s," m.")
end
drivingCourseModified[end].s=csModified.s_end # rounding up to s_end
end #if
if t_recoveryAvailable>=(csModified.t_total-csOriginal.t_total)
return (csModified, drivingCourseModified, true)
else # time loss is to high and the CS has to be calculated again with larger acceleration section (so with a smaller reduction of the acceleration section)
accelerationReduction=min(accelerationReduction/10, csModified.v_reach-csModified.v_entry, csModified.v_reach-csModified.v_exit)
end
end #while
# there is no energy saving modification for this CS with the available recovery time
return (CharacteristicSection(), [], false)
else
# there is no energy saving modification for this CS because v_reach can not be lowered below v_entry or v_exit or because there is no acceleration section that can be transformed into a cruising section
return (CharacteristicSection(), [], false)
end #if haskey
end # function decreaseMaximumVelocity
# combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && (haskey(csOriginal.behaviorSections, "braking") || haskey(csOriginal.behaviorSections, "coasting")) && csOriginal.v_reach>csOriginal.v_entry && csOriginal.v_reach>csOriginal.v_exit
csCombined=CharacteristicSection(csOriginal)
drivingCourseCombined=Vector{Waypoint}()
for i in 1:length(drivingCourse)
push!(drivingCourseCombined, Waypoint(drivingCourse[i]))
end
ΔE=0.0 # saved energy (in Ws)
Δt=0.0 # time loss (in s)
while (Δt<t_recoveryAvailable && ΔE<=0.0)
(csCombined, drivingCourseCombined, newMaximumVelocity)=decreaseMaximumVelocity(csCombined, drivingCourseCombined, settings, vehicle, allCSs, t_recoveryAvailable)
if newMaximumVelocity
ΔE=csOriginal.E_total-csCombined.E_total # saved energy (in Ws)
Δt=csCombined.t_total-csOriginal.t_total # time loss (in s)
while (haskey(csOriginal.behaviorSections, "cruising") && (Δt<=0.0 || ΔE<=0.0)) #Δt<=0.0) #&& ΔE<=0.0) # && Δt<=0.0)
(csCombined, drivingCourseCombined, newCoasting)=increaseCostingSection(csCombined, drivingCourseCombined, settings, vehicle, allCSs, t_recoveryAvailable-Δt)
if newCoasting
ΔE=csOriginal.E_total-csCombined.E_total # saved energy (in Ws)
Δt=csCombined.t_total-csOriginal.t_total # time loss (in s)
else
break
end # if newCoasting
end # while haskey
else
return (CharacteristicSection(), [], false)
end # if newMaximumVelocity
end # while
return (csCombined, drivingCourseCombined, (ΔE>0.0))# && Δt>0.0))
else
# there is no energy saving modification for this CS because v_reach can not be lowered below v_entry or v_exit or because there is no acceleration section and braking section or coasting section that can be transformed into a cruising section or coasting section
return (CharacteristicSection(), [], false)
end #if
end #function combineEnergySavingMethods
end #module RailwayDrivingDynamicsEnergySaving

View File

@ -0,0 +1,600 @@
module RailwayDrivingDynamicsInput
import YAML
using ..types
export readInput
function readInput(vehicleFilePath::String, pathFilePath::String, settingsFilePath::String)
# this function reads the input information from YAML files, saves it in a different objects and returns them
vehicle=inputVehicle(vehicleFilePath)
path=inputPath(pathFilePath)
settings=inputSettings(settingsFilePath)
return (vehicle, path, settings)
end #function readInput
function inputVehicle(vehicleFilePath::String)
# this function reads vehicle information from a YAML file, saves it in a Vehicle object and returns it
data = YAML.load(open(vehicleFilePath))
collect(keys(data))
collect(values(data))
vehicle=Vehicle()
if haskey(data["vehicle"],"name")
vehicle.name=data["vehicle"]["name"] # vehicles name
delete!(data["vehicle"], "name")
else
error("ERROR at reading the vehicle yaml file: The keyword name is missing. It has to be added.")
end
vehicle.id=1 # vehicles identifier
if haskey(data["vehicle"],"vehicleType")
if typeof(data["vehicle"]["vehicleType"])==String && (data["vehicle"]["vehicleType"]=="freight" || data["vehicle"]["vehicleType"]=="motor coach train" || data["vehicle"]["vehicleType"]=="passenger")
vehicle.vehicleType=data["vehicle"]["vehicleType"] # "passenger" or "freight" or "motor coach train"
delete!(data["vehicle"], "vehicleType")
else
error("ERROR at reading the vehicle yaml file: The value of vehicleType is wrong. It has to be freight, motor coach train or passenger.")
end
else
error("ERROR at reading the vehicle yaml file: The keyword vehicleType is missing. It has to be added with the value freight, motor coach train or passenger.")
end
if haskey(data["vehicle"],"l_union")
if typeof(data["vehicle"]["l_union"])==Float64 && data["vehicle"]["l_union"]>0.0
vehicle.l_union=data["vehicle"]["l_union"] # total length (in m)
delete!(data["vehicle"], "l_union")
elseif typeof(data["vehicle"]["l_union"])==Int64 && data["vehicle"]["l_union"]>0
vehicle.l_union=convert(AbstractFloat, data["vehicle"]["l_union"]) # total length (in m)
delete!(data["vehicle"], "l_union")
else
error("ERROR at reading the vehicle yaml file: The value of the length is no real floating point number >0.0.")
end
else
error("ERROR at reading the vehicle yaml file: The keyword length is missing. It has to be added with a value of type real floating point number >0.0.")
end
# speed limit: # vehicles speed limit (in m/s)
if haskey(data["vehicle"],"v_limit") && haskey(data["vehicle"],"v_limit_kmh")
if data["vehicle"]["v_limit"]!=nothing
if typeof(data["vehicle"]["v_limit"])==Float64 && data["vehicle"]["v_limit"]>0.0
vehicle.v_limit=data["vehicle"]["v_limit"] # vehicles speed limit (in m/s)
delete!(data["vehicle"], "v_limit")
elseif typeof(data["vehicle"]["v_limit"])==Int64 && data["vehicle"]["v_limit"]>0
vehicle.v_limit=convert(AbstractFloat, data["vehicle"]["v_limit"]) # vehicles speed limit (in m/s)
delete!(data["vehicle"], "v_limit")
else
error("ERROR at reading the vehicle yaml file: The value of v_limit is no real floating point number >0.0.")
end
if data["vehicle"]["v_limit_kmh"]!=nothing
v_limit_kmh=data["vehicle"]["v_limit_kmh"]
if abs(vehicle.v_limit-v_limit_kmh/3.6)>0.001
println("WARNING: at reading the vehicle yaml file: The values of v_limit and v_limit_kmh differ by more than 0.001 m/s. The value v_limit=",vehicle.v_limit," m/s is used." )
end
end
elseif data["vehicle"]["v_limit_kmh"]!=nothing
if typeof(data["vehicle"]["v_limit_kmh"])==Float64 && data["vehicle"]["v_limit_kmh"]>0.0
vehicle.v_limit=data["vehicle"]["v_limit_kmh"]/3.6 # vehicles speed limit (from km/h to m/s)
elseif typeof(data["vehicle"]["v_limit_kmh"])==Int64 && data["vehicle"]["v_limit_kmh"]>0
vehicle.v_limit=convert(AbstractFloat, data["vehicle"]["v_limit_kmh"])/3.6 # vehicles speed limit (from km/h to m/s)
else
error("ERROR at reading the vehicle yaml file: The value of the v_limit_kmh is no real floating point number >0.0.")
end
else
vehicle.v_limit=1000/3.6
println("WARNING at reading the vehicle yaml file: There is no value for v_limit. The value v_limit=1000 km/h =",vehicle.v_limit," m/s is used." )
end # if
elseif haskey(data["vehicle"],"v_limit")
if typeof(data["vehicle"]["v_limit"])==Float64 && data["vehicle"]["v_limit"]>0.0
vehicle.v_limit=data["vehicle"]["v_limit"] # vehicles speed limit (in m/s)
elseif typeof(data["vehicle"]["v_limit"])==Int64 && data["vehicle"]["v_limit"]>0
vehicle.v_limit=convert(AbstractFloat, data["vehicle"]["v_limit"]) # vehicles speed limit (in m/s)
else
error("ERROR at reading the vehicle yaml file: The value of v_limit is no real floating point number >0.0.")
end
elseif haskey(data["vehicle"],"v_limit_kmh")
if typeof(data["vehicle"]["v_limit_kmh"])==Float64 && data["vehicle"]["v_limit_kmh"]>0.0
vehicle.v_limit=data["vehicle"]["v_limit_kmh"]/3.6 # vehicles speed limit (from km/h to m/s)
elseif typeof(data["vehicle"]["v_limit_kmh"])==Int64 && data["vehicle"]["v_limit_kmh"]>0
vehicle.v_limit=convert(AbstractFloat, data["vehicle"]["v_limit_kmh"])/3.6 # vehicles speed limit (from km/h to m/s)
else
error("ERROR at reading the vehicle yaml file: The value of v_limit_kmh is no real floating point number >0.0.")
end
else
error("ERROR at reading the vehicle yaml file: The keyword v_limit or v_limit_kmh is missing. It has to be added with a value of type real floating point number >0.0.")
end
delete!(data["vehicle"], "v_limit")
delete!(data["vehicle"], "v_limit_kmh")
# a_braking
if haskey(data["vehicle"],"a_braking")
if typeof(data["vehicle"]["a_braking"])==Float64
vehicle.a_braking=data["vehicle"]["a_braking"]
elseif typeof(data["vehicle"]["a_braking"])==Int64
vehicle.a_braking=convert(AbstractFloat, data["vehicle"]["a_braking"])
else
error("ERROR at reading the vehicle yaml file: The value of the a_braking is no real floating point number <0.0.")
end
delete!(data["vehicle"], "a_braking")
if vehicle.a_braking > 0.0
vehicle.a_braking =-vehicle.a_braking
println("WARNING at reading the vehicle yaml file: The value for a_braking is >0.0. The braking acceleration has to be <0.0. Therefore a_braking =",vehicle.a_braking," m/s^2 is used." )
elseif vehicle.a_braking == 0.0
error("ERROR at reading the vehicle yaml file: The value for a_braking is 0.0. The braking acceleration has to be <0.0.")
end
else
error("ERROR at reading the vehicle yaml file: The keyword a_braking is missing. It has to be added with a value of type real floating point number <0.0.")
end
# mass on the traction units driving axles (in kg)
if haskey(data["vehicle"],"m_td")
if typeof(data["vehicle"]["m_td"])==Float64 && data["vehicle"]["m_td"]>0.0
vehicle.m_td=data["vehicle"]["m_td"]
elseif typeof(data["vehicle"]["m_td"])==Int64 && data["vehicle"]["m_td"]>0
vehicle.m_td=convert(AbstractFloat, data["vehicle"]["m_td"])
delete!(data["vehicle"], "m_td")
else
error("ERROR at reading the vehicle yaml file: The value of m_td is no real floating point number >0.0.")
end
else
error("ERROR at reading the vehicle yaml file: The keyword m_td is missing. It has to be added with a value of type real floating point number >0.0.")
end
delete!(data["vehicle"], "m_td")
# mass on the traction units carrying axles (in kg)
if haskey(data["vehicle"],"m_tc")
if typeof(data["vehicle"]["m_tc"])==Float64 && data["vehicle"]["m_tc"]>=0.0
vehicle.m_tc=data["vehicle"]["m_tc"]
elseif typeof(data["vehicle"]["m_tc"])==Int64 && data["vehicle"]["m_tc"]>=0
vehicle.m_tc=convert(AbstractFloat, data["vehicle"]["m_tc"])
else
error("ERROR at reading the vehicle yaml file: The value of m_tc is no real floating point number >=0.0.")
end
else
error("ERROR at reading the vehicle yaml file: The keyword m_tc is missing. It has to be added with a value of type real floating point number >=0.0.")
end
delete!(data["vehicle"], "m_tc")
# mass of the traction unit (in kg)
vehicle.m_t=vehicle.m_td+vehicle.m_tc
# mass of theconsist (set of wagons) (in kg)
if haskey(data["vehicle"],"m_w")
if typeof(data["vehicle"]["m_w"])==Float64 && data["vehicle"]["m_w"]>=0.0
vehicle.m_w=data["vehicle"]["m_w"]
elseif typeof(data["vehicle"]["m_w"])==Int64 && data["vehicle"]["m_w"]>=0
vehicle.m_w=convert(AbstractFloat, data["vehicle"]["m_w"])
else
error("ERROR at reading the vehicle yaml file: The value of m_w is no real floating point number >=0.0.")
end
else
vehicle.m_w=0.0
println("WARNING at reading the vehicle yaml file: The keyword m_w is missing. Therefore m_w =",vehicle.m_w," kg is used.")
end
delete!(data["vehicle"], "m_w")
# total mass (in kg)
vehicle.m_union=vehicle.m_t+vehicle.m_w
if haskey(data["vehicle"],"rotationMassFactor_union") && (typeof(data["vehicle"]["rotationMassFactor_union"])==Float64 || typeof(data["vehicle"]["rotationMassFactor_union"])==Int64)
if typeof(data["vehicle"]["rotationMassFactor_union"])==Float64 && data["vehicle"]["rotationMassFactor_union"]>0.0
vehicle.ξ_union=data["vehicle"]["rotationMassFactor_union"]
elseif typeof(data["vehicle"]["rotationMassFactor_union"])==Int64 && data["vehicle"]["rotationMassFactor_union"]>0
vehicle.ξ_union=convert(AbstractFloat, data["vehicle"]["rotationMassFactor_union"])
else
error("ERROR at reading the vehicle yaml file: The value of rotationMassFactor_union is no real floating point number >0.0.")
end
elseif haskey(data["vehicle"],"rotationMassFactor_t") && (typeof(data["vehicle"]["rotationMassFactor_t"])==Float64 || typeof(data["vehicle"]["rotationMassFactor_t"])==Int64) && (vehicle.m_w==0.0 || haskey(data["vehicle"],"rotationMassFactor_w") && (typeof(data["vehicle"]["rotationMassFactor_w"])==Float64 || typeof(data["vehicle"]["rotationMassFactor_w"])==Int64))
if typeof(data["vehicle"]["rotationMassFactor_t"])==Float64 && data["vehicle"]["rotationMassFactor_t"]>0.0
vehicle.ξ_t=data["vehicle"]["rotationMassFactor_t"]
elseif typeof(data["vehicle"]["rotationMassFactor_t"])==Int64 && data["vehicle"]["rotationMassFactor_t"]>0
vehicle.ξ_t=convert(AbstractFloat, data["vehicle"]["rotationMassFactor_t"])
else
error("ERROR at reading the vehicle yaml file: The value of rotationMassFactor_t is no real floating point number >0.0.")
end
if vehicle.m_w>0.0
if typeof(data["vehicle"]["rotationMassFactor_w"])==Float64 && data["vehicle"]["rotationMassFactor_w"]>=0.0
vehicle.ξ_w=data["vehicle"]["rotationMassFactor_w"]
elseif typeof(data["vehicle"]["rotationMassFactor_w"])==Int64 && data["vehicle"]["rotationMassFactor_w"]>=0
vehicle.ξ_w=convert(AbstractFloat, data["vehicle"]["rotationMassFactor_w"])
else
error("ERROR at reading the vehicle yaml file: The value of rotationMassFactor_w is no real floating point number >=0.0.")
end
else
vehicle.ξ_w=0.0
end
vehicle.ξ_union=(vehicle.ξ_t*vehicle.m_t + vehicle.ξ_w*vehicle.m_w)/vehicle.m_union # rotation mass factor of the whole vehicle (without unit)
else
error("ERROR at reading the vehicle yaml file: The keywords rotationMassFactor_union or rotationMassFactor_t and rotationMassFactor_w are missing. They has to be added with a value of type real floating point number.")
end
delete!(data["vehicle"], "rotationMassFactor_union")
delete!(data["vehicle"], "rotationMassFactor_t")
delete!(data["vehicle"], "rotationMassFactor_w")
# input for function tractiveEffort(v)
# TODO: The types of the lists elements can be checked and the user can get warnings or error messages
# TODO: What if there are values in F_T_pairs and in F_T_pairs_kmh. That should be checked and the user should be informed
# TODO: It could be checked if all the array elements are correct.
if haskey(data["vehicle"],"F_T_pairs") && data["vehicle"]["F_T_pairs"]!=nothing
F_T_pairs=data["vehicle"]["F_T_pairs"]
vehicle.tractiveEffortArray=[]
if F_T_pairs[1][1]==0.0
push!(vehicle.tractiveEffortArray, [F_T_pairs[1][1], F_T_pairs[1][1], F_T_pairs[1][2]])
elseif F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first value is used
push!(vehicle.tractiveEffortArray, [0.0, F_T_pairs[1][1]/3.6, F_T_pairs[1][2]])
println("WARNING at reading the vehicle yaml file: The tractive effort for v=0 m/s is missing. Therefore the first given value F_T(v=",F_T_pairs[1][1]," m/s)=",F_T_pairs[1][2]," N will be used." )
else
error("ERROR at reading the vehicle yaml file: There is a negative speed value in the list. Only positive values for speed and tractive effort are allowed. ")
end
for row in 2:length(F_T_pairs)
if F_T_pairs[row][1]>F_T_pairs[row-1][1]
if F_T_pairs[row][2]==vehicle.tractiveEffortArray[end][3]
vehicle.tractiveEffortArray[end][2]=F_T_pairs[row][1]
else
push!(vehicle.tractiveEffortArray, [F_T_pairs[row][1], F_T_pairs[row][1], F_T_pairs[row][2]])
end
else
error("ERROR at reading the vehicle yaml file: The F_T_pairs are not in the correct order. They have to be arranged by speed values from low to high.")
end
end # for
if length(F_T_pairs[1])>2
println("INFO according the vehicle yaml file: Only the first two columns of F_T_pairs are used in this tool.")
end
elseif haskey(data["vehicle"],"F_T_pairs_kmh") && data["vehicle"]["F_T_pairs_kmh"]!=nothing
F_T_pairs_kmh=data["vehicle"]["F_T_pairs_kmh"]
vehicle.tractiveEffortArray=[]
if F_T_pairs_kmh[1][1]==0.0
push!(vehicle.tractiveEffortArray, [F_T_pairs_kmh[1][1]/3.6, F_T_pairs_kmh[1][1]/3.6, F_T_pairs_kmh[1][2]])
elseif F_T_pairs_kmh[1][1]>0.0 # if there is no F_T for v=0.0, the first value is used
push!(vehicle.tractiveEffortArray, [0.0, F_T_pairs_kmh[1][1]/3.6, F_T_pairs_kmh[1][2]])
println("WARNING at reading the vehicle yaml file: The tractive effort for v=0 km/h is missing. Therefore the first given value F_T(v=",F_T_pairs_kmh[1][1]," km/h)=",F_T_pairs_kmh[1][2]," N will be used." )
else
error("ERROR at reading the vehicle yaml file: There is a negative speed value in the list. Only positive values for speed and tractive effort are allowed. ")
end
for row in 2:length(F_T_pairs_kmh)
if F_T_pairs_kmh[row][1]>F_T_pairs_kmh[row-1][1]
if F_T_pairs_kmh[row][2]==vehicle.tractiveEffortArray[end][3]
vehicle.tractiveEffortArray[end][2]=F_T_pairs_kmh[row][1]/3.6
else
push!(vehicle.tractiveEffortArray, [F_T_pairs_kmh[row][1]/3.6, F_T_pairs_kmh[row][1]/3.6, F_T_pairs_kmh[row][2]])
end
else
error("ERROR at reading the vehicle yaml file: The F_T_pairs_kmh are not in the correct order. They have to be arranged by speed values from low to high.")
end
end # for
if length(F_T_pairs_kmh[1])>2
println("INFO at reading the vehicle yaml file: Only the first two columns of F_T_pairs_kmh are used in this tool.")
end
else
error("ERROR at reading the vehicle yaml file: There has to be one of the keywords F_T_pairs or F_T_pairs_kmh filled with a list of pairs of velocity and tractive effort.")
end # if
delete!(data["vehicle"], "F_T_pairs")
delete!(data["vehicle"], "F_T_pairs_kmh")
# coefficients for the vehicle resistance of the traction unit
vehicle.Δv_t=15.0/3.6 # coefficient for velocitiy difference between traction unit and outdoor air
# coefficient for basic resistance due to the traction units driving axles (in ‰)
if haskey(data["vehicle"],"f_Rtd0") && data["vehicle"]["f_Rtd0"]!=nothing
if typeof(data["vehicle"]["f_Rtd0"])==Float64 && data["vehicle"]["f_Rtd0"]>=0.0
vehicle.f_Rtd0=data["vehicle"]["f_Rtd0"]
elseif typeof(data["vehicle"]["f_Rtd0"])==Int64 && data["vehicle"]["f_Rtd0"]>=0
vehicle.f_Rtd0=convert(AbstractFloat, data["vehicle"]["f_Rtd0"])
else
error("ERROR at reading the vehicle yaml file: The value of f_Rtd0 is no real floating point number >=0.0.")
end
else
vehicle.f_Rtd0=0.0
println("WARNING at reading the vehicle yaml file: The keyword f_Rtd0 is missing. Therefore f_Rtd0=0.0 ‰ will be assumed and used." )
end
delete!(data["vehicle"], "f_Rtd0")
# coefficient for basic resistance due to the traction units carring axles (in ‰)
if haskey(data["vehicle"],"f_Rtc0") && data["vehicle"]["f_Rtc0"]!=nothing
if typeof(data["vehicle"]["f_Rtc0"])==Float64 && data["vehicle"]["f_Rtc0"]>=0.0
vehicle.f_Rtc0=data["vehicle"]["f_Rtc0"]
elseif typeof(data["vehicle"]["f_Rtc0"])==Int64 && data["vehicle"]["f_Rtc0"]>=0
vehicle.f_Rtc0=convert(AbstractFloat, data["vehicle"]["f_Rtc0"])
else
error("ERROR at reading the vehicle yaml file: The value of f_Rtc0 is no real floating point number >=0.0.")
end
else
vehicle.f_Rtc0=0.0
println("WARNING at reading the vehicle yaml file: The keyword f_Rtc0 is missing. Therefore f_Rtc0=0.0 ‰ will be assumed and used." )
end
delete!(data["vehicle"], "f_Rtc0")
# coefficient for air resistance of the traction units (in N)
if haskey(data["vehicle"],"F_Rt2") && data["vehicle"]["F_Rt2"]!=nothing
if typeof(data["vehicle"]["F_Rt2"])==Float64 && data["vehicle"]["F_Rt2"]>=0.0
vehicle.F_Rt2=data["vehicle"]["F_Rt2"]
elseif typeof(data["vehicle"]["F_Rt2"])==Int64 && data["vehicle"]["F_Rt2"]>=0
vehicle.F_Rt2=convert(AbstractFloat, data["vehicle"]["F_Rt2"])
else
error("ERROR at reading the vehicle yaml file: The value of F_Rt2 is no real floating point number >=0.0.")
end
else
vehicle.F_Rt2=0.0
println("WARNING at reading the vehicle yaml file: The keyword F_Rt2 is missing. Therefore F_Rt2=0.0 N will be assumed and used." )
end
delete!(data["vehicle"], "F_Rt2")
# coefficients for the vehicle resistance of the consist (set of wagons)
# coefficient for velocitiy difference betweenconsist (set of wagons) and outdoor air (in m/s)
if vehicle.vehicleType=="passenger" || vehicle.vehicleType=="motor coach train"
vehicle.Δv_w=15.0/3.6
elseif vehicle.vehicleType== "freight"
vehicle.Δv_w=0.0
end # if
# coefficient for basic resistance of theconsist (set of wagons) (in ‰)
if haskey(data["vehicle"],"f_Rw0") && data["vehicle"]["f_Rw0"]!=nothing
if typeof(data["vehicle"]["f_Rw0"])==Float64 && data["vehicle"]["f_Rw0"]>=0.0
vehicle.f_Rw0=data["vehicle"]["f_Rw0"]
elseif typeof(data["vehicle"]["f_Rw0"])==Int64 && data["vehicle"]["f_Rw0"]>=0
vehicle.f_Rw0=convert(AbstractFloat, data["vehicle"]["f_Rw0"])
else
error("ERROR at reading the vehicle yaml file: The value of f_Rw0 is no real floating point number >=0.0.")
end
else
vehicle.f_Rw0=0.0
println("WARNING at reading the vehicle yaml file: The keyword f_Rw0 is missing. Therefore f_Rw0=0.0 ‰ will be assumed and used." )
end
delete!(data["vehicle"], "f_Rw0")
# coefficient for basic resistance of theconsist (set of wagons) (in ‰)
if haskey(data["vehicle"],"f_Rw1") && data["vehicle"]["f_Rw1"]!=nothing
if typeof(data["vehicle"]["f_Rw1"])==Float64 && data["vehicle"]["f_Rw1"]>=0.0
vehicle.f_Rw1=data["vehicle"]["f_Rw1"]
elseif typeof(data["vehicle"]["f_Rw1"])==Int64 && data["vehicle"]["f_Rw1"]>=0
vehicle.f_Rw1=convert(AbstractFloat, data["vehicle"]["f_Rw1"])
else
error("ERROR at reading the vehicle yaml file: The value of f_Rw1 is no real floating point number >=0.0.")
end
else
vehicle.f_Rw1=0.0
println("WARNING at reading the vehicle yaml file: The keyword f_Rw1 is missing. Therefore f_Rw1=0.0 ‰ will be assumed and used." )
end
delete!(data["vehicle"], "f_Rw1")
# coefficient for basic resistance of the consist (set of wagons) (in ‰)
if haskey(data["vehicle"],"f_Rw2") && data["vehicle"]["f_Rw2"]!=nothing
if typeof(data["vehicle"]["f_Rw2"])==Float64 && data["vehicle"]["f_Rw2"]>=0.0
vehicle.f_Rw2=data["vehicle"]["f_Rw2"]
elseif typeof(data["vehicle"]["f_Rw2"])==Int64 && data["vehicle"]["f_Rw2"]>=0
vehicle.f_Rw2=convert(AbstractFloat, data["vehicle"]["f_Rw2"])
else
error("ERROR at reading the vehicle yaml file: The value of f_Rw2 is no real floating point number >=0.0.")
end
else
vehicle.f_Rw2=0.0
println("WARNING at reading the vehicle yaml file: The keyword f_Rw2 is missing. Therefore f_Rw2=0.0 ‰ will be assumed and used." )
end
delete!(data["vehicle"], "f_Rw2")
# informing the user, which keywords of the input data are not used in this tool:
if length(data["vehicle"])>0
println("INFO at reading the vehicle yaml file: The following Keywords are not used in this tool:")
for key in keys(data["vehicle"])
println(" - ",key)
end
end
return vehicle
end #function inputVehicle
function inputPath(pathFilePath::String)
# this function reads path information from a YAML file, saves it in a Path object and returns it
data = YAML.load(open(pathFilePath))
collect(keys(data))
collect(values(data))
if haskey(data["path"],"name") && data["path"]["name"]!=nothing
name=data["path"]["name"] # path name
else
error("ERROR at reading the path yaml file: The keyword name is missing. It has to be added.")
end
delete!(data["path"], "name")
id=1 # path identifier
path=Path(name, id, [])
# TODO: It could be checked if all the array elements are correct.
# TODO: The types of the lists elements can be checked and the user can get warnings or error messages
# TODO: What if there are values in sectionStarts and in sectionStarts_kmh? The user should be informed
if haskey(data["path"],"sectionStarts") && data["path"]["sectionStarts"]!=nothing
sectionStartsArray=data["path"]["sectionStarts"]
conversionFactor=1.0 # conversion factor between the units m/s and m/s
elseif haskey(data["path"],"sectionStarts_kmh") && data["path"]["sectionStarts_kmh"]!=nothing
sectionStartsArray=data["path"]["sectionStarts_kmh"]
conversionFactor=1/3.6 # conversion factor between the units km/h and m/s
else
error("ERROR at reading the path yaml file: The keyword sectionStarts oder sectionStarts_kmh is missing. It has to be added.")
end # if
delete!(data["path"], "sectionStarts")
delete!(data["path"], "sectionStarts_kmh")
if length(sectionStartsArray)>=2
if length(sectionStartsArray[1])>=3
for row in 2:length(sectionStartsArray)
s_start=sectionStartsArray[row-1][1] # starting point of the section (in m)
s_startNext=sectionStartsArray[row][1] # starting point of the next section (in m)
if s_startNext<s_start
error("ERROR at reading the path yaml file: The keyword sectionStartsArray needs to be filled with the three columns [s, v_limit, gradient].")
end
v_limit=sectionStartsArray[row-1][2]*conversionFactor # paths speed limt (in m/s)
n=sectionStartsArray[row-1][3] # gradient (in ‰)
f_Rp=n # specific path resistance of the section (in ‰)
section=PathSection(s_start, s_startNext, v_limit, n, f_Rp)
push!(path.sections, section)
end # for
if length(sectionStartsArray[1])>3
println("INFO at reading the path yaml file: Only the first three columns of sectionStartsArray are used in this tool.")
end
else
error("ERROR at reading the path yaml file: The keyword sectionStartsArray needs to be filled with the three columns [s, v_limit, gradient].")
end
else
error("ERROR at reading the path yaml file: The keyword sectionStartsArray needs at least two rows for two points each with the three columns [s, v_limit, gradient].")
end
# informing the user, which keywords of the input data are not used in this tool:
if length(data["path"])>0
println("INFO at reading the path yaml file: The following Keywords are not used in this tool:")
for key in keys(data["path"])
println(" - ",key)
end
end
return path
end # function inputPath
function inputSettings(settingsFilePath::String)
# this function reads setting information from a YAML file, saves it in a Setting object and returns it
data = YAML.load(open(settingsFilePath))
collect(keys(data))
collect(values(data))
settings=Settings()
# model type of the unions mass "mass point" or "homogeneous strip"
if haskey(data["settings"],"massModel")
if typeof(data["settings"]["massModel"])==String && (data["settings"]["massModel"]=="mass point" || data["settings"]["massModel"]=="homogeneous strip")
settings.massModel=data["settings"]["massModel"] # "mass point" or "homogeneous strip"
else
error("ERROR at reading the settings yaml file: The value of massModel is wrong. It has to be mass point or homogeneous strip.")
end
else
error("ERROR at reading the settings yaml file: The keyword massModel is missing. It has to be added with the value mass point or homogeneous strip.")
end
delete!(data["settings"], "massModel")
# step variable of the step method "s in m", "t in s" or "v in m/s"
if haskey(data["settings"],"stepVariable")
if typeof(data["settings"]["stepVariable"])==String && (data["settings"]["stepVariable"]=="s in m" || data["settings"]["stepVariable"]=="t in s" || data["settings"]["stepVariable"]=="v in m/s")
settings.stepVariable=data["settings"]["stepVariable"] # "s in m", "t in s" or "v in m/s"
else
error("ERROR at reading the settings yaml file: The value of stepVariable is wrong. It has to be s in m, t in s or v in m/s.")
end
else
error("ERROR for the settings yaml file: The keyword stepVariable is missing. It has to be added with the value s in m, t in s or v in m/s.")
end
delete!(data["settings"], "stepVariable")
# step size (unit depends on steapVariable: s in m, t in s and v in m/s)
if haskey(data["settings"],"stepSize")
if typeof(data["settings"]["stepSize"])==Float64 && data["settings"]["stepSize"]>0.0
settings.stepSize=data["settings"]["stepSize"]
elseif typeof(data["settings"]["stepSize"])==Int64 && data["settings"]["stepSize"]>0
settings.stepSize=convert(AbstractFloat, data["settings"]["stepSize"])
else
error("ERROR at reading the settings yaml file: The value of the stepSize is no real floating point number >0.0.")
end
else
error("ERROR at reading the settings yaml file: The keyword stepSize is missing. It has to be added with a value of type real floating point number >0.0.")
end
delete!(data["settings"], "stepSize")
# operation mode "minimum running time"
if haskey(data["settings"],"operationModeMinimumRunningTime") && data["settings"]["operationModeMinimumRunningTime"]!=nothing
if typeof(data["settings"]["operationModeMinimumRunningTime"])==Bool
settings.operationModeMinimumRunningTime=data["settings"]["operationModeMinimumRunningTime"]
else
error("ERROR at reading the settings yaml file: The value of the keyword operationModeMinimumRunningTime is not correct. The value has to be of type boolean.")
end
else
settings.operationModeMinimumRunningTime=false
println("WARNING at reading the settings yaml file: The keyword operationModeMinimumRunningTime or its value is missing. Therefore operationModeMinimumRunningTime=",settings.operationModeMinimumRunningTime," is assumed and used.")
end
delete!(data["settings"], "operationModeMinimumRunningTime")
# operation mode "minimum energy consumption"
if haskey(data["settings"],"operationModeMinimumEnergyConsumption") && data["settings"]["operationModeMinimumEnergyConsumption"]!=nothing
if typeof(data["settings"]["operationModeMinimumEnergyConsumption"])==Bool
settings.operationModeMinimumEnergyConsumption=data["settings"]["operationModeMinimumEnergyConsumption"]
else
error("ERROR at reading the settings yaml file: The value of the keyword operationModeMinimumEnergyConsumption is not correct. The value has to be of type boolean.")
end
else
settings.operationModeMinimumEnergyConsumption=false
println("WARNING at reading the settings yaml file: The keyword operationModeMinimumEnergyConsumption or its value is missing. Therefore operationModeMinimumEnergyConsumption=",settings.operationModeMinimumEnergyConsumption," is assumed and used.")
end
delete!(data["settings"], "operationModeMinimumEnergyConsumption")
# output as "julia dictionary" or as "CSV"
if haskey(data["settings"],"typeOfOutput")
if typeof(data["settings"]["typeOfOutput"])==String && (data["settings"]["typeOfOutput"]=="julia dictionary" || data["settings"]["typeOfOutput"]=="CSV")
settings.typeOfOutput=data["settings"]["typeOfOutput"] # "julia dictionary" or "CSV"
else
error("ERROR at reading the settings yaml file: The value of typeOfOutput is wrong. It has to be julia dictionary or CSV.")
end
else
error("ERROR at reading the settings yaml file: The keyword typeOfOutput is missing. It has to be added with the value julia dictionary or CSV.")
end
delete!(data["settings"], "typeOfOutput")
# TODO: it could be checked if the path is existing on the pc
if settings.typeOfOutput=="CSV"
if haskey(data["settings"],"csvFolderPath")
if typeof(data["settings"]["csvFolderPath"])==String
settings.csvFolderPath=data["settings"]["csvFolderPath"]
else
error("ERROR at reading the settings yaml file: The value of csvFolderPath is wrong. It has to be of type String.")
end
else
error("ERROR at reading the settings yaml file: The keyword csvFolderPath is missing. It has to be added.")
end
delete!(data["settings"], "csvFolderPath")
end # if
# should the output be "reduced" or "driving course"
if haskey(data["settings"],"detailOfOutput")
if typeof(data["settings"]["detailOfOutput"])==String && (data["settings"]["detailOfOutput"]=="reduced" || data["settings"]["detailOfOutput"]=="driving course")
settings.detailOfOutput=data["settings"]["detailOfOutput"] # "reduced" or "driving course"
else
error("ERROR at reading the settings yaml file: The value of detailOfOutput is wrong. It has to be reduced or driving course.")
end
else
error("ERROR at reading the settings yaml file: The keyword detailOfOutput is missing. It has to be added with the value reduced or driving course.")
end
delete!(data["settings"], "detailOfOutput")
# informing the user, which keywords of the input data are not used in this tool:
if length(data["settings"])>0
println("INFO at reading the settings yaml file: The following Keywords are not used in this tool:")
for key in keys(data["settings"])
println(" - ",key)
end
end
return settings
end # function inputSettings
end # module RailwayDrivingDynamicsInput

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,478 @@
module RailwayDrivingDynamicsOperationModes
using ..types
include("./RailwayDrivingDynamicsMovingPhases.jl")
include("./RailwayDrivingDynamicsEnergySaving.jl")
using .RailwayDrivingDynamicsMovingPhases
using .RailwayDrivingDynamicsEnergySaving
export simulateMinimumRunningTime!, simulateMinimumEnergyConsumption
function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Settings, vehicle::Vehicle)
# this function simulates a train run focussing on using the minimum possible running time
startingPoint=Waypoint()
startingPoint.i=1
drivingCourse=[startingPoint] # List of waypoints
drivingCourse[end].s=movingSection.characteristicSections[1].s_start
for csId in 1:length(movingSection.characteristicSections)
# check if the CS has a cruising section
s_starting=get(movingSection.characteristicSections[csId].behaviorSections, "starting", BehaviorSection()).s_total
s_cruisingBeforeAcceleration=get(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).s_total
s_acceleration=get(movingSection.characteristicSections[csId].behaviorSections, "acceleration", BehaviorSection()).s_total
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-movingSection.characteristicSections[csId].v_reach^2)/2/vehicle.a_braking, digits=10)) # ceil is used to be sure that the vehicle stops at s_end in spite of rounding errors
s_cruising=movingSection.characteristicSections[csId].s_total-s_starting-s_cruisingBeforeAcceleration-s_acceleration-s_braking
# reset the moving section (MS), delete characteristic sections (CS) that were used during the preperation for setting v_entry, v_reach and v_exit
delete!(movingSection.characteristicSections[csId].behaviorSections, "starting")
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration")
delete!(movingSection.characteristicSections[csId].behaviorSections, "acceleration")
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruising")
movingSection.characteristicSections[csId].E_total=0.0
movingSection.characteristicSections[csId].t_total=0.0
if s_cruisingBeforeAcceleration == movingSection.characteristicSections[csId].s_total
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruisingBeforeAcceleration, settings, vehicle, movingSection.characteristicSections, "cruisingBeforeAcceleration")
elseif s_cruising == movingSection.characteristicSections[csId].s_total
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, vehicle, movingSection.characteristicSections, "cruising")
elseif s_cruising >0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0)
if drivingCourse[end].v<movingSection.characteristicSections[csId].v_reach
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, vehicle, movingSection.characteristicSections)
end #if
if (movingSection.characteristicSections[csId].s_end-drivingCourse[end].s-max(0.0, (movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking))<-0.001 # ceil is used to be sure that the vehicle stops at s_end in spite of rounding errors
println("ERROR: After accelerating in CS ",csId," the braking distance is too short!")
println(" before acceleration in CS",csId, " with s=",drivingCourse[end].s," s_braking=",((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking)," s_end=",movingSection.characteristicSections[csId].s_end)
println(" and v=",drivingCourse[end].v," v_reach=",movingSection.characteristicSections[csId].v_reach," v_exit=",movingSection.characteristicSections[csId].v_exit)
end
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10)) # ceil is used to be sure that the vehicle stops at s_end in spite of rounding errors
s_cruising=movingSection.characteristicSections[csId].s_end-drivingCourse[end].s-s_braking
if s_cruising>0
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, vehicle, movingSection.characteristicSections, "cruising")
end
else
if movingSection.characteristicSections[csId].v_entry<movingSection.characteristicSections[csId].v_reach
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhaseWithIntersection!(movingSection.characteristicSections[csId], drivingCourse, settings, vehicle, movingSection.characteristicSections)
end #if
end #if
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10)) # ceil is used to be sure that the vehicle stops at s_end in spite of rounding errors
if drivingCourse[end].v>movingSection.characteristicSections[csId].v_exit
(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings.massModel, vehicle, movingSection.characteristicSections)
end #if
if drivingCourse[end].s < movingSection.characteristicSections[csId].s_end
if haskey(movingSection.characteristicSections[csId].behaviorSections, "cruising")
println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_end=",movingSection.characteristicSections[csId].s_end)
end
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, vehicle, movingSection.characteristicSections, "cruising")
end
end #for
movingSection.t_total=drivingCourse[end].t # total running time (in s)
movingSection.E_total=drivingCourse[end].E # total energy consumption (in Ws)
return (movingSection, drivingCourse)
end #function simulateMinimumRunningTime
function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumRunningTime::Vector{Waypoint}, settings::Settings, vehicle::Vehicle)
# this function simulates a train run focussing on using the minimum possible energy consumption
# booleans for choosing which methods are used for saving energy
doMethod1=true
doMethod2=true
doCombinationOfMethods=true
#creating a new moving section for the minimum energy consumption
movingSectionOriginal=MovingSection(movingSectionMinimumRunningTime)
# creating a new driving course for the minimum energy consumption
drivingCourseOriginal=Waypoint[]
for i in 1:length(drivingCourseMinimumRunningTime)
push!(drivingCourseOriginal, Waypoint(drivingCourseMinimumRunningTime[i])) # List of waypoints till the start of energy saving
end
# calculation the recovery time
movingSectionOriginal.t_recovery=calculateRecoveryTime(movingSectionOriginal.s_total, movingSectionOriginal.t_total, vehicle)
movingSectionOriginal.t_recoveryAvailable=movingSectionOriginal.t_recovery
# println("t_recovery=",movingSectionOriginal.t_recovery)
# creating arrays for each method with all the available energy saving modifications
energySavingModificationsWithCoasting=EnergySavingModification[]
energySavingModificationsWithMaximumSpeed=EnergySavingModification[]
energySavingModificationsWithCombination=EnergySavingModification[]
for csId in 1:length(movingSectionOriginal.characteristicSections)
# method 1: increase coasting
if doMethod1==true
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=increaseCostingSection(movingSectionOriginal.characteristicSections[csId], drivingCourseOriginal, settings, vehicle, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable)
if new
energySavingModification=EnergySavingModification()
energySavingModification.csId=csId # identifier of the characteristic section
energySavingModification.type="increasing coasting" # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified=characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified=drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE=movingSectionOriginal.characteristicSections[csId].E_total-energySavingModification.csModified.E_total # saved energy (in Ws)
energySavingModification.Δt=energySavingModification.csModified.t_total-movingSectionOriginal.characteristicSections[csId].t_total # time loss (in s)
if energySavingModification.Δt<=movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE>=0.0
energySavingModification.ratio=energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
elseif energySavingModification.Δt==0.0 #
energySavingModification.ratio=energySavingModification.ΔE/0.000000001
else # Δt is to high
energySavingModification.ratio=0.0
end
push!(energySavingModificationsWithCoasting, energySavingModification)
else # there is no modification possible for the current CS
push!(energySavingModificationsWithCoasting, EnergySavingModification())
end
end #if doMethod1
# method 2: accelerate to a lower v_reach
if doMethod2==true
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(movingSectionOriginal.characteristicSections[csId], drivingCourseOriginal, settings, vehicle, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable)
if new
energySavingModification=EnergySavingModification()
energySavingModification.csId=csId # identifier of the characteristic section
energySavingModification.type="decreasing maximum velocity" # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified=characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified=drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE=movingSectionOriginal.characteristicSections[csId].E_total-energySavingModification.csModified.E_total # saved energy (in Ws)
energySavingModification.Δt=energySavingModification.csModified.t_total-movingSectionOriginal.characteristicSections[csId].t_total # time loss (in s)
if energySavingModification.Δt<=movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE>=0.0
energySavingModification.ratio=energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
elseif energySavingModification.Δt==0.0
energySavingModification.ratio=energySavingModification.ΔE/0.000000001
else # Δt is to high or ΔE < 0.0 Ws
energySavingModification.ratio=0.0
end
push!(energySavingModificationsWithMaximumSpeed, energySavingModification)
else # there is no modification possible for the current CS
push!(energySavingModificationsWithMaximumSpeed, EnergySavingModification())
end
end #if doMethod2
if doCombinationOfMethods==true
# calculating the combination of methods
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(movingSectionOriginal.characteristicSections[csId], drivingCourseOriginal, settings, vehicle, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable)
if new
energySavingModification=EnergySavingModification()
energySavingModification.csId=csId # identifier of the characteristic section
energySavingModification.type="combination of energy saving methods" # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified=characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified=drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE=movingSectionOriginal.characteristicSections[csId].E_total-energySavingModification.csModified.E_total # saved energy (in Ws)
energySavingModification.Δt=energySavingModification.csModified.t_total-movingSectionOriginal.characteristicSections[csId].t_total # time loss (in s)
if energySavingModification.Δt<=movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE>=0.0
energySavingModification.ratio=sign(energySavingModification.Δt)*energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
elseif energySavingModification.Δt==0.0 #
energySavingModification.ratio=energySavingModification.ΔE/0.000000001
else # Δt is to high or ΔE < 0.0 Ws
energySavingModification.ratio=0.0
end
push!(energySavingModificationsWithCombination, energySavingModification)
else # there is no modification possible for the current CS
push!(energySavingModificationsWithCombination, EnergySavingModification())
end
end #if
end # for
while (movingSectionOriginal.t_recoveryAvailable>0.0)
# comparison of modifications
ratioMax=0.0
csIdMax=0
typeMax="none"
for modNr in 1:length(energySavingModificationsWithMaximumSpeed)
if energySavingModificationsWithMaximumSpeed[modNr].ratio>ratioMax
if energySavingModificationsWithMaximumSpeed[modNr].Δt<=movingSectionOriginal.t_recoveryAvailable
ratioMax=energySavingModificationsWithMaximumSpeed[modNr].ratio
csIdMax=energySavingModificationsWithMaximumSpeed[modNr].csId
typeMax=energySavingModificationsWithMaximumSpeed[modNr].type
else # Δt is to high
energySavingModificationsWithMaximumSpeed[modNr].ratio=0.0
end #if
end #if
end #for
for modNr in 1:length(energySavingModificationsWithCoasting)
if energySavingModificationsWithCoasting[modNr].ratio>ratioMax
if energySavingModificationsWithCoasting[modNr].Δt<=movingSectionOriginal.t_recoveryAvailable
ratioMax=energySavingModificationsWithCoasting[modNr].ratio
csIdMax=energySavingModificationsWithCoasting[modNr].csId
typeMax=energySavingModificationsWithCoasting[modNr].type
else # Δt is to high
energySavingModificationsWithCoasting[modNr].ratio=0.0
end #if
end #if
end #for
for modNr in 1:length(energySavingModificationsWithCombination)
if energySavingModificationsWithCombination[modNr].ratio>ratioMax
if energySavingModificationsWithCombination[modNr].Δt<=movingSectionOriginal.t_recoveryAvailable
ratioMax=energySavingModificationsWithCombination[modNr].ratio
csIdMax=energySavingModificationsWithCombination[modNr].csId
typeMax=energySavingModificationsWithCombination[modNr].type
else # Δt is to high
energySavingModificationsWithCombination[modNr].ratio=0.0
end #if
end #if
end #for
# selection of most efficient modification and update the original characteristicSection, drivingCourse and movingSection
# in case none of the modifications has a ratio>0 stop the calculation
if typeMax=="none"
break
elseif typeMax=="increasing coasting"
# println("Energy saving modification number ",length(movingSectionOriginal.energySavingModifications)+1," (coasting) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax].Δt," ΔE=", energySavingModificationsWithCoasting[csIdMax].ΔE," t_recoveryAvailable=", movingSectionOriginal.t_recoveryAvailable-energySavingModificationsWithCoasting[csIdMax].Δt)
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCoasting[csIdMax])
elseif typeMax=="decreasing maximum velocity"
# println("Energy saving modification number ",length(movingSectionOriginal.energySavingModifications)+1," (lowering v_reach) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax].Δt," ΔE=", energySavingModificationsWithCoasting[csIdMax].ΔE," t_recoveryAvailable=", movingSectionOriginal.t_recoveryAvailable-energySavingModificationsWithCoasting[csIdMax].Δt)
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithMaximumSpeed[csIdMax])
elseif typeMax=="combination of energy saving methods"
# println("Energy saving modification number ",length(movingSectionOriginal.energySavingModifications)+1," (combination) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax].Δt," ΔE=", energySavingModificationsWithCoasting[csIdMax].ΔE," t_recoveryAvailable=", movingSectionOriginal.t_recoveryAvailable-energySavingModificationsWithCoasting[csIdMax].Δt)
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCombination[csIdMax])
end #if
movingSectionOriginal.t_recoveryAvailable=movingSectionOriginal.t_recoveryAvailable-movingSectionOriginal.energySavingModifications[end].Δt
lastIdOfModifiedCs=get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "braking", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "cruisingAfterCoasting", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "coasting", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "cruising", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "acceleration", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "cruisingBeforeAcceleration", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "starting", BehaviorSection()))))))).waypoints[end]
drivingCourseNew=Vector{Waypoint}()
for i in 1:length(movingSectionOriginal.energySavingModifications[end].drivingCourseModified)
push!(drivingCourseNew, Waypoint(movingSectionOriginal.energySavingModifications[end].drivingCourseModified[i]))
end
# # for testing if the modifications driving course and the original one have the same speed value at their transition point
# if lastIdOfModifiedCs+1<=drivingCourseOriginal[end].i
# if drivingCourseOriginal[lastIdOfModifiedCs].v-drivingCourseNew[end].v!=0.0
# println("INFO: Inconsistency while adding the CS",csIdMax," that has been modified for consuming less energy. The difference at its end is ",(drivingCourseOriginal[lastIdOfModifiedCs].v-drivingCourseNew[end].v)," m/s."
# end
# end # for testing
#filling up the rest of the driving course
drivingCourseNew[end].F_T=drivingCourseOriginal[lastIdOfModifiedCs].F_T
drivingCourseNew[end].F_Rt=drivingCourseOriginal[lastIdOfModifiedCs].F_Rt
drivingCourseNew[end].F_Rw=drivingCourseOriginal[lastIdOfModifiedCs].F_Rw
drivingCourseNew[end].F_Runion=drivingCourseOriginal[lastIdOfModifiedCs].F_Runion
drivingCourseNew[end].F_Rp=drivingCourseOriginal[lastIdOfModifiedCs].F_Rp
drivingCourseNew[end].F_R=drivingCourseOriginal[lastIdOfModifiedCs].F_R
drivingCourseNew[end].a=drivingCourseOriginal[lastIdOfModifiedCs].a
endOfModificationId=drivingCourseNew[end].i # is needed for updating the other modified driving courses
difference=drivingCourseNew[end].i-lastIdOfModifiedCs
i=lastIdOfModifiedCs+1
while (i<=length(drivingCourseOriginal))
push!(drivingCourseNew, Waypoint(drivingCourseOriginal[i]))
drivingCourseNew[end].i=length(drivingCourseNew)
drivingCourseNew[end].t=drivingCourseNew[end-1].t+drivingCourseNew[end].Δt
drivingCourseNew[end].E=drivingCourseNew[end-1].E+drivingCourseNew[end].ΔE
drivingCourseNew[end].W_T=drivingCourseNew[end-1].W_T+drivingCourseNew[end].ΔW_T
i=i+1
end # while
# updating all the waypoint references in the behaviour sections of the following characteristic sections and the other modified characteristic sections
if difference!= 0
allBs=["starting", "cruisingBeforeAcceleration", "acceleration", "cruising", "coasting", "cruisingAfterCoasting", "braking"]
for csId in csIdMax+1:length(movingSectionOriginal.characteristicSections)
for bs in 1: length(allBs)
if haskey(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs])
for point in 1:length(get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).waypoints)
get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]=get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]+difference
end
end #if
end #for
end #for
# updating the waypoints in the following modified charateristic sections and the following points in the driving course
for modNr in csIdMax+1:length(energySavingModificationsWithCoasting)
if energySavingModificationsWithCoasting[modNr].ratio>0
# updating the behavior sections of the modified charateristic section
for bs in 1: length(allBs)
if haskey(energySavingModificationsWithCoasting[modNr].csModified.behaviorSections, allBs[bs])
for point in 1:length(get(energySavingModificationsWithCoasting[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints)
get(energySavingModificationsWithCoasting[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]=get(energySavingModificationsWithCoasting[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]+difference
end
end #if
end #for
# correctig the points of the modified driving course
drivingCourseModifiedNew=Vector{Waypoint}()
for i in 1:endOfModificationId
push!(drivingCourseModifiedNew, Waypoint(drivingCourseNew[i]))
end # while
i=lastIdOfModifiedCs+1
while (i<=length(energySavingModificationsWithCoasting[modNr].drivingCourseModified))
push!(drivingCourseModifiedNew, Waypoint(energySavingModificationsWithCoasting[modNr].drivingCourseModified[i]))
drivingCourseModifiedNew[end].i=length(drivingCourseModifiedNew)
drivingCourseModifiedNew[end].t=drivingCourseModifiedNew[end-1].t+drivingCourseModifiedNew[end].Δt
drivingCourseModifiedNew[end].E=drivingCourseModifiedNew[end-1].E+drivingCourseModifiedNew[end].ΔE
drivingCourseModifiedNew[end].W_T=drivingCourseModifiedNew[end-1].W_T+drivingCourseModifiedNew[end].ΔW_T
i=i+1
end # while
energySavingModificationsWithCoasting[modNr].drivingCourseModified=drivingCourseModifiedNew
end #if
end #for
for modNr in csIdMax+1:length(energySavingModificationsWithMaximumSpeed)
if energySavingModificationsWithMaximumSpeed[modNr].ratio>0
# updating the behavior sections of the modified charateristic section
for bs in 1: length(allBs)
if haskey(energySavingModificationsWithMaximumSpeed[modNr].csModified.behaviorSections, allBs[bs])
for point in 1:length(get(energySavingModificationsWithMaximumSpeed[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints)
get(energySavingModificationsWithMaximumSpeed[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]=get(energySavingModificationsWithMaximumSpeed[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]+difference
end
end #if
end #for
# correctig the points of the modified driving course
drivingCourseModifiedNew=Vector{Waypoint}()
for i in 1:endOfModificationId
push!(drivingCourseModifiedNew, Waypoint(drivingCourseNew[i]))
end # while
i=lastIdOfModifiedCs+1
while (i<=length(energySavingModificationsWithMaximumSpeed[modNr].drivingCourseModified))
push!(drivingCourseModifiedNew, Waypoint(energySavingModificationsWithMaximumSpeed[modNr].drivingCourseModified[i]))
drivingCourseModifiedNew[end].i=length(drivingCourseModifiedNew)
drivingCourseModifiedNew[end].t=drivingCourseModifiedNew[end-1].t+drivingCourseModifiedNew[end].Δt
drivingCourseModifiedNew[end].E=drivingCourseModifiedNew[end-1].E+drivingCourseModifiedNew[end].ΔE
drivingCourseModifiedNew[end].W_T=drivingCourseModifiedNew[end-1].W_T+drivingCourseModifiedNew[end].ΔW_T
i=i+1
end # while
energySavingModificationsWithMaximumSpeed[modNr].drivingCourseModified=drivingCourseModifiedNew
end #if
end #for
for modNr in csIdMax+1:length(energySavingModificationsWithCombination)
if energySavingModificationsWithCombination[modNr].ratio>0
# updating the behavior sections of the modified charateristic section
for bs in 1: length(allBs)
if haskey(energySavingModificationsWithCombination[modNr].csModified.behaviorSections, allBs[bs])
for point in 1:length(get(energySavingModificationsWithCombination[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints)
get(energySavingModificationsWithCombination[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]=get(energySavingModificationsWithCombination[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).waypoints[point]+difference
end
end #if
end #for
# updating the points of the modified driving course
drivingCourseModifiedNew=Vector{Waypoint}()
for i in 1:endOfModificationId
push!(drivingCourseModifiedNew, Waypoint(drivingCourseNew[i]))
end # while
i=lastIdOfModifiedCs+1
while (i<=length(energySavingModificationsWithCombination[modNr].drivingCourseModified))
push!(drivingCourseModifiedNew, Waypoint(energySavingModificationsWithCombination[modNr].drivingCourseModified[i]))
drivingCourseModifiedNew[end].i=length(drivingCourseModifiedNew)
drivingCourseModifiedNew[end].t=drivingCourseModifiedNew[end-1].t+drivingCourseModifiedNew[end].Δt
drivingCourseModifiedNew[end].E=drivingCourseModifiedNew[end-1].E+drivingCourseModifiedNew[end].ΔE
drivingCourseModifiedNew[end].W_T=drivingCourseModifiedNew[end-1].W_T+drivingCourseModifiedNew[end].ΔW_T
i=i+1
end # while
energySavingModificationsWithCombination[modNr].drivingCourseModified=drivingCourseModifiedNew
end #if
end #for
end # if difference
drivingCourseOriginal=drivingCourseNew
movingSectionOriginal.characteristicSections[csIdMax]=CharacteristicSection(movingSectionOriginal.energySavingModifications[end].csModified)
movingSectionOriginal.t_total=drivingCourseOriginal[end].t # total running time (in s)
movingSectionOriginal.E_total=drivingCourseOriginal[end].E # total energy consumption (in Ws)
# modify new CS for the considered methods
# method 1: increase coasting
if doMethod1==true
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=increaseCostingSection(movingSectionOriginal.characteristicSections[csIdMax], drivingCourseOriginal, settings, vehicle, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable)
if new
energySavingModification=EnergySavingModification()
energySavingModification.csId=csIdMax # identifier of the characteristic section
energySavingModification.type="increasing coasting" # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified=characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified=drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE=movingSectionOriginal.characteristicSections[csIdMax].E_total-energySavingModification.csModified.E_total # saved energy (in Ws)
energySavingModification.Δt=energySavingModification.csModified.t_total-movingSectionOriginal.characteristicSections[csIdMax].t_total # time loss (in s)
if energySavingModification.Δt<=movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE>=0.0 #&& energySavingModification.Δt>0.0
energySavingModification.ratio=energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
elseif energySavingModification.Δt==0.0
energySavingModification.ratio=energySavingModification.ΔE/0.000000001
else # Δt is to high
energySavingModification.ratio=0.0
end
energySavingModificationsWithCoasting[csIdMax]=energySavingModification
else # there is no modification possible for the current CS
energySavingModificationsWithCoasting[csIdMax]=EnergySavingModification()
end
end #if if doMethod1
# method 2: accelerate to a lower v_reach
if doMethod2==true
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(movingSectionOriginal.characteristicSections[csIdMax], drivingCourseOriginal, settings, vehicle, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable)
if new
energySavingModification=EnergySavingModification()
energySavingModification.csId=csIdMax # identifier of the characteristic section
energySavingModification.type="decreasing maximum velocity" # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified=characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified=drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE=movingSectionOriginal.characteristicSections[csIdMax].E_total-energySavingModification.csModified.E_total # saved energy (in Ws)
energySavingModification.Δt=energySavingModification.csModified.t_total-movingSectionOriginal.characteristicSections[csIdMax].t_total # time loss (in s)
if energySavingModification.Δt<=movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE>=0.0
energySavingModification.ratio=energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
elseif energySavingModification.Δt==0.0
energySavingModification.ratio=energySavingModification.ΔE/0.000000001
else # Δt is to high
energySavingModification.ratio=0.0
end
energySavingModificationsWithMaximumSpeed[csIdMax]=energySavingModification
else # there is no modification possible for the current CS
energySavingModificationsWithMaximumSpeed[csIdMax]=EnergySavingModification()
end
end #if if doMethod
# combination of both methods
if doCombinationOfMethods==true
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(movingSectionOriginal.characteristicSections[csIdMax], drivingCourseOriginal, settings, vehicle, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable)
if new
energySavingModification=EnergySavingModification()
energySavingModification.csId=csIdMax # identifier of the characteristic section
energySavingModification.type="combination of energy saving methods" # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified=characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified=drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE=movingSectionOriginal.characteristicSections[csIdMax].E_total-energySavingModification.csModified.E_total # saved energy (in Ws)
energySavingModification.Δt=energySavingModification.csModified.t_total-movingSectionOriginal.characteristicSections[csIdMax].t_total # time loss (in s)
if energySavingModification.Δt<=movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE>=0.0
energySavingModification.ratio=energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
elseif energySavingModification.Δt==0.0 #
println("Energiesparanpassung durch Kombination bei CS ",csIdMax," ist 0 s. Das kann eigentlich nicht sein!")
energySavingModification.ratio=energySavingModification.ΔE/0.000000001
else # Δt is to high
energySavingModification.ratio=0.0
end
energySavingModificationsWithCombination[csIdMax]=energySavingModification
else # there is no modification possible for the current CS
energySavingModificationsWithCombination[csIdMax]=EnergySavingModification()
end
end #if doCombinationOfMethods
end # while
# println("t_recoveryAvailable=",movingSectionOriginal.t_recoveryAvailable)
return (movingSectionOriginal, drivingCourseOriginal)
end #function simulateMinimumEnergyConsumption
end #module RailwayDrivingDynamicsOperationModes

View File

@ -0,0 +1,371 @@
module RailwayDrivingDynamicsOutput
using ..types
using Plots
using CSV, DataFrames, Dates
export createOutput
export plotDrivingCourse, printImportantValues, printSectionInformation # functions for showing results during the development
function createOutput(settings::Settings, pathName::String, vehicleName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
# method of function createOutput for one operation mode
if settings.typeOfOutput == "CSV"
return createOutputCsv(settings, pathName, vehicleName, drivingCourse, movingSection)
else
return createOutputDict(settings, pathName, vehicleName, drivingCourse, movingSection)
end
end # funtion createOutput
function createOutput(settings::Settings, pathName::String, vehicleName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
# method of function createOutput for two operation modes
if settings.typeOfOutput == "CSV"
return createOutputCsv(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
else
return createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
end
end # funtion createOutput
function createOutputDict(settings::Settings, pathName::String, vehicleName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
# method of function createOutputDict for one operation mode
if settings.operationModeMinimumRunningTime
if settings.operationModeMinimumEnergyConsumption
operationMode="minimum running time and minimum energy consumption"
else
operationMode="minimum running time"
end
else
if settings.operationModeMinimumEnergyConsumption
operationMode="minimum energy consumption"
else
# should never be the case
println("No Output was demanded. So no output dictionary is created")
return
end
end
outputDict=Dict([("path name", pathName), ("vehicle name", vehicleName), ("operation mode", operationMode), ("mass model", settings.massModel), ("step variable", settings.stepVariable), ("step size", settings.stepSize)])
# creating an output array
outputArray=Array{Any, 1}[]
if settings.detailOfOutput=="reduced"
push!(outputArray, ["s_total (in m)", "t_total (in s)","E_total (in Ws)"]) # push header to outputArray
row=[movingSection.s_total, movingSection.t_total, movingSection.E_total]
push!(outputArray, row) # push row to outputArray
elseif settings.detailOfOutput=="driving course"
push!(outputArray, ["i", "Δ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)","F_Rp (in N)","F_Runion (in N)","F_Rt (in N)","F_Rw (in N)", "ΔW_T (in Ws)","W_T (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray
for point in drivingCourse
row=[point.i, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.F_Rp, point.F_Runion, point.F_Rt, point.F_Rw, point.ΔW_T, point.W_T, point.ΔE, point.E, point.a]
push!(outputArray, row) # push row to outputArray
end
end
if length(movingSection.energySavingModifications)>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption
merge!(outputDict, Dict("outputArrayMinimumEnergyConsumption"=>outputArray))
else
merge!(outputDict, Dict("outputArrayMinimumRunningTime"=>outputArray))
end
println("The output dictionary has been created for ",operationMode,".")
return outputDict
end # function createOutputDict
function createOutputDict(settings::Settings, pathName::String, vehicleName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
# method of function createOutputDict for two operation modes
if settings.operationModeMinimumRunningTime
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
if settings.operationModeMinimumEnergyConsumption
# creating the second output array
outputArrayMinimumEnergyConsumption=Array{Any, 1}[]
if settings.detailOfOutput=="reduced"
push!(outputArrayMinimumEnergyConsumption, ["s_total (in m)", "t_total (in s)","E_total (in Ws)"]) # push header to outputArrayMinimumEnergyConsumption
row=[movingSectionMinimumEnergyConsumption.s_total, movingSectionMinimumEnergyConsumption.t_total, movingSectionMinimumEnergyConsumption.E_total]
push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption
elseif settings.detailOfOutput=="driving course"
push!(outputArrayMinimumEnergyConsumption, ["i", "Δ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)","F_Rp (in N)","F_Runion (in N)","F_Rt (in N)","F_Rw (in N)", "ΔW_T (in Ws)","W_T (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption
for point in drivingCourseMinimumEnergyConsumption
row=[point.i, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.F_Rp, point.F_Runion, point.F_Rt, point.F_Rw, point.ΔW_T, point.W_T, point.ΔE, point.E, point.a]
push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption
end
end
merge!(outputDict, Dict("outputArrayMinimumEnergyConsumption"=>outputArrayMinimumEnergyConsumption))
end
else
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
end
# println("The output dictionary has been created for minimum running time and minimum energy consumption.")
return outputDict
end # function createOutputDict
function createOutputCsv(settings::Settings, pathName::String, vehicleName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
# method of function createOutputDict for one operation mode
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourse, movingSection)
if length(movingSection.energySavingModifications)>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption
operationMode="minimum energy consumption"
outputArray="outputArrayMinimumEnergyConsumption"
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_MinimumEnergyConsumption.csv"
else
operationMode="minimum running time"
outputArray="outputArrayMinimumRunningTime"
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_MinimumRunningTime.csv"
end
# creating information block
infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "vehicle name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, vehicleName, operationMode, settings.massModel, settings.stepVariable, string(settings.stepSize), ""])
for column in 3:length(outputDict[outputArray][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
end # for
allColumns=Array{Any,1}[]
if settings.detailOfOutput=="reduced"
header=outputDict["outputArrayMinimumRunningTime"][1]
elseif settings.detailOfOutput=="driving course"
header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","F_Rp (in N)","F_Runion (in N)","F_Rt (in N)","F_Rw (in N)"," Delta W_T (in Ws)","W_T (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end
for column in 1:length(outputDict[outputArray][1])
push!(infoColumns[column], header[column])
for row in outputDict[outputArray][2:end]
push!(infoColumns[column], row[column])
end
push!(allColumns, infoColumns[column])
end # for
# combining the columns in a data frame and saving it as a CSV-file at csvFolderPath
if settings.detailOfOutput=="reduced"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course"
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])
end
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for ",operationMode," at ",csvFilePath)
return outputDict
end #function createOutputCsv
function createOutputCsv(settings::Settings, pathName::String, vehicleName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
# method of function createOutputDict for two operation modes
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
if settings.operationModeMinimumRunningTime
#creating information block
infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "vehicle name", "operation mode", "mass model", "step variable", "step size", ""])
#push!(infoColumns, [pathName, vehicleName, "minimum running time", settings.massModel, settings.stepVariable, settings.stepSize, ""])
push!(infoColumns, [pathName, vehicleName, "minimum running time", settings.massModel, settings.stepVariable, string(settings.stepSize), ""])
for column in 3:length(outputDict["outputArrayMinimumRunningTime"][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
# println("push wird ausgeführt")
end # for
allColumns=Array{Any,1}[]
if settings.detailOfOutput=="reduced"
header=outputDict["outputArrayMinimumRunningTime"][1]
elseif settings.detailOfOutput=="driving course"
header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","F_Rp (in N)","F_Runion (in N)","F_Rt (in N)","F_Rw (in N)"," Delta W_T (in Ws)","W_T (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end
for column in 1:length(outputDict["outputArrayMinimumRunningTime"][1])
push!(infoColumns[column], header[column])
for row in outputDict["outputArrayMinimumRunningTime"][2:end]
push!(infoColumns[column], row[column])
end
push!(allColumns, infoColumns[column])
end # for
#combining the columns in a data frame and saving it as a CSV-file at csvFolderPath
if settings.detailOfOutput=="reduced"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course"
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])
end
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_dataMinimumRunningTime.csv"
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for minimum running time at ",csvFilePath)
end #if settings.operationModeMinimumRunningTime
if settings.operationModeMinimumEnergyConsumption
#creating information block
infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "vehicle name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, vehicleName, "minimum energy consumption", settings.massModel, settings.stepVariable, settings.stepSize, ""])
for column in 3:length(outputDict["outputArrayMinimumEnergyConsumption"][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
end # for
allColumns=Array{Any,1}[]
if settings.detailOfOutput=="reduced"
header=outputDict["outputArrayMinimumRunningTime"][1]
elseif settings.detailOfOutput=="driving course"
header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","F_Rp (in N)","F_Runion (in N)","F_Rt (in N)","F_Rw (in N)"," Delta W_T (in Ws)","W_T (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end
for column in 1:length(outputDict["outputArrayMinimumEnergyConsumption"][1])
push!(infoColumns[column], header[column])
for row in outputDict["outputArrayMinimumEnergyConsumption"][2:end]
push!(infoColumns[column], row[column])
end
push!(allColumns, infoColumns[column])
end # for
#combining the columns in a data frame
if settings.detailOfOutput=="reduced"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course"
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])
end
# creating a CSV-file at csvFolderPath
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_dataMinimumEnergyConsumption.csv"
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for minimum energy consumption at ",csvFilePath)
end # if settings.operationModeMinimumEnergyConsumption
return outputDict
end #function createOutputCsv
function printImportantValues(drivingCourse::Vector{Waypoint})
println("i 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(drivingCourse)
println(drivingCourse[i].i,". ",drivingCourse[i].s," ",drivingCourse[i].v*3.6," ",drivingCourse[i].t/60," ",drivingCourse[i].a," ",drivingCourse[i].F_R/1000," ",drivingCourse[i].F_T/1000," ",drivingCourse[i].E/3600/1000)
end #for
println("i 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::MovingSection)
println("MS mit s_total=", movingSection.s_total," mit t_total=", movingSection.t_total)
allBs=["starting", "cruisingBeforeAcceleration","acceleration", "cruising", "coasting","cruisingAfterCoasting", "braking"]
for csId in 1:length(movingSection.characteristicSections)
println("CS ",csId," mit s_total=", movingSection.characteristicSections[csId].s_total," mit t_total=", movingSection.characteristicSections[csId].t_total)
for bs in 1: length(allBs)
if haskey(movingSection.characteristicSections[csId].behaviorSections, allBs[bs])
println("BS ",allBs[bs], " mit s_start=",get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).s_start, " und t_total=",get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).t_total)
# for point in 1:length(get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).waypoints)
# println(get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).waypoints[point])
# end
end #if
end #for
end #for
end #function printSectionInformation
function plotDrivingCourse(drivingCourse::Vector{Waypoint})
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")
p2=plot([t], [v], title = "v in m/s", label = ["v"], xlabel = "t in s")
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")
p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s")
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{Waypoint},drivingCourseMinimumEnergyConsumption::Vector{Waypoint}) #,movingSection1::MovingSection,movingSection2::MovingSection)
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)
display(all)
println("Plots for different variables have been created.")
end #function plotDrivingCourse
end # module RailwayDrivingDynamicsOutput

View File

@ -0,0 +1,137 @@
module RailwayDrivingDynamicsPreparation
using ..types
include("./RailwayDrivingDynamicsMovingPhases.jl")
using .RailwayDrivingDynamicsMovingPhases
export preparateSections
## creating a moving section and its containing characteristic sections which braking and acceleration behavior is secured
function preparateSections(path::Path, vehicle::Vehicle, settings::Settings)
movingSection=createMovingSection(path, vehicle.v_limit)
movingSection=secureBrakingBehavior!(movingSection, vehicle.a_braking)
movingSection=secureAccelerationBehavior!(movingSection, settings, vehicle)
return movingSection
end #function preparateSections
## creating a moving section containing characteristic sections
function createMovingSection(path::Path, v_vehicleLimit::AbstractFloat)
# this function creates and returns a moving section dependent on the paths attributes
movingSection=MovingSection()
movingSection.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
movingSection.t_total=0.0 # total running time (in s)
movingSection.E_total=0.0 # total energy consumption (in Ws)
movingSection.s_start=path.sections[1].s_start # first position (in m)
movingSection.s_end=path.sections[length(path.sections)].s_startNext # last position (in m)
movingSection.s_total=movingSection.s_end-movingSection.s_start # total length (in m)
s_csStart=movingSection.s_start
csId=1
for row in 2:length(path.sections)
if min(path.sections[row-1].v_limit, v_vehicleLimit) != min(path.sections[row].v_limit, v_vehicleLimit) || path.sections[row-1].f_Rp != path.sections[row].f_Rp
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[row-1], min(path.sections[row-1].v_limit, v_vehicleLimit)))
s_csStart=path.sections[row].s_start
csId=csId+1
end #if
end #for
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end].v_limit, v_vehicleLimit)))
return movingSection
end #function createMovingSection
##
function createCharacteristicSection(csId::Integer, s_csStart::AbstractFloat, section::PathSection, v_csLimit::AbstractFloat)
# this function creates and returns a characteristic section dependent on the paths attributes
characteristicSection=CharacteristicSection()
characteristicSection.id=csId # identifier
characteristicSection.s_start=s_csStart # first position (in m)
characteristicSection.s_end=section.s_startNext # last position (in m)
characteristicSection.s_total=characteristicSection.s_end-characteristicSection.s_start # total length (in m)
characteristicSection.t_total=0.0 # total running time (in s)
characteristicSection.E_total=0.0 # total energy consumption (in Ws)
characteristicSection.v_limit=v_csLimit # speed limit (in m/s)
# initializing v_entry, v_reach and v_exit with v_limit
characteristicSection.v_reach=characteristicSection.v_limit # maximum reachable speed (in m/s)
characteristicSection.v_entry=characteristicSection.v_limit # maximum entry speed (in m/s)
characteristicSection.v_exit=characteristicSection.v_limit # maximum exit speed (in m/s)
characteristicSection.f_Rp=section.f_Rp # path resistance (in ‰)
return characteristicSection
end #function createCharacteristicSection
## defining the intersection velocities between the characterisitc sections
function secureBrakingBehavior!(movingSection::MovingSection, a_braking::AbstractFloat)
# this function limits the entry and exit velocity of the characteristic sections to secure that the vehicle stops at the moving sections end
csId=length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_exit=0.0 # the exit velocity of the last characteristic section is 0.0 m/s
while csId >= 1
v_entryMax=sqrt(movingSection.characteristicSections[csId].v_exit^2-2*a_braking*movingSection.characteristicSections[csId].s_total)
v_entryMax=floor(v_entryMax, digits=12)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_limit, v_entryMax)
movingSection.characteristicSections[csId].v_reach=movingSection.characteristicSections[csId].v_entry
csId=csId-1
if csId >= 1
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_limit, movingSection.characteristicSections[csId+1].v_entry)
end #if
end #while
return movingSection
end #function secureBrakingBehavior!
##
function secureAccelerationBehavior!(movingSection::MovingSection, settings::Settings, vehicle::Vehicle)
# this function limits the entry and exit velocity of the characteristic sections for case that the vehicle accelerates in every section and cruises aterwards
movingSection.characteristicSections[1].v_entry=0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint=Waypoint()
startingPoint.i=1
previousCSv_exit=0.0
for csId in 1:length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_entry, previousCSv_exit)
startingPoint.s=movingSection.characteristicSections[csId].s_start
startingPoint.v=movingSection.characteristicSections[csId].v_entry
accelerationCourse=[startingPoint] # List of waypoints
if movingSection.characteristicSections[csId].v_entry<movingSection.characteristicSections[csId].v_reach
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, vehicle, movingSection.characteristicSections) # this function changes the accelerationCourse
movingSection.characteristicSections[csId].v_reach=accelerationCourse[end].v
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, movingSection.characteristicSections[csId].v_reach)
if settings.stepVariable=="v in m/s" # with the new v_reach the calculation will be defferent a second time. Therefore the CS has to be calculated again for velocity step method to refresh the length of the acceleration section for further simulation
delete!(movingSection.characteristicSections[csId].behaviorSections, "starting")
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration")
delete!(movingSection.characteristicSections[csId].behaviorSections, "acceleration")
movingSection.characteristicSections[csId].E_total=0.0
movingSection.characteristicSections[csId].t_total=0.0
accelerationCourse=[startingPoint] # List of waypoints
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, vehicle, movingSection.characteristicSections) # this function changes the accelerationCourse
end
else #movingSection.characteristicSections[csId].v_entry==movingSection.characteristicSections[csId].v_reach
# v_exit stays the same
end #if
# securing cruising behavior
# is need if the path resistance is too high, the vehicle can not cruise at v_reach and is getting slower
s_cruisingMax=movingSection.characteristicSections[csId].s_end-accelerationCourse[end].s
if s_cruisingMax>0.0
(movingSection.characteristicSections[csId], accelerationCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], accelerationCourse, s_cruisingMax, settings, vehicle, movingSection.characteristicSections, "cruising")
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, accelerationCourse[end].v)
end
previousCSv_exit=movingSection.characteristicSections[csId].v_exit
# println("CS",csId,": s_start: ",movingSection.characteristicSections[csId].s_start," v_entry: ", round(movingSection.characteristicSections[csId].v_entry*3.6, digits=5), ", v_reach: ", round(movingSection.characteristicSections[csId].v_reach*3.6, digits=5), " v_exit: ", round(movingSection.characteristicSections[csId].v_exit*3.6, digits=5))
end #for
return movingSection
end #function secureAccelerationBehavior!
end #module RailwayDrivingDynamicsPreparation

202
src/types.jl Normal file
View File

@ -0,0 +1,202 @@
module types
# definition of all the additional types and their constructors
export Settings, Vehicle, PathSection, Path, Waypoint, BehaviorSection, CharacteristicSection, EnergySavingModification, MovingSection
## settings for the simulation
mutable struct Settings
massModel::String # model type of the unions mass "mass point" or "homogeneous strip"
stepVariable::String # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize::AbstractFloat # step size (unit depends on steapVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime::Bool # operation mode "minimum running time"
operationModeMinimumEnergyConsumption::Bool # operation mode "minimum energy consumption"
# output:
typeOfOutput::String # output as "julia dictionary" or as "CSV"
csvFolderPath::String # path of the folder in which the CSV fiiles willl be saved
detailOfOutput::String # detail of output "reduced" or "everything"
end # mutable struct Settings
Settings()=Settings("", "", 0.0, false, false, "", "", "")
## vehicle
mutable struct Vehicle
name::String # vehicles name
id # vehicles identifier
vehicleType::String # type of vehicle "passenger" or "freight" or "motor coach train"
l_union::AbstractFloat # total length (in m)
v_limit::AbstractFloat # vehicles speed limit (in m/s)
a_braking::AbstractFloat # braking acceleration (in m/s^2)
m_union::AbstractFloat # total mass (in kg)
ξ_union::AbstractFloat # rotation mass factor of the whole vehicle union (without unit)
# if not available use ξ_t and ξ_w
# traction unit
m_t::AbstractFloat # mass of the traction unit (in kg)
m_td::AbstractFloat # mass on the traction units driving axles (in kg)
m_tc::AbstractFloat # mass on the traction units carrying axles (in kg)
ξ_t::AbstractFloat # rotation mass factor of the traction unit (without unit)
# in case ξ_union is not available
tractiveEffortArray # list values for tractive effort (in [m/s , N])
f_Rtd0::AbstractFloat # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0::AbstractFloat # coefficient for basic resistance due to the traction units carring axles (in ‰)
F_Rt2::AbstractFloat #todo: war mal:forceRT2 # coefficient for air resistance of the traction units (in N)
Δv_t::AbstractFloat # coefficient for velocitiy difference between traction unit and outdoor air
# set of wagons
m_w::AbstractFloat # mass of the set of wagons (in kg)
ξ_w::AbstractFloat # rotation mass factor of the set of wagons (without unit)
# in case ξ_union is not available
f_Rw0::AbstractFloat # coefficient for basic resistance of the set of wagons (in ‰)
f_Rw1::AbstractFloat # coefficient for resistance to rolling of the set of wagons (in ‰)
f_Rw2::AbstractFloat # coefficient for air resistance of the set of wagons (in ‰)
Δv_w::AbstractFloat # coefficient for velocitiy difference between set of wagons and outdoor air (in m/s)
end # mutable struct Vehicle
Vehicle()=Vehicle("", 0, "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
## path separated in smaler sections
struct PathSection
s_start::AbstractFloat # starting point of the section (in m)
s_startNext::AbstractFloat # starting point of the next section (in m)
v_limit::AbstractFloat # paths speed limt (in m/s)
n::AbstractFloat # gradient (in ‰)
# TODO: curve radius
# TODO: turnout
# TODO: tunnel
f_Rp::AbstractFloat # specific path resistance of the section (in ‰)
end # struct pathSection
PathSection()=(0.0, 0.0, 0.0, 0.0, 0.0)
struct Path
name::String # paths name
id # paths identifier
sections::Vector{PathSection} # list of PathSection elements
# s_start in firt entry defines the paths beginning
# s_startNext in last entry defines the paths ending
end # struct Path
Path()=("", 0, Vector{PathSection}())
## a waypoint is the smallest element of the driving course. A step of the step approach is between two waypoints
mutable struct Waypoint
i::Integer # identifier and counter variable of the dricing course
s::AbstractFloat # position (in m)
Δs::AbstractFloat # step size (in m)
t::AbstractFloat # point in time (in s)
Δt::AbstractFloat # step size (in s)
v::AbstractFloat # velocity (in m/s)
Δv::AbstractFloat # step size (in m/s)
a::AbstractFloat # acceleration (in m/s^2)
W_T::AbstractFloat # mechanical work (in Ws)
ΔW_T::AbstractFloat # mechanical work in this step (in Ws)
E::AbstractFloat # energy consumption (in Ws)
ΔE::AbstractFloat # energy consumption in this step (in Ws)
F_T::AbstractFloat # tractive effort (in N)
F_R::AbstractFloat # resisting force (in N)
F_Rp::AbstractFloat # line resistanc (in N)
F_Runion::AbstractFloat # vehicle resistance (in N)
F_Rt::AbstractFloat # traction unit resistance (in N)
F_Rw::AbstractFloat # set of wagons resistance (in N)
end # mutable struct Waypoint
Waypoint()=Waypoint(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
Waypoint(original::Waypoint)=Waypoint(original.i, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W_T, original.ΔW_T, original.E, original.ΔE, original.F_T, original.F_R, original.F_Rp, original.F_Runion, original.F_Rt, original.F_Rw)
## different sections the whole path can be devided in the following
## smallest section of the path is the behavior section. It relates to the containing waypoints via their identifier.
mutable struct BehaviorSection
type::String # type of behavior section: "starting", "cruisingBeforeAcceleration", "acceleration", "cruising", "coasting", "cruisingAfterCoasting" or "braking"
s_total::AbstractFloat # total length (in m)
s_start::AbstractFloat # first position (in m)
s_end::AbstractFloat # last position (in m)
t_total::AbstractFloat # total running time (in s)
E_total::AbstractFloat # total energy consumption (in Ws)
v_entry::AbstractFloat # entry speed (in m/s)
v_exit::AbstractFloat # exit speed (in m/s)
waypoints::Vector{Integer} # list of identifiers of the containing waypoints
end # mutable struct BehaviorSection
BehaviorSection()=BehaviorSection("", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [])
function BehaviorSection(original::BehaviorSection)
bsWaypoints=[]
for i in 1:length(original.waypoints)
push!(bsWaypoints, original.waypoints[i])
end
return BehaviorSection(original.type, original.s_total, original.s_start, original.s_end, original.t_total, original.E_total, original.v_entry, original.v_exit, bsWaypoints)
end
## a characteristic section is a part of the moving section. It contains behavior sections.
mutable struct CharacteristicSection
id::Integer # identifier
s_total::AbstractFloat # total length (in m)
s_start::AbstractFloat # first position (in m)
s_end::AbstractFloat # last position (in m)
t_total::AbstractFloat # total running time (in s)
E_total::AbstractFloat # total energy consumption (in Ws)
v_limit::AbstractFloat # speed limit (in m/s)
v_reach::AbstractFloat # maximum reachable speed (in m/s)
v_entry::AbstractFloat # maximum entry speed (in m/s)
v_exit::AbstractFloat # maximum exit speed (in m/s)
f_Rp::AbstractFloat # spedific line resistance (in ‰)
behaviorSections::AbstractDict{String, BehaviorSection} # list of containing behavior sections
end # mutable struct CharacteristicSection
CharacteristicSection()=CharacteristicSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Dict{String, BehaviorSection}())
function CharacteristicSection(original::CharacteristicSection)
copy=CharacteristicSection(original.id, original.s_total, original.s_start, original.s_end, original.t_total, original.E_total, original.v_limit, original.v_reach, original.v_entry, original.v_exit, original.f_Rp, Dict{String, BehaviorSection}())
allBs=["starting", "cruisingBeforeAcceleration","acceleration", "cruising", "coasting","cruisingAfterCoasting", "braking"]
for bs in 1: length(allBs)
if haskey(original.behaviorSections, allBs[bs])
merge!(copy.behaviorSections, Dict(allBs[bs]=>BehaviorSection(get(original.behaviorSections, allBs[bs], BehaviorSection()))))
end #if
end #for
return copy
end #function CharacteristicSection
## for the energy saving operation mode it is nesserary to compare different energy saving modifications. These are part of the moving section.
mutable struct EnergySavingModification
csId::Integer # identifier of the characteristic section
type::String # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
ΔE::AbstractFloat # saved energy (in Ws)
Δt::AbstractFloat # time loss (in s)
ratio::AbstractFloat # ratio of ΔE and Δt (in Ws/s)
csModified::CharacteristicSection # the modified characteristic section
drivingCourseModified::Vector{Waypoint} #drivingCourse for the modified characteristic section
end # mutable struct EnergySavingModification
EnergySavingModification()=EnergySavingModification(0, "", 0.0, 0.0, 0.0, CharacteristicSection(), [])
function EnergySavingModification(original::EnergySavingModification)
copy=EnergySavingModification(original.csId, original.type, original.ΔE, original.Δt, original.ratio, CharacteristicSection(), Waypoint[])
copy.csModified=CharacteristicSection(original.csModified)
for i in 1:length(original.drivingCourseModified)
push!(copy.drivingCourseModified, Waypoint(original.drivingCourseModified[i]))
end
return copy
end #function EnergySavingModification
## a moving section contains all the smaller sections from one stop to an other
mutable struct MovingSection
id # identifier
s_total::AbstractFloat # total length (in m)
s_start::AbstractFloat # first position (in m)
s_end::AbstractFloat # last position (in m)
t_total::AbstractFloat # total running time (in s)
E_total::AbstractFloat # total energy consumption (in Ws)
t_recovery::AbstractFloat # total recovery time for energy-saving modifications (in s)
t_recoveryAvailable::AbstractFloat # still available recovery time for energy-saving modifications (in s)
characteristicSections::Vector{CharacteristicSection} # list of containing characteristic sections
energySavingModifications::Vector{EnergySavingModification} # list of containing all the used energy saving modifications
end # mutable struct MovingSection
MovingSection()=MovingSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [], [])
function MovingSection(original::MovingSection)
copy=MovingSection(original.id, original.s_total, original.s_start, original.s_end, original.t_total, original.E_total, original.t_recovery, original.t_recoveryAvailable, [], [])
for csId in 1:length(original.characteristicSections)
push!(copy.characteristicSections, CharacteristicSection(original.characteristicSections[csId]))
end #for
for modId in 1:length(original.energySavingModifications)
push!(copy.energySavingModifications, EnergySavingModification(original.energySavingModifications[modId]))
end #for
return copy
end #function CharacteristicSection
end #module

70
test/runtests.jl Normal file
View File

@ -0,0 +1,70 @@
# Ausführen im pkg mode mit >>>>> ] test RailwayDrivingDynamics <<<<
using RailwayDrivingDynamics, Test
# das hier waren die zu testenden Funktionen:
#foo(x::T, y::T) where T <: Real = x + y - 5
#bar(z::Float64) = foo(sqrt(z), z)
#=
That file may typically contain calls to other
test files via include(fname). In our case there
is only two functions to test, so we will just
write in runtests.jl directly:
=#
# todo: Beispiel:
#=
@testset "foo" begin
x, y = 5, 7
@test foo(x, y) == 7
x = "blah"
@test_throws MethodError foo(x, y)
end
@testset "bar" begin
z = 4.
@test bar(z) == 1.
end =#
#vehicleFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Fahrzeug- und Streckendaten\\Fahrzeuge\\vehicle_passenger_IC2.yaml"
#vehicleFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Fahrzeug- und Streckendaten\\Fahrzeuge\\vehicle_passenger_SiemensDesiroClassic.yaml"
vehicleFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Fahrzeug- und Streckendaten\\Fahrzeuge\\vehicle_freight_V90withOreConsist.yaml"
#pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Fahrzeug- und Streckendaten\\Strecken\\path_10km_noGradient.yaml"
pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Fahrzeug- und Streckendaten\\Strecken\\path_10km_differentGradient.yaml"
#pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Fahrzeug- und Streckendaten\\Strecken\\path_10km_different_v_limits.yaml"
#pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Fahrzeug- und Streckendaten\\Strecken\\path_real_Ostsachsen_V220_DG-DN_spp_5.yaml"
settingsFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\settings.yaml"
#settingsFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\settings_s.yaml"
testDict=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
println("Vergleichswerte für FBS berechnet")
#=
#pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\track_DAFW_DAFN.yaml"
#pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\test.yaml"
settingsFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\settings.yaml"
testDict=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
vehicleFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\vehicle.yaml"
pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\track_DAFW_DAFN.yaml"
#pathFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\path_Heilbronn.yaml"
settingsFilePath="C:\\Users\\Offline-Konto\\Dateien\\Masterarbeit\\TU-BS_IfEV\\Julia-Files\\settings.yaml"
calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
=#
println("test finished")
# toto: einfach so ausführen geht nicht.
# da muss ich wahrscheilich noch anders importieren oder auf das Modul verweisen?
# Ausführen kann ich es aber auch mit>>>>> test RailwayDrivingDynamics <<<< im pkg mode. Das geht.