new type Path as a struct, working test sets, structure rework
parent
9b00bb8b12
commit
00eda496f5
|
@ -18,12 +18,17 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- '1.6'
|
||||
- '1.7'
|
||||
- 'nightly'
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macOS-latest
|
||||
- windows-latest
|
||||
arch:
|
||||
- x86
|
||||
- x64
|
||||
- aarch64
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: julia-actions/setup-julia@v1
|
||||
|
|
|
@ -15,12 +15,19 @@ Categories: Added, Changed, Deprecated, Removed, Fixed, and Security.
|
|||
|
||||
### Changed
|
||||
* replaced settings::Dict with type Settings as struct
|
||||
* replaced path::Dict with type Path as struct
|
||||
* restructured examples/ and data/ in docs/ and test/
|
||||
* modified test to work with Julia Testsets and with simplier naming of input files
|
||||
* renamed Validate.jl into types.jl
|
||||
* renamed TrainRunCalc.jl into calc.jl
|
||||
* changed tilte of include files from upper case to lower case
|
||||
* moved trainrun function from calc.jl to TrainRun.jl
|
||||
* moved createDataPoint() from behavior.jl to types.jl
|
||||
* moved createBehaviorSection() from behavior.jl to types.jl
|
||||
* moved createMovingSection() from characteristics.jl to types.jl
|
||||
* moved createCharacteristicSection() from characteristics.jl to types.jl
|
||||
* changed title of include files from upper case to lower case
|
||||
* changed seperation of submodules into a single module with file include
|
||||
* updated test files to railtoolkit/schema (2022.04)
|
||||
|
||||
### Removed
|
||||
* dependency Plots
|
||||
|
|
|
@ -5,28 +5,77 @@ email, or any other method with the owners of this repository before making a ch
|
|||
|
||||
Please note we have a code of conduct, please follow it in all your interactions with the project.
|
||||
|
||||
# Julia Development Environment
|
||||
## Julia Development Environment
|
||||
|
||||
Link your local git repository to Julia:
|
||||
```console
|
||||
$ ln -s ~/path/to/TrainRun.jl ~/.julia/dev/TrainRun
|
||||
```
|
||||
|
||||
Have a look here how to develop Julia packages: https://github.com/ShozenD/julia-pkg-dev
|
||||
Have a look how to develop Julia packages: https://github.com/ShozenD/julia-pkg-dev
|
||||
You might want to use `Revise.jl` as well:
|
||||
```julia
|
||||
Pkg.add("Revise")
|
||||
```
|
||||
and then just load with `using Revise` (preferably by putting it in the `~/.julia/config/startup.jl` file)
|
||||
and then just load with `using Revise` (preferably by putting it in the `~/.julia/config/startup.jl` file).
|
||||
|
||||
You can overide the standard TrainRun package with the local development branch (see linking above) with:
|
||||
```julia
|
||||
julia> # use the ] key
|
||||
(@v1.x) pkg> develop TrainRun
|
||||
(@v1.x) pkg> # use backspace
|
||||
julia> using TrainRun # local development branch will be loaded
|
||||
```
|
||||
|
||||
If you want to add a dependency use:
|
||||
```julia
|
||||
julia> # use the ] key
|
||||
(@v1.x) pkg> activate TrainRun
|
||||
(TrainRun) pkg>
|
||||
```
|
||||
|
||||
## TrainRun files
|
||||
|
||||
# Pull Request Process
|
||||
TODO!
|
||||
|
||||
* add your changes to the CHANGELOG.md under [Unreleased]
|
||||
* TODO!
|
||||
## Reporting Issues
|
||||
|
||||
* It's always good to start with a quick search for an existing issue to post on,
|
||||
or related issues for context, before opening a new issue
|
||||
* Including minimal examples is greatly appreciated
|
||||
* If it's a bug, or unexpected behaviour, reproducing on the latest development version
|
||||
(`Pkg.add(name="TrainRun", rev="master")`) is a good gut check and can streamline the process,
|
||||
along with including the first two lines of output from `versioninfo()`
|
||||
|
||||
## Style Guidelines
|
||||
|
||||
TODO
|
||||
|
||||
## Git Recommendations For Pull Requests
|
||||
|
||||
* Avoid working from the `master` branch of your fork, creating a new branch will make it
|
||||
easier if TrainRun.jl `master` branch changes and you need to update your pull request;
|
||||
* All PRs and issues should be opened against the `master` branch not against the current release;
|
||||
* Run tests of your code before sending any commit to GitHub. Only push changes when
|
||||
the tests of the change are passing locally. In particular note that it is not a problem
|
||||
if you send several commits in one push command to GitHub as CI will be run only once then;
|
||||
* If any conflicts arise due to changes in TrainRun.jl `master` branch, prefer updating your pull
|
||||
request branch with `git rebase` (rather than `git merge`), since the latter will introduce a merge
|
||||
commit that might confuse GitHub when displaying the diff of your PR, which makes your changes more
|
||||
difficult to review. Alternatively use conflict resolution tool available at GitHub;
|
||||
* Please try to use descriptive commit messages to simplify the review process;
|
||||
* Using `git add -p` or `git add -i` can be useful to avoid accidently committing unrelated changes;
|
||||
* Maintainers get notified of all changes made on GitHub. However, what is useful is writing a short
|
||||
message after a sequence of changes is made summarizing what has changed and that the PR is ready
|
||||
for a review;
|
||||
* When linking to specific lines of code in discussion of an issue or pull request, hit the `y` key
|
||||
while viewing code on GitHub to reload the page with a URL that includes the specific commit that
|
||||
you're viewing. That way any lines of code that you refer to will still be correct in the future, even
|
||||
if additional commits are pushed to the branch you are reviewing;
|
||||
* Please make sure you follow the code formatting guidelines when submitting a PR;
|
||||
Also preferably do not modify parts of code that you are not editing as this makes
|
||||
reviewing the PR harder (it is better to open a separate maintenance PR
|
||||
if e.g. code layout can be improved);
|
||||
* If a PR is not finished yet and should not be reviewed yet then it should be opened as DRAFT
|
||||
(in this way maintainers will know that they can ignore such PR until it is made non-draft or the author
|
||||
asks for a review).
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name = "TrainRun"
|
||||
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
|
||||
authors = ["Max Kannenberg, Martin Scheidt, and contributors"]
|
||||
authors = ["Max Kannenberg", "Martin Scheidt", "contributors"]
|
||||
version = "0.8.0"
|
||||
|
||||
[deps]
|
||||
|
@ -8,10 +8,15 @@ CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
|||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
JSONSchema = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
|
||||
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
|
||||
|
||||
[compat]
|
||||
julia = "1.7"
|
||||
CSV = "^0"
|
||||
DataFrames = "^1"
|
||||
JSONSchema = "^1"
|
||||
YAML = "^0"
|
||||
julia = "^1.6"
|
||||
|
||||
[extras]
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
|
17
README.md
17
README.md
|
@ -15,27 +15,24 @@ TrainRun.jl is a step towards open science and open data in railway engineering.
|
|||
|
||||
The required julia packages are
|
||||
- YAML.jl
|
||||
- JSONSchema.jl
|
||||
- Dates.jl
|
||||
- DataFrames.jl
|
||||
- CSV.jl
|
||||
- Plots.jl
|
||||
|
||||
Review the settings.yaml file for your appropriate settings.
|
||||
|
||||
------------
|
||||
|
||||
# Minimal working example
|
||||
|
||||
```julia
|
||||
include("../src/TrainRun.jl")
|
||||
using .TrainRun
|
||||
import TrainRun
|
||||
|
||||
train_directory = "data/trains/train_freight_V90withOreConsist.yaml"
|
||||
running_path_directory = "data/paths/path_1_10km_nConst_vConst.yaml"
|
||||
settings_directory = "data/settings.yaml"
|
||||
(train, running_path, settings) = importYamlFiles(train_directory, running_path_directory, setting_directory)
|
||||
train = Train("test/data/trains/freight.yaml")
|
||||
path = Path("test/data/paths/const.yaml")
|
||||
|
||||
train_run = trainRun(train, running_path, settings)
|
||||
runtime = trainrun(train, path)
|
||||
|
||||
println("The train needs $runtime seconds for the running path.")
|
||||
```
|
||||
|
||||
------------
|
||||
|
|
|
@ -22,7 +22,7 @@ for path in paths
|
|||
for train in trains
|
||||
# println("train: ", train[:name])
|
||||
for settings in settings
|
||||
resultsDict = trainRun(train, path, settings)
|
||||
resultsDict = trainrun(train, path, settings)
|
||||
if haskey(settings, :outputFormat) && settings[:outputFormat] == "CSV"
|
||||
exportToCsv(resultsDict, settings)
|
||||
sleep(2)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#!/usr/bin/env julia
|
||||
|
||||
import TrainRun
|
||||
using TrainRun
|
||||
|
||||
train = Train("data/trains/train_freight_V90withOreConsist.yaml")
|
||||
path = Path("data/paths/path_1_10km_nConst_vConst.yaml")
|
||||
train = Train("test/data/trains/freight.yaml")
|
||||
path = Path("test/data/paths/const.yaml")
|
||||
|
||||
runtime = trainRun(train, path)
|
||||
runtime = trainrun(train, path)
|
||||
|
||||
println("The train needs $runtime seconds for the running path.")
|
||||
|
|
|
@ -8,8 +8,14 @@ __precompile__(true)
|
|||
|
||||
module TrainRun
|
||||
|
||||
## loading standard library packages
|
||||
using UUIDs, Dates
|
||||
## loading external packages
|
||||
using YAML, JSONSchema, CSV, DataFrames, Dates
|
||||
using YAML, JSONSchema, CSV, DataFrames
|
||||
|
||||
export
|
||||
## Interface
|
||||
trainrun, Path, Settings, exportToCsv
|
||||
|
||||
## include package files
|
||||
include("types.jl")
|
||||
|
@ -21,10 +27,42 @@ include("import.jl")
|
|||
include("export.jl")
|
||||
include("calc.jl")
|
||||
|
||||
export
|
||||
## Interface
|
||||
trainRun, Settings, exportToCsv
|
||||
## main function
|
||||
"""
|
||||
trainrun(train::Dict, path::Path, settings::Settings)
|
||||
|
||||
## main functions
|
||||
Calculate the running time of a `train` on a `path`.
|
||||
The `settings` provides the choice of models for the calculation.
|
||||
`settings` can be omitted. If so, a default is used.
|
||||
The running time will be return in seconds.
|
||||
|
||||
# Examples
|
||||
```julia-repl
|
||||
julia> trainrun(train, path)
|
||||
xxx.xx # in seconds
|
||||
```
|
||||
"""
|
||||
function trainrun(trainInput::Dict, path::Path, settings=Settings()::Settings)
|
||||
# copy Input data for not changing them
|
||||
# TODO: or should they be changed? normally it would only make it "better" except for settings.outputDetail == :points_of_interest && isempty(path.poi)
|
||||
train = copy(trainInput)
|
||||
|
||||
# check the input data
|
||||
train = checkAndSetTrain!(train)
|
||||
settings.outputDetail == :everything && println("The input has been checked.")
|
||||
|
||||
# prepare the input data
|
||||
movingSection = determineCharacteristics(path, train, settings)
|
||||
settings.outputDetail == :everything && println("The moving section has been prepared.")
|
||||
|
||||
# calculate the train run for oparation mode "minimum running time"
|
||||
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
|
||||
settings.outputDetail == :everything && println("The driving course for the shortest running time has been calculated.")
|
||||
|
||||
# accumulate data and create an output dictionary
|
||||
output = createOutput(train, settings, path, movingSection, drivingCourse)
|
||||
|
||||
return output
|
||||
end # function trainrun
|
||||
|
||||
end # module TrainRun
|
||||
|
|
164
src/behavior.jl
164
src/behavior.jl
|
@ -176,9 +176,12 @@ function getCurrentSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::
|
|||
return currentSpeedLimit
|
||||
end #function getCurrentSpeedLimit
|
||||
|
||||
function getNextPointOfInterest(pointsOfInterest::Vector{Real}, s::Real)
|
||||
"""
|
||||
?
|
||||
"""
|
||||
function getNextPointOfInterest(pointsOfInterest::Vector{Tuple}, s::Real)
|
||||
for s_POI in pointsOfInterest
|
||||
if s_POI > s
|
||||
if s_POI[1] > s
|
||||
return s_POI
|
||||
end
|
||||
end
|
||||
|
@ -327,7 +330,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
while !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached && !previousSpeedLimitReached
|
||||
currentStepSize = settings.stepSize # initialize the step size that can be reduced near intersections
|
||||
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
|
||||
for cycle in 1:settings.approxLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
if !ignoreBraking
|
||||
|
@ -335,7 +338,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
end
|
||||
|
||||
while !targetSpeedReached && !speedLimitReached && !brakingStartReached && !pointOfInterestReached && tractionSurplus && !previousSpeedLimitReached
|
||||
# 03/08 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit
|
||||
# 03/08 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit
|
||||
if drivingCourse[end][:s] >= currentSpeedLimit[:s_end]
|
||||
# could be asked after creating an data point. This way here prevents even a minimal exceedance of speed limit will be noticed. On the other hand the train cruises possibly a little to long
|
||||
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train[:length])
|
||||
|
@ -360,7 +363,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
previousSpeedLimitReached = currentSpeedLimit[:v] < CS[:v_limit] && (drivingCourse[end][:v] > currentSpeedLimit[:v] || (drivingCourse[end][:v] == currentSpeedLimit[:v] && drivingCourse[end][:s] < currentSpeedLimit[:s_end]))
|
||||
targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak]
|
||||
#targetSpeedReached = speedLimitReached
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest # POIs include s_exit as well
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] # POIs include s_exit as well
|
||||
tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
|
||||
end #while
|
||||
|
||||
|
@ -380,10 +383,10 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest[1]) # for testing
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
@ -420,16 +423,16 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_limitCurrent=",currentSpeedLimit[:v]) # for testing
|
||||
break
|
||||
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing
|
||||
if nextPointOfInterest == CS[:s_exit]
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest[1]) # for testing
|
||||
if nextPointOfInterest[1] == CS[:s_exit]
|
||||
endOfCSReached = true
|
||||
end
|
||||
break
|
||||
|
||||
else
|
||||
println("v=",drivingCourse[end][:v]," v_peak= ", CS[:v_peak] , " v_cLimit=", currentSpeedLimit[:v])
|
||||
println("s=" ,drivingCourse[end][:s]," s_exit=", CS[:s_exit], " s+s_braking=", drivingCourse[end][:s] +s_braking," nextPOI=",nextPointOfInterest)
|
||||
println("s=" ,drivingCourse[end][:s]," s_exit=", CS[:s_exit], " s+s_braking=", drivingCourse[end][:s] +s_braking," nextPOI=",nextPointOfInterest[1])
|
||||
println("F_T=",drivingCourse[end][:F_T] ," F_R=", drivingCourse[end][:F_R])
|
||||
|
||||
error("ERROR at accelerating section: With the step variable ",settings.stepVariable," the while loop will be left although v<v_peak and s<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
|
||||
|
@ -467,9 +470,9 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing
|
||||
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
|
||||
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
|
||||
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
|
||||
|
||||
elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
|
||||
|
@ -590,12 +593,12 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
# use the conditions for the cruising section
|
||||
while trainInPreviousCS && !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
|
||||
currentStepSize = settings.stepSize
|
||||
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
nextPointOfInterest[1] = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
|
||||
for cycle in 1:settings.approxLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
while trainInPreviousCS && !targetPositionReached && !pointOfInterestReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
|
||||
# 03/09 old: while drivingCourse[end][:s] < CS[:s_entry] + train[:length] && drivingCourse[end][:s] < BS[:s_entry] +s_cruising && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R]
|
||||
# 03/09 old: while drivingCourse[end][:s] < CS[:s_entry] + train[:length] && drivingCourse[end][:s] < BS[:s_entry] +s_cruising && drivingCourse[end][:s] < nextPointOfInterest[1] && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R]
|
||||
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS
|
||||
#TODO: maybe just consider former CS with different path resistance?
|
||||
# tractive effort (in N):
|
||||
|
@ -629,7 +632,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
#end
|
||||
|
||||
# conditions for the next while cycle
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest # POIs include s_exit as well
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] # POIs include s_exit as well
|
||||
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
|
||||
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising
|
||||
trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train[:length]
|
||||
|
@ -647,9 +650,9 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
elseif trainIsBrakingDownhill && !resistingForceNegative
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
@ -667,7 +670,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
elseif drivingCourse[end][:s] >= CS[:s_entry] + train[:length]
|
||||
break
|
||||
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest[1]
|
||||
break
|
||||
|
||||
elseif !trainInPreviousCS
|
||||
|
@ -689,8 +692,8 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
resistingForceNegative = drivingCourse[end][:F_R] < 0.0
|
||||
|
||||
else # if the level of approximation is reached
|
||||
if drivingCourse[end][:s] > nextPointOfInterest
|
||||
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
|
||||
if drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
|
||||
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
|
||||
elseif drivingCourse[end][:s] > BS[:s_entry]+s_cruising
|
||||
if BS[:type] != "clearing"
|
||||
|
@ -723,7 +726,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
|
||||
while !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
|
||||
# 03/09 old: while drivingCourse[end][:s] < BS[:s_entry]+s_cruising && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
|
||||
nextPointOfInterest = min(BS[:s_entry]+s_cruising, getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]))
|
||||
nextPointOfInterest = min(BS[:s_entry]+s_cruising, getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])[1])
|
||||
|
||||
# tractive effort (in N):
|
||||
#03/25 drivingCourse[end][:F_T] = min(drivingCourse[end][:F_T], max(0.0, drivingCourse[end][:F_R]))
|
||||
|
@ -739,7 +742,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
|
||||
# calculate the remaining cruising way
|
||||
#s_cruisingRemaining=BS[:s_entry] + s_cruising-drivingCourse[end][:s]
|
||||
s_cruisingRemaining = min(nextPointOfInterest -drivingCourse[end][:s], BS[:s_entry] +s_cruising -drivingCourse[end][:s])
|
||||
s_cruisingRemaining = min(nextPointOfInterest[1] -drivingCourse[end][:s], BS[:s_entry] +s_cruising -drivingCourse[end][:s])
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], :distance, s_cruisingRemaining, CS[:id]))
|
||||
|
@ -818,12 +821,12 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
|
||||
while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||
currentStepSize=settings.stepSize # initialize the step size that can be reduced near intersections
|
||||
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])[1]
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
|
||||
for cycle in 1:settings.approxLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
while tractionDeficit && !brakingStartReached && !pointOfInterestReached && !targetSpeedReached
|
||||
# 03/09 old: while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end
|
||||
# 03/09 old: while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1] && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
|
||||
|
||||
|
@ -839,7 +842,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
|
||||
end
|
||||
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
targetSpeedReached = drivingCourse[end][:v] <= 0.0
|
||||
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
|
||||
endOfCSReached = drivingCourse[end][:s] == CS[:s_exit]
|
||||
|
@ -867,10 +870,10 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest[1]) # for testing
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
@ -879,8 +882,8 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing
|
||||
break
|
||||
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest[1]) # for testing
|
||||
break
|
||||
|
||||
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R]
|
||||
|
@ -924,9 +927,9 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
tractionDeficit = true
|
||||
endOfCSReached = false
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing
|
||||
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
|
||||
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
|
||||
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
|
||||
|
||||
elseif drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
|
||||
|
@ -936,7 +939,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
else
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: else with v=", drivingCourse[end][:v]," > 0.0 and F_T=", drivingCourse[end][:F_T]," <= F_R=", drivingCourse[end][:F_R]) # for testing
|
||||
#println(" and s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing
|
||||
#println(" and s=", drivingCourse[end][:s]," <= nextPointOfInterest=",nextPointOfInterest) # for testing
|
||||
#println(" and s=", drivingCourse[end][:s]," <= nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
|
||||
|
||||
# if drivingCourse[end][:s] + s_braking == CS[:s_exit]
|
||||
# brakingStartReached = true
|
||||
|
@ -998,12 +1001,12 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
|
||||
while !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||
currentStepSize=settings.stepSize # initialize the step size that can be reduced near intersections
|
||||
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
nextPointOfInterest[1] = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
|
||||
for cycle in 1:settings.approxLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
while !targetSpeedReached && !brakingStartReached && !pointOfInterestReached
|
||||
# 03/09 old : while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest
|
||||
# 03/09 old : while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1]
|
||||
# traction effort and resisting forces (in N):
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel)
|
||||
|
||||
|
@ -1018,7 +1021,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
# conditions for the next while cycle
|
||||
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
|
||||
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] || drivingCourse[end][:v] > CS[:v_peak]
|
||||
end # while
|
||||
|
||||
|
@ -1030,11 +1033,11 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
|
||||
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
@ -1061,8 +1064,8 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," == v_exit=", CS[:v_exit]) # for testing
|
||||
break
|
||||
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest
|
||||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: s =", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest[1]
|
||||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: s =", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
|
||||
break
|
||||
|
||||
else
|
||||
|
@ -1105,8 +1108,8 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
pointOfInterestReached = false
|
||||
# targetSpeedReached = true
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
|
||||
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
|
||||
else
|
||||
# do nothing for example for drivingCourse[end][:s] + s_braking == CS[:s_exit]
|
||||
|
@ -1156,11 +1159,11 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
while !targetSpeedReached && !endOfCSReached
|
||||
currentStepSize = settings.stepSize # initialize the step size that can be reduced near intersections
|
||||
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
|
||||
for cycle in 1:settings.approxLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
while !targetSpeedReached && !endOfCSReached && !pointOfInterestReached
|
||||
# 03/09 old: while drivingCourse[end][:v] > CS[:v_exit] && !targetSpeedReached && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest
|
||||
# 03/09 old: while drivingCourse[end][:v] > CS[:v_exit] && !targetSpeedReached && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest[1]
|
||||
# traction effort and resisting forces (in N):
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel)
|
||||
|
||||
|
@ -1184,7 +1187,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
#println(drivingCourse[end][:i],". s=",drivingCourse[end][:s]," s_exit=", CS[:s_exit]," v_exit=", CS[:v_exit]," v=",drivingCourse[end][:v])
|
||||
|
||||
# conditions for the next while cycle
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1]
|
||||
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit]
|
||||
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
|
||||
end # while
|
||||
|
@ -1193,14 +1196,14 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
# TODO: is there a better way than rounding like in the following?
|
||||
if cycle < settings.approxLevel+1
|
||||
if drivingCourse[end][:v] < CS[:v_exit]
|
||||
if settings.stepVariable == velocity
|
||||
if settings.stepVariable == :velocity
|
||||
currentStepSize = drivingCourse[end-1][:v] - CS[:v_exit]
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
@ -1217,7 +1220,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
targetSpeedReached = true
|
||||
# println(" with a=", drivingCourse[end-1][:a]) # for testing
|
||||
break
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] == nextPointOfInterest[1]
|
||||
break
|
||||
end
|
||||
|
||||
|
@ -1243,8 +1246,8 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
# recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
|
||||
drivingCourse[end][:s] = CS[:s_exit]
|
||||
break
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest[1]
|
||||
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
|
||||
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
|
||||
break
|
||||
elseif drivingCourse[end][:v] == CS[:v_exit] && drivingCourse[end][:s] == CS[:s_exit]
|
||||
|
@ -1266,7 +1269,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
targetSpeedReached = true
|
||||
break
|
||||
else
|
||||
# do nothing for example for drivingCourse[end][:s]==nextPointOfInterest
|
||||
# do nothing for example for drivingCourse[end][:s]==nextPointOfInterest[1]
|
||||
end
|
||||
end
|
||||
end #for
|
||||
|
@ -1332,47 +1335,6 @@ function mergeBehaviorSection!(BSs::Dict, BS::Dict)
|
|||
return BSs
|
||||
end #function mergeBehaviorSection!
|
||||
|
||||
function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
|
||||
BS= Dict(#:type => behavior, # type of behavior section: breakFree, clearing, accelerating, cruising, diminishing, coasting, braking or standstill
|
||||
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "downhillBraking", "diminishing", "coasting", "braking" or "standstill"
|
||||
:length => 0.0, # total length (in m)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => 0.0, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:v_entry => v_entry, # entry speed (in m/s)
|
||||
:v_exit => 0.0, # exit speed (in m/s)
|
||||
:dataPoints => [startingPoint]) # list of identifiers of the containing data points starting with the initial point
|
||||
return BS
|
||||
end #function createBehaviorSection
|
||||
|
||||
"""
|
||||
a data point is the smallest element of the driving course. One step of the step approach is between two data points
|
||||
"""
|
||||
function createDataPoint()
|
||||
dataPoint = Dict(:i => 0, # identifier and counter variable of the dricing course
|
||||
:behavior => "", # type of behavior section the data point is part of ("breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "standstill")
|
||||
# a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
|
||||
:s => 0.0, # position (in m)
|
||||
:Δs => 0.0, # step size (in m)
|
||||
:t => 0.0, # point in time (in s)
|
||||
:Δt => 0.0, # step size (in s)
|
||||
:v => 0.0, # velocity (in m/s)
|
||||
:Δv => 0.0, # step size (in m/s)
|
||||
:a => 0.0, # acceleration (in m/s^2)
|
||||
:W => 0.0, # mechanical work (in Ws)
|
||||
:ΔW => 0.0, # mechanical work in this step (in Ws)
|
||||
:E => 0.0, # energy consumption (in Ws)
|
||||
:ΔE => 0.0, # energy consumption in this step (in Ws)
|
||||
:F_T => 0.0, # tractive effort (in N)
|
||||
:F_R => 0.0, # resisting force (in N)
|
||||
:R_path => 0.0, # path resistance (in N)
|
||||
:R_train => 0.0, # train resistance (in N)
|
||||
:R_traction => 0.0, # traction unit resistance (in N)
|
||||
:R_wagons => 0.0) # set of wagons resistance (in N)
|
||||
return dataPoint
|
||||
end #function createDataPoint
|
||||
|
||||
function recalculateLastBrakingPoint!(drivingCourse, s_target, v_target)
|
||||
currentPoint = drivingCourse[end]
|
||||
previousPoint = drivingCourse[end-1]
|
||||
|
|
37
src/calc.jl
37
src/calc.jl
|
@ -5,42 +5,7 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
# Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
|
||||
|
||||
"""
|
||||
trainRun(train::Dict, path::Dict, settings::Settings)
|
||||
|
||||
Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding dictionaries `train`, `path`, `settings`.
|
||||
|
||||
# Examples
|
||||
```julia-repl
|
||||
julia> trainRun(trainDict, pathDict)
|
||||
todo !!!
|
||||
```
|
||||
"""
|
||||
function trainRun(trainInput::Dict, pathInput::Dict, settings=Settings()::Settings)
|
||||
# copy Input data for not changing them
|
||||
# TODO: or should they be changed? normally it would only make it "better" except for settings.outputDetail == :points_of_interest && !haskey(path, :pointsOfInterest)
|
||||
train = copy(trainInput)
|
||||
path = copy(pathInput)
|
||||
|
||||
# check the input data
|
||||
(train, path) = checkAndSetInput!(train, path, settings)
|
||||
settings.outputDetail == :everything && println("The input has been checked.")
|
||||
|
||||
# prepare the input data
|
||||
movingSection = determineCharacteristics(path, train, settings)
|
||||
settings.outputDetail == :everything && println("The moving section has been prepared.")
|
||||
|
||||
# calculate the train run for oparation mode "minimum running time"
|
||||
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
|
||||
settings.outputDetail == :everything && println("The driving course for the shortest running time has been calculated.")
|
||||
|
||||
# accumulate data and create an output dictionary
|
||||
output = createOutput(train, settings, path, movingSection, drivingCourse)
|
||||
|
||||
return output
|
||||
end # function trainRun
|
||||
# Calculate the running time of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
|
||||
|
||||
# calculate a train run focussing on using the minimum possible running time
|
||||
function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, train::Dict)
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
# __license__ = "ISC"
|
||||
|
||||
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior
|
||||
function determineCharacteristics(path::Dict, train::Dict, settings::Settings)
|
||||
movingSection = createMovingSection(path, train[:v_limit])
|
||||
function determineCharacteristics(path::Path, train::Dict, settings::Settings)
|
||||
movingSection = createMovingSection(path, train[:v_limit], train[:length])
|
||||
movingSection = secureBrakingBehavior!(movingSection, train[:a_braking])
|
||||
movingSection = secureAcceleratingBehavior!(movingSection, settings, train)
|
||||
#movingSection = secureCruisingBehavior!(movingSection, settings, train)
|
||||
|
@ -15,77 +15,6 @@ function determineCharacteristics(path::Dict, train::Dict, settings::Settings)
|
|||
return movingSection
|
||||
end #function determineCharacteristics
|
||||
|
||||
## create a moving section containing characteristic sections
|
||||
function createMovingSection(path::Dict, v_trainLimit::Real)
|
||||
# this function creates and returns a moving section dependent on the paths attributes
|
||||
|
||||
s_entry = path[:sections][1][:s_start] # first position (in m)
|
||||
s_exit = path[:sections][end][:s_end] # last position (in m)
|
||||
pathLength = s_exit - s_entry # total length (in m)
|
||||
|
||||
CSs=Vector{Dict}()
|
||||
s_csStart=s_entry
|
||||
csId=1
|
||||
for row in 2:length(path[:sections])
|
||||
previousSection = path[:sections][row-1]
|
||||
currentSection = path[:sections][row]
|
||||
speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit)
|
||||
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
|
||||
if speedLimitIsDifferent || pathResistanceIsDifferent
|
||||
# 03/09 old: if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
|
||||
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), path))
|
||||
s_csStart = currentSection[:s_start]
|
||||
csId = csId+1
|
||||
end #if
|
||||
end #for
|
||||
push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][end], min(path[:sections][end][:v_limit], v_trainLimit), path))
|
||||
|
||||
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore
|
||||
:length => pathLength, # total length (in m)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => s_exit, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:characteristicSections => CSs) # list of containing characteristic sections
|
||||
|
||||
return movingSection
|
||||
end #function createMovingSection
|
||||
|
||||
|
||||
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
|
||||
function createCharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, path::Dict)
|
||||
# Create and return a characteristic section dependent on the paths attributes
|
||||
characteristicSection= Dict(:id => id, # identifier
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => section[:s_end], # last position (in m)
|
||||
:length => section[:s_end] -s_entry, # total length (in m)
|
||||
:r_path => section[:f_Rp], # path resistance (in ‰)
|
||||
:behaviorSections => Dict(), # list of containing behavior sections
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:v_limit => v_limit, # speed limit (in m/s)
|
||||
# initializing :v_entry, :v_peak and :v_exit with :v_limit
|
||||
:v_peak => v_limit, # maximum reachable speed (in m/s)
|
||||
:v_entry => v_limit, # maximum entry speed (in m/s)
|
||||
:v_exit => v_limit) # maximum exit speed (in m/s)
|
||||
|
||||
# list of positions of every point of interest (POI) in this charateristic section for which data points should be calculated
|
||||
s_exit = characteristicSection[:s_exit]
|
||||
pointsOfInterest = Vector{Real}()
|
||||
if haskey(path, :pointsOfInterest)
|
||||
for POI in path[:pointsOfInterest]
|
||||
if s_entry < POI && POI < s_exit
|
||||
push!(pointsOfInterest, POI)
|
||||
end
|
||||
end
|
||||
end
|
||||
push!(pointsOfInterest, s_exit) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
|
||||
|
||||
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
|
||||
|
||||
return characteristicSection
|
||||
end #function createCharacteristicSection
|
||||
|
||||
## define the intersection velocities between the characterisitc sections to secure braking behavior
|
||||
function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
|
||||
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
|
||||
|
|
|
@ -5,18 +5,22 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
function createOutput(train::Dict, settings::Settings, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
function createOutput(train::Dict, settings::Settings, path::Path, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
if settings.outputDetail == :running_time
|
||||
output = movingSection[:t] # TODO: or use drivingCourse[end][:t]
|
||||
|
||||
elseif settings.outputDetail == :points_of_interest
|
||||
# add points of interest
|
||||
if haskey(path, :pointsOfInterest)
|
||||
output = Vector{Dict}()
|
||||
if !isempty(path.poi)
|
||||
|
||||
# for elem in 1:length(driving_course)
|
||||
# end
|
||||
|
||||
output = Dict[]
|
||||
POI = 1
|
||||
i = 1
|
||||
while POI <= length(path[:pointsOfInterest]) && i <= drivingCourse[end][:i]
|
||||
if path[:pointsOfInterest][POI] == drivingCourse[i][:s]
|
||||
while POI <= length(path.poi) && i <= drivingCourse[end][:i]
|
||||
if path.poi[POI][:station] == drivingCourse[i][:s]
|
||||
push!(output, drivingCourse[i])
|
||||
POI = POI+1
|
||||
end
|
||||
|
@ -42,12 +46,12 @@ function createOutput(train::Dict, settings::Settings, path::Dict, movingSection
|
|||
end
|
||||
|
||||
# add points of interest
|
||||
if haskey(path, :pointsOfInterest)
|
||||
if !isempty(path.poi)
|
||||
pointsOfInterest = Vector{Dict}()
|
||||
POI = 1
|
||||
i = 1
|
||||
while POI <= length(path[:pointsOfInterest]) && i <= drivingCourse[end][:i]
|
||||
if path[:pointsOfInterest][POI] == drivingCourse[i][:s]
|
||||
while POI <= length(path.poi) && i <= drivingCourse[end][:i]
|
||||
if path.poi[POI] == drivingCourse[i][:s]
|
||||
push!(pointsOfInterest, drivingCourse[i])
|
||||
POI = POI+1
|
||||
end
|
||||
|
@ -67,7 +71,7 @@ function createOutput(train::Dict, settings::Settings, path::Dict, movingSection
|
|||
end
|
||||
|
||||
#=
|
||||
function createOutputDict(train::Dict, settings::Settings, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
function createOutputDict(train::Dict, settings::Settings, path::Path, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
outputDict = Dict{Symbol,Any}()
|
||||
merge!(outputDict, Dict(:train => train, :path => path, :settings => settings))
|
||||
|
||||
|
@ -82,12 +86,12 @@ function createOutputDict(train::Dict, settings::Settings, path::Dict, movingSec
|
|||
end
|
||||
|
||||
# add points of interest
|
||||
if haskey(path, :pointsOfInterest)
|
||||
if !isempty(path.poi)
|
||||
pointsOfInterest = Vector{Dict}()
|
||||
POI = 1
|
||||
i = 1
|
||||
while POI <= length(path[:pointsOfInterest]) && i <= drivingCourse[end][:i]
|
||||
if path[:pointsOfInterest][POI] == drivingCourse[i][:s]
|
||||
while POI <= length(path.poi) && i <= drivingCourse[end][:i]
|
||||
if path.poi[POI] == drivingCourse[i][:s]
|
||||
push!(pointsOfInterest, drivingCourse[i])
|
||||
POI = POI+1
|
||||
end
|
||||
|
|
678
src/types.jl
678
src/types.jl
|
@ -41,7 +41,9 @@ struct Settings
|
|||
outputFormat = :julia_dict
|
||||
outputDir = "."
|
||||
|
||||
## load from file
|
||||
if file != "DEFAULT"
|
||||
|
||||
## JSON schema for YAML-file validation
|
||||
schema = Schema("""{
|
||||
"properties": {
|
||||
|
@ -83,7 +85,7 @@ struct Settings
|
|||
try
|
||||
validate(schema, settings)
|
||||
catch err
|
||||
println("Could not load settings file $file.\n Format is not recognized - using default as fall back.")
|
||||
println("Could not load settings file '$file'.\n Format is not recognized - using default as fall back.")
|
||||
settings = Dict()
|
||||
end
|
||||
|
||||
|
@ -104,18 +106,283 @@ struct Settings
|
|||
end #struct Settings
|
||||
|
||||
"""
|
||||
Read the input information from YAML files for train, path and settings, save it in different dictionaries and return them.
|
||||
"""
|
||||
function checkAndSetInput!(train::Dict, path::Dict, settings::Settings)
|
||||
checkAndSetTrain!(train)
|
||||
checkAndSetPath!(path)
|
||||
Path(file, type = :YAML)
|
||||
|
||||
if settings.outputDetail == :points_of_interest && !haskey(path, :pointsOfInterest)
|
||||
throw(DomainError(settings.outputDetail, "INFO at checking the input for settings and path:\n
|
||||
settings[:outputDetail] is 'points of interest' but the path does not for pointsOfInterest."))
|
||||
Path is a datastruture for calculation context.
|
||||
The function Path() will create a running path for the train.
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> my_path = Path("file.yaml") # will generate a path from a YAML file.
|
||||
Path(variables)
|
||||
```
|
||||
"""
|
||||
struct Path
|
||||
|
||||
name::String # a name or description of the path
|
||||
id::String # a short string as identifier
|
||||
uuid::UUID # a unique identifier
|
||||
poi::Vector # a vector of triples with points along the path
|
||||
sections::Vector # a vector of the characteristic sections
|
||||
|
||||
## constructor
|
||||
function Path(file, type = :YAML)
|
||||
|
||||
## default values
|
||||
name = ""
|
||||
id = ""
|
||||
uuid = UUIDs.uuid4()
|
||||
poi = []
|
||||
sections = []
|
||||
|
||||
## process flags
|
||||
POI_PRESENT = false
|
||||
|
||||
## load from file
|
||||
if type == :YAML
|
||||
|
||||
path = YAML.load(open(file))["path"]
|
||||
|
||||
## JSON schema for YAML-file validation
|
||||
railtoolkit_schema = Schema("""{
|
||||
"required": [ "name", "id", "characteristic_sections" ],
|
||||
"properties": {
|
||||
"characteristic_sections": {
|
||||
"description": "",
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "array",
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"description": "",
|
||||
"prefixItems": [
|
||||
{ "type": "number" },
|
||||
{ "type": "number" },
|
||||
{ "type": "number" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"description": "Identifier of the path",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the path",
|
||||
"type": "string"
|
||||
},
|
||||
"points_of_interest": {
|
||||
"description": "",
|
||||
"type": "array",
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "array",
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"description": "",
|
||||
"prefixItems": [
|
||||
{ "type": "number" },
|
||||
{ "type": "string" },
|
||||
{ "enum": [ "front", "rear" ] }
|
||||
]
|
||||
}
|
||||
},
|
||||
"UUID": {
|
||||
"description": "The unique identifier for a path",
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
}""")
|
||||
|
||||
try
|
||||
validate(railtoolkit_schema, path)
|
||||
catch err
|
||||
error("Could not load path file '$file'.\n
|
||||
YAML format is not recognized.
|
||||
Currently supported: railtoolkit/schema (2022.04)")
|
||||
end
|
||||
return (train, path)
|
||||
end #function checkAndSetInput!
|
||||
|
||||
## set the variables if they exist in "settings"
|
||||
# required
|
||||
name = path["name"]
|
||||
id = path["id"]
|
||||
tmp_sec = path["characteristic_sections"]
|
||||
# optional
|
||||
haskey(path, "UUID") ? uuid = parse(UUID, path["UUID"] ) : nothing
|
||||
haskey(path, "points_of_interest") ? POI_PRESENT = true : nothing
|
||||
haskey(path, "points_of_interest") ? tmp_points = path["points_of_interest"] : nothing
|
||||
|
||||
else
|
||||
error("Unknown file type '$type'")
|
||||
end #if type
|
||||
|
||||
## process characteristic sections
|
||||
sort!(tmp_sec, by = x -> x[1])
|
||||
for row in 2:length(tmp_sec)
|
||||
s_start = tmp_sec[row-1][1] # first point of the section (in m)
|
||||
s_end = tmp_sec[row][1] # first point of the next section (in m)
|
||||
v_limit = tmp_sec[row-1][2]/3.6 # paths speed limt (in m/s)
|
||||
f_Rp = tmp_sec[row-1][3] # specific path resistance of the section (in ‰)
|
||||
|
||||
section = Dict(:s_start => s_start,
|
||||
:s_end => s_end,
|
||||
:v_limit => v_limit,
|
||||
:f_Rp => f_Rp)
|
||||
push!(sections, section)
|
||||
end #for row
|
||||
# s_start in first entry defines the path's beginning
|
||||
# s_end in last entry defines the path's ending
|
||||
|
||||
## process points of interest
|
||||
if POI_PRESENT
|
||||
sort!(tmp_points, by = x -> x[1])
|
||||
for elem in tmp_points
|
||||
station = elem[1] # first point of the section (in m)
|
||||
label = elem[2] # paths speed limt (in m/s)
|
||||
measure = elem[3] # specific path resistance of the section (in ‰)
|
||||
|
||||
point = Dict(:station => station,
|
||||
:label => label,
|
||||
:measure => measure)
|
||||
push!(poi, point)
|
||||
end #for elem
|
||||
end #if !isempty(points)
|
||||
|
||||
new(name, id, uuid, poi, sections)
|
||||
|
||||
end #function Path
|
||||
|
||||
end #struct Path
|
||||
|
||||
"""
|
||||
a DataPoint is the smallest element of the driving course. One step of the step approach is between two data points
|
||||
"""
|
||||
function createDataPoint()
|
||||
dataPoint = Dict(
|
||||
:i => 0, # identifier and counter variable of the driving course
|
||||
:behavior => "", # type of behavior section the data point is part of - see createBehaviorSection()
|
||||
# a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
|
||||
:s => 0.0, # position (in m)
|
||||
:Δs => 0.0, # step size (in m)
|
||||
:t => 0.0, # point in time (in s)
|
||||
:Δt => 0.0, # step size (in s)
|
||||
:v => 0.0, # velocity (in m/s)
|
||||
:Δv => 0.0, # step size (in m/s)
|
||||
:a => 0.0, # acceleration (in m/s^2)
|
||||
:W => 0.0, # mechanical work (in Ws)
|
||||
:ΔW => 0.0, # mechanical work in this step (in Ws)
|
||||
:E => 0.0, # energy consumption (in Ws)
|
||||
:ΔE => 0.0, # energy consumption in this step (in Ws)
|
||||
:F_T => 0.0, # tractive effort (in N)
|
||||
:F_R => 0.0, # resisting force (in N)
|
||||
:R_path => 0.0, # path resistance (in N)
|
||||
:R_train => 0.0, # train resistance (in N)
|
||||
:R_traction => 0.0, # traction unit resistance (in N)
|
||||
:R_wagons => 0.0, # set of wagons resistance (in N)
|
||||
:label => "" # a label for importend points
|
||||
)
|
||||
return dataPoint
|
||||
end #function createDataPoint
|
||||
|
||||
"""
|
||||
BehaviorSection() TODO!
|
||||
"""
|
||||
function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
|
||||
BS= Dict(
|
||||
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "downhillBraking", "diminishing", "coasting", "braking" or "standstill"
|
||||
:length => 0.0, # total length (in m)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => 0.0, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:v_entry => v_entry, # entry speed (in m/s)
|
||||
:v_exit => 0.0, # exit speed (in m/s)
|
||||
:dataPoints => [startingPoint] # list of identifiers of the containing data points starting with the initial point
|
||||
)
|
||||
return BS
|
||||
end #function createBehaviorSection
|
||||
|
||||
## create a moving section containing characteristic sections
|
||||
function createMovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real)
|
||||
# this function creates and returns a moving section dependent on the paths attributes
|
||||
|
||||
s_entry = path.sections[1][:s_start] # first position (in m)
|
||||
s_exit = path.sections[end][:s_end] # last position (in m)
|
||||
pathLength = s_exit - s_entry # total length (in m)
|
||||
|
||||
CSs=Vector{Dict}()
|
||||
s_csStart=s_entry
|
||||
csId=1
|
||||
for row in 2:length(path.sections)
|
||||
previousSection = path.sections[row-1]
|
||||
currentSection = path.sections[row]
|
||||
speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit)
|
||||
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
|
||||
if speedLimitIsDifferent || pathResistanceIsDifferent
|
||||
# 03/09 old: if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
|
||||
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, path))
|
||||
s_csStart = currentSection[:s_start]
|
||||
csId = csId+1
|
||||
end #if
|
||||
end #for
|
||||
push!(CSs, createCharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, path))
|
||||
|
||||
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore
|
||||
:length => pathLength, # total length (in m)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => s_exit, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:characteristicSections => CSs) # list of containing characteristic sections
|
||||
|
||||
return movingSection
|
||||
end #function createMovingSection
|
||||
|
||||
|
||||
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
|
||||
function createCharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, path::Path)
|
||||
# Create and return a characteristic section dependent on the paths attributes
|
||||
characteristicSection= Dict(:id => id, # identifier
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => section[:s_end], # last position (in m)
|
||||
:length => section[:s_end] -s_entry, # total length (in m)
|
||||
:r_path => section[:f_Rp], # path resistance (in ‰)
|
||||
:behaviorSections => Dict(), # list of containing behavior sections
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:v_limit => v_limit, # speed limit (in m/s)
|
||||
# initializing :v_entry, :v_peak and :v_exit with :v_limit
|
||||
:v_peak => v_limit, # maximum reachable speed (in m/s)
|
||||
:v_entry => v_limit, # maximum entry speed (in m/s)
|
||||
:v_exit => v_limit) # maximum exit speed (in m/s)
|
||||
|
||||
# list of positions of every point of interest (POI) in this charateristic section for which data points should be calculated
|
||||
s_exit = characteristicSection[:s_exit]
|
||||
|
||||
##TODO: use a tuple with naming
|
||||
pointsOfInterest = Tuple[]
|
||||
# pointsOfInterest = Real[]
|
||||
if !isempty(path.poi)
|
||||
for POI in path.poi
|
||||
s_poi = POI[:station]
|
||||
if POI[:measure] == "rear"
|
||||
s_poi -= s_trainLength
|
||||
end
|
||||
if s_entry < s_poi && s_poi < s_exit
|
||||
push!(pointsOfInterest, (s_poi, POI[:label]) )
|
||||
# push!(pointsOfInterest, s_poi )
|
||||
end
|
||||
end
|
||||
end
|
||||
push!(pointsOfInterest, (s_exit,"")) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
|
||||
# push!(pointsOfInterest, s_exit) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
|
||||
|
||||
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
|
||||
|
||||
return characteristicSection
|
||||
end #function createCharacteristicSection
|
||||
|
||||
"""
|
||||
Read the train information from a YAML file, save it in a train Dict and return it.
|
||||
|
@ -174,7 +441,7 @@ function checkAndSetTrain!(train::Dict)
|
|||
return train
|
||||
end #function checkAndSetTrain!
|
||||
|
||||
function checkAndSetPath!(path::Dict)
|
||||
function checkAndSetPath!(path::Path)
|
||||
# check path information from input dictionary
|
||||
|
||||
checkAndSetString!(path, "path", :name, "")
|
||||
|
@ -561,217 +828,220 @@ function getDefault_Δv_w(type::String) # coefficient for velocitiy differen
|
|||
return Δv_w
|
||||
end #function getDefault_Δv_w!
|
||||
|
||||
function checkAndSetSections!(path::Dict)
|
||||
# check the section information
|
||||
if haskey(path,:sections) && path[:sections]!=nothing
|
||||
# TODO: check typeof(path[:sections]) == Dict
|
||||
if (haskey(path, :sectionStarts) && path[:sectionStarts]!=nothing) && (haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing)
|
||||
println("WARNING at checking the input for the path: There are values for sections, sectionStarts and sectionStarts_kmh. The dictionary sections is used." )
|
||||
# function checkAndSetSections!(path::Path)
|
||||
# # check the section information
|
||||
# if haskey(path,:sections) && path.sections!=nothing
|
||||
# # TODO: check typeof(path.sections) == Dict
|
||||
# if (haskey(path, :sectionStarts) && path[:sectionStarts]!=nothing) && (haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing)
|
||||
# println("WARNING at checking the input for the path: There are values for sections, sectionStarts and sectionStarts_kmh. The dictionary sections is used." )
|
||||
|
||||
elseif haskey(path,:sectionStarts) && path[:sectionStarts]!=nothing
|
||||
println("WARNING at checking the input for the path: There are values for sections and sectionStarts. The dictionary sections is used." )
|
||||
# elseif haskey(path,:sectionStarts) && path[:sectionStarts]!=nothing
|
||||
# println("WARNING at checking the input for the path: There are values for sections and sectionStarts. The dictionary sections is used." )
|
||||
|
||||
elseif haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
|
||||
println("WARNING at checking the input for the path: There are values for sections and sectionStarts_kmh. The dictionary sections is used." )
|
||||
end
|
||||
elseif haskey(path,:sectionStarts) && path[:sectionStarts]!=nothing
|
||||
# TODO: check typeof(path[:sections]) == Array
|
||||
createSections!(path, :sectionStarts)
|
||||
|
||||
if haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
|
||||
println("WARNING at checking the input for the path: There are values for sectionStarts and sectionStarts_kmh. The array sectionStarts is used." )
|
||||
end
|
||||
elseif haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
|
||||
# TODO: check typeof(path[:sections]) == Array
|
||||
createSections!(path, :sectionStarts_kmh)
|
||||
else
|
||||
error("ERROR at checking the input for the path: The Symbol :sections is missing. It has to be added with a list of sections. Each has to be a dictionary with the keys :s_tart, :s_end, :v_limit and :f_Rp.")
|
||||
section = Dict(:s_start => 0.0,
|
||||
:s_end => 15.0,
|
||||
:v_limit => 1000.0/3.6,
|
||||
:f_Rp => 0.0)
|
||||
merge!(path, Dict(:sections => [section]))
|
||||
return path
|
||||
end
|
||||
|
||||
sections = path[:sections]
|
||||
|
||||
checkedSections = []
|
||||
increasing = false
|
||||
decreasing = false
|
||||
|
||||
#TODO: throw error for each issue or collect the issues and use the Bool errorDetected like in createSections?
|
||||
|
||||
# check values for section==1
|
||||
checkAndSetRealNumber!(sections[1], "path[:sections][1]", :s_start, "m", 0.0) # first point of the section (in m)
|
||||
checkAndSetRealNumber!(sections[1], "path[:sections][1]", :s_end, "m", 0.0) # first point of the next section (in m)
|
||||
checkAndSetPositiveNumber!(sections[1], "path[:sections][1]", :v_limit, "m/s", 1000.0/3.6) # paths speed limt (in m/s)
|
||||
checkAndSetRealNumber!(sections[1], "path[:sections][1]", :f_Rp, "‰", 0.0) # specific path resistance of the section (in ‰)
|
||||
|
||||
push!(checkedSections, sections[1])
|
||||
|
||||
if sections[1][:s_start] < sections[1][:s_end]
|
||||
increasing = true
|
||||
elseif sections[1][:s_start] > sections[1][:s_end]
|
||||
decreasing = true
|
||||
else
|
||||
pop!(checkedSections)
|
||||
println("WARNING at checking the input for the path: The first section of :sections has the same position for starting and end point. The section will be deleted and not used in the tool.")
|
||||
end
|
||||
|
||||
|
||||
for sectionNr in 2:length(sections)
|
||||
checkAndSetRealNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :s_start, "m", sections[sectionNr-1][:s_end]) # first point of the section (in m)
|
||||
# TODO how to define default values? which has to be checked and defined fist? s_end-1 and s_start need each other as default values
|
||||
#if sectionNr < length(sections) && haskey(sections[sectionNr], :s_start) && sections[sectionNr][:s_start]!=nothing && typeof(sections[sectionNr][:s_start]) <: Real
|
||||
# defaultEnd = sections[sectionNr+1][:s_start]
|
||||
# elseif haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
|
||||
# println("WARNING at checking the input for the path: There are values for sections and sectionStarts_kmh. The dictionary sections is used." )
|
||||
# end
|
||||
defaultEnd = sections[sectionNr][:s_start] # so the default value for s_end creates a sections of lenght=0.0 #TODO should be changed!
|
||||
checkAndSetRealNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :s_end, "m", defaultEnd) # first point of the next section (in m)
|
||||
checkAndSetPositiveNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :v_limit, "m/s", 1000.0/3.6) # paths speed limt (in m/s)
|
||||
checkAndSetRealNumber!(sections[sectionNr], "path[:sections]["*string(sectionNr)*"]", :f_Rp, "‰", 0.0) # specific path resistance of the section (in ‰)
|
||||
# elseif haskey(path,:sectionStarts) && path[:sectionStarts]!=nothing
|
||||
# # TODO: check typeof(path.sections) == Array
|
||||
# createSections!(path, :sectionStarts)
|
||||
|
||||
push!(checkedSections, sections[sectionNr])
|
||||
# if haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
|
||||
# println("WARNING at checking the input for the path: There are values for sectionStarts and sectionStarts_kmh. The array sectionStarts is used." )
|
||||
# end
|
||||
# elseif haskey(path,:sectionStarts_kmh) && path[:sectionStarts_kmh]!=nothing
|
||||
# # TODO: check typeof(path.sections) == Array
|
||||
# createSections!(path, :sectionStarts_kmh)
|
||||
# else
|
||||
# error("ERROR at checking the input for the path: The Symbol :sections is missing. It has to be added with a list of sections. Each has to be a dictionary with the keys :s_tart, :s_end, :v_limit and :f_Rp.")
|
||||
# section = Dict(:s_start => 0.0,
|
||||
# :s_end => 15.0,
|
||||
# :v_limit => 1000.0/3.6,
|
||||
# :f_Rp => 0.0)
|
||||
# merge!(path, Dict(:sections => [section]))
|
||||
# return path
|
||||
# end
|
||||
|
||||
# compare the section's start and end position
|
||||
if sections[sectionNr][:s_start] < sections[sectionNr][:s_end]
|
||||
increasing = true
|
||||
elseif sections[sectionNr][:s_start] > sections[sectionNr][:s_end]
|
||||
decreasing = true
|
||||
else
|
||||
pop!(checkedSections)
|
||||
println("INFO at checking the input for the path: The ",sectionNr,". section of :sections has the same position for starting and end point. The section will be deleted and not used in the tool.")
|
||||
end
|
||||
if increasing && decreasing
|
||||
error("ERROR at checking the input for the path: The positions of the :sections are not increasing/decreasing consistently. The direction in the ",sectionNr,". section differs from the previous.")
|
||||
end
|
||||
# sections = path.sections
|
||||
|
||||
# checkedSections = []
|
||||
# increasing = false
|
||||
# decreasing = false
|
||||
|
||||
# #TODO: throw error for each issue or collect the issues and use the Bool errorDetected like in createSections?
|
||||
|
||||
# # check values for section==1
|
||||
# checkAndSetRealNumber!(sections[1], "path.sections[1]", :s_start, "m", 0.0) # first point of the section (in m)
|
||||
# checkAndSetRealNumber!(sections[1], "path.sections[1]", :s_end, "m", 0.0) # first point of the next section (in m)
|
||||
# checkAndSetPositiveNumber!(sections[1], "path.sections[1]", :v_limit, "m/s", 1000.0/3.6) # paths speed limt (in m/s)
|
||||
# checkAndSetRealNumber!(sections[1], "path.sections[1]", :f_Rp, "‰", 0.0) # specific path resistance of the section (in ‰)
|
||||
|
||||
# push!(checkedSections, sections[1])
|
||||
|
||||
# if sections[1][:s_start] < sections[1][:s_end]
|
||||
# increasing = true
|
||||
# elseif sections[1][:s_start] > sections[1][:s_end]
|
||||
# decreasing = true
|
||||
# else
|
||||
# pop!(checkedSections)
|
||||
# println("WARNING at checking the input for the path: The first section of :sections has the same position for starting and end point. The section will be deleted and not used in the tool.")
|
||||
# end
|
||||
|
||||
|
||||
if length(checkedSections)>1 && sections[sectionNr][:s_start] != checkedSections[end-1][:s_end]
|
||||
error("ERROR at checking the input for the path[:sections]: The starting position of the ",section,". section (s=",sections[sectionNr][:s_start]," m) does not euqal the last position of the previous section(s=",checkedSections[end-1][:s_end]," m). The sections have to be sequential.")
|
||||
# TODO: maybe if there is a gab create a new section and only if there a jumps in the wrong direction throw an error?
|
||||
end
|
||||
end #for
|
||||
# for sectionNr in 2:length(sections)
|
||||
# checkAndSetRealNumber!(sections[sectionNr], "path.sections["*string(sectionNr)*"]", :s_start, "m", sections[sectionNr-1][:s_end]) # first point of the section (in m)
|
||||
# # TODO how to define default values? which has to be checked and defined fist? s_end-1 and s_start need each other as default values
|
||||
# #if sectionNr < length(sections) && haskey(sections[sectionNr], :s_start) && sections[sectionNr][:s_start]!=nothing && typeof(sections[sectionNr][:s_start]) <: Real
|
||||
# # defaultEnd = sections[sectionNr+1][:s_start]
|
||||
# #end
|
||||
# defaultEnd = sections[sectionNr][:s_start] # so the default value for s_end creates a sections of lenght=0.0 #TODO should be changed!
|
||||
# checkAndSetRealNumber!(sections[sectionNr], "path.sections["*string(sectionNr)*"]", :s_end, "m", defaultEnd) # first point of the next section (in m)
|
||||
# checkAndSetPositiveNumber!(sections[sectionNr], "path.sections["*string(sectionNr)*"]", :v_limit, "m/s", 1000.0/3.6) # paths speed limt (in m/s)
|
||||
# checkAndSetRealNumber!(sections[sectionNr], "path.sections["*string(sectionNr)*"]", :f_Rp, "‰", 0.0) # specific path resistance of the section (in ‰)
|
||||
|
||||
return path
|
||||
end #function checkAndSetSections!
|
||||
# push!(checkedSections, sections[sectionNr])
|
||||
|
||||
function createSections!(path::Dict, key::Symbol)
|
||||
# read the section starting positions and corresponding information
|
||||
if key == :sectionStarts
|
||||
sectionStartsArray = path[:sectionStarts]
|
||||
conversionFactor = 1.0 # conversion factor between the units m/s and m/s
|
||||
|
||||
if haskey(path,:sectionStarts) && path[:sectionStarts_kmh]!=nothing
|
||||
println("WARNING at checking the input for the path: There are values for sectionStarts and sectionStarts_kmh. The values for sectionStarts are used." )
|
||||
end
|
||||
elseif key == :sectionStarts_kmh
|
||||
sectionStartsArray = path[:sectionStarts_kmh]
|
||||
conversionFactor = 1/3.6 # conversion factor between the units km/h and m/s
|
||||
else
|
||||
error("ERROR at checking the input for the path: The keyword sectionStarts or sectionStarts_kmh is missing. The sections can not be created without them.")
|
||||
end # if
|
||||
|
||||
# check if the array is correct and if elements of the array have the correct type and valid values
|
||||
errorDetected = false
|
||||
if length(sectionStartsArray)<2
|
||||
error("ERROR at checking the input for the path: The keyword ",key," needs at least two rows for two points each with the three columns [s, v_limit, f_Rp].")
|
||||
end
|
||||
|
||||
for row in 1:length(sectionStartsArray)
|
||||
if length(sectionStartsArray[row])>=3
|
||||
if length(sectionStartsArray[row])>3
|
||||
println("INFO at checking the input for the path: Only the first three columns of sectionStartsArray are used in this tool.")
|
||||
end
|
||||
else
|
||||
error("ERROR at checking the input for the path: The keyword ",key," needs to be filled with the three columns [s, v_limit, f_Rp].")
|
||||
end
|
||||
|
||||
if !(typeof(sectionStartsArray[row][1]) <: Real)
|
||||
errorDetected=true
|
||||
println("ERROR at checking the input for the path: The position value (column 1) of ",key," in row ", row ," is no real floating point number.")
|
||||
end
|
||||
if !(typeof(sectionStartsArray[row][2]) <: Real && sectionStartsArray[row][2] >= 0.0)
|
||||
errorDetected=true
|
||||
println("ERROR at checking the input for the path: The speed limit (column 2) of ",key," in row ", row ," is no real floating point number >=0.0.")
|
||||
end
|
||||
if !(typeof(sectionStartsArray[row][3]) <: Real)
|
||||
errorDetected=true
|
||||
println("ERROR at checking the input for the path: The tractive effort value (column 3) of ",key," in row ", row ," is no real floating point number.")
|
||||
end
|
||||
end # for
|
||||
if errorDetected
|
||||
error("ERROR at checking the input for the path: The values of ",key," have to be corrected.")
|
||||
end
|
||||
# # compare the section's start and end position
|
||||
# if sections[sectionNr][:s_start] < sections[sectionNr][:s_end]
|
||||
# increasing = true
|
||||
# elseif sections[sectionNr][:s_start] > sections[sectionNr][:s_end]
|
||||
# decreasing = true
|
||||
# else
|
||||
# pop!(checkedSections)
|
||||
# println("INFO at checking the input for the path: The ",sectionNr,". section of :sections has the same position for starting and end point. The section will be deleted and not used in the tool.")
|
||||
# end
|
||||
# if increasing && decreasing
|
||||
# error("ERROR at checking the input for the path: The positions of the :sections are not increasing/decreasing consistently. The direction in the ",sectionNr,". section differs from the previous.")
|
||||
# end
|
||||
|
||||
|
||||
sections = []
|
||||
for row in 2:length(sectionStartsArray)
|
||||
s_start = sectionStartsArray[row-1][1] # first point of the section (in m)
|
||||
s_end = sectionStartsArray[row][1] # first point of the next section (in m)
|
||||
v_limit = sectionStartsArray[row-1][2]*conversionFactor # paths speed limt (in m/s)
|
||||
f_Rp = sectionStartsArray[row-1][3] # specific path resistance of the section (in ‰)
|
||||
# if length(checkedSections)>1 && sections[sectionNr][:s_start] != checkedSections[end-1][:s_end]
|
||||
# error("ERROR at checking the input for the path.sections: The starting position of the ",section,". section (s=",sections[sectionNr][:s_start]," m) does not euqal the last position of the previous section(s=",checkedSections[end-1][:s_end]," m). The sections have to be sequential.")
|
||||
# # TODO: maybe if there is a gab create a new section and only if there a jumps in the wrong direction throw an error?
|
||||
# end
|
||||
# end #for
|
||||
|
||||
section = Dict(:s_start => s_start,
|
||||
:s_end => s_end,
|
||||
:v_limit => v_limit,
|
||||
:f_Rp => f_Rp)
|
||||
push!(sections, section)
|
||||
end # for
|
||||
# s_start in first entry defines the path's beginning
|
||||
# s_end in last entry defines the path's ending
|
||||
# return path
|
||||
# end #function checkAndSetSections!
|
||||
|
||||
merge!(path, Dict(:sections => sections))
|
||||
return path
|
||||
end #function createSections!
|
||||
# function createSections!(path::Path, key::Symbol)
|
||||
# # read the section starting positions and corresponding information
|
||||
# if key == :sectionStarts
|
||||
# sectionStartsArray = path[:sectionStarts]
|
||||
# conversionFactor = 1.0 # conversion factor between the units m/s and m/s
|
||||
|
||||
function checkAndSetPOIs!(path::Dict)
|
||||
# read the section starting positions and corresponding information
|
||||
if haskey(path, :pointsOfInterest)
|
||||
if path[:pointsOfInterest] != nothing
|
||||
pointsOfInterest = path[:pointsOfInterest]
|
||||
# if haskey(path,:sectionStarts) && path[:sectionStarts_kmh]!=nothing
|
||||
# println("WARNING at checking the input for the path: There are values for sectionStarts and sectionStarts_kmh. The values for sectionStarts are used." )
|
||||
# end
|
||||
# elseif key == :sectionStarts_kmh
|
||||
# sectionStartsArray = path[:sectionStarts_kmh]
|
||||
# conversionFactor = 1/3.6 # conversion factor between the units km/h and m/s
|
||||
# elseif key == :characteristic_sections
|
||||
# sectionStartsArray = path[:characteristic_sections]
|
||||
# conversionFactor = 1/3.6 # conversion factor between the units km/h and m/s
|
||||
# else
|
||||
# error("ERROR at checking the input for the path: The keyword sectionStarts or sectionStarts_kmh is missing. The sections can not be created without them.")
|
||||
# end # if
|
||||
|
||||
sortingNeeded = false
|
||||
errorDetected = false
|
||||
for element in 1:length(pointsOfInterest)
|
||||
if typeof(pointsOfInterest[element]) <: Real
|
||||
if element > 1
|
||||
if pointsOfInterest[element] < pointsOfInterest[element-1]
|
||||
sortingNeeded = true
|
||||
println("INFO at checking the input for the path: The point of interest in element ", element ," (",pointsOfInterest[element]," m) has to be higher than the value of the previous element (",pointsOfInterest[element-1]," m). The points of interest will be sorted.")
|
||||
end
|
||||
end
|
||||
else
|
||||
errorDetected = true
|
||||
println("ERROR at checking the input for the path: The point of interest in element ", element ," is no real floating point number.")
|
||||
end
|
||||
end # for
|
||||
# # check if the array is correct and if elements of the array have the correct type and valid values
|
||||
# errorDetected = false
|
||||
# if length(sectionStartsArray)<2
|
||||
# error("ERROR at checking the input for the path: The keyword ",key," needs at least two rows for two points each with the three columns [s, v_limit, f_Rp].")
|
||||
# end
|
||||
|
||||
if errorDetected
|
||||
error("ERROR at checking the input for the path: The values of pointsOfInterest have to be corrected.")
|
||||
end
|
||||
if sortingNeeded == true
|
||||
sort!(pointsOfInterest)
|
||||
end
|
||||
# for row in 1:length(sectionStartsArray)
|
||||
# if length(sectionStartsArray[row])>=3
|
||||
# if length(sectionStartsArray[row])>3
|
||||
# println("INFO at checking the input for the path: Only the first three columns of sectionStartsArray are used in this tool.")
|
||||
# end
|
||||
# else
|
||||
# error("ERROR at checking the input for the path: The keyword ",key," needs to be filled with the three columns [s, v_limit, f_Rp].")
|
||||
# end
|
||||
|
||||
copiedPOIs = []
|
||||
for element in 1:length(pointsOfInterest)
|
||||
if element == 1
|
||||
push!(copiedPOIs, pointsOfInterest[element])
|
||||
elseif element > 1 && pointsOfInterest[element] > pointsOfInterest[element-1]
|
||||
push!(copiedPOIs, pointsOfInterest[element])
|
||||
end
|
||||
end # for
|
||||
path[:pointsOfInterest] = copiedPOIs
|
||||
# if !(typeof(sectionStartsArray[row][1]) <: Real)
|
||||
# errorDetected=true
|
||||
# println("ERROR at checking the input for the path: The position value (column 1) of ",key," in row ", row ," is no real floating point number.")
|
||||
# end
|
||||
# if !(typeof(sectionStartsArray[row][2]) <: Real && sectionStartsArray[row][2] >= 0.0)
|
||||
# errorDetected=true
|
||||
# println("ERROR at checking the input for the path: The speed limit (column 2) of ",key," in row ", row ," is no real floating point number >=0.0.")
|
||||
# end
|
||||
# if !(typeof(sectionStartsArray[row][3]) <: Real)
|
||||
# errorDetected=true
|
||||
# println("ERROR at checking the input for the path: The tractive effort value (column 3) of ",key," in row ", row ," is no real floating point number.")
|
||||
# end
|
||||
# end # for
|
||||
# if errorDetected
|
||||
# error("ERROR at checking the input for the path: The values of ",key," have to be corrected.")
|
||||
# end
|
||||
|
||||
else
|
||||
println("INFO at checking the input for the path: The key pointsOfInterest exists but without values.")
|
||||
delete!(path, :pointsOfInterest)
|
||||
end
|
||||
end
|
||||
|
||||
return path
|
||||
end #function checkAndSetPOIs!
|
||||
# sections = []
|
||||
# for row in 2:length(sectionStartsArray)
|
||||
# s_start = sectionStartsArray[row-1][1] # first point of the section (in m)
|
||||
# s_end = sectionStartsArray[row][1] # first point of the next section (in m)
|
||||
# v_limit = sectionStartsArray[row-1][2]*conversionFactor # paths speed limt (in m/s)
|
||||
# f_Rp = sectionStartsArray[row-1][3] # specific path resistance of the section (in ‰)
|
||||
|
||||
# section = Dict(:s_start => s_start,
|
||||
# :s_end => s_end,
|
||||
# :v_limit => v_limit,
|
||||
# :f_Rp => f_Rp)
|
||||
# push!(sections, section)
|
||||
# end # for
|
||||
# # s_start in first entry defines the path's beginning
|
||||
# # s_end in last entry defines the path's ending
|
||||
|
||||
# merge!(path, Dict(:sections => sections))
|
||||
# return path
|
||||
# end #function createSections!
|
||||
|
||||
# function checkAndSetPOIs!(path::Path)
|
||||
# # read the section starting positions and corresponding information
|
||||
# if haskey(path, :pointsOfInterest)
|
||||
# # if path.poi != nothing
|
||||
# pointsOfInterest = path[:points_of_interest]
|
||||
|
||||
# sortingNeeded = false
|
||||
# errorDetected = false
|
||||
# for element in 1:length(pointsOfInterest)
|
||||
# if typeof(pointsOfInterest[element]) <: Real
|
||||
# if element > 1
|
||||
# if pointsOfInterest[element] < pointsOfInterest[element-1]
|
||||
# sortingNeeded = true
|
||||
# println("INFO at checking the input for the path: The point of interest in element ", element ," (",pointsOfInterest[element]," m) has to be higher than the value of the previous element (",pointsOfInterest[element-1]," m). The points of interest will be sorted.")
|
||||
# end
|
||||
# end
|
||||
# else
|
||||
# errorDetected = true
|
||||
# println("ERROR at checking the input for the path: The point of interest in element ", element ," is no real floating point number.")
|
||||
# end
|
||||
# end # for
|
||||
|
||||
# if errorDetected
|
||||
# error("ERROR at checking the input for the path: The values of pointsOfInterest have to be corrected.")
|
||||
# end
|
||||
# if sortingNeeded == true
|
||||
# sort!(pointsOfInterest)
|
||||
# end
|
||||
|
||||
# copiedPOIs = []
|
||||
# for element in 1:length(pointsOfInterest)
|
||||
# if element == 1
|
||||
# push!(copiedPOIs, pointsOfInterest[element])
|
||||
# elseif element > 1 && pointsOfInterest[element] > pointsOfInterest[element-1]
|
||||
# push!(copiedPOIs, pointsOfInterest[element])
|
||||
# end
|
||||
# end # for
|
||||
# path[:points_of_interest ] = copiedPOIs
|
||||
|
||||
# # else
|
||||
# # println("INFO at checking the input for the path: The key pointsOfInterest exists but without values.")
|
||||
# # delete!(path, :points_of_interest)
|
||||
# # end
|
||||
# end
|
||||
|
||||
# return path
|
||||
# end #function checkAndSetPOIs!
|
||||
|
||||
#function informAboutUnusedKeys(dictionary::Dict, dictionaryType::String) # inform the user which Symbols of the input dictionary are not used in this tool
|
||||
function informAboutUnusedKeys(allKeys::AbstractVector, usedKeys::Vector{Symbol}, dictionaryType::String) # inform the user which Symbols of the input dictionary are not used in this tool
|
||||
|
|
|
@ -2,8 +2,18 @@
|
|||
---
|
||||
path:
|
||||
name: "10 km, no gradient, 160 km/h"
|
||||
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
|
||||
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
|
||||
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
|
||||
- [0, 160, 0]
|
||||
- [10000, 160, 0]
|
||||
id: const
|
||||
UUID: 23ff336e-9b9a-4535-bdb6-9db488b10945
|
||||
points_of_interest:
|
||||
# [ station in m, name, front or rear ]
|
||||
- [ 999.00, point_1, front ]
|
||||
- [ 2000.00, point_2, front ]
|
||||
- [ 3333.30, point_3, rear ]
|
||||
- [ 5000.00, point_4, front ]
|
||||
- [ 7777.00, point_5, front ]
|
||||
- [ 9000.00, point_6, front ]
|
||||
- [ 9500.95, point_7, front ]
|
||||
characteristic_sections:
|
||||
# [ station in m, speed limit in km/h, resistance in ‰ ]
|
||||
- [ 0.0, 160, 0.00 ]
|
||||
- [ 10000.0, 160, 0.00 ]
|
||||
|
|
|
@ -2,25 +2,31 @@
|
|||
---
|
||||
path:
|
||||
name: "'infra_Ostsachsen': track id='tr_80.6212_2' name='DG-DN' -> spp_5"
|
||||
# source: https://www.railml.org/en/user/exampledata.html -> "Real world railway examples from professional tools" -> "East Saxony railway network by FBS" -> "Ostsachsen_V220.railml" -> 'infra_Ostsachsen': track id='tr_80.6212_2' name='DG-DN' -> spp_5
|
||||
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
|
||||
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
|
||||
- [0.0, 40, 0]
|
||||
- [318.0, 40, 2]
|
||||
- [399.0, 40, -3]
|
||||
- [500.0, 40, 0]
|
||||
- [579.0, 40, 1]
|
||||
id: realworld
|
||||
UUID: 2b31a0c5-85bc-4721-b7e0-66f9df95f7b6
|
||||
# source: https://www.railml.org/en/user/exampledata.html
|
||||
# -> "Real world railway examples from professional tools"
|
||||
# -> "East Saxony railway network by FBS"
|
||||
# -> "Ostsachsen_V220.railml"
|
||||
# -> 'infra_Ostsachsen': track id='tr_80.6212_2' name='DG-DN' -> spp_5
|
||||
characteristic_sections:
|
||||
# [ s in m, v_limit in km/h, f_Rp in ‰ ]
|
||||
- [ 0.0, 40, 0.0 ]
|
||||
- [ 318.0, 40, 2.0 ]
|
||||
- [ 399.0, 40, -3.0 ]
|
||||
- [ 500.0, 40, 0.0 ]
|
||||
- [ 579.0, 40, 1.0 ]
|
||||
- [ 784.0, 40, 5.3 ]
|
||||
- [868.0, 40, 20]
|
||||
- [ 868.0, 40, 20.0 ]
|
||||
- [ 1082.0, 40, 16.1 ]
|
||||
- [ 1287.0, 40, 18.1 ]
|
||||
- [ 1800.0, 110, 18.1 ]
|
||||
- [ 2242.0, 110, 15.4 ]
|
||||
- [3295.0, 110, 11]
|
||||
- [ 3295.0, 110, 11.0 ]
|
||||
- [ 3880.0, 110, 11.1 ]
|
||||
- [ 4680.0, 45, 11.1 ]
|
||||
- [ 4686.0, 90, 11.1 ]
|
||||
- [6122.0, 90, 0]
|
||||
- [ 6122.0, 90, 0.0 ]
|
||||
- [ 6487.0, 90, 1.5 ]
|
||||
- [ 6588.0, 70, 1.5 ]
|
||||
- [ 6589.0, 70, 2.4 ]
|
||||
|
@ -28,12 +34,12 @@ path:
|
|||
- [ 6723.0, 150, 1.3 ]
|
||||
- [ 6928.0, 160, 1.3 ]
|
||||
- [ 7030.0, 160, 7.5 ]
|
||||
- [7300.0, 160, 8]
|
||||
- [7552.0, 160, 5]
|
||||
- [ 7300.0, 160, 8.0 ]
|
||||
- [ 7552.0, 160, 5.0 ]
|
||||
- [ 7675.0, 160, 6.7 ]
|
||||
- [ 7800.0, 160, 7.4 ]
|
||||
- [7920.0, 160, 7]
|
||||
- [8020.0, 140, 7]
|
||||
- [ 7920.0, 160, 7.0 ]
|
||||
- [ 8020.0, 140, 7.0 ]
|
||||
- [ 8100.0, 140, 6.3 ]
|
||||
- [ 8168.0, 140, 7.4 ]
|
||||
- [ 8226.0, 140, 8.4 ]
|
||||
|
@ -42,10 +48,10 @@ path:
|
|||
- [ 8600.0, 150, 7.8 ]
|
||||
- [ 8900.0, 150, 6.7 ]
|
||||
- [ 9100.0, 150, 7.8 ]
|
||||
- [9600.0, 150, 8]
|
||||
- [ 9600.0, 150, 8.0 ]
|
||||
- [ 9845.0, 150, 7.3 ]
|
||||
- [ 10005.0, 160, 7.3 ]
|
||||
- [10600.0, 160, 6]
|
||||
- [ 10600.0, 160, 6.0 ]
|
||||
- [ 10748.0, 160, 7.3 ]
|
||||
- [ 11100.0, 160, 4.5 ]
|
||||
- [ 11280.0, 160, 3.6 ]
|
||||
|
@ -62,7 +68,7 @@ path:
|
|||
- [ 14764.0, 160, -2.8 ]
|
||||
- [ 15000.0, 160, -3.3 ]
|
||||
- [ 15500.0, 160, -0.9 ]
|
||||
- [16000.0, 160, 0]
|
||||
- [ 16000.0, 160, 0.0 ]
|
||||
- [ 16470.0, 160, 1.2 ]
|
||||
- [ 16572.0, 160, 2.2 ]
|
||||
- [ 16700.0, 160, 3.8 ]
|
||||
|
@ -73,21 +79,21 @@ path:
|
|||
- [ 17406.0, 160, 3.4 ]
|
||||
- [ 17727.0, 150, 3.4 ]
|
||||
- [ 17807.0, 150, 4.6 ]
|
||||
- [18049.0, 150, 3]
|
||||
- [18210.0, 140, 3]
|
||||
- [ 18049.0, 150, 3.0 ]
|
||||
- [ 18210.0, 140, 3.0 ]
|
||||
- [ 18300.0, 140, 4.6 ]
|
||||
- [ 18680.0, 140, 3.2 ]
|
||||
- [ 18761.0, 150, 3.2 ]
|
||||
- [ 19047.0, 150, 5.1 ]
|
||||
- [19305.0, 150, 3]
|
||||
- [19406.0, 160, 3]
|
||||
- [ 19305.0, 150, 3.0 ]
|
||||
- [ 19406.0, 160, 3.0 ]
|
||||
- [ 19414.0, 160, -0.3 ]
|
||||
- [19900.0, 160, 3]
|
||||
- [ 19900.0, 160, 3.0 ]
|
||||
- [ 20150.0, 160, 1.8 ]
|
||||
- [20470.0, 160, -4]
|
||||
- [ 20470.0, 160, -4.0 ]
|
||||
- [ 20940.0, 160, -3.6 ]
|
||||
- [ 21150.0, 160, -1.5 ]
|
||||
- [21390.0, 160, 0]
|
||||
- [ 21390.0, 160, 0.0 ]
|
||||
- [ 21702.0, 160, 1.5 ]
|
||||
- [ 22188.0, 150, 1.5 ]
|
||||
- [ 22294.0, 150, 1.8 ]
|
||||
|
@ -96,7 +102,7 @@ path:
|
|||
- [ 22900.0, 160, 4.6 ]
|
||||
- [ 23542.0, 160, 0.2 ]
|
||||
- [ 23736.0, 160, 0.9 ]
|
||||
- [24124.0, 160, 7]
|
||||
- [ 24124.0, 160, 7.0 ]
|
||||
- [ 24918.0, 160, 7.6 ]
|
||||
- [ 25100.0, 150, 7.1 ]
|
||||
- [ 25580.0, 150, 7.4 ]
|
||||
|
@ -111,7 +117,7 @@ path:
|
|||
- [ 27310.0, 160, 3.5 ]
|
||||
- [ 27595.0, 160, 3.4 ]
|
||||
- [ 28530.0, 160, 4.6 ]
|
||||
- [29115.0, 160, 0]
|
||||
- [ 29115.0, 160, 0.0 ]
|
||||
- [ 29700.0, 160, -5.2 ]
|
||||
- [ 30055.0, 120, -4.3 ]
|
||||
- [ 30301.0, 120, -6.2 ]
|
||||
|
@ -124,7 +130,7 @@ path:
|
|||
- [ 31795.0, 120, 4.1 ]
|
||||
- [ 32010.0, 120, 3.2 ]
|
||||
- [ 32138.0, 130, 3.2 ]
|
||||
- [32365.0, 130, -4]
|
||||
- [ 32365.0, 130, -4.0 ]
|
||||
- [ 33000.0, 130, 6.1 ]
|
||||
- [ 33426.0, 160, 6.1 ]
|
||||
- [ 33907.0, 160, 7.1 ]
|
||||
|
@ -136,15 +142,15 @@ path:
|
|||
- [ 35173.0, 150, 5.6 ]
|
||||
- [ 35400.0, 150, -0.2 ]
|
||||
- [ 35597.0, 160, -0.2 ]
|
||||
- [35900.0, 160, 0]
|
||||
- [ 35900.0, 160, 0.0 ]
|
||||
- [ 36700.0, 160, 3.9 ]
|
||||
- [36938.0, 160, 0]
|
||||
- [ 36938.0, 160, 0.0 ]
|
||||
- [ 37700.0, 160, -0.3 ]
|
||||
- [ 37978.0, 150, -5.6 ]
|
||||
- [ 38063.0, 150, -1.9 ]
|
||||
- [ 38141.0, 150, -3.1 ]
|
||||
- [38210.0, 150, 0]
|
||||
- [38406.0, 150, -7]
|
||||
- [ 38210.0, 150, 0.0 ]
|
||||
- [ 38406.0, 150, -7.0 ]
|
||||
- [ 38900.0, 150, -7.5 ]
|
||||
- [ 39200.0, 150, -8.7 ]
|
||||
- [ 39298.0, 150, -6.4 ]
|
||||
|
@ -165,10 +171,10 @@ path:
|
|||
- [ 43388.0, 160, -0.6 ]
|
||||
- [ 43700.0, 160, 0.8 ]
|
||||
- [ 44030.0, 160, 2.7 ]
|
||||
- [44430.0, 160, 0]
|
||||
- [ 44430.0, 160, 0.0 ]
|
||||
- [ 44708.0, 160, -7.2 ]
|
||||
- [ 45477.0, 160, -7.8 ]
|
||||
- [45890.0, 160, -1]
|
||||
- [ 45890.0, 160, -1.0 ]
|
||||
- [ 46562.0, 160, -1.6 ]
|
||||
- [ 47000.0, 160, -6.9 ]
|
||||
- [ 47500.0, 160, -7.7 ]
|
||||
|
@ -195,15 +201,15 @@ path:
|
|||
- [ 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]
|
||||
- [ 55788.0, 140, 0.0 ]
|
||||
- [ 55918.0, 100, 0.0 ]
|
||||
- [ 56433.0, 150, 0.0 ]
|
||||
- [ 56560.0, 150, -2.1 ]
|
||||
- [ 56624.0, 150, -6.7 ]
|
||||
- [ 57012.0, 150, 1.3 ]
|
||||
- [ 57260.0, 150, 6.6 ]
|
||||
- [ 57800.0, 150, 5.3 ]
|
||||
- [57987.0, 150, 0]
|
||||
- [ 57987.0, 150, 0.0 ]
|
||||
- [ 57990.0, 150, 7.6 ]
|
||||
- [ 58321.0, 150, 6.4 ]
|
||||
- [ 59090.0, 150, 6.9 ]
|
||||
|
@ -212,7 +218,7 @@ path:
|
|||
- [ 60683.0, 150, 4.1 ]
|
||||
- [ 61156.0, 150, 2.3 ]
|
||||
- [ 61181.0, 130, 2.3 ]
|
||||
- [61325.0, 130, 0]
|
||||
- [ 61325.0, 130, 0.0 ]
|
||||
- [ 61605.0, 130, 7.3 ]
|
||||
- [ 62108.0, 150, 7.3 ]
|
||||
- [ 62246.0, 150, 6.6 ]
|
||||
|
@ -222,22 +228,22 @@ path:
|
|||
- [ 63802.0, 150, 4.6 ]
|
||||
- [ 64344.0, 150, 0.2 ]
|
||||
- [ 64932.0, 150, -0.6 ]
|
||||
- [65100.0, 150, 0]
|
||||
- [ 65100.0, 150, 0.0 ]
|
||||
- [ 65690.0, 150, 1.8 ]
|
||||
- [ 65878.0, 150, 2.5 ]
|
||||
- [66266.0, 150, -1]
|
||||
- [ 66266.0, 150, -1.0 ]
|
||||
- [ 66339.0, 150, 6.3 ]
|
||||
- [ 66448.0, 160, 6.3 ]
|
||||
- [66587.0, 160, 0]
|
||||
- [ 66587.0, 160, 0.0 ]
|
||||
- [ 66856.0, 160, 3.2 ]
|
||||
- [ 67480.0, 160, 3.6 ]
|
||||
- [ 67697.0, 160, 2.2 ]
|
||||
- [67800.0, 160, 6]
|
||||
- [67851.0, 130, 6]
|
||||
- [ 67800.0, 160, 6.0 ]
|
||||
- [ 67851.0, 130, 6.0 ]
|
||||
- [ 68027.0, 130, 2.7 ]
|
||||
- [ 68172.0, 130, 0.6 ]
|
||||
- [ 68328.0, 130, 2.5 ]
|
||||
- [68357.0, 130, 0]
|
||||
- [ 68357.0, 130, 0.0 ]
|
||||
- [ 68479.0, 130, 7.1 ]
|
||||
- [ 68783.0, 130, 7.4 ]
|
||||
- [ 69056.0, 150, 7.4 ]
|
||||
|
@ -245,7 +251,7 @@ path:
|
|||
- [ 69741.0, 160, 6.8 ]
|
||||
- [ 69900.0, 160, 6.6 ]
|
||||
- [ 70757.0, 160, 3.6 ]
|
||||
- [71384.0, 160, 6]
|
||||
- [ 71384.0, 160, 6.0 ]
|
||||
- [ 71568.0, 160, 7.1 ]
|
||||
- [ 71800.0, 160, 7.4 ]
|
||||
- [ 72100.0, 160, 7.3 ]
|
||||
|
@ -253,7 +259,7 @@ path:
|
|||
- [ 74317.0, 140, 7.3 ]
|
||||
- [ 74448.0, 140, 1.5 ]
|
||||
- [ 74590.0, 140, -1.5 ]
|
||||
- [74620.0, 140, -5]
|
||||
- [ 74620.0, 140, -5.0 ]
|
||||
- [ 74950.0, 140, -4.3 ]
|
||||
- [ 75100.0, 140, -1.8 ]
|
||||
- [ 75154.0, 130, -1.8 ]
|
||||
|
@ -262,22 +268,22 @@ path:
|
|||
- [ 76062.0, 100, -5.6 ]
|
||||
- [ 76100.0, 100, -6.4 ]
|
||||
- [ 76350.0, 100, -5.7 ]
|
||||
- [76476.0, 100, -7]
|
||||
- [ 76476.0, 100, -7.0 ]
|
||||
- [ 76600.0, 100, -6.4 ]
|
||||
- [ 76601.0, 90, -6.4 ]
|
||||
- [ 76726.0, 90, -6.2 ]
|
||||
- [ 77256.0, 90, -2.1 ]
|
||||
- [ 77285.0, 80, -2.1 ]
|
||||
- [77299.0, 80, -14]
|
||||
- [ 77299.0, 80, -14.0 ]
|
||||
- [ 77331.0, 80, -1.6 ]
|
||||
- [ 77379.0, 90, -1.6 ]
|
||||
- [ 77425.0, 110, -1.6 ]
|
||||
- [ 77455.0, 110, -4.9 ]
|
||||
- [77498.0, 110, 0]
|
||||
- [77505.0, 160, 0]
|
||||
- [ 77498.0, 110, 0.0 ]
|
||||
- [ 77505.0, 160, 0.0 ]
|
||||
- [ 77555.0, 160, -5.6 ]
|
||||
- [77662.0, 160, 0]
|
||||
- [78085.0, 160, -4]
|
||||
- [ 77662.0, 160, 0.0 ]
|
||||
- [ 78085.0, 160, -4.0 ]
|
||||
- [ 78223.0, 160, -6.8 ]
|
||||
- [ 78337.0, 130, -6.8 ]
|
||||
- [ 78856.0, 130, -6.6 ]
|
||||
|
@ -289,20 +295,20 @@ path:
|
|||
- [ 81300.0, 150, -4.8 ]
|
||||
- [ 81634.0, 110, -4.8 ]
|
||||
- [ 81943.0, 110, -5.4 ]
|
||||
- [82166.0, 110, 0]
|
||||
- [ 82166.0, 110, 0.0 ]
|
||||
- [ 82408.0, 110, 4.8 ]
|
||||
- [ 82790.0, 110, 5.9 ]
|
||||
- [ 83137.0, 120, 5.9 ]
|
||||
- [83300.0, 120, 0]
|
||||
- [83519.0, 150, 0]
|
||||
- [ 83300.0, 120, 0.0 ]
|
||||
- [ 83519.0, 150, 0.0 ]
|
||||
- [ 83597.0, 150, -7.8 ]
|
||||
- [ 83827.0, 150, -8.1 ]
|
||||
- [ 84150.0, 150, -7.2 ]
|
||||
- [84391.0, 150, 0]
|
||||
- [84966.0, 150, -4]
|
||||
- [ 84391.0, 150, 0.0 ]
|
||||
- [ 84966.0, 150, -4.0 ]
|
||||
- [ 85529.0, 130, -2.3 ]
|
||||
- [85589.0, 130, -4]
|
||||
- [86081.0, 130, 0]
|
||||
- [ 85589.0, 130, -4.0 ]
|
||||
- [ 86081.0, 130, 0.0 ]
|
||||
- [ 86514.0, 130, 7.8 ]
|
||||
- [ 86577.0, 120, 7.8 ]
|
||||
- [ 87554.0, 90, 7.8 ]
|
||||
|
@ -315,12 +321,12 @@ path:
|
|||
- [ 88450.0, 160, 6.7 ]
|
||||
- [ 89050.0, 160, 7.4 ]
|
||||
- [ 89350.0, 160, -7.1 ]
|
||||
- [90365.0, 160, 0]
|
||||
- [ 90365.0, 160, 0.0 ]
|
||||
- [ 90700.0, 160, -7.3 ]
|
||||
- [ 92000.0, 160, -7.9 ]
|
||||
- [92166.0, 160, -4]
|
||||
- [ 92166.0, 160, -4.0 ]
|
||||
- [ 92460.0, 160, -5.4 ]
|
||||
- [93330.0, 160, 0]
|
||||
- [ 93330.0, 160, 0.0 ]
|
||||
- [ 93901.0, 160, 0.7 ]
|
||||
- [ 94156.0, 160, 5.2 ]
|
||||
- [ 94440.0, 160, -2.8 ]
|
||||
|
@ -332,14 +338,14 @@ path:
|
|||
- [ 96500.0, 160, -4.4 ]
|
||||
- [ 96700.0, 160, -5.6 ]
|
||||
- [ 97000.0, 160, -4.6 ]
|
||||
- [97590.0, 160, 0]
|
||||
- [97858.0, 120, 0]
|
||||
- [ 97590.0, 160, 0.0 ]
|
||||
- [ 97858.0, 120, 0.0 ]
|
||||
- [ 98224.0, 120, -1.5 ]
|
||||
- [98264.0, 120, 0]
|
||||
- [ 98264.0, 120, 0.0 ]
|
||||
- [ 98577.0, 120, 7.5 ]
|
||||
- [98738.0, 120, 0]
|
||||
- [99055.0, 130, 0]
|
||||
- [99427.0, 130, -2]
|
||||
- [ 98738.0, 120, 0.0 ]
|
||||
- [ 99055.0, 130, 0.0 ]
|
||||
- [ 99427.0, 130, -2.0 ]
|
||||
- [ 99610.0, 130, -3.1 ]
|
||||
- [ 99906.0, 120, -3.1 ]
|
||||
- [ 99980.0, 120, -1.3 ]
|
||||
|
@ -351,4 +357,4 @@ path:
|
|||
- [101332.0, 100, -6.3 ]
|
||||
- [101365.0, 100, -2.4 ]
|
||||
- [101551.0, 110, -2.4 ]
|
||||
- [101800.0, 110, 0]
|
||||
- [101800.0, 110, 0.0 ]
|
||||
|
|
|
@ -2,18 +2,26 @@
|
|||
---
|
||||
path:
|
||||
name: "10 km, different gradient, 160 km/h"
|
||||
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
|
||||
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
|
||||
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
|
||||
- [0, 160, 0]
|
||||
- [1000, 160, 1]
|
||||
- [2000, 160, 2]
|
||||
- [3000, 160, 5]
|
||||
- [4000, 160, -3]
|
||||
- [5000, 160, 5]
|
||||
- [6000, 160, -10]
|
||||
- [7000, 160, 15]
|
||||
- [8000, 160, -10]
|
||||
- [8500, 160, 20]
|
||||
- [9000, 160, 0]
|
||||
- [10000, 160, 0]
|
||||
id: slope
|
||||
UUID: ffd243a9-0223-4210-8c7d-e6c90fde70d3
|
||||
points_of_interest:
|
||||
# [ station in m, name, front or rear ]
|
||||
- [ 850.00, view_point_1, front ]
|
||||
- [ 1000.00, distant_signal_1, front ]
|
||||
- [ 2000.00, main_signal_1, front ]
|
||||
- [ 9000.00, main_signal_3, front ]
|
||||
- [ 9050.00, clearing_point_1, rear ]
|
||||
characteristic_sections:
|
||||
# [ station in m, speed limit in km/h, resistance in ‰ ]
|
||||
- [ 0.0, 160, 0.00 ]
|
||||
- [ 1000.0, 160, 1.00 ]
|
||||
- [ 2000.0, 160, 2.00 ]
|
||||
- [ 3000.0, 160, 5.00 ]
|
||||
- [ 4000.0, 160, -3.00 ]
|
||||
- [ 5000.0, 160, 5.00 ]
|
||||
- [ 6000.0, 160, -10.00 ]
|
||||
- [ 7000.0, 160, 15.00 ]
|
||||
- [ 8000.0, 160, -10.00 ]
|
||||
- [ 8500.0, 160, 20.00 ]
|
||||
- [ 9000.0, 160, 0.00 ]
|
||||
- [ 10000.0, 160, 0.00 ]
|
||||
|
|
|
@ -2,16 +2,26 @@
|
|||
---
|
||||
path:
|
||||
name: "10 km, no gradient, different speed limits"
|
||||
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
|
||||
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
|
||||
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
|
||||
- [0, 160, 0.0]
|
||||
- [3000, 60, 0.0]
|
||||
- [4000, 160, 0.0]
|
||||
- [5000, 60, 0.0]
|
||||
- [6000, 160, 0.0]
|
||||
- [6500, 60, 0.0]
|
||||
- [6700, 65, 0.0]
|
||||
- [6800, 70, 0.0]
|
||||
- [7000, 120.00, 0]
|
||||
- [10000, 160.00, 0.0]
|
||||
id: speed
|
||||
UUID: 401b8ce7-fa75-4576-8a4a-43be2eb55e50
|
||||
points_of_interest:
|
||||
# [ station in m, name, front or rear ]
|
||||
- [ 999.00, point_1, front ]
|
||||
- [ 2000.00, point_2, front ]
|
||||
- [ 3333.30, point_3, rear ]
|
||||
- [ 5000.00, point_4, front ]
|
||||
- [ 7777.00, point_5, front ]
|
||||
- [ 9000.00, point_6, front ]
|
||||
- [ 9500.95, point_7, front ]
|
||||
characteristic_sections:
|
||||
# [ station in m, speed limit in km/h, resistance in ‰ ]
|
||||
- [ 0.0, 160, 0.00 ]
|
||||
- [ 3000.0, 60, 0.00 ]
|
||||
- [ 4000.0, 160, 0.00 ]
|
||||
- [ 5000.0, 60, 0.00 ]
|
||||
- [ 6000.0, 160, 0.00 ]
|
||||
- [ 6500.0, 60, 0.00 ]
|
||||
- [ 6700.0, 65, 0.00 ]
|
||||
- [ 6800.0, 70, 0.00 ]
|
||||
- [ 7000.0, 120, 0.00 ]
|
||||
- [ 10000.0, 160, 0.00 ]
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# default settings for the calculation
|
||||
stepSize: 5 # step size, unit depends on stepVariable - distance in meter, time in seconds and velocity in meter/second.
|
||||
approxLevel: 6 # value for approximation; used when rounding or interating
|
||||
outputDetail: "running_time" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
||||
outputFormat: "julia_dict" # output as "julia_dict" or as "csv"
|
||||
outputDir: "." # used if other outputFormat than "julia dict"
|
|
@ -0,0 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputDetail: "everything" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
|
@ -0,0 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputDetail: "points_of_interest" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
118
test/runtests.jl
118
test/runtests.jl
|
@ -7,63 +7,83 @@
|
|||
|
||||
using TrainRun, Test
|
||||
|
||||
paths=Dict()
|
||||
push!(paths, "const" => TrainRun.importFromYaml(:path, "test/data/paths/const.yaml"))
|
||||
push!(paths, "slope" => TrainRun.importFromYaml(:path, "test/data/paths/slope.yaml"))
|
||||
push!(paths, "speed" => TrainRun.importFromYaml(:path, "test/data/paths/speed.yaml"))
|
||||
push!(paths, "realworld" => TrainRun.importFromYaml(:path, "test/data/paths/realworld.yaml"))
|
||||
|
||||
settings=Dict()
|
||||
push!(settings, "default" => Settings())
|
||||
push!(settings, "detail" => Settings("test/data/settings/detail.yaml"))
|
||||
push!(settings, "driving_course" => Settings("test/data/settings/driving_course.yaml"))
|
||||
push!(settings, "strip" => Settings("test/data/settings/strip.yaml"))
|
||||
push!(settings, "time" => Settings("test/data/settings/time.yaml"))
|
||||
push!(settings, "time_strip" => Settings("test/data/settings/time_strip.yaml"))
|
||||
push!(settings, "velocity" => Settings("test/data/settings/velocity.yaml"))
|
||||
push!(settings, "csv_export" => Settings("test/data/settings/csv_export.yaml"))
|
||||
|
||||
trains = Dict()
|
||||
push!(trains, TrainRun.importFromYaml(:train, "test/data/trains/freight.yaml"))
|
||||
push!(trains, TrainRun.importFromYaml(:train, "test/data/trains/local.yaml"))
|
||||
push!(trains, TrainRun.importFromYaml(:train, "test/data/trains/longdistance.yaml"))
|
||||
paths = Dict()
|
||||
settings = Dict()
|
||||
|
||||
@testset "TrainRun.jl" begin
|
||||
@testset "load data" begin
|
||||
|
||||
println("testing load train data")
|
||||
push!(trains, :freight => @time TrainRun.importFromYaml(:train, "test/data/trains/freight.yaml"))
|
||||
push!(trains, :local => @time TrainRun.importFromYaml(:train, "test/data/trains/local.yaml"))
|
||||
push!(trains, :longdistance => @time TrainRun.importFromYaml(:train, "test/data/trains/longdistance.yaml"))
|
||||
|
||||
println("testing load path data")
|
||||
push!(paths, :const => @time Path("test/data/paths/const.yaml"))
|
||||
push!(paths, :slope => @time Path("test/data/paths/slope.yaml"))
|
||||
push!(paths, :speed => @time Path("test/data/paths/speed.yaml"))
|
||||
push!(paths, :realworld => @time Path("test/data/paths/realworld.yaml"))
|
||||
|
||||
println("testing load settings data")
|
||||
push!(settings, "default" => @time Settings())
|
||||
push!(settings, "poi" => @time Settings("test/data/settings/points_of_interest.yaml"))
|
||||
push!(settings, "drivingcourse" => @time Settings("test/data/settings/driving_course.yaml"))
|
||||
push!(settings, "everything" => @time Settings("test/data/settings/everything.yaml"))
|
||||
push!(settings, "strip" => @time Settings("test/data/settings/strip.yaml"))
|
||||
push!(settings, "time" => @time Settings("test/data/settings/time.yaml"))
|
||||
push!(settings, "timestrip" => @time Settings("test/data/settings/time_strip.yaml"))
|
||||
push!(settings, "velocity" => @time Settings("test/data/settings/velocity.yaml"))
|
||||
push!(settings, "csvexport" => @time Settings("test/data/settings/csv_export.yaml"))
|
||||
|
||||
@test typeof(first(paths)[2]) == Path
|
||||
@test typeof(first(settings)[2]) == Settings
|
||||
|
||||
end
|
||||
|
||||
println("====================")
|
||||
|
||||
tests = Base.Iterators.product(trains,paths)
|
||||
|
||||
## routine to generate the anticipated Dict()
|
||||
# anticipated = Dict()
|
||||
# for test in tests
|
||||
# println(test[1][1],"-",test[2][1])
|
||||
# result = @time trainrun(test[1][2],test[2][2])
|
||||
# push!(anticipated, Symbol(String(test[1][1]) * "_" * String(test[2][1])) => result )
|
||||
# end
|
||||
|
||||
anticipated = Dict(
|
||||
:default => Dict(
|
||||
:longdistance_speed => 499.96109564970516,
|
||||
:freight_slope => 831.4768274141168,
|
||||
:local_slope => 396.99313307033276,
|
||||
:longdistance_const => 328.83479381353095,
|
||||
:freight_realworld => 8971.50124080998,
|
||||
:longdistance_slope => 329.22915822053164,
|
||||
:freight_const => 727.7969403041934,
|
||||
:longdistance_realworld => 2900.1198723158523,
|
||||
:local_speed => 524.3948201513945,
|
||||
:local_realworld => 3443.917823618831,
|
||||
:freight_speed => 733.2610572579886,
|
||||
:local_const => 392.7234008268302
|
||||
)
|
||||
)
|
||||
|
||||
@testset "function trainrun()" begin
|
||||
|
||||
@testset "Default settings" begin
|
||||
|
||||
@test typeof(Settings()) == Settings
|
||||
|
||||
@testset "const path" begin
|
||||
|
||||
path = TrainRun.importFromYaml(:path, "test/data/paths/const.yaml")
|
||||
@test typeof(path) == Dict{Any,Any}
|
||||
|
||||
@testset "freight train - const path" begin
|
||||
train = TrainRun.importFromYaml(:train, "test/data/trains/freight.yaml")
|
||||
data = trainRun(train, path)
|
||||
expected = 727.796900196972
|
||||
for test in tests
|
||||
test_name = String(test[1][1]) * "_" * String(test[2][1])
|
||||
println("testing $test_name")
|
||||
@time result = trainrun(test[1][2],test[2][2])
|
||||
expected = anticipated[:default][Symbol(test_name)]
|
||||
# compare result to test data set
|
||||
@test isapprox(data, expected, atol=0.01)
|
||||
end
|
||||
|
||||
@testset "local train - const path" begin
|
||||
train = TrainRun.importFromYaml(:train, "test/data/trains/local.yaml")
|
||||
data = trainRun(train, path)
|
||||
expected = 392.723361763612
|
||||
# compare result to test data set
|
||||
@test isapprox(data, expected, atol=0.01)
|
||||
end
|
||||
|
||||
@testset "long distance train - const path" begin
|
||||
train = TrainRun.importFromYaml(:train, "test/data/trains/longdistance.yaml")
|
||||
data = trainRun(train, path)
|
||||
expected = 328.83487704779117
|
||||
# compare result to test data set
|
||||
@test isapprox(data, expected, atol=0.01)
|
||||
@test isapprox(result, expected, atol=0.01)
|
||||
println("--------------------")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
println("====================")
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue