Integrate calculation for additional points of interest

development
Max Kannenberg 2022-01-22 03:11:43 +01:00
parent 8802ef7bc7
commit 917a16782d
13 changed files with 763 additions and 470 deletions

View File

@ -21,9 +21,10 @@ Review the settings.yaml file for your appropriate settings.
include("../src/TrainRun.jl")
using .TrainRun
train = "data/trains/train_freight_V90withOreConsist.yaml"
running_path = "data/paths/path_1_10km_nConst_vConst.yaml"
settings = "data/settings.yaml"
train_directory = "data/trains/train_freight_V90withOreConsist.yaml"
running_path_directory = "data/paths/path_1_10km_nConst_vConst.yaml"
settings_directory = "data/settings.yaml"
(train, running_path, settings) = importYamlFiles(train_directory, running_path_directory, setting_directory)
train_run = calculateDrivingDynamics(train, running_path, settings)
```

View File

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

View File

@ -2,6 +2,7 @@
---
path:
name: "10 km, different gradient, 160 km/h"
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
- [0, 160, 0]

View File

@ -2,6 +2,7 @@
---
path:
name: "10 km, no gradient, different speed limits"
pointsOfInterest: [999, 2000, 3333.3, 5000, 7777, 9000, 9500.95] # points of interest: positions in m
sectionStarts: # with path speed limt (in m/s) # [s in m, v_limit in m/s, f_Rp in ‰]
sectionStarts_kmh: # with path speed limt (in km/h) # [s in m, v_limit in km/h, f_Rp in ‰]
- [0, 160, 0.0]

View File

@ -125,10 +125,10 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{Dict},driving
println("Plots for different variables have been created.")
end #function plotDrivingCourse
function printImportantValues(drivingCourse::Vector{Dict})
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(drivingCourse)
println(drivingCourse[i][:i],". ",drivingCourse[i][:s]," ",drivingCourse[i][:v]*3.6," ",drivingCourse[i][:t]/60," ",drivingCourse[i][:a]," ",drivingCourse[i][:F_R]/1000," ",drivingCourse[i][:F_T]/1000," ",drivingCourse[i][:E]/3600/1000)
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
@ -136,13 +136,13 @@ end #function printImportantValues
function printSectionInformation(movingSection::Dict)
CSs::Vector{Dict} = movingSection[:characteristicSections]
println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t])
println("MS with length=", movingSection[:length]," with t=", movingSection[:t])
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :braking, :standstill]
for csId in 1:length(CSs)
println("CS ",csId," mit length=", CSs[csId][:length]," mit t=", CSs[csId][:t])
println("CS ",csId," with length=", CSs[csId][:length]," with t=", CSs[csId][:t])
for bs in 1: length(allBs)
if haskey(CSs[csId][:behaviorSections], allBs[bs])
println("BS ",allBs[bs], " mit s_entry=", CSs[csId][:behaviorSections][allBs[bs]][:s_entry], " und t=", CSs[csId][:behaviorSections][allBs[bs]][:t])
println("BS ",allBs[bs], " with s_entry=", CSs[csId][:behaviorSections][allBs[bs]][:s_entry], " and t=", CSs[csId][:behaviorSections][allBs[bs]][:t])
# for point in 1:length(CSs[csId][:behaviorSections][allBs[bs]][:dataPoints])
# println(CSs[csId][:behaviorSections][allBs[bs]][:dataPoints][point])
# end

File diff suppressed because it is too large Load Diff

View File

@ -29,12 +29,12 @@ function createMovingSection(path::Dict, v_trainLimit::Real)
previousSection = path[:sections][row-1]
currentSection = path[:sections][row]
if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit)))
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), path))
s_csStart = currentSection[:s_start]
csId = csId+1
end #if
end #for
push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][end], min(path[:sections][end][:v_limit], v_trainLimit)))
push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][end], min(path[:sections][end][:v_limit], v_trainLimit), path))
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore
:length => pathLength, # total length (in m)
@ -49,21 +49,36 @@ end #function createMovingSection
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
function createCharacteristicSection(csId::Integer, s_csStart::Real, section::Dict, v_csLimit::Real)
function createCharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, path::Dict)
# Create and return a characteristic section dependent on the paths attributes
characteristicSection= Dict(:id => csId, # identifier
:s_entry => s_csStart, # first position (in m)
characteristicSection= Dict(:id => id, # identifier
:s_entry => s_entry, # first position (in m)
:s_exit => section[:s_end], # last position (in m)
:length => section[:s_end]-s_csStart, # total length (in m)
:length => section[:s_end] -s_entry, # total length (in m)
:r_path => section[:f_Rp], # path resistance (in ‰)
:behaviorSections => Dict(), # list of containing behavior sections
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_limit => v_csLimit, # speed limit (in m/s)
:v_limit => v_limit, # speed limit (in m/s)
# initializing :v_entry, :v_peak and :v_exit with :v_limit
:v_peak => v_csLimit, # maximum reachable speed (in m/s)
:v_entry => v_csLimit, # maximum entry speed (in m/s)
:v_exit => v_csLimit) # maximum exit speed (in m/s)
:v_peak => v_limit, # maximum reachable speed (in m/s)
:v_entry => v_limit, # maximum entry speed (in m/s)
:v_exit => v_limit) # maximum exit speed (in m/s)
# list of positions of every point of interest (POI) in this charateristic section for which data points should be calculated
s_exit = characteristicSection[:s_exit]
pointsOfInterest = Vector{Real}()
if haskey(path, :pointsOfInterest)
for POI in path[:pointsOfInterest]
if s_entry < POI && POI < s_exit
push!(pointsOfInterest, POI)
end
end
end
push!(pointsOfInterest, s_exit) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
return characteristicSection
end #function createCharacteristicSection

View File

@ -4,6 +4,7 @@
# TODO: calculation time for passenger trains on path1 is very long and should be reduced
# TODO from 2022/01/18: Test if enum trainType is working correctly in function calculateRecoveryTime or if only the else-pathis taken
# TODO from 2022/01/19: Are here calculations that should be transferred to DrivingDynamics.jl?
# TODO from 2022/01/22: use always copyCharacteristicSection and don't do it manually like "csModified=Dict(:id => csOriginal[:id], ..." three times
module EnergySaving
@ -35,7 +36,7 @@ function addOperationModeEnergySaving!(summarizedDict::Dict)
# summarize data and create an output dictionary
merge!(summarizedDict, Dict(:movingSectionMinimumEnergyConsumption => movingSectionMinimumEnergyConsumption, :drivingCourseMinimumEnergyConsumption => drivingCourseMinimumEnergyConsumption))
else
println("No output for minimum energy consumption has been demanded and so none will be calculated")
println("No output for minimum energy consumption has been demanded and so none will be calculated.")
end #if
return summarizedDict
@ -275,7 +276,8 @@ function copyCharacteristicSection(originalCS::Dict)
:v_limit => originalCS[:v_limit], # speed limit (in m/s)
:v_peak => originalCS[:v_peak], # maximum reachable speed (in m/s)
:v_entry => originalCS[:v_entry], # maximum entry speed (in m/s)
:v_exit => originalCS[:v_exit]) # maximum exit speed (in m/s)
:v_exit => originalCS[:v_exit], # maximum exit speed (in m/s)
:pointsOfInterest => originalCS[:pointsOfInterest]) # points of interest for which data points should be calculated
return copiedCS
end # CharacteristicSection
@ -699,7 +701,8 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
:v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
:v_exit => csOriginal[:v_exit], # maximum exit speed (in m/s)
:pointsOfInterest => csOriginal[:pointsOfInterest]) # points of interest for which data points should be calculated
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
@ -774,7 +777,8 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
:v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
:v_exit => csOriginal[:v_exit], # maximum exit speed (in m/s)
:pointsOfInterest => csOriginal[:pointsOfInterest]) # points of interest for which data points should be calculated
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
@ -881,7 +885,9 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict
:v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
:v_exit => csOriginal[:v_exit], # maximum exit speed (in m/s)
:pointsOfInterest => csOriginal[:pointsOfInterest]) # points of interest for which data points should be calculated
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])

View File

@ -10,9 +10,9 @@ export importYamlFiles, importYamlFile
Read the input information from YAML files for train, path and settings, save it in different dictionaries and return them.
"""
function importYamlFiles(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
train=importTrainFromYaml(trainDirectory)
path=importPathFromYaml(pathDirectory)
settings=importSettingsFromYaml(settingsDirectory)
train = importTrainFromYaml(trainDirectory)
path = importPathFromYaml(pathDirectory)
settings = importSettingsFromYaml(settingsDirectory)
return (train, path, settings)
end #function importYamlFiles
@ -114,7 +114,7 @@ function importPathFromYaml(pathDirectory::String)
data = YAML.load(open(pathDirectory))
name = getString!(data, "path", "name")
id=1 # path identifier
id=1 # path identifier
sections = getSections!(data)
# save values in the path Dict
@ -122,6 +122,8 @@ function importPathFromYaml(pathDirectory::String)
:id => id,
:sections => sections)
addPointsOfInterest!(path, data)
informAboutUnusedKeys(data, "path") # inform the user, which keywords of the imported data are not used in this tool
return path
@ -502,6 +504,48 @@ function getSections!(data::Dict)
return sections
end #function getSections!
function addPointsOfInterest!(path::Dict, data::Dict)
# read the section starting positions and corresponding information
if haskey(data["path"],"pointsOfInterest") && data["path"]["pointsOfInterest"]!=nothing
pointsOfInterest = data["path"]["pointsOfInterest"]
delete!(data["path"], "pointsOfInterest")
sortingNeeded = false
errorDetected = false
for element in 1:length(pointsOfInterest)
if typeof(pointsOfInterest[element]) <: Real
if element > 1
if pointsOfInterest[element] < pointsOfInterest[element-1]
sortingNeeded = true
println("INFO at reading the path yaml file: The point of interest in element ", element ," (",pointsOfInterest[element]," m) has to be higher than the value of the previous element (",pointsOfInterest[element-1]," m). The points of interest will be sorted.")
end
end
else
errorDetected = true
println("ERROR at reading the path yaml file: The point of interest in element ", element ," is no real floating point number.")
end
end # for
if errorDetected
error("ERROR at reading the path yaml file: The values of the point of interest have to be corrected.")
end
if sortingNeeded == true
sort!(pointsOfInterest)
end
copiedPOIs = []
for element in 1:length(pointsOfInterest)
if element == 1
push!(copiedPOIs, pointsOfInterest[element])
elseif element > 1 && pointsOfInterest[element] > pointsOfInterest[element-1]
push!(copiedPOIs, pointsOfInterest[element])
end
end # for
merge!(path, Dict(:pointsOfInterest => copiedPOIs))
end
return (path, data)
end #function addPointsOfInterest!
function informAboutUnusedKeys(data::Dict, dataSet::String) # inform the user which keywords of the imported data are not used in this tool
if length(data[dataSet])>0
println("INFO at reading the ",dataSet," yaml file: The following Keywords are not used in this tool:")

View File

@ -68,6 +68,7 @@ function checkAndSetPath!(path::Dict)
checkString(path, "path", :name)
# TODO checkId ? path[:id] # path identifier
checkAndSetSections!(path)
checkAndSetPOIs!(path)
# TODO: informAboutUnusedKeys(path, "path") # inform the user, which Symbols of the input dictionary are not used in this tool
@ -400,6 +401,52 @@ function checkAndSetSections!(path::Dict)
return path
end #function checkAndSetSections!
function checkAndSetPOIs!(path::Dict)
# read the section starting positions and corresponding information
if haskey(path,:pointsOfInterest)
if path[:pointsOfInterest] != nothing
pointsOfInterest = path[:pointsOfInterest]
sortingNeeded = false
errorDetected = false
for element in 1:length(pointsOfInterest)
if typeof(pointsOfInterest[element]) <: Real
if element > 1
if pointsOfInterest[element] < pointsOfInterest[element-1]
sortingNeeded = true
println("INFO at checking the input dictionary for the path: The point of interest in element ", element ," (",pointsOfInterest[element]," m) has to be higher than the value of the previous element (",pointsOfInterest[element-1]," m). The points of interest will be sorted.")
end
end
else
errorDetected = true
println("ERROR at checking the input dictionary for the path: The point of interest in element ", element ," is no real floating point number.")
end
end # for
if errorDetected
error("ERROR at checking the input dictionary for the path: The values of the point of interest have to be corrected.")
end
if sortingNeeded == true
sort!(pointsOfInterest)
end
copiedPOIs = []
for element in 1:length(pointsOfInterest)
if element == 1
push!(copiedPOIs, pointsOfInterest[element])
elseif element > 1 && pointsOfInterest[element] > pointsOfInterest[element-1]
push!(copiedPOIs, pointsOfInterest[element])
end
end # for
path[:pointsOfInterest] = copiedPOIs
end
else
delete!(path, :pointsOfInterest)
end
return path
end #function checkAndSetPOIs!
function informAboutUnusedKeys(dictionary::Dict, dictionaryType::String) # inform the user which Symbols of the input dictionary are not used in this tool
#= if length(dictionary)>0
println("INFO at checking the input dictionary for the ",dictionaryType,": The following Keywords are not used in this tool:")

View File

@ -3,14 +3,37 @@ module Output
export createOutputDict
function createOutputDict(train::Dict, settings::Dict, path::Dict, movingSection::Dict, drivingCourse::Vector{Dict})
outputDict=Dict{Symbol,Any}()
outputDict = Dict{Symbol,Any}()
merge!(outputDict, Dict(:train => train, :path => path, :settings => settings))
# adding moving section and drving courses
# add moving section and driving courses
if settings[:operationModeMinimumRunningTime] == true
merge!(outputDict, Dict(:movingSectionMinimumRunningTime => movingSection, :drivingCourseMinimumRunningTime => drivingCourse))
merge!(outputDict, Dict(:movingSectionMinimumRunningTime => movingSection,
:drivingCourseMinimumRunningTime => drivingCourse))
elseif settings[:operationModeMinimumEnergyConsumption] == true
merge!(outputDict, Dict(:movingSectionMinimumEnergyConsumption => movingSection, :drivingCourseMinimumEnergyConsumption => drivingCourse))
merge!(outputDict, Dict(:movingSectionMinimumEnergyConsumption => movingSection,
:drivingCourseMinimumEnergyConsumption => drivingCourse))
end
# add points of interest
if haskey(path, :pointsOfInterest)
pointsOfInterest = Vector{Dict}()
POI = 1
i = 1
while(POI <= length(path[:pointsOfInterest]) && i <= drivingCourse[end][:i])
if path[:pointsOfInterest][POI] == drivingCourse[i][:s]
push!(pointsOfInterest, drivingCourse[i])
POI = POI+1
end
i = i+1
end
if settings[:operationModeMinimumRunningTime] == true
merge!(outputDict, Dict(:pointsOfInterestMinimumRunningTime => pointsOfInterest))
elseif settings[:operationModeMinimumEnergyConsumption] == true
merge!(outputDict, Dict(:pointsOfInterestMinimumEnergyConsumption => pointsOfInterest))
end
end
return outputDict

View File

@ -43,7 +43,7 @@ function calculateDrivingDynamics(train::Dict, path::Dict, settings::Dict)
# calculate the train run for oparation mode "minimum running time"
if settings[:operationModeMinimumRunningTime] || settings[:operationModeMinimumEnergyConsumption]
(movingSection, drivingCourse)=calculateMinimumRunningTime!(movingSection, settings, train)
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
println("The driving course for the shortest running time has been calculated.")
# summarize data and create an output dictionary
@ -79,11 +79,6 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
s_cruising = CS[:length] - s_breakFree - s_clearing - s_acceleration - s_braking
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
# 01/07 old: delete!(BSs, :breakFree)
# 01/07 old: delete!(BSs, :clearing)
# 01/07 old: delete!(BSs, :acceleration)
# 01/07 old: delete!(BSs, :diminishing)
# 01/07 old: delete!(BSs, :cruising)
CS[:behaviorSections] = Dict()
CS[:E] = 0.0
CS[:t] = 0.0
@ -98,7 +93,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
# 09/21 elseif s_cruising > 0.0
# 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0)
if drivingCourse[end][:v] < CS[:v_peak]
(CS, drivingCourse)=addAccelerationSection!(CS, drivingCourse, settings, train, CSs)
(CS, drivingCourse) = addAccelerationSection!(CS, drivingCourse, settings, train, CSs)
end #if
if CS[:s_exit]-drivingCourse[end][:s]-max(0.0, (CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
@ -121,8 +116,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end #if
end #if
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
if drivingCourse[end][:v] > CS[:v_exit]
#(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings[:massModel], train, CSs)
@ -138,7 +132,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end =#
end #for
(CSs[end], drivingCourse)=addStandstill!(CSs[end], drivingCourse, settings, train, CSs)
(CSs[end], drivingCourse) = addStandstill!(CSs[end], drivingCourse, settings, train, CSs)
movingSection[:t] = drivingCourse[end][:t] # total running time (in s)
movingSection[:E] = drivingCourse[end][:E] # total energy consumption (in Ws)

View File

@ -8,24 +8,25 @@
using TrainRun, Test
allPaths=[]
push!(allPaths, "data/paths/path_1_10km_nConst_vConst.yaml")
push!(allPaths, "data/paths/path_2_10km_nVar_vConst.yaml")
push!(allPaths, "data/paths/path_3_10km_nConst_vVar.yaml")
push!(allPaths, "data/paths/path_4_real_Ostsachsen_DG-DN_spp_5.yaml")
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"))
allSettings=[]
push!(allSettings, "data/settings.yaml")
push!(allSettings, importYamlFile(:settings, "data/settings.yaml"))
allTrains=[]
push!(allTrains, "data/trains/train_freight_V90withOreConsist.yaml")
push!(allTrains, "data/trains/train_passenger_SiemensDesiroClassic.yaml")
push!(allTrains, "data/trains/train_passenger_IC2.yaml")
for pathDirectory in allPaths
for trainDirectory in allTrains
for settingsDirectory in allSettings
testDict=calculateDrivingDynamics(trainDirectory, pathDirectory, settingsDirectory)
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"))
for path in allPaths
for train in allTrains
for settings in allSettings
testDict=calculateDrivingDynamics(train, path, settings)
exportToCsv(testDict)
sleep(2)
# TODO: