new type Settings as struct
parent
25959f7302
commit
e2842157da
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -9,6 +9,24 @@ Categories: Added, Changed, Deprecated, Removed, Fixed, and Security.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
* dependency JSONSchema
|
||||
* validation of YAML input via JSON schema
|
||||
|
||||
### Changed
|
||||
* replaced settings::Dict with type Settings 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 capital letter of include files to lower letter
|
||||
* changed seperation of submodules into a single module with file include
|
||||
|
||||
### Removed
|
||||
* dependency Plots
|
||||
* AdditionalOutput.jl
|
||||
* EnergySaving.jl
|
||||
* test/testEnums.jl
|
||||
|
||||
## Version [0.8] 2022-01-20
|
||||
|
||||
|
|
|
@ -5,6 +5,15 @@ 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
|
||||
|
||||
```
|
||||
$ ln -s ~/path/to/TrainRun.jl ~/.julia/dev/TrainRun
|
||||
```
|
||||
|
||||
and use `Revise.jl`
|
||||
|
||||
|
||||
# Pull Request Process
|
||||
|
||||
* add your changes to the CHANGELOG.md under [Unreleased]
|
||||
|
|
14
Project.toml
14
Project.toml
|
@ -1,12 +1,20 @@
|
|||
name = "TrainRun"
|
||||
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
|
||||
authors = ["Max Kannenberg"]
|
||||
authors = ["Max Kannenberg, Martin Scheidt, and contributors"]
|
||||
version = "0.8.0"
|
||||
|
||||
[deps]
|
||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
JSONSchema = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
|
||||
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
|
||||
|
||||
[compat]
|
||||
julia = "1.7"
|
||||
|
||||
[extras]
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[targets]
|
||||
test = ["Test"]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# TrainRun
|
||||
|
||||
[![License: ISC](https://img.shields.io/badge/license-ISC-green.svg)](https://opensource.org/licenses/ISC) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6448563.svg)](https://doi.org/10.5281/zenodo.6448563)
|
||||
[![License: ISC](https://img.shields.io/badge/license-ISC-green.svg)](https://opensource.org/licenses/ISC) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6448563.svg)](https://doi.org/10.5281/zenodo.6448563)
|
||||
[![Build Status](https://github.com/railtoolkit/TrainRun.jl/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/railtoolkit/TrainRun.jl/actions/workflows/CI.yml?query=branch%3Amaster)
|
||||
|
||||
------------
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# settings for the simulation
|
||||
massModel: "homogeneous strip" # model type of train mass "mass point" or "homogeneous strip"
|
||||
stepVariable: "s in m" # step variable of the step method "s in m", "t in s" or "v in m/s"
|
||||
stepSize: 10 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
|
||||
operationModeMinimumRunningTime: true # operation mode "minimum running time"
|
||||
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
|
||||
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
|
||||
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
|
||||
csvDirectory: "~/Desktop/TrainRun"
|
|
@ -1,12 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# settings for the simulation
|
||||
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
|
||||
stepVariable: "s in m" # step variable of the step method "s in m", "t in s" or "v in m/s"
|
||||
stepSize: 10 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
|
||||
operationModeMinimumRunningTime: true # operation mode "minimum running time"
|
||||
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
|
||||
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
|
||||
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
|
||||
csvDirectory: "~/Desktop/TrainRun"
|
|
@ -1,12 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# settings for the simulation
|
||||
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
|
||||
stepVariable: "s in m" # step variable of the step method "s in m", "t in s" or "v in m/s"
|
||||
stepSize: 10 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
|
||||
operationModeMinimumRunningTime: true # operation mode "minimum running time"
|
||||
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
|
||||
typeOfOutput: "CSV" # output as "julia dictionary" or as "CSV"
|
||||
detailOfOutput: "running time" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
|
||||
csvDirectory: "~/Desktop/TrainRun"
|
|
@ -1,12 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# settings for the simulation
|
||||
massModel: "homogeneous strip" # model type of train mass "mass point" or "homogeneous strip"
|
||||
stepVariable: "t in s" # step variable of the step method "s in m", "t in s" or "v in m/s"
|
||||
stepSize: 3.0 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
|
||||
operationModeMinimumRunningTime: true # operation mode "minimum running time"
|
||||
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
|
||||
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
|
||||
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
|
||||
csvDirectory: "~/Desktop/TrainRun"
|
|
@ -1,12 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# settings for the simulation
|
||||
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
|
||||
stepVariable: "t in s" # step variable of the step method "s in m", "t in s" or "v in m/s"
|
||||
stepSize: 3.0 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
|
||||
operationModeMinimumRunningTime: true # operation mode "minimum running time"
|
||||
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
|
||||
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
|
||||
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
|
||||
csvDirectory: "~/Desktop/TrainRun"
|
|
@ -1,12 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# settings for the simulation
|
||||
massModel: "mass point" # model type of train mass "mass point" or "homogeneous strip"
|
||||
stepVariable: "v in m/s" # step variable of the step method "s in m", "t in s" or "v in m/s"
|
||||
stepSize: 0.1 # step size (unit depends on stepVariable s in m, t in s and v in m/s)
|
||||
operationModeMinimumRunningTime: true # operation mode "minimum running time"
|
||||
operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption"
|
||||
typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV"
|
||||
detailOfOutput: "driving course" # should the output be only the value of the "running time" or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
|
||||
csvDirectory: "~/Desktop/TrainRun"
|
|
@ -0,0 +1,11 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
# default settings for the calculation
|
||||
massModel: "mass_point" # type of train model used: "mass_point" or "homogeneous_strip"
|
||||
stepVariable: "distance" # variable of the linear multistep method: "distance", "time" or "velocity"
|
||||
stepSize: 20 # step size, unit depends on stepVariable - distance in meter, time in seconds and velocity in meter/second.
|
||||
approxLevel: 3 # value for approximation; used when rounding or interating
|
||||
outputDetail: "running_time" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
||||
outputFormat: "julia_dict" # output as "julia_dict" or as "csv"
|
||||
outputDir: "." # used if other outputFormat than "julia dict"
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env julia
|
||||
|
||||
import TrainRun
|
||||
|
||||
paths=[]
|
||||
push!(paths, importFromYaml(:path, "data/paths/path_1_10km_nConst_vConst.yaml"))
|
||||
push!(paths, importFromYaml(:path, "data/paths/path_2_10km_nVar_vConst.yaml"))
|
||||
push!(paths, importFromYaml(:path, "data/paths/path_3_10km_nConst_vVar.yaml"))
|
||||
push!(paths, importFromYaml(:path, "data/paths/path_4_real_Germany_EastSaxony_DG-DN.yaml"))
|
||||
|
||||
settings=[]
|
||||
push!(settings, importFromYaml(:settings, "data/settings/settings_distanceStep_massPoint.yaml"))
|
||||
|
||||
trains=[]
|
||||
push!(trains, importFromYaml(:train, "data/trains/train_freight_V90withOreConsist.yaml"))
|
||||
push!(trains, importFromYaml(:train, "data/trains/train_passenger_SiemensDesiroClassic.yaml"))
|
||||
push!(trains, importFromYaml(:train, "data/trains/train_passenger_IC2.yaml"))
|
||||
|
||||
for path in paths
|
||||
# println(" - - - - - - - - -")
|
||||
# println("path: ", path[:name])
|
||||
for train in trains
|
||||
# println("train: ", train[:name])
|
||||
for settings in settings
|
||||
resultsDict = trainRun(train, path, settings)
|
||||
if haskey(settings, :outputFormat) && settings[:outputFormat] == "CSV"
|
||||
exportToCsv(resultsDict, settings)
|
||||
sleep(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env julia
|
||||
|
||||
import TrainRun
|
||||
|
||||
train = Train("data/trains/train_freight_V90withOreConsist.yaml")
|
||||
path = Path("data/paths/path_1_10km_nConst_vConst.yaml")
|
||||
|
||||
runtime = trainRun(train, path)
|
||||
|
||||
println("The train needs $runtime seconds for the running path.")
|
|
@ -1,44 +0,0 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.0
|
||||
# __author__ = "Max Kannenberg"
|
||||
# __copyright__ = "2021"
|
||||
# __license__ = "ISC"
|
||||
|
||||
include("../src/TrainRun.jl")
|
||||
using .TrainRun
|
||||
|
||||
allPaths=[]
|
||||
push!(allPaths, importFromYaml(:path, "data/paths/path_1_10km_nConst_vConst.yaml"))
|
||||
push!(allPaths, importFromYaml(:path, "data/paths/path_2_10km_nVar_vConst.yaml"))
|
||||
push!(allPaths, importFromYaml(:path, "data/paths/path_3_10km_nConst_vVar.yaml"))
|
||||
push!(allPaths, importFromYaml(:path, "data/paths/path_4_real_Germany_EastSaxony_DG-DN.yaml"))
|
||||
|
||||
allSettings=[]
|
||||
push!(allSettings, importFromYaml(:settings, "data/settings/settings_distanceStep_massPoint.yaml"))
|
||||
|
||||
allTrains=[]
|
||||
push!(allTrains, importFromYaml(:train, "data/trains/train_freight_V90withOreConsist.yaml"))
|
||||
push!(allTrains, importFromYaml(:train, "data/trains/train_passenger_SiemensDesiroClassic.yaml"))
|
||||
push!(allTrains, importFromYaml(:train, "data/trains/train_passenger_IC2.yaml"))
|
||||
|
||||
for path in allPaths
|
||||
# println(" - - - - - - - - -")
|
||||
# println("path: ", path[:name])
|
||||
for train in allTrains
|
||||
# println("train: ", train[:name])
|
||||
for settings in allSettings
|
||||
resultsDict = trainRun(train, path, settings)
|
||||
if haskey(settings, :typeOfOutput) && settings[:typeOfOutput] == "CSV"
|
||||
exportToCsv(resultsDict, settings)
|
||||
sleep(2)
|
||||
end
|
||||
# println("")
|
||||
end
|
||||
end
|
||||
# println("")
|
||||
end
|
||||
|
||||
# println("")
|
||||
# println("________________________")
|
||||
# println("")
|
|
@ -1,19 +0,0 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.0
|
||||
# __author__ = "Max Kannenberg"
|
||||
# __copyright__ = "2021"
|
||||
# __license__ = "ISC"
|
||||
|
||||
include("../src/TrainRun.jl")
|
||||
using .TrainRun
|
||||
|
||||
train_directory = "data/trains/train_freight_V90withOreConsist.yaml"
|
||||
running_path_directory = "data/paths/path_1_10km_nConst_vConst.yaml"
|
||||
setting_directory = "data/settings/settings_distanceStep_massPoint_runningTime.yaml"
|
||||
(train, running_path, settings) = importYamlFiles(train_directory, running_path_directory, setting_directory)
|
||||
|
||||
runtime = trainRun(train, running_path, settings)
|
||||
|
||||
exportToCsv(runtime, settings)
|
||||
println("The V 90 with 10 ore wagons needs $runtime seconds for 10 km with no gradient.")
|
|
@ -1,210 +0,0 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.2
|
||||
# __author__ = "Max Kannenberg"
|
||||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
# INFO: AdditionalOutput should not be used because it is not completed yet. It was used to show first results during development.
|
||||
# TODO: It has to be optimized so that the created plots and printed information is clear and understandable.
|
||||
|
||||
module AdditionalOutput
|
||||
|
||||
using Plots
|
||||
|
||||
export plotResults, plotDrivingCourse, printImportantValues, printSectionInformation
|
||||
|
||||
function plotResults(output::Dict)
|
||||
opModeMinTime = output[:settings][:operationModeMinimumRunningTime]
|
||||
opModeMinEnergy = output[:settings][:operationModeMinimumEnergyConsumption]
|
||||
|
||||
if opModeMinTime == true && opModeMinEnergy == true
|
||||
plotDrivingCourse(output[:drivingCourseMinimumRunningTime], output[:drivingCourseMinimumEnergyConsumption])
|
||||
elseif opModeMinTime == true
|
||||
plotDrivingCourse(output[:drivingCourseMinimumRunningTime])
|
||||
elseif opModeMinEnergy == true
|
||||
plotDrivingCourse(output[:drivingCourseMinimumEnergyConsumption])
|
||||
else
|
||||
output[:settings][:detailOfOutput] == "everything" && println("No Output was demanded. So no plot is created.")
|
||||
end
|
||||
|
||||
return true
|
||||
end #function plotResults
|
||||
|
||||
function plotResults(drivingCourse::Vector{Dict})
|
||||
plotDrivingCourse(drivingCourse)
|
||||
|
||||
return true
|
||||
end #function plotResults
|
||||
|
||||
function plotResults(singleValue::AbstractFloat)
|
||||
println("Not able to plot the single value ",singleValue)
|
||||
|
||||
return false
|
||||
end #function plotResults
|
||||
|
||||
function plotDrivingCourse(drivingCourse::Vector{Dict})
|
||||
a=[]
|
||||
E=[]
|
||||
s=[]
|
||||
t=[]
|
||||
v=[]
|
||||
for i in 1:length(drivingCourse)
|
||||
push!(a, drivingCourse[i][:a])
|
||||
push!(E, drivingCourse[i][:E])
|
||||
push!(s, drivingCourse[i][:s])
|
||||
push!(t, drivingCourse[i][:t])
|
||||
push!(v, drivingCourse[i][:v])
|
||||
end #for
|
||||
|
||||
# p1=plot([s], [v], title = "v in m/s", label = ["v"], xlabel = "s in m")
|
||||
p1=plot([s/1000], [v*3.6], title = "v in km/h", label = ["v"], xlabel = "s in km")
|
||||
|
||||
# p2=plot([t], [v], title = "v in m/s", label = ["v"], xlabel = "t in s")
|
||||
p2=plot([t/60], [v*3.6], title = "v in km/h", label = ["v"], xlabel = "t in min")
|
||||
|
||||
# p3=plot([s], [t], title = "t in s", label = ["t"], xlabel = "s in m")
|
||||
|
||||
# p4=plot([t], [s], title = "s in m", label = ["s"], xlabel = "t in s")
|
||||
|
||||
#p5=plot([s], [E], title = "E in Ws", label = ["E"], xlabel = "s in m")
|
||||
p5=plot([s/1000], [E], title = "E in Ws", label = ["E"], xlabel = "s in km")
|
||||
|
||||
#p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s")
|
||||
p6=plot([t/60], [E], title = "E in Ws", label = ["E"], xlabel = "t in min")
|
||||
|
||||
all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false)
|
||||
#=
|
||||
# p5=plot([s], [E], title = "E in Ws", label = ["E"], xlabel = "s in m")
|
||||
|
||||
# p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s")
|
||||
|
||||
all=plot(p1, p2, layout = (1, 2), legend = false)=#
|
||||
# all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
|
||||
display(all)
|
||||
println("Plots for different variables have been created.")
|
||||
end #function plotDrivingCourse
|
||||
|
||||
function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{Dict},drivingCourseMinimumEnergyConsumption::Vector{Dict})
|
||||
a_minTime=[]
|
||||
E_minTime=[]
|
||||
s_minTime=[]
|
||||
t_minTime=[]
|
||||
v_minTime=[]
|
||||
for i in 1:length(drivingCourseMinimumRunningTime)
|
||||
push!(a_minTime, drivingCourseMinimumRunningTime[i][:a])
|
||||
push!(E_minTime, drivingCourseMinimumRunningTime[i][:E])
|
||||
push!(s_minTime, drivingCourseMinimumRunningTime[i][:s])
|
||||
push!(t_minTime, drivingCourseMinimumRunningTime[i][:t])
|
||||
push!(v_minTime, drivingCourseMinimumRunningTime[i][:v])
|
||||
end #for
|
||||
|
||||
a_minEnergy=[]
|
||||
E_minEnergy=[]
|
||||
s_minEnergy=[]
|
||||
t_minEnergy=[]
|
||||
v_minEnergy=[]
|
||||
for i in 1:length(drivingCourseMinimumEnergyConsumption)
|
||||
push!(a_minEnergy, drivingCourseMinimumEnergyConsumption[i][:a])
|
||||
push!(E_minEnergy, drivingCourseMinimumEnergyConsumption[i][:E])
|
||||
push!(s_minEnergy, drivingCourseMinimumEnergyConsumption[i][:s])
|
||||
push!(t_minEnergy, drivingCourseMinimumEnergyConsumption[i][:t])
|
||||
push!(v_minEnergy, drivingCourseMinimumEnergyConsumption[i][:v])
|
||||
end #for
|
||||
|
||||
p1=plot([s_minTime,s_minEnergy],
|
||||
[v_minTime,v_minEnergy],
|
||||
title = "v in m/s",
|
||||
label = ["v for t_min" "v for E_min"],
|
||||
xlabel = "s in m")# lw = 3)
|
||||
|
||||
p2=plot([t_minTime,t_minEnergy],
|
||||
[v_minTime,v_minEnergy],
|
||||
title = "v in m/s",
|
||||
label = ["v for t_min" "v for E_min"],
|
||||
xlabel = "t in s")
|
||||
|
||||
# p3=plot([s_minTime,s_minEnergy],
|
||||
# [t_minTime,t_minEnergy],
|
||||
# title = "t in s",
|
||||
# label = ["t for t_min" "t for E_min"],
|
||||
# xlabel = "s in m")
|
||||
|
||||
# p4=plot([t_minTime,t_minEnergy],
|
||||
# [s_minTime,s_minEnergy],
|
||||
# title = "s in m",
|
||||
# label = ["s for t_min" "s for E_min"],
|
||||
# xlabel = "t in s")
|
||||
|
||||
p5=plot([s_minTime,s_minEnergy],
|
||||
[E_minTime,E_minEnergy],
|
||||
title = "E in Ws",
|
||||
label = ["E for t_min" "E for E_min"],
|
||||
xlabel = "s in m")
|
||||
|
||||
p6=plot([t_minTime,t_minEnergy],
|
||||
[E_minTime,E_minEnergy],
|
||||
title = "E in Ws",
|
||||
label = ["E for t_min" "E for E_min"],
|
||||
xlabel = "t in s")
|
||||
|
||||
# all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
|
||||
all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false)
|
||||
display(all)
|
||||
println("Plots for different variables have been created.")
|
||||
end #function plotDrivingCourse
|
||||
|
||||
function printImportantValues(dataPoints::Vector{Dict})
|
||||
println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh")
|
||||
for i in 1:length(dataPoints)
|
||||
println(dataPoints[i][:i],". ",dataPoints[i][:behavior]," ",dataPoints[i][:s]," ",dataPoints[i][:v]*3.6," ",dataPoints[i][:t]/60," ",dataPoints[i][:a]," ",dataPoints[i][:F_R]/1000," ",dataPoints[i][:F_T]/1000," ",dataPoints[i][:E]/3600/1000)
|
||||
end #for
|
||||
println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh")
|
||||
end #function printImportantValues
|
||||
|
||||
function printSectionInformation(movingSection::Dict)
|
||||
CSs::Vector{Dict} = movingSection[:characteristicSections]
|
||||
|
||||
println("MS with length=", movingSection[:length]," with t=", movingSection[:t])
|
||||
#allBSs=[:breakFree, :clearing, :accelerating, :clearing2, :accelerating2, :clearing3, :accelerating3, :cruising, :downhillBraking, :diminishing, :coasting, :braking, :standstill]
|
||||
for csId in 1:length(CSs)
|
||||
println("CS ",csId," with length=", CSs[csId][:length]," with t=", CSs[csId][:t])
|
||||
# for bs in 1: length(allBSs)
|
||||
# if haskey(CSs[csId][:behaviorSections], allBSs[bs])
|
||||
# println("BS ",allBSs[bs], " with s_entry=", CSs[csId][:behaviorSections][allBSs[bs]][:s_entry], " and length=",CSs[csId][:behaviorSections][allBSs[bs]][:length]) # and t=", CSs[csId][:behaviorSections][allBSs[bs]][:t])
|
||||
# # for point in 1:length(CSs[csId][:behaviorSections][allBSs[bs]][:dataPoints])
|
||||
# # println(CSs[csId][:behaviorSections][allBSs[bs]][:dataPoints][point])
|
||||
# # end
|
||||
# end #if
|
||||
# end #for
|
||||
|
||||
tempBSs = collect(keys(CSs[csId][:behaviorSections]))
|
||||
while length(tempBSs) > 0
|
||||
currentBS = :default
|
||||
for bs in 1: length(tempBSs)
|
||||
if currentBS == :default
|
||||
currentBS = tempBSs[bs]
|
||||
else
|
||||
if CSs[csId][:behaviorSections][currentBS][:s_entry] > CSs[csId][:behaviorSections][tempBSs[bs]][:s_entry]
|
||||
currentBS = tempBSs[bs]
|
||||
end
|
||||
end
|
||||
end #for
|
||||
|
||||
println("BS ",currentBS, " with s_entry=", CSs[csId][:behaviorSections][currentBS][:s_entry], " and length=",CSs[csId][:behaviorSections][currentBS][:length]) # and t=", CSs[csId][:behaviorSections][currentBS][:t])
|
||||
# for point in 1:length(CSs[csId][:behaviorSections][currentBS][:dataPoints])
|
||||
# println(CSs[csId][:behaviorSections][currentBS][:dataPoints][point])
|
||||
# end
|
||||
|
||||
newTempBSs = []
|
||||
for bs in 1: length(tempBSs)
|
||||
if currentBS != tempBSs[bs]
|
||||
push!(newTempBSs, tempBSs[bs])
|
||||
end #if
|
||||
end #for
|
||||
tempBSs = newTempBSs
|
||||
end #while
|
||||
end #for
|
||||
end #function printSectionInformation
|
||||
|
||||
end # module AdditionalOutput
|
225
src/Behavior.jl
225
src/Behavior.jl
|
@ -5,22 +5,6 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
module Behavior
|
||||
|
||||
include("./Formulary.jl")
|
||||
using .Formulary
|
||||
|
||||
export addBreakFreeSection!, addClearingSection!, addAcceleratingSection!, addCruisingSection!, addDiminishingSection!, addCoastingSection!, addBrakingSection!, addStandstill!,
|
||||
# addBrakingSectionInOneStep! is not used in the current version of the tool
|
||||
calculateForces!, createDataPoint,
|
||||
|
||||
# export functions from Formulary
|
||||
calcBrakingDistance, calcBrakingStartVelocity, calc_Δs_with_Δt
|
||||
|
||||
|
||||
approximationLevel = 6 # value for approximation to intersections TODO further explanation (e.g. approximationLevel = 3 -> with stepSize 10 m the approximation will be calculated accurate on 10 mm ; 1s -> 1 ms; 1 km/h -> 3.6 mm/s)
|
||||
# TODO: define it in TrainRun and give it to each function?
|
||||
|
||||
## functions for calculating tractive effort and resisting forces
|
||||
"""
|
||||
calculateTractiveEffort(v, tractiveEffortVelocityPairs)
|
||||
|
@ -62,10 +46,11 @@ end #function calculateTractiveEffort
|
|||
"""
|
||||
calculate and return the path resistance dependend on the trains position and mass model
|
||||
"""
|
||||
function calculatePathResistance(CSs::Vector{Dict}, csId::Integer, s::Real, massModel::String, train::Dict)
|
||||
if massModel == "mass point"
|
||||
function calculatePathResistance(CSs::Vector{Dict}, csId::Integer, s::Real, massModel, train::Dict)
|
||||
|
||||
if massModel == :mass_point
|
||||
pathResistance = calcForceFromCoefficient(CSs[csId][:r_path], train[:m_train])
|
||||
elseif massModel == "homogeneous strip"
|
||||
elseif massModel == :homogeneous_strip
|
||||
pathResistance = 0.0
|
||||
s_rear = s - train[:length] # position of the rear of the train
|
||||
while csId > 0 && s_rear < CSs[csId][:s_exit]
|
||||
|
@ -84,7 +69,7 @@ end #function calculatePathResistance
|
|||
"""
|
||||
calculate and return tractive and resisting forces for a data point
|
||||
"""
|
||||
function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Dict, massModel::String)
|
||||
function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Dict, massModel)
|
||||
# calculate resisting forces
|
||||
dataPoint[:R_traction] = calcTractionUnitResistance(dataPoint[:v], train)
|
||||
dataPoint[:R_wagons] = calcWagonsResistance(dataPoint[:v], train)
|
||||
|
@ -108,7 +93,7 @@ end #function calculateForces!
|
|||
"""
|
||||
TODO
|
||||
"""
|
||||
function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, csId::Integer)
|
||||
function moveAStep(previousPoint::Dict, stepVariable::Symbol, stepSize::Real, csId::Integer)
|
||||
# stepSize is the currentStepSize depending on the accessing function
|
||||
# TODO: csId is only for error messages. Should it be removed?
|
||||
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =#
|
||||
|
@ -118,7 +103,7 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
|
|||
newPoint[:i] = previousPoint[:i]+1 # identifier
|
||||
|
||||
# calculate s, t, v, E
|
||||
if stepVariable == "s in m" # distance step method
|
||||
if stepVariable == :distance # distance step method
|
||||
newPoint[:Δs] = stepSize # step size (in m)
|
||||
if previousPoint[:a] == 0.0
|
||||
if previousPoint[:v] == 0.0
|
||||
|
@ -138,12 +123,12 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
|
|||
newPoint[:Δv] = calc_Δv_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m/s)
|
||||
end
|
||||
|
||||
elseif stepVariable == "t in s" # time step method
|
||||
elseif stepVariable == :time # time step method
|
||||
newPoint[:Δt] = stepSize # step size (in s)
|
||||
newPoint[:Δs] = calc_Δs_with_Δt(newPoint[:Δt], previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
newPoint[:Δv] = calc_Δv_with_Δt(newPoint[:Δt], previousPoint[:a]) # step size (in m/s)
|
||||
|
||||
elseif stepVariable == "v in m/s" # velocity step method
|
||||
elseif stepVariable == :velocity # velocity step method
|
||||
if previousPoint[:a] == 0.0
|
||||
if previousPoint[:v] == 0.0
|
||||
error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".")
|
||||
|
@ -203,7 +188,7 @@ end #function getNextPointOfInterest
|
|||
## This function calculates the data points of the breakFree section.
|
||||
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed.
|
||||
# Info: currently the values of the breakFree section will be calculated like in the accelerating section
|
||||
function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
|
||||
function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Dict, CSs::Vector{Dict})
|
||||
# conditions for the break free section
|
||||
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached]
|
||||
trainIsHalting = drivingCourse[end][:v] == 0.0
|
||||
|
@ -213,7 +198,7 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:
|
|||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel]) # currently the tractive effort is calculated like in the accelerating section
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel) # currently the tractive effort is calculated like in the accelerating section
|
||||
|
||||
# calculate the breakFree section with calculating the accelerating section and just using the first step and removing the rest
|
||||
try (CS, drivingCourse, stateFlags) = addAcceleratingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
|
||||
|
@ -272,7 +257,7 @@ end #function addBreakFreeSection!
|
|||
|
||||
## This function calculates the data points of the clearing section.
|
||||
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the clearing section.
|
||||
function addClearingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
|
||||
function addClearingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Dict, CSs::Vector{Dict})
|
||||
if stateFlags[:previousSpeedLimitReached]
|
||||
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train[:length])
|
||||
|
||||
|
@ -287,7 +272,7 @@ function addClearingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, currentSpeedLimit[:s_end] - drivingCourse[end][:s])
|
||||
if s_clearing > 0.0
|
||||
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_clearing, settings, train, CSs, "clearing")
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel)
|
||||
# stateFlags[:brakingStartReached] = brakingStartReached
|
||||
# stateFlags[:endOfCSReached] = stateFlags[:endOfCSReached] || drivingCourse[end][:s] == CS[:s_exit]
|
||||
else
|
||||
|
@ -305,14 +290,14 @@ end #function addClearingSection
|
|||
|
||||
## This function calculates the data points of the accelerating section.
|
||||
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the accelerating section
|
||||
function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
|
||||
#function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, ignoreBraking::Bool)
|
||||
#=if drivingCourse would also be part of movingSectiong: function addAcceleratingSection!(movingSection::Dict, stateFlags::Dict, csId::Integer, settings::Dict, train::Dict)
|
||||
function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Dict, CSs::Vector{Dict})
|
||||
#function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Settings, train::Dict, CSs::Vector{Dict}, ignoreBraking::Bool)
|
||||
#=if drivingCourse would also be part of movingSectiong: function addAcceleratingSection!(movingSection::Dict, stateFlags::Dict, csId::Integer, settings::Settings, train::Dict)
|
||||
CSs = movingSection[:characteristicSections]
|
||||
CS = CSs[csId]
|
||||
drivingCourse = movingSection[:drivingCourse]=#
|
||||
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel)
|
||||
|
||||
if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics]
|
||||
ignoreBraking = true
|
||||
|
@ -340,11 +325,11 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
#speedLimitReached = drivingCourse[end][:v] > currentSpeedLimit[:v]
|
||||
#targetSpeedReached = speedLimitReached
|
||||
while !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached && !previousSpeedLimitReached
|
||||
currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections
|
||||
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
|
||||
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
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
|
||||
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
|
||||
end
|
||||
|
@ -360,11 +345,11 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
||||
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel)
|
||||
|
||||
# conditions for the next while cycle
|
||||
if !ignoreBraking
|
||||
|
@ -386,41 +371,41 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
end
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
if cycle < approximationLevel+1
|
||||
if cycle < settings.approxLevel+1
|
||||
if drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit]
|
||||
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
|
||||
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
|
||||
if settings[:stepVariable] == "s in m"
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:v] > CS[:v_peak]
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing
|
||||
if settings[:stepVariable] == "v in m/s"
|
||||
if settings.stepVariable == :speed
|
||||
currentStepSize = CS[:v_peak]-drivingCourse[end-1][:v]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:v] > currentSpeedLimit[:v]
|
||||
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing
|
||||
if settings[:stepVariable] == "v in m/s"
|
||||
if settings.stepVariable == :velocity
|
||||
currentStepSize = currentSpeedLimit[:v]-drivingCourse[end-1][:v]
|
||||
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:s] +s_braking == CS[:s_exit]
|
||||
elseif drivingCourse[end][:s] + s_braking == CS[:s_exit]
|
||||
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
|
||||
if s_braking == 0.0
|
||||
endOfCSReached = true
|
||||
|
@ -447,7 +432,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
println("s=" ,drivingCourse[end][:s]," s_exit=", CS[:s_exit], " s+s_braking=", drivingCourse[end][:s] +s_braking," nextPOI=",nextPointOfInterest)
|
||||
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")
|
||||
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")
|
||||
end
|
||||
# delete last data point for recalculating the last step with reduced step size
|
||||
pop!(drivingCourse)
|
||||
|
@ -551,15 +536,15 @@ end #function addAcceleratingSection!
|
|||
|
||||
## This function calculates the data points of the cruising section.
|
||||
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed.
|
||||
function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String)
|
||||
function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, s_cruising::Real, settings::Settings, train::Dict, CSs::Vector{Dict}, cruisingType::String)
|
||||
trainIsClearing = cruisingType == "clearing"
|
||||
trainIsBrakingDownhill = cruisingType == "downhillBraking"
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
if !trainIsBrakingDownhill # TODO: or just give BS[:type] instead of "cruising"/"braking"?
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
|
||||
else
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel)
|
||||
end
|
||||
|
||||
if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics]
|
||||
|
@ -587,14 +572,14 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
s_cruising = min(s_cruising, CS[:s_exit]-BS[:s_entry])
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
#03/25 calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
|
||||
#03/25 calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
|
||||
if !trainIsBrakingDownhill
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
|
||||
else
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel)
|
||||
end
|
||||
|
||||
if settings[:massModel]=="homogeneous strip" && CS[:id] > 1
|
||||
if settings.massModel == :homogeneous_strip && CS[:id] > 1
|
||||
# conditions for cruising section
|
||||
trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train[:length]
|
||||
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising
|
||||
|
@ -604,11 +589,11 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
#&& targetSpeedReached
|
||||
# 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]
|
||||
currentStepSize = settings.stepSize
|
||||
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
|
||||
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
|
||||
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
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]
|
||||
# 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
|
||||
|
@ -626,21 +611,21 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
drivingCourse[end][:a] = 0.0
|
||||
|
||||
# create the next data point
|
||||
if settings[:stepVariable] =="s in m" || settings[:stepVariable] =="t in s"
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
|
||||
if settings.stepVariable == :distance || settings.stepVariable == time
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
|
||||
else
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s in m", train[:length]/(10.0^cycle), CS[:id])) # TODO which step size should be used?
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], position, train[:length]/(10.0^cycle), CS[:id])) # TODO which step size should be used?
|
||||
end
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel])
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel)
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
|
||||
#if !trainIsBrakingDownhill
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
|
||||
#else
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings[:massModel])
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel)
|
||||
#end
|
||||
|
||||
# conditions for the next while cycle
|
||||
|
@ -652,28 +637,28 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
end #while
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
if cycle < approximationLevel+1
|
||||
if cycle < settings.approxLevel+1
|
||||
if drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif !trainIsBrakingDownhill && resistingForceNegative
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif trainIsBrakingDownhill && !resistingForceNegative
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
if settings[:stepVariable] == "s in m"
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:s] > BS[:s_entry] + s_cruising # TODO also the following? drivingCourse[end][:s] > CSs[CS[:id]][:s_entry] + train[:length]))
|
||||
if settings[:stepVariable] == "s in m"
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize=BS[:s_entry] + s_cruising-drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:s] == BS[:s_entry] + s_cruising # || drivingCourse[end][:s]==CS[:s_exit]
|
||||
|
@ -689,7 +674,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
break
|
||||
|
||||
else
|
||||
error("ERROR at cruising section: With the step variable ",settings[:stepVariable]," the while loop will be left although the if cases don't apply in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
|
||||
error("ERROR at cruising section: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
|
||||
end
|
||||
|
||||
# delete last data point for recalculating the last step with reduced step size
|
||||
|
@ -757,16 +742,16 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
s_cruisingRemaining = min(nextPointOfInterest -drivingCourse[end][:s], BS[:s_entry] +s_cruising -drivingCourse[end][:s])
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s in m", s_cruisingRemaining, CS[:id]))
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], :distance, s_cruisingRemaining, CS[:id]))
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
||||
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel])
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel)
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
|
||||
#if !trainIsBrakingDownhill
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
|
||||
#else
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings[:massModel])
|
||||
# calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel)
|
||||
#end
|
||||
|
||||
# conditions for the next while cycle
|
||||
|
@ -808,8 +793,8 @@ end #function addCruisingSection!
|
|||
|
||||
|
||||
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower
|
||||
function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "diminishing", train, settings[:massModel])
|
||||
function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Dict, CSs::Vector{Dict})
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "diminishing", train, settings.massModel)
|
||||
|
||||
if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics]
|
||||
ignoreBraking = true
|
||||
|
@ -832,22 +817,22 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
|
||||
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
|
||||
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
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
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
||||
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel)
|
||||
|
||||
# conditions for the next while cycle
|
||||
if !ignoreBraking
|
||||
|
@ -867,27 +852,27 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
end
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
if cycle < approximationLevel+1
|
||||
if cycle < settings.approxLevel+1
|
||||
if drivingCourse[end][:v] < 0.0
|
||||
if settings[:stepVariable] == "v in m/s"
|
||||
if settings.stepVariable == velocity
|
||||
currentStepSize = drivingCourse[end-1][:v]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
|
||||
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," > F_R=",drivingCourse[end][:F_R]) # for testing
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit]
|
||||
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
|
||||
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
|
||||
if settings[:stepVariable] == "s in m"
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:s] + s_braking == CS[:s_exit]
|
||||
|
@ -908,7 +893,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
" F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.")
|
||||
|
||||
else
|
||||
error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
|
||||
error("ERROR during diminishing run: With the step variable ",settings.stepVariable," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
|
||||
end
|
||||
# delete last data point for recalculating the last step with reduced step size
|
||||
pop!(drivingCourse)
|
||||
|
@ -995,7 +980,7 @@ end #function addDiminishingSection!
|
|||
|
||||
## This function calculates the data points of the coasting section.
|
||||
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
|
||||
function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
|
||||
function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Dict, CSs::Vector{Dict})
|
||||
# TODO: if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
|
||||
# with getCurrentSpeedLimit
|
||||
|
||||
|
@ -1012,21 +997,21 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
while !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
|
||||
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
|
||||
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
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
|
||||
# traction effort and resisting forces (in N):
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel)
|
||||
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
||||
|
||||
|
@ -1040,33 +1025,33 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
testFlag = false
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
if cycle < approximationLevel+1
|
||||
if cycle < settings.approxLevel+1
|
||||
if drivingCourse[end][:s] + s_braking > CS[:s_exit]
|
||||
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
|
||||
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
|
||||
|
||||
if settings[:stepVariable] == "s in m"
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:v] < CS[:v_exit] # TODO: if accelereation and coasting functions will be combined this case is only for coasting
|
||||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," < v_exit=", CS[:v_exit]) # for testing
|
||||
if settings[:stepVariable] == "v in m/s"
|
||||
if settings.stepVariable == velocity
|
||||
currentStepSize = drivingCourse[end-1][:v] - CS[:v_exit]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
elseif drivingCourse[end][:v] > CS[:v_peak]
|
||||
testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=", CS[:v_peak]) # for testing
|
||||
if settings[:stepVariable] == "v in m/s"
|
||||
if settings.stepVariable == velocity
|
||||
currentStepSize = CS[:v_peak] - drivingCourse[end-1][:v]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
elseif drivingCourse[end][:s] + s_braking == CS[:s_exit]
|
||||
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
|
||||
|
@ -1082,7 +1067,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
|
||||
else
|
||||
# TODO: not needed. just for testing
|
||||
error("ERROR at coasting until braking section: With the step variable ",settings[:stepVariable]," the while loop will be left although v<v_peak and s+s_braking<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
|
||||
error("ERROR at coasting until braking section: With the step variable ",settings.stepVariable," the while loop will be left although v<v_peak and s+s_braking<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
|
||||
end
|
||||
# delete last data point for recalculating the last step with reduced step size
|
||||
pop!(drivingCourse)
|
||||
|
@ -1158,7 +1143,7 @@ end #function addCoastingSection!
|
|||
|
||||
## This function calculates the data points of the braking section.
|
||||
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
|
||||
function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
|
||||
function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Dict, CSs::Vector{Dict})
|
||||
# conditions for braking section
|
||||
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
|
||||
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached]
|
||||
|
@ -1169,21 +1154,21 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
while !targetSpeedReached && !endOfCSReached
|
||||
currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections
|
||||
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
|
||||
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
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
|
||||
# traction effort and resisting forces (in N):
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel)
|
||||
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end][:a] = train[:a_braking]
|
||||
# TODO or: drivingCourse[end][:a] = calcBrakingAcceleration(drivingCourse[end][:v], CS[:v_exit], CS[:s_exit]-drivingCourse[end][:s])
|
||||
|
||||
if settings[:stepVariable] == "s in m" && ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0
|
||||
if settings.stepVariable == :distance && ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0
|
||||
# create empty data point and set it for the values of s_exit and v_exit
|
||||
push!(drivingCourse, createDataPoint())
|
||||
drivingCourse[end][:i] = drivingCourse[end-1][:i]+1
|
||||
|
@ -1192,7 +1177,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
|
||||
else
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
||||
end
|
||||
|
@ -1206,18 +1191,18 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
# TODO: is there a better way than rounding like in the following?
|
||||
if cycle < approximationLevel+1
|
||||
if cycle < settings.approxLevel+1
|
||||
if drivingCourse[end][:v] < CS[:v_exit]
|
||||
if settings[:stepVariable] == "v in m/s"
|
||||
if settings.stepVariable == velocity
|
||||
currentStepSize = drivingCourse[end-1][:v] - CS[:v_exit]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
elseif drivingCourse[end][:s] > nextPointOfInterest
|
||||
if settings[:stepVariable] == "s in m"
|
||||
if settings.stepVariable == :distance
|
||||
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
|
||||
else
|
||||
currentStepSize = settings[:stepSize] / 10.0^cycle
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
elseif drivingCourse[end][:v] == CS[:v_exit] && drivingCourse[end][:s] == CS[:s_exit]
|
||||
break
|
||||
|
@ -1306,7 +1291,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_exit]
|
||||
stateFlags[:endOfCSReached] = endOfCSReached
|
||||
stateFlags[:error] = !(endOfCSReached)
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel)
|
||||
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
|
||||
|
||||
return (CS, drivingCourse, stateFlags)
|
||||
|
@ -1315,7 +1300,7 @@ end #function addBrakingSection!
|
|||
|
||||
## This function calculates the data point of the standstill.
|
||||
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed.
|
||||
function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
|
||||
function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Settings, train::Dict, CSs::Vector{Dict})
|
||||
if drivingCourse[end][:v] == 0.0
|
||||
BS = createBehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
merge!(BS, Dict(:length => 0.0, # total length (in m)
|
||||
|
@ -1326,7 +1311,7 @@ function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, t
|
|||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel)
|
||||
|
||||
merge!(CS[:behaviorSections], Dict(:standstill => BS))
|
||||
end # else: return the characteristic section without a standstillSection section
|
||||
|
@ -1411,5 +1396,3 @@ function recalculateLastBrakingPoint!(drivingCourse, s_target, v_target)
|
|||
currentPoint[:ΔE] = currentPoint[:ΔW] # energy consumption in this step (in Ws)
|
||||
currentPoint[:E] = previousPoint[:E] + currentPoint[:ΔE] # energy consumption (in Ws)
|
||||
end #function recalculateLastBrakingPoint
|
||||
|
||||
end #module Behavior
|
||||
|
|
|
@ -5,83 +5,55 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
module TrainRunCalc
|
||||
|
||||
# include modules of TrainRunCalc
|
||||
include("./Validate.jl")
|
||||
include("./Characteristics.jl")
|
||||
include("./Behavior.jl")
|
||||
include("./Output.jl")
|
||||
|
||||
|
||||
# use modules of TrainRunCalc
|
||||
using .Validate
|
||||
using .Characteristics
|
||||
using .Behavior
|
||||
using .Output
|
||||
|
||||
# export main function
|
||||
export trainRun
|
||||
|
||||
approximationLevel = 6 # value for approximation to intersections and precisely calculated digits
|
||||
# TODO: define it here and give it to each function? (Behavior, ...)
|
||||
|
||||
# Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
|
||||
|
||||
"""
|
||||
trainRun(train::Dict, path::Dict, settings::Dict)
|
||||
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, settingsDict)
|
||||
julia> trainRun(trainDict, pathDict)
|
||||
todo !!!
|
||||
```
|
||||
"""
|
||||
function trainRun(trainInput::Dict, pathInput::Dict, settingsInput::Dict)
|
||||
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[:detailOfOutput] == "points of interest" && !haskey(path, :pointsOfInterest)
|
||||
# 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)
|
||||
settings = copy(settingsInput)
|
||||
|
||||
# check the input data
|
||||
(train, path, settings) = checkAndSetInput!(train, path, settings)
|
||||
settings[:detailOfOutput] == "everything" && println("The input has been checked.")
|
||||
(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[:detailOfOutput] == "everything" && println("The moving section has been prepared.")
|
||||
settings.outputDetail == :everything && println("The moving section has been prepared.")
|
||||
|
||||
# calculate the train run for oparation mode "minimum running time"
|
||||
if settings[:operationModeMinimumRunningTime] || settings[:operationModeMinimumEnergyConsumption]
|
||||
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
|
||||
settings[:detailOfOutput] == "everything" && println("The driving course for the shortest running time has been calculated.")
|
||||
(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)
|
||||
# 30/31 old: output = createOutputDict(train, settings, path, movingSection, drivingCourse)
|
||||
else
|
||||
output = nothing
|
||||
# 30/31 old: output = Dict()
|
||||
end #if
|
||||
# accumulate data and create an output dictionary
|
||||
output = createOutput(train, settings, path, movingSection, drivingCourse)
|
||||
|
||||
return output
|
||||
end # function trainRun
|
||||
|
||||
# calculate a train run focussing on using the minimum possible running time
|
||||
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
|
||||
function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, train::Dict)
|
||||
CSs::Vector{Dict} = movingSection[:characteristicSections]
|
||||
|
||||
if settings[:massModel] == "homogeneous strip" && settings[:stepVariable] == "v in m/s"
|
||||
if settings.massModel == :homogeneous_strip && settings.stepVariable == speed
|
||||
println("WARNING: ! ! ! TrainRun.jl doesn't work reliably for the mass model homogeneous strip with step size v in m/s. The calculation time can be extremely high when calcutlating paths with steep gradients ! ! !")
|
||||
end
|
||||
|
||||
startingPoint=createDataPoint()
|
||||
startingPoint[:i]=1
|
||||
startingPoint[:s]=CSs[1][:s_entry]
|
||||
calculateForces!(startingPoint, CSs, 1, "default", train, settings[:massModel]) # traction effort and resisting forces (in N)
|
||||
calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N)
|
||||
drivingCourse::Vector{Dict} = [startingPoint] # List of data points
|
||||
|
||||
for csId in 1:length(CSs)
|
||||
|
@ -96,7 +68,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
|
|||
|
||||
# determine the different flags for switching between the states for creatinge moving phases
|
||||
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel]) # tractive effort and resisting forces (in N)
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) # tractive effort and resisting forces (in N)
|
||||
|
||||
previousSpeedLimitReached = false
|
||||
stateFlags = Dict(:endOfCSReached => drivingCourse[end][:s] > CS[:s_exit],
|
||||
|
@ -122,11 +94,11 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
|
|||
|
||||
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached]
|
||||
# cruise only one step
|
||||
if settings[:stepVariable] =="s in m"
|
||||
s_cruising = settings[:stepSize]
|
||||
elseif settings[:stepVariable] =="t in s"
|
||||
s_cruising = calc_Δs_with_Δt(settings[:stepSize], drivingCourse[end][:a], drivingCourse[end][:v])
|
||||
elseif settings[:stepVariable] =="v in m/s"
|
||||
if settings.stepVariable == :distance
|
||||
s_cruising = settings.stepSize
|
||||
elseif settings.stepVariable == time
|
||||
s_cruising = calc_Δs_with_Δt(settings.stepSize, drivingCourse[end][:a], drivingCourse[end][:v])
|
||||
elseif settings.stepVariable == velocity
|
||||
s_cruising = train[:length]/(10.0) # TODO which step size should be used?
|
||||
end
|
||||
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising")
|
||||
|
@ -186,5 +158,3 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
|
|||
|
||||
return (movingSection, drivingCourse)
|
||||
end #function calculateMinimumRunningTime
|
||||
|
||||
end # module TrainRunCalc
|
|
@ -5,15 +5,8 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
module Characteristics
|
||||
|
||||
include("./Behavior.jl")
|
||||
using .Behavior
|
||||
|
||||
export determineCharacteristics
|
||||
|
||||
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior
|
||||
function determineCharacteristics(path::Dict, train::Dict, settings::Dict)
|
||||
function determineCharacteristics(path::Dict, train::Dict, settings::Settings)
|
||||
movingSection = createMovingSection(path, train[:v_limit])
|
||||
movingSection = secureBrakingBehavior!(movingSection, train[:a_braking])
|
||||
movingSection = secureAcceleratingBehavior!(movingSection, settings, train)
|
||||
|
@ -123,7 +116,7 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
|
|||
end #function secureBrakingBehavior!
|
||||
|
||||
## define the intersection velocities between the characterisitc sections to secure accelerating behavior
|
||||
function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train::Dict)
|
||||
function secureAcceleratingBehavior!(movingSection::Dict, settings::Settings, train::Dict)
|
||||
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
|
@ -136,7 +129,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train:
|
|||
CS[:v_entry] = min(CS[:v_entry], previousCSv_exit)
|
||||
startingPoint[:s] = CS[:s_entry]
|
||||
startingPoint[:v] = CS[:v_entry]
|
||||
calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings[:massModel]) # traction effort and resisting forces (in N)
|
||||
calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings.massModel) # traction effort and resisting forces (in N)
|
||||
acceleratingCourse::Vector{Dict} = [startingPoint] # List of data points
|
||||
|
||||
if CS[:v_entry] < CS[:v_peak]
|
||||
|
@ -160,7 +153,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train:
|
|||
(CS, acceleratingCourse, stateFlags) = addClearingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function is needed in case the train is not allowed to accelerate because of a previous speed limit
|
||||
end
|
||||
else
|
||||
if settings[:massModel] == "mass point" || acceleratingCourse[end][:s] > CS[:s_entry] + train[:length]
|
||||
if settings.massModel == :mass_point || acceleratingCourse[end][:s] > CS[:s_entry] + train[:length]
|
||||
break
|
||||
else
|
||||
(CS, acceleratingCourse, stateFlags) = addDiminishingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function is needed in case the resisitng forces are higher than the maximum possible tractive effort
|
||||
|
@ -190,7 +183,7 @@ end #function secureAcceleratingBehavior!
|
|||
|
||||
#=
|
||||
## define the intersection velocities between the characterisitc sections to secure cruising behavior
|
||||
function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dict)
|
||||
function secureCruisingBehavior!(movingSection::Dict, settings::Settings, train::Dict)
|
||||
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
|
@ -225,7 +218,7 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
|
|||
(CS, cruisingCourse, stateFlags) = addCruisingSection!(CS, cruisingCourse, stateFlags, s_cruising, settings, train, CSs, "downhillBraking")
|
||||
end
|
||||
else
|
||||
if settings[:massModel] == "mass point" || cruisingCourse[end][:s] > CS[:s_entry] + train[:length]
|
||||
if settings.massModel == :mass_point || cruisingCourse[end][:s] > CS[:s_entry] + train[:length]
|
||||
break
|
||||
else
|
||||
(CS, cruisingCourse, stateFlags) = addDiminishingSection!(CS, cruisingCourse, stateFlags, settings, train, CSs) # this function is needed in case the resisitng forces are higher than the maximum possible tractive effort
|
||||
|
@ -246,4 +239,3 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
|
|||
return movingSection
|
||||
end #function secureCruisingBehavior!
|
||||
=#
|
||||
end #module Characteristics
|
||||
|
|
1045
src/EnergySaving.jl
1045
src/EnergySaving.jl
File diff suppressed because it is too large
Load Diff
|
@ -5,32 +5,26 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
module Export
|
||||
|
||||
using CSV, DataFrames, Dates
|
||||
|
||||
export exportToCsv
|
||||
|
||||
function exportToCsv(runningTime::AbstractFloat, settings::Dict)
|
||||
function exportToCsv(runningTime::AbstractFloat, settings::Settings)
|
||||
createCsvFile(runningTime, settings)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function exportToCsv(dataPointsToExport::Vector{Dict}, settings::Dict)
|
||||
function exportToCsv(dataPointsToExport::Vector{Dict}, settings::Settings)
|
||||
createCsvFile(dataPointsToExport, settings)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function exportToCsv(output::Dict)
|
||||
if output[:settings][:typeOfOutput] == "CSV"
|
||||
if output[:settings][:outputFormat] == "CSV"
|
||||
pathName = output[:path][:name]
|
||||
trainName = output[:train][:name]
|
||||
|
||||
if output[:settings][:operationModeMinimumRunningTime] == true
|
||||
operationMode = "minimum running time"
|
||||
if output[:settings][:detailOfOutput] == "points of interest"
|
||||
if output[:settings][:outputDetail] == "points of interest"
|
||||
dataPointsToExport = output[:pointsOfInterestMinimumRunningTime]
|
||||
else
|
||||
dataPointsToExport = output[:drivingCourseMinimumRunningTime]
|
||||
|
@ -39,7 +33,7 @@ function exportToCsv(output::Dict)
|
|||
end
|
||||
if output[:settings][:operationModeMinimumEnergyConsumption] == true
|
||||
operationMode = "minimum energy consumption"
|
||||
if output[:settings][:detailOfOutput] == "points of interest"
|
||||
if output[:settings][:outputDetail] == "points of interest"
|
||||
dataPointsToExport = output[:pointsOfInterestMinimumEnergyConsumption]
|
||||
else
|
||||
dataPointsToExport = output[:drivingCourseMinimumEnergyConsumption]
|
||||
|
@ -51,15 +45,15 @@ function exportToCsv(output::Dict)
|
|||
return false
|
||||
end #function exportToCsv
|
||||
|
||||
function createCsvFile(runningTime::AbstractFloat, settings::Dict)
|
||||
function createCsvFile(runningTime::AbstractFloat, settings::Settings)
|
||||
# create DataFrame with running time information
|
||||
df = DataFrame(column1=["t (in s)", runningTime])
|
||||
|
||||
# save DataFrame as a CSV-file at csvDirectory
|
||||
# save DataFrame as a CSV-file at outputDir
|
||||
date = Dates.now()
|
||||
dateString = Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
|
||||
csvFilePath = settings[:csvDirectory]*"/"*dateString*"_RunningTime.csv"
|
||||
csvFilePath = settings[:outputDir]*"/"*dateString*"_RunningTime.csv"
|
||||
|
||||
CSV.write(csvFilePath, df, header=false)
|
||||
println("The output CSV file has been created at ",csvFilePath)
|
||||
|
@ -68,8 +62,8 @@ function createCsvFile(runningTime::AbstractFloat, settings::Dict)
|
|||
end #function createCsvFile
|
||||
|
||||
|
||||
function createCsvFile(dataPointsToExport::Vector{Dict}, settings::Dict)
|
||||
detailOfOutput = settings[:detailOfOutput]
|
||||
function createCsvFile(dataPointsToExport::Vector{Dict}, settings::Settings)
|
||||
outputDetail = settings[:outputDetail]
|
||||
|
||||
header = ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]
|
||||
columnSymbols = [:i, :behavior, :Δs, :s, :Δt, :t, :Δv, :v, :F_T, :F_R, :R_path, :R_train, :R_traction, :R_wagons, :ΔW, :W, :ΔE, :E, :a]
|
||||
|
@ -85,8 +79,8 @@ function createCsvFile(dataPointsToExport::Vector{Dict}, settings::Dict)
|
|||
end # for
|
||||
|
||||
|
||||
# combine the columns in a data frame and saving it as a CSV-file at csvDirectory
|
||||
if detailOfOutput == "driving course" || detailOfOutput == "points of interest"
|
||||
# combine the columns in a data frame and saving it as a CSV-file at outputDir
|
||||
if outputDetail == "driving course" || outputDetail == "points of interest"
|
||||
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18], c19=allColumns[19])
|
||||
|
||||
else
|
||||
|
@ -95,7 +89,7 @@ function createCsvFile(dataPointsToExport::Vector{Dict}, settings::Dict)
|
|||
|
||||
date = Dates.now()
|
||||
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_DataPoints.csv"
|
||||
csvFilePath=settings[:outputDir]*"/"*dateString*"_DataPoints.csv"
|
||||
CSV.write(csvFilePath, df, header=false)
|
||||
println("The output CSV file has been created at ",csvFilePath)
|
||||
|
||||
|
@ -103,12 +97,12 @@ function createCsvFile(dataPointsToExport::Vector{Dict}, settings::Dict)
|
|||
end #function createCsvFile
|
||||
|
||||
|
||||
function createCsvFile(dataPointsToExport::Vector{Dict}, operationMode::String, pathName::String, trainName::String, settings::Dict)
|
||||
detailOfOutput = settings[:detailOfOutput]
|
||||
function createCsvFile(dataPointsToExport::Vector{Dict}, operationMode::String, pathName::String, trainName::String, settings::Settings)
|
||||
outputDetail = settings[:outputDetail]
|
||||
|
||||
massModel = settings[:massModel]
|
||||
stepVariable = settings[:stepVariable]
|
||||
stepSize = string(settings[:stepSize])
|
||||
massModel = settings.massModel
|
||||
stepVariable = settings.stepVariable
|
||||
stepSize = string(settings.stepSize)
|
||||
|
||||
# create accumulated data block
|
||||
accumulatedData = Array{Any, 1}[]
|
||||
|
@ -135,15 +129,15 @@ function createCsvFile(dataPointsToExport::Vector{Dict}, operationMode::String,
|
|||
end
|
||||
end # for
|
||||
|
||||
# combine the columns in a data frame and saving it as a CSV-file at csvDirectory
|
||||
# combine the columns in a data frame and saving it as a CSV-file at outputDir
|
||||
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18], c19=allColumns[19])
|
||||
|
||||
date = Dates.now()
|
||||
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
if operationMode == "minimum running time"
|
||||
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumRunningTime.csv"
|
||||
csvFilePath=settings[:outputDir]*"/"*dateString*"_MinimumRunningTime.csv"
|
||||
elseif operationMode == "minimum energy consumption"
|
||||
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumEnergyConsumption.csv"
|
||||
csvFilePath=settings[:outputDir]*"/"*dateString*"_MinimumEnergyConsumption.csv"
|
||||
else
|
||||
# should not be possible
|
||||
end
|
||||
|
@ -156,20 +150,20 @@ end #function createCsvFile
|
|||
|
||||
|
||||
#=
|
||||
function createCsvFile(movingSection::Dict, dataPointsToExport::Vector{Dict}, operationMode::String, pathName::String, trainName::String, settings::Dict)
|
||||
detailOfOutput = settings[:detailOfOutput]
|
||||
function createCsvFile(movingSection::Dict, dataPointsToExport::Vector{Dict}, operationMode::String, pathName::String, trainName::String, settings::Settings)
|
||||
outputDetail = settings[:outputDetail]
|
||||
|
||||
massModel = settings[:massModel]
|
||||
stepVariable = settings[:stepVariable]
|
||||
stepSize = string(settings[:stepSize])
|
||||
massModel = settings.massModel
|
||||
stepVariable = settings.stepVariable
|
||||
stepSize = string(settings.stepSize)
|
||||
|
||||
# create accumulated data block
|
||||
accumulatedData = Array{Any, 1}[]
|
||||
if detailOfOutput == "minimal"
|
||||
if outputDetail == "minimal"
|
||||
push!(accumulatedData, ["s (in m)", "t (in s)","E (in Ws)"]) # push header to accumulatedData
|
||||
row = [movingSection[:length], movingSection[:t], movingSection[:E]]
|
||||
push!(accumulatedData, row) # push row to accumulatedData
|
||||
elseif detailOfOutput == "driving course" || detailOfOutput == "points of interest"
|
||||
elseif outputDetail == "driving course" || outputDetail == "points of interest"
|
||||
push!(accumulatedData, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to accumulatedData
|
||||
for point in dataPointsToExport
|
||||
row = [point[:i], point[:behavior], point[:Δs], point[:s], point[:Δt], point[:t], point[:Δv], point[:v], point[:F_T], point[:F_R], point[:R_path], point[:R_train], point[:R_traction], point[:R_wagons], point[:ΔW], point[:W], point[:ΔE], point[:E], point[:a]]
|
||||
|
@ -194,19 +188,19 @@ function createCsvFile(movingSection::Dict, dataPointsToExport::Vector{Dict}, op
|
|||
end
|
||||
end # for
|
||||
|
||||
# combine the columns in a data frame and saving it as a CSV-file at csvDirectory
|
||||
if detailOfOutput == "minimal"
|
||||
# combine the columns in a data frame and saving it as a CSV-file at outputDir
|
||||
if outputDetail == "minimal"
|
||||
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
|
||||
elseif detailOfOutput=="driving course" || detailOfOutput == "points of interest"
|
||||
elseif outputDetail=="driving course" || outputDetail == "points of interest"
|
||||
df = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18], c19=allColumns[19])
|
||||
end
|
||||
|
||||
date = Dates.now()
|
||||
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
if operationMode == "minimum running time"
|
||||
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumRunningTime.csv"
|
||||
csvFilePath=settings[:outputDir]*"/"*dateString*"_MinimumRunningTime.csv"
|
||||
elseif operationMode == "minimum energy consumption"
|
||||
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumEnergyConsumption.csv"
|
||||
csvFilePath=settings[:outputDir]*"/"*dateString*"_MinimumEnergyConsumption.csv"
|
||||
else
|
||||
# should not be possible
|
||||
end
|
||||
|
@ -216,5 +210,3 @@ function createCsvFile(movingSection::Dict, dataPointsToExport::Vector{Dict}, op
|
|||
return true
|
||||
end #function createCsvFile
|
||||
=#
|
||||
|
||||
end #module Export
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
# __copyright__ = "2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
module Formulary
|
||||
|
||||
#########################
|
||||
## literature the driving dynamics equations are based on:
|
||||
##
|
||||
|
@ -21,17 +19,6 @@ module Formulary
|
|||
## isbn = {978-3-777-10462-1},
|
||||
## publisher = {Eurailpress DVV Media Group},
|
||||
## }
|
||||
## @article{Jaekel:2014,
|
||||
## author = {Jaekel, Birgit and Albrecht, Thomas},
|
||||
## year = {2014},
|
||||
## title = {Comparative analysis of algorithms and models for train running simulation},
|
||||
## journal = {Journal of Rail Transport Planning \& Management},
|
||||
## doi = {10.1016/j.jrtpm.2014.06.002},
|
||||
## volume = {4},
|
||||
## number = {1-2},
|
||||
## pages = {14--27},
|
||||
## publisher = {Elsevier},
|
||||
## }
|
||||
## @Book{Wende:2003,
|
||||
## author = {Wende, Dietrich},
|
||||
## date = {2003},
|
||||
|
@ -41,25 +28,10 @@ module Formulary
|
|||
## }
|
||||
#########################
|
||||
|
||||
# export resisting forces and acceleration
|
||||
export calcTractionUnitResistance, calcWagonsResistance, calcForceFromCoefficient, calcAcceleration,
|
||||
|
||||
# export step sizes in different units
|
||||
calc_Δs_with_Δt, calc_Δs_with_Δv,
|
||||
calc_Δt_with_Δs, calc_Δt_with_Δv, calc_Δt_with_constant_v,
|
||||
calc_Δv_with_Δs, calc_Δv_with_Δt,
|
||||
calc_ΔW, calc_ΔE,
|
||||
|
||||
# export braking information
|
||||
calcBrakingDistance, calcBrakingStartVelocity, calcBrakingAcceleration
|
||||
|
||||
approxLevel = 6
|
||||
v00 = 100/3.6 # velocity factor (in m/s)
|
||||
g = 9.81 # acceleration due to gravity (in m/s^2) # TODO: should more digits of g be used? g=9,80665 m/s^2
|
||||
|
||||
approximationLevel = 6 # value for approximation to intersections TODO further explanation (e.g. approximationLevel = 3 -> with stepSize 10 m the approximation will be calculated accurate on 10 mm ; 1s -> 1 ms; 1 km/h -> 3.6 mm/s)
|
||||
# TODO: necessary here?
|
||||
|
||||
|
||||
## calculate forces
|
||||
|
||||
#TODO: replace the ? ? ?
|
||||
|
@ -213,8 +185,8 @@ function calc_ΔW(F_T_prev::Real, Δs::Real)
|
|||
end #function calc_ΔW
|
||||
|
||||
function calc_ΔE(ΔW::Real)
|
||||
# simplified equation is based on [Jaekel:2014, page 6]
|
||||
|
||||
# simplified equation
|
||||
# TODO!
|
||||
# ΔW: mechanical work in this step (in Ws)
|
||||
ΔE = ΔW # energy consumption in this step (in Ws)
|
||||
return ΔE
|
||||
|
@ -228,8 +200,8 @@ function calcBrakingDistance(v_start::Real, v_end::Real, a_braking::Real)
|
|||
# a_braking: constant braking acceleration (in m/s^2)
|
||||
s_braking = (v_end^2 - v_start^2) /2 /a_braking # braking distance (in m)
|
||||
# TODO: also possible: calc_Δs_with_Δv(v_end-v_start, a_braking, v_start)
|
||||
# return max(0.0, ceil(s_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
|
||||
return max(0.0, ceil(s_braking, digits=approximationLevel +1)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
|
||||
# return max(0.0, ceil(s_braking, digits=approxLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
|
||||
return max(0.0, ceil(s_braking, digits=approxLevel +1)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
|
||||
end #function calcBrakingDistance
|
||||
|
||||
function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real)
|
||||
|
@ -239,8 +211,8 @@ function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real)
|
|||
# a_braking: constant braking acceleration (in m/s^2)
|
||||
# s_braking: braking distance (in Ws)
|
||||
v_start = sqrt(v_end^2 - 2*a_braking *s_braking) # braking start velocity (in m/s)
|
||||
# return floor(v_start, digits=approximationLevel)
|
||||
return floor(v_start, digits=approximationLevel +1)
|
||||
# return floor(v_start, digits=approxLevel)
|
||||
return floor(v_start, digits=approxLevel +1)
|
||||
end #function calcBrakingStartVelocity
|
||||
|
||||
function calcBrakingAcceleration(v_start::Real, v_end::Real, s_braking::Real)
|
||||
|
@ -252,5 +224,3 @@ function calcBrakingAcceleration(v_start::Real, v_end::Real, s_braking::Real)
|
|||
a_braking = (v_end^2 - v_start^2) /2 /s_braking # constant braking acceleration (in m/s^2)
|
||||
return a_braking
|
||||
end #function calcBrakingAcceleration
|
||||
|
||||
end #module Formulary
|
||||
|
|
|
@ -5,21 +5,14 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
module Import
|
||||
|
||||
import YAML
|
||||
|
||||
export importYamlFiles, importFromYaml
|
||||
|
||||
"""
|
||||
Read the input information from YAML files for train, path and settings, save it in different dictionaries and return them.
|
||||
"""
|
||||
function importYamlFiles(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
|
||||
function importYamlFiles(trainDirectory::String, pathDirectory::String)
|
||||
train = importFromYaml(:train, trainDirectory)
|
||||
path = importFromYaml(:path, pathDirectory)
|
||||
settings = importFromYaml(:settings, settingsDirectory)
|
||||
|
||||
return (train, path, settings)
|
||||
return (train, path)
|
||||
end #function importYamlFiles
|
||||
|
||||
"""
|
||||
|
@ -40,5 +33,3 @@ function importFromYaml(dataType::Symbol, directory::String)
|
|||
end
|
||||
return dictionary
|
||||
end # function importFromYaml
|
||||
|
||||
end # module Input
|
||||
|
|
|
@ -5,15 +5,11 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
module Output
|
||||
|
||||
export createOutput
|
||||
|
||||
function createOutput(train::Dict, settings::Dict, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
if settings[:detailOfOutput] == "running time"
|
||||
function createOutput(train::Dict, settings::Settings, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
if settings.outputDetail == :running_time
|
||||
output = movingSection[:t] # TODO: or use drivingCourse[end][:t]
|
||||
|
||||
elseif settings[:detailOfOutput] == "points of interest"
|
||||
elseif settings.outputDetail == :points_of_interest
|
||||
# add points of interest
|
||||
if haskey(path, :pointsOfInterest)
|
||||
output = Vector{Dict}()
|
||||
|
@ -28,10 +24,10 @@ function createOutput(train::Dict, settings::Dict, path::Dict, movingSection::Di
|
|||
end
|
||||
end
|
||||
|
||||
elseif settings[:detailOfOutput] == "driving course"
|
||||
elseif settings.outputDetail == :driving_course
|
||||
output = drivingCourse
|
||||
|
||||
elseif settings[:detailOfOutput] == "everything"
|
||||
elseif settings.outputDetail == :everything
|
||||
output = Dict{Symbol,Any}()
|
||||
merge!(output, Dict(:train => train, :path => path, :settings => settings))
|
||||
|
||||
|
@ -71,7 +67,7 @@ function createOutput(train::Dict, settings::Dict, path::Dict, movingSection::Di
|
|||
end
|
||||
|
||||
#=
|
||||
function createOutputDict(train::Dict, settings::Dict, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
function createOutputDict(train::Dict, settings::Settings, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
outputDict = Dict{Symbol,Any}()
|
||||
merge!(outputDict, Dict(:train => train, :path => path, :settings => settings))
|
||||
|
||||
|
@ -108,5 +104,3 @@ function createOutputDict(train::Dict, settings::Dict, path::Dict, movingSection
|
|||
return outputDict
|
||||
end # function createOutputDict
|
||||
=#
|
||||
|
||||
end # module Output
|
||||
|
|
|
@ -1,55 +1,30 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.2
|
||||
# __author__ = "Max Kannenberg"
|
||||
# __author__ = "Max Kannenberg, Martin Scheidt"
|
||||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
__precompile__(true)
|
||||
|
||||
module TrainRun
|
||||
|
||||
# include main module TrainRunCalc
|
||||
include("./TrainRunCalc.jl")
|
||||
## loading external packages
|
||||
using YAML, JSONSchema, CSV, DataFrames, Dates
|
||||
|
||||
# include additional modules
|
||||
include("./Import.jl")
|
||||
include("./Export.jl")
|
||||
## include package files
|
||||
include("types.jl")
|
||||
include("formulary.jl")
|
||||
include("characteristics.jl")
|
||||
include("behavior.jl")
|
||||
include("output.jl")
|
||||
include("import.jl")
|
||||
include("export.jl")
|
||||
include("calc.jl")
|
||||
|
||||
# include additional modules that are not recommended to use in this state
|
||||
include("./AdditionalOutput.jl")
|
||||
include("./EnergySaving.jl")
|
||||
|
||||
# use main module TrainRunCalc
|
||||
using .TrainRunCalc
|
||||
|
||||
# use additional modules
|
||||
using .Import
|
||||
using .Export
|
||||
|
||||
# use additional modules that are not recommended to use in this state
|
||||
using .AdditionalOutput
|
||||
using .EnergySaving
|
||||
|
||||
# main function
|
||||
export trainRun,
|
||||
|
||||
# import functions
|
||||
importYamlFiles, importFromYaml,
|
||||
|
||||
# functions for saving energy that are not recommended to use in this state
|
||||
addOperationModeEnergySaving!,
|
||||
|
||||
# export functions
|
||||
exportToCsv,
|
||||
|
||||
# functions for visualising results that are not recommended to use in this state
|
||||
plotResults, plotDrivingCourse, printImportantValues, printSectionInformation
|
||||
|
||||
# approximationLevel = 6 # value for approximation to intersections
|
||||
# TODO: define it here and give it to each function? (Behavior, EnergySaving, ..)
|
||||
|
||||
"""
|
||||
TODO: Package description
|
||||
"""
|
||||
export
|
||||
## Interface
|
||||
trainRun, Settings, exportToCsv
|
||||
|
||||
## main functions
|
||||
|
||||
end # module TrainRun
|
||||
|
|
|
@ -1,31 +1,120 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.2
|
||||
# __author__ = "Max Kannenberg"
|
||||
# __author__ = "Max Kannenberg, Martin Scheidt"
|
||||
# __copyright__ = "2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
# TODO: 2022-04-07: if EnergySaving should be used. The train type has do be defined and checked
|
||||
module Validate
|
||||
"""
|
||||
Settings(file)
|
||||
|
||||
export checkAndSetInput!
|
||||
Settings is a datastruture for calculation context.
|
||||
The function Settings() will create a set of settings for the train run calculation.
|
||||
`file` is optinal may be used to load settings in the YAML format.
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> my_settings = Settings() # will generate default settings
|
||||
Settings(mass_point, :distance, 20, 3, running_time, julia_dict, ".")
|
||||
```
|
||||
"""
|
||||
struct Settings
|
||||
|
||||
approximationLevel = 6 # value for approximation to intersections TODO further explanation
|
||||
massModel::Symbol # model type of train mass ":mass_point" or ":homogeneous_strip".
|
||||
stepVariable::Symbol # variable of the linear multistep method: ":distance", ":time" or ":velocity".
|
||||
stepSize::Real # step size, unit depends on stepVariable - :distance in meter, time in seconds and velocity in meter/second.
|
||||
approxLevel::Int # value for approximation; used when rounding or interating.
|
||||
outputDetail::Symbol # single Float() ":running_time", Array() of ":points_of_interest",
|
||||
# complete Array() ":driving_course", or Dict() ":everything".
|
||||
outputFormat::Symbol # output as ":julia_dict" or as ":csv".
|
||||
outputDir::String # if outputFormat is not ":julia_dict".
|
||||
|
||||
## constructor
|
||||
function Settings(file="DEFAULT")
|
||||
|
||||
## default values
|
||||
massModel = :mass_point
|
||||
stepVariable = :distance
|
||||
stepSize = 20
|
||||
approxLevel = 3
|
||||
outputDetail = :running_time
|
||||
outputFormat = :julia_dict
|
||||
outputDir = "."
|
||||
|
||||
if file != "DEFAULT"
|
||||
## JSON schema for YAML-file validation
|
||||
schema = Schema("""{
|
||||
"properties": {
|
||||
"massModel": {
|
||||
"description": "type of train model",
|
||||
"type": "string",
|
||||
"enum": [ "mass_point", "homogeneous_strip" ]
|
||||
},
|
||||
"stepVariable": {
|
||||
"description": "variable of the linear multistep method",
|
||||
"type": "string",
|
||||
"enum": [ "distance", "time", "velocity" ]
|
||||
},
|
||||
"stepSize": {
|
||||
"description": "step size acording to stepVariable",
|
||||
"type": "number",
|
||||
"exclusiveMinimum": 0
|
||||
},
|
||||
"outputDetail": {
|
||||
"description": "Selecting the detail of the result",
|
||||
"type": "string",
|
||||
"enum": [ "running_time", "points_of_interest", "driving_course", "everything" ]
|
||||
},
|
||||
"outputFormat": {
|
||||
"description": "Output format",
|
||||
"type": "string",
|
||||
"enum": [ "julia_dict", "csv" ]
|
||||
},
|
||||
"outputDir": {
|
||||
"description": "Path for the CSV export",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}""")
|
||||
|
||||
settings = YAML.load(open(file))["settings"]
|
||||
|
||||
## validate the loaded file
|
||||
try
|
||||
validate(schema, settings)
|
||||
catch err
|
||||
println("Could not load settings file $file.\n Format is not recognized - using default as fall back.")
|
||||
settings = Dict()
|
||||
end
|
||||
|
||||
## set the variables if they exist in "settings"
|
||||
haskey(settings, "massModel") ? massModel = Symbol(settings["massModel"]) : nothing
|
||||
haskey(settings, "stepVariable") ? stepVariable = Symbol(settings["stepVariable"]) : nothing
|
||||
haskey(settings, "stepSize") ? stepSize = settings["stepSize"] : nothing
|
||||
haskey(settings, "approxLevel") ? approxLevel = settings["approxLevel"] : nothing
|
||||
haskey(settings, "outputDetail") ? outputDetail = Symbol(settings["outputDetail"]) : nothing
|
||||
haskey(settings, "outputFormat") ? outputFormat = Symbol(settings["outputFormat"]) : nothing
|
||||
haskey(settings, "outputDir") ? outputDir = settings["outputDir"] : nothing
|
||||
end
|
||||
|
||||
new(massModel, stepVariable, stepSize, approxLevel, outputDetail, outputFormat, outputDir)
|
||||
|
||||
end #function Settings() # constructor
|
||||
|
||||
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::Dict)
|
||||
checkAndSetTrain!(train)
|
||||
checkAndSetPath!(path)
|
||||
checkAndSetSettings!(settings)
|
||||
function checkAndSetInput!(train::Dict, path::Dict, settings::Settings)
|
||||
checkAndSetTrain!(train)
|
||||
checkAndSetPath!(path)
|
||||
|
||||
if settings[:detailOfOutput] == "points of interest" && !haskey(path, :pointsOfInterest)
|
||||
settings[:detailOfOutput] = "driving course"
|
||||
println("INFO at checking the input for settings and path: settings[:detailOfOutput] is 'points of interest' but the path does not have a list for pointsOfInterest. Therefore the detailOfOut is changed to 'driving course'.")
|
||||
end
|
||||
return (train, path, settings)
|
||||
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."))
|
||||
end
|
||||
return (train, path)
|
||||
end #function checkAndSetInput!
|
||||
|
||||
"""
|
||||
|
@ -102,39 +191,6 @@ function checkAndSetPath!(path::Dict)
|
|||
return path
|
||||
end # function checkAndSetPath!
|
||||
|
||||
|
||||
## settings for the calculation
|
||||
function checkAndSetSettings!(settings::Dict)
|
||||
# check settings information from input dictionary
|
||||
|
||||
checkAndSetString!(settings, "settings", :massModel, "mass point", ["mass point", "homogeneous strip"]) # model type of the train's mass "mass point" or "homogeneous strip"
|
||||
checkAndSetString!(settings, "settings", :stepVariable, "s in m", ["s in m", "t in s", "v in m/s"]) # step variable of the step method "s in m", "t in s" or "v in m/s"
|
||||
|
||||
checkAndSetPositiveNumber!(settings, "settings", :stepSize, "("*settings[:stepVariable]*")", getDefaultStepSize(settings[:stepVariable])) # step size (unit depends on stepVariable: s in m, t in s and v in m/s)
|
||||
checkAndSetBool!(settings, "settings", :operationModeMinimumRunningTime, true) # operation mode "minimum running time"
|
||||
checkAndSetBool!(settings, "settings", :operationModeMinimumEnergyConsumption, false) # operation mode "minimum energy consumption"
|
||||
checkAndSetString!(settings, "settings", :typeOfOutput, "julia dictionary", ["julia dictionary", "CSV"]) # output as "julia dictionary" or as "CSV"
|
||||
|
||||
if settings[:typeOfOutput] == "CSV"
|
||||
checkAndSetString!(settings, "settings", :csvDirectory, "~/Desktop/TrainRun")
|
||||
# TODO use correct default directory
|
||||
# TODO: it could be checked if the path is existing on the pc
|
||||
end # if
|
||||
|
||||
checkAndSetString!(settings, "settings", :detailOfOutput, "running time", ["running time", "points of interest", "driving course", "everything"]) # should the output be only the value of the "running time", or an array of "points of interest" or the complete "driving course" as array or a dictionary with "everything"?
|
||||
|
||||
# inform the user about keys of the input dictionary that are not used in this tool
|
||||
usedKeys = [:massModel, :stepVariable, :stepSize,
|
||||
:operationModeMinimumRunningTime, :operationModeMinimumEnergyConsumption,
|
||||
:typeOfOutput, :detailOfOutput]
|
||||
if settings[:typeOfOutput] == "CSV"
|
||||
push!(usedKeys, :csvDirectory)
|
||||
end
|
||||
informAboutUnusedKeys(collect(keys(settings)), usedKeys::Vector{Symbol}, "settings")
|
||||
|
||||
return settings
|
||||
end # function checkAndSetSettings!
|
||||
|
||||
function checkAndSetBool!(dictionary::Dict, dictionaryType::String, key::Symbol, defaultValue::Bool)
|
||||
if haskey(dictionary,key) && dictionary[key]!=nothing
|
||||
if typeof(dictionary[key]) != Bool
|
||||
|
@ -186,7 +242,7 @@ function checkAndSetPositiveNumberWithDifferentNames!(dictionary::Dict, dictiona
|
|||
|
||||
if mainKey_temp >= 0.0 && alternativeKey_temp >= 0.0
|
||||
difference = abs(mainKey_temp - alternativeKey_temp)
|
||||
if difference > 1/(10^approximationLevel) # TODO or use difference > 0.0 ?
|
||||
if difference > 1/(10^approxLevel) # TODO or use difference > 0.0 ?
|
||||
delete!(dictionary, alternativeKey)
|
||||
println("WARNING at checking the input for the ",dictionaryType,": The values of ",mainKey," and ",alternativeKey," differ by ",difference," ",unit,". The value ",String(mainKey),"=",default," ",unit," is used." )
|
||||
end
|
||||
|
@ -226,7 +282,7 @@ function checkAndSetPositiveNumberWithDifferentNames!(dictionary::Dict, dictiona
|
|||
|
||||
if mainKey_temp >= 0.0 && alternativeKey_temp >= 0.0
|
||||
difference = abs(mainKey_temp - alternativeKey_temp)
|
||||
if difference > 1/(10^approximationLevel) # TODO or use difference > 0.0 ?
|
||||
if difference > 1/(10^approxLevel) # TODO or use difference > 0.0 ?
|
||||
delete!(dictionary, alternativeKey)
|
||||
println("WARNING at checking the input for the ",dictionaryType,": The values of ",mainKey," and ",alternativeKey," differ by ",difference," ",unit,". The value ",String(mainKey),"=",default," ",unit," is used." )
|
||||
end
|
||||
|
@ -261,7 +317,7 @@ function checkAndSetSum!(dictionary::Dict, dictionaryType::String, sum::Symbol,
|
|||
if haskey(dictionary,sum) && dictionary[sum]!=nothing
|
||||
if typeof(dictionary[sum]) <: Real && dictionary[sum] >= 0.0
|
||||
difference = abs(dictionary[sum] - (dictionary[summand1]+dictionary[summand2]))
|
||||
if difference > 1/(10^approximationLevel)
|
||||
if difference > 1/(10^approxLevel)
|
||||
error("ERROR at checking the input for the ",dictionaryType,": The value of ",String(sum)," is not exactly the sum of ",String(summand1)," and ",String(summand2),". It differs by ",difference,".")
|
||||
end
|
||||
else
|
||||
|
@ -332,7 +388,7 @@ function checkAndSetSpeedLimit!(train::Dict)
|
|||
|
||||
if v_limit_temp > 0.0 && v_limit_kmh_temp > 0.0
|
||||
difference = abs(v_limit_temp - v_limit_kmh_temp/3.6)
|
||||
if difference > 1/(10^approximationLevel) # TODO or use difference > 0.0 ?
|
||||
if difference > 1/(10^approxLevel) # TODO or use difference > 0.0 ?
|
||||
delete!(train, :v_limit_kmh)
|
||||
println("WARNING at checking the input for the train: The values of v_limit and v_limit_kmh differ by ",difference," m/s. The value v_limit=",v_limit_temp," m/s is used." )
|
||||
end
|
||||
|
@ -388,7 +444,7 @@ function checkAndSetRotationMassFactors!(train::Dict)
|
|||
if haskey(train, :ξ_t) && train[:ξ_t]!=nothing && train[:ξ_t]>0.0 && (train[:m_w]==0.0 || (haskey(train, :ξ_w) && train[:ξ_w]!=nothing))
|
||||
# TODO: is && train[:ξ_t]>0.0 necessary here?
|
||||
difference = abs(train[:ξ_train] - (train[:ξ_t]*train[:m_t] + train[:ξ_w]*train[:m_w])/train[:m_train])
|
||||
if difference > 1/(10^approximationLevel)
|
||||
if difference > 1/(10^approxLevel)
|
||||
error("ERROR at checking the input for the train: The value of ξ_train is not exactly ξ_train=(ξ_t*m_t + ξ_w*m_w)/m_train. It differs by ",difference,".")
|
||||
end
|
||||
end
|
||||
|
@ -717,18 +773,6 @@ function checkAndSetPOIs!(path::Dict)
|
|||
return path
|
||||
end #function checkAndSetPOIs!
|
||||
|
||||
function getDefaultStepSize(stepVariable::String)
|
||||
if stepVariable == "s in m"
|
||||
return 10.0
|
||||
elseif stepVariable == "t in s"
|
||||
return 3.0
|
||||
elseif stepVariable == "v in m/s"
|
||||
return 0.1
|
||||
#else
|
||||
# error("ERROR at getting a default step size. The step variable ",stepVariable," can not be used.")
|
||||
end
|
||||
end #function getDefaultStepSize
|
||||
|
||||
#function informAboutUnusedKeys(dictionary::Dict, dictionaryType::String) # inform the user which Symbols of the input dictionary are not used in this tool
|
||||
function informAboutUnusedKeys(allKeys::AbstractVector, usedKeys::Vector{Symbol}, dictionaryType::String) # inform the user which Symbols of the input dictionary are not used in this tool
|
||||
unusedKeys = []
|
||||
|
@ -753,5 +797,3 @@ function informAboutUnusedKeys(allKeys::AbstractVector, usedKeys::Vector{Symbol}
|
|||
end
|
||||
end
|
||||
end #function informAboutUnusedKeys
|
||||
|
||||
end # module Validate
|
|
@ -0,0 +1,5 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputFormat: "csv" # output as "julia_dict" or as "csv"
|
||||
outputDir: "." # used if other outputFormat than "julia dict"
|
|
@ -0,0 +1,9 @@
|
|||
%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: "driving_course" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
|
@ -0,0 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
massModel: "homogeneous_strip" # type of train model used: "mass_point" or "homogeneous_strip"
|
|
@ -0,0 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
stepVariable: "time" # variable of the linear multistep method: "distance", "time" or "velocity"
|
|
@ -0,0 +1,5 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
stepVariable: "time" # variable of the linear multistep method: "distance", "time" or "velocity"
|
||||
massModel: "homogeneous_strip" # type of train model used: "mass_point" or "homogeneous_strip"
|
|
@ -0,0 +1,5 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
stepVariable: "velocity" # variable of the linear multistep method: "distance", "time" or "velocity"
|
||||
stepSize: 0.1 # step size, unit depends on stepVariable - position in meter, time in seconds and velocity in meter/second
|
|
@ -1,40 +1,69 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.0
|
||||
# __author__ = "Max Kannenberg"
|
||||
# __author__ = "Max Kannenberg, Martin Scheidt"
|
||||
# __copyright__ = "2021"
|
||||
# __license__ = "ISC"
|
||||
|
||||
using TrainRun, Test
|
||||
|
||||
allPaths=[]
|
||||
push!(allPaths, importYamlFile(:path, "data/paths/path_1_10km_nConst_vConst.yaml"))
|
||||
push!(allPaths, importYamlFile(:path, "data/paths/path_2_10km_nVar_vConst.yaml"))
|
||||
push!(allPaths, importYamlFile(:path, "data/paths/path_3_10km_nConst_vVar.yaml"))
|
||||
push!(allPaths, importYamlFile(:path, "data/paths/path_4_real_Germany_EastSaxony_DG-DN.yaml"))
|
||||
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"))
|
||||
|
||||
allSettings=[]
|
||||
push!(allSettings, importYamlFile(:settings, "data/settings.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"))
|
||||
|
||||
allTrains=[]
|
||||
push!(allTrains, importYamlFile(:train, "data/trains/train_freight_V90withOreConsist.yaml"))
|
||||
push!(allTrains, importYamlFile(:train, "data/trains/train_passenger_SiemensDesiroClassic.yaml"))
|
||||
push!(allTrains, importYamlFile(:train, "data/trains/train_passenger_IC2.yaml"))
|
||||
@testset "TrainRun.jl" begin
|
||||
|
||||
for path in allPaths
|
||||
for train in allTrains
|
||||
for settings in allSettings
|
||||
testDict=trainRun(train, path, settings)
|
||||
exportToCsv(testDict)
|
||||
sleep(2)
|
||||
@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
|
||||
# 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)
|
||||
end
|
||||
|
||||
# TODO:
|
||||
# compare result to test data set
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
println("test finished")
|
||||
# TODO:
|
||||
# print test results
|
||||
end
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.0
|
||||
# __author__ = "Martin Scheidt"
|
||||
# __copyright__ = "2021"
|
||||
# __license__ = "ISC"
|
||||
|
||||
include("../src/types.jl")
|
||||
include("../src/Validate.jl")
|
||||
|
||||
using .Input
|
||||
using YAML, Test
|
||||
|
||||
@enum trainType passenger=1 freight=2 motorCoachTrain=3
|
||||
|
||||
@test Input.getEnum("passenger", trainType) == passenger::trainType
|
||||
@test Input.getEnum("freight", trainType) == freight::trainType
|
||||
@test Input.getEnum("motorCoachTrain", trainType) == motorCoachTrain::trainType
|
||||
|
||||
data = YAML.load(open("data/trains/train_passenger_IC2.yaml"))
|
||||
@test Input.getEnum(data["train"]["trainType"], trainType) == passenger::trainType
|
||||
|
||||
data = YAML.load(open("data/trains/train_freight_V90withOreConsist.yaml"))
|
||||
@test Input.getEnum(data["train"]["trainType"], trainType) == freight::trainType
|
Loading…
Reference in New Issue