Rename modules and variables

pull/1/head v0.2
Max Kannenberg 2021-12-08 13:35:25 +01:00
parent 6f3a391ab0
commit a57944b166
18 changed files with 1462 additions and 1461 deletions

View File

@ -1,7 +1,7 @@
name = "RailwayDrivingDynamics"
name = "TrainRun"
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
authors = ["Max Kannenberg"]
version = "0.1.0"
version = "0.2.0"
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"

View File

@ -1,4 +1,4 @@
# RailwayDrivingDynamics
# TrainRun
------------
@ -23,6 +23,11 @@ See folder examples.
# History
## Version 0.2
Modules and variables were renamed.
## Version 0.1
Proof of concept and master thesis submission.

View File

@ -8,4 +8,4 @@ settings:
operationModeMinimumEnergyConsumption: true # operation mode "minimum energy consumption"
typeOfOutput: "CSV" # output as "julia dictionary" or as "CSV"
detailOfOutput: "driving course" # should the output be "reduced" or "driving course"?
csvFolderPath: "~/Desktop/RailwayDrivingDynamics"
csvFolderPath: "~/Desktop/TrainRun"

View File

@ -1,5 +1,5 @@
---
vehicle:
train:
name: "V 90 with 10 ore wagons of type Facs 124" # (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90 and https://dybas.de/dybas/gw/gw_f_1/g124.html)
l_union: 205.3 # in m (source: FBS: DB 290 with 10x Facs124)
m_td: 80000 # mass on driving axles of the traction unit in kg (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
@ -9,7 +9,7 @@ vehicle:
rotationMassFactor_t: 1.09 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit)
rotationMassFactor_w: 1.03 # (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 13 for "Güterwagenzug beladen" -> 1.03 to 1.04)
powerType: diesel # diesel or electric (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
vehicleType: freight # "freight" or "passenger" or "motor coach train" (source: https://dybas.de/dybas/gw/gw_f_1/g124.html)
trainType: freight # "freight" or "passenger" or "motor coach train" (source: https://dybas.de/dybas/gw/gw_f_1/g124.html)
v_limit: # in m/s
v_limit_kmh: 80 # in km/h (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
a_braking: -0.4124 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 290 with with 10x Facs124)

View File

@ -1,5 +1,5 @@
---
vehicle:
train:
name: "Intercity 2 (Traxx P160 AC2 + double deck coaches)" # (source: https://de.wikipedia.org/wiki/Bombardier_Twindexx_Vario#Intercity_2 and https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
l_union: 152 # in m (source: FBS: DB146.5 with 1x DApza687.2, 3x DBpza668.2, 1x DBpbzfa668.2)
m_td: 84000 # mass on driving axles of the traction unit in kg (source: FBS: DB146.5)
@ -9,7 +9,7 @@ vehicle:
rotationMassFactor_t: 1.09 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit)
rotationMassFactor_w: 1.06 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for freight wagons)
powerType: electric # diesel or electric (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn)#Gemeinsame_Merkmale)
vehicleType: passenger # "freight" or "passenger" or "motor coach train" (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
trainType: passenger # "freight" or "passenger" or "motor coach train" (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
v_limit: # in m/s
v_limit_kmh: 160 # in km/h (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn)#Gemeinsame_Merkmale)
a_braking: -0.3507 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB146.5 with 1x DApza687.2, 3x DBpza668.2, 1x DBpbzfa668.2)

View File

@ -1,5 +1,5 @@
---
vehicle:
train:
name: "Siemens Desiro Classic" # (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
l_union: 41.7 # in m (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
m_td: 52800 # mass on driving axles of the traction unit in kg (source: FBS: DB 642; proportionately to the number of axles: 4 to 2, see: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
@ -9,7 +9,7 @@ vehicle:
rotationMassFactor_t:
rotationMassFactor_w:
powerType: diesel # diesel or electric (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
vehicleType: motor coach train # "freight" or "passenger" or "motor coach train" (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
trainType: motor coach train # "freight" or "passenger" or "motor coach train" (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
v_limit: # in m/s
v_limit_kmh: 120 # in km/h (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
a_braking: -0.4253 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 642)

View File

@ -1,34 +1,40 @@
include("../src/RailwayDrivingDynamics.jl")
using .RailwayDrivingDynamics
include("../src/TrainRun.jl")
using .TrainRun
# println("")
# println("________________________")
# println("")
allPaths=["../data/paths/path_1_10km_nConst_vConst.yaml" , "../data/paths/path_2_10km_nVar_vConst.yaml", "../data/paths/path_3_10km_nConst_vVar.yaml", "../data/paths/path_4_real_Ostsachsen_DG-DN_spp_5.yaml"]
settingsFilePath="../data/settings.yaml"
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")
for pathFilePath in allPaths
allSettings=[]
push!(allSettings, "../data/settings.yaml")
allTrains=[]
push!(allTrains, "../data/trains/train_freight_V90withOreConsist.yaml")
push!(allTrains, "../data/trains/train_yaml_files\\train_passenger_SiemensDesiroClassic.yaml")
push!(allTrains, "../data/trains/train_passenger_IC2.yaml")
for pathDirectory in allPaths
# println("")
# println(" - - - - - - - - -")
# println("path: ", pathFilePath)
# println("path: ", pathDirectory)
for trainDirectory in allTrains
# println("train: ", trainDirectory)
for settingsDirectory in allSettings
testDict=calculateDrivingDynamics(trainDirectory, pathDirectory, settingsDirectory)
vehicleFilePath="../data/vehicles/vehicle_passenger_intercity.yaml"
testDict1=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
sleep(2)
sleep(2)
vehicleFilePath="../data/vehicles/vehicle_passenger_suburban.yaml"
testDict2=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
sleep(2)
vehicleFilePath="../data/vehicles/vehicle_freight.yaml"
testDict3=calculateDrivingDynamics(vehicleFilePath, pathFilePath, settingsFilePath)
# println("")
# println("")
# println("")
# println("")
# println("")
# println("")
# println("")
end
end
end

View File

@ -1,92 +1,92 @@
module RailwayDrivingDynamicsEnergySaving
module EnergySaving
using ..types
using ..RailwayDrivingDynamicsMovingPhases
using ..MovingPhases
export calculateRecoveryTime, increaseCostingSection, decreaseMaximumVelocity, combineEnergySavingMethods
export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity, combineEnergySavingMethods
function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, vehicle::Vehicle)
function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, train::Train)
# function for calculating the recovery time that can be used for energy saving
if vehicle.vehicleType=="motor coach train"
if train.trainType=="motor coach train"
if s_MS<= 30000
c_s=0.0
else s_MS> 30000
c_s=0.0006
end # if s_MS
if vehicle.v_limit<=140/3.6 # unit is m/s
if train.v_limit<=140/3.6 # unit is m/s
c_t=0.03
elseif vehicle.v_limit<=160/3.6 # unit is m/s
elseif train.v_limit<=160/3.6 # unit is m/s
c_t=0.04
elseif vehicle.v_limit<=200/3.6 # unit is m/s
elseif train.v_limit<=200/3.6 # unit is m/s
c_t=0.05
elseif vehicle.v_limit<=250/3.6 # unit is m/s
elseif train.v_limit<=250/3.6 # unit is m/s
c_t=0.06
else # vehicle.v_limit>120/3.6 # unit is m/s
else # train.v_limit>120/3.6 # unit is m/s
c_t=0.07
end # if vehicle.v_limit
end # if train.v_limit
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
elseif vehicle.vehicleType=="freight" && vehicle.v_limit<=120/3.6 # unit is m/s
elseif train.trainType=="freight" && train.v_limit<=120/3.6 # unit is m/s
t_recovery1=s_MS*0.0006 +t_MS*0.03
t_recovery2=s_MS*0.0018 +t_MS*0.0
t_recovery3=s_MS*0.0 +t_MS*0.04
t_recovery=max(t_recovery1, t_recovery2, t_recovery3)
return t_recovery
else # vehicle.vehicleType=="passenger" || (vehicle.vehicleType=="freight" && vehicle.v_limit>120/3.6) # unit is m/s
else # train.trainType=="passenger" || (train.trainType=="freight" && train.v_limit>120/3.6) # unit is m/s
if s_MS<= 30000
c_s=0.0
else s_MS> 30000
c_s=0.0009
end # if s_MS
if vehicle.v_limit<=140/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
if train.v_limit<=140/3.6 # unit is m/s
if train.m_union<=300000 # unit is kg
c_t=0.03
elseif vehicle.m_union<=500000 # unit is kg
elseif train.m_union<=500000 # unit is kg
c_t=0.04
elseif vehicle.m_union<=700000 # unit is kg
elseif train.m_union<=700000 # unit is kg
c_t=0.04
else # vehicle.m_union>700000 # unit is kg
else # train.m_union>700000 # unit is kg
c_t=0.05
end # if vehicle.m_union
elseif vehicle.v_limit<=160/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
end # if train.m_union
elseif train.v_limit<=160/3.6 # unit is m/s
if train.m_union<=300000 # unit is kg
c_t=0.03
elseif vehicle.m_union<=500000 # unit is kg
elseif train.m_union<=500000 # unit is kg
c_t=0.04
else # vehicle.m_union>500000 # unit is kg
else # train.m_union>500000 # unit is kg
c_t=0.0
end # if vehicle.m_union
elseif vehicle.v_limit<=200/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
end # if train.m_union
elseif train.v_limit<=200/3.6 # unit is m/s
if train.m_union<=300000 # unit is kg
c_t=0.04
elseif vehicle.m_union<=500000 # unit is kg
elseif train.m_union<=500000 # unit is kg
c_t=0.05
else # vehicle.m_union>500000 # unit is kg
else # train.m_union>500000 # unit is kg
c_t=0.06
end # if vehicle.m_union
else # vehicle.v_limit>200/3.6 # unit is m/s
if vehicle.m_union<=300000 # unit is kg
end # if train.m_union
else # train.v_limit>200/3.6 # unit is m/s
if train.m_union<=300000 # unit is kg
c_t=0.05
elseif vehicle.m_union<=500000 # unit is kg
elseif train.m_union<=500000 # unit is kg
c_t=0.06
else # vehicle.m_union>500000 # unit is kg
else # train.m_union>500000 # unit is kg
c_t=0.07
end # if vehicle.m_union
end # if vehicle.v_limit
end # if train.m_union
end # if train.v_limit
c_tMin=s_MS/t_MS*0.0012
c_t=max(c_t, c_tMin)
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
end # if vehicle.vehicleType
end # if train.trainType
end #function calculateRecoveryTime
function increaseCostingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "braking")
cruisingReduction=settings.stepSize
while cruisingReduction>=settings.stepSize/100
@ -97,8 +97,10 @@ function increaseCostingSection(csOriginal::CharacteristicSection, drivingCourse
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
# tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])]
drivingCourseModified=[Waypoint(drivingCourse[1])]
for i in 2:energySavingStartId
# tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of waypoints till the start of energy saving
push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving
end
@ -121,7 +123,7 @@ function increaseCostingSection(csOriginal::CharacteristicSection, drivingCourse
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "starting", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "starting", BehaviorSection()).t_total
end
if haskey(csOriginal.behaviorSections, "cruisingBeforeAcceleration") # this section is needed before acceleration if the mass strip model is used and if the vehicle wants to accelerate to a velocity higher than the limit in the other CS where parts of the union are still located
if haskey(csOriginal.behaviorSections, "cruisingBeforeAcceleration") # this section is needed before acceleration if the mass strip model is used and if the train wants to accelerate to a velocity higher than the limit in the other CS where parts of the union are still located
cruisingBeforeAccelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("cruisingBeforeAcceleration"=>cruisingBeforeAccelerationSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).E_total
@ -136,13 +138,13 @@ function increaseCostingSection(csOriginal::CharacteristicSection, drivingCourse
# calculating the new and now shorter cruising section
if s_cruising>0.0
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, vehicle, allCSs, "cruising")
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end
(csModified, drivingCourseModified)=addCoastingPhaseWithIntersection!(csModified, drivingCourseModified, settings, vehicle, allCSs)
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
if drivingCourseModified[end].v<csModified.v_exit || drivingCourseModified[end].s>csModified.s_end
# the vehicle reaches v_exit before reaching s_end. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section)
# the train reaches v_exit before reaching s_end. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section)
cruisingReduction=cruisingReduction/10
else
break
@ -150,11 +152,11 @@ function increaseCostingSection(csOriginal::CharacteristicSection, drivingCourse
end # while cruisingReduction
if drivingCourseModified[end].v>csModified.v_exit
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, vehicle, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
elseif drivingCourseModified[end].v==csModified.v_exit && drivingCourseModified[end].s<csModified.s_end
# v_exit is already reached. Now cruising till the end of the CS
s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, vehicle, allCSs, "cruisingAfterCoasting")
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end
if t_recoveryAvailable<(csModified.t_total-csOriginal.t_total) || drivingCourseModified[end].v!=csModified.v_exit || drivingCourseModified[end].s!=csModified.s_end # time loss is to high and the CS has to be calculated again with larger cruising section (so with a smaller reduction of the cruising section) or v_exit or s_end are not reached excatly
@ -169,13 +171,13 @@ function increaseCostingSection(csOriginal::CharacteristicSection, drivingCourse
# there is no energy saving modification for this CS because a cruising section AND a braking section are needed to be transformed into a coasting section
return (CharacteristicSection(), [], false)
end
end # function increaseCostingSection
end # function increaseCoastingSection
# method 2 with shortening the acceleration by stepsize
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && csOriginal.v_reach>csOriginal.v_entry && csOriginal.v_reach>csOriginal.v_exit
# instead of calculating the new final velocity of the acceleration phase with the step sizes for the different step variables, the velocity of the point before the last will be the new v_reach
# because it it easier at the moment (TODO)
@ -197,6 +199,7 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
drivingCourseModified=Vector{Waypoint}()
for i in 1:energySavingStartId
# tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of waypoints till the start of energy saving
push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving
end
@ -204,20 +207,20 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
# calculation of the new and now shorter acceleration section
if drivingCourseModified[end].v<csModified.v_reach
(csModified, drivingCourseModified)=addAccelerationPhase!(csModified, drivingCourseModified, settings, vehicle, allCSs)
(csModified, drivingCourseModified)=addAccelerationPhase!(csModified, drivingCourseModified, settings, train, allCSs)
end #if
# TODO: instead of copying the drivingCourse till the start of acceleration and calculating the acceleration again till the point before the last it would be possible to copy the drivingCouse until this point. Then it would not be necessary to calculate the accelerationPhase again. But then it is difficult to reduce accelerationReduction.
s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_reach^2)/2/vehicle.a_braking, digits=10)) # ceil is used to be sure that the vehicle stops at s_end in spite of rounding errors
s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_reach^2)/2/train.a_braking, digits=10)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors
s_cruising=csModified.s_end-drivingCourseModified[end].s-s_braking
if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, vehicle, allCSs, "cruising")
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/vehicle.a_braking, digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train.a_braking, digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified.v_exit
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, vehicle, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
elseif drivingCourseModified[end].s<csModified.s_end
if (csModified.s_end-drivingCourseModified[end].s)>0.001
println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_reach.")
@ -243,23 +246,24 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
end # function decreaseMaximumVelocity
# combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && (haskey(csOriginal.behaviorSections, "braking") || haskey(csOriginal.behaviorSections, "coasting")) && csOriginal.v_reach>csOriginal.v_entry && csOriginal.v_reach>csOriginal.v_exit
csCombined=CharacteristicSection(csOriginal)
drivingCourseCombined=Vector{Waypoint}()
for i in 1:length(drivingCourse)
# tried to insert copy on 15.07.2021 push!(drivingCourseCombined, copy(drivingCourse[i]))
push!(drivingCourseCombined, Waypoint(drivingCourse[i]))
end
ΔE=0.0 # saved energy (in Ws)
Δt=0.0 # time loss (in s)
while (Δt<t_recoveryAvailable && ΔE<=0.0)
(csCombined, drivingCourseCombined, newMaximumVelocity)=decreaseMaximumVelocity(csCombined, drivingCourseCombined, settings, vehicle, allCSs, t_recoveryAvailable)
(csCombined, drivingCourseCombined, newMaximumVelocity)=decreaseMaximumVelocity(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable)
if newMaximumVelocity
ΔE=csOriginal.E_total-csCombined.E_total # saved energy (in Ws)
Δt=csCombined.t_total-csOriginal.t_total # time loss (in s)
while (haskey(csOriginal.behaviorSections, "cruising") && (Δt<=0.0 || ΔE<=0.0)) #Δt<=0.0) #&& ΔE<=0.0) # && Δt<=0.0)
(csCombined, drivingCourseCombined, newCoasting)=increaseCostingSection(csCombined, drivingCourseCombined, settings, vehicle, allCSs, t_recoveryAvailable-Δt)
(csCombined, drivingCourseCombined, newCoasting)=increaseCoastingSection(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable-Δt)
if newCoasting
ΔE=csOriginal.E_total-csCombined.E_total # saved energy (in Ws)
Δt=csCombined.t_total-csOriginal.t_total # time loss (in s)
@ -278,4 +282,4 @@ function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCo
end #if
end #function combineEnergySavingMethods
end #module RailwayDrivingDynamicsEnergySaving
end #module EnergySaving

634
src/Input.jl Normal file
View File

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

View File

@ -1,14 +1,16 @@
module RailwayDrivingDynamicsMovingPhases
module MovingPhases
using ..types
export addAccelerationPhase!, addAccelerationPhaseWithIntersection!, addCruisingPhase!, addCoastingPhaseWithIntersection!, addBrakingPhase!
export addAccelerationPhase!, addAccelerationPhaseUntilBraking!, addCruisingPhase!, addCoastingPhaseUntilBraking!, addBrakingPhase!
v00=100/3.6 # velocity constant (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
## functions for calculating tractive effort and resisting forces
"""
calculate the trains tractive effort dependend on the velocity
"""
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortArray)
# this function calculates the vehicles tractive effort dependend on the velocity
for row in 1:length(tractiveEffortArray)
if tractiveEffortArray[row][1]<=v && v<=tractiveEffortArray[row][2]
return tractiveEffortArray[row][3]
@ -24,18 +26,25 @@ function calculateTractiveEffort(v::AbstractFloat, tractiveEffortArray)
end #for
end #function calculateTractiveEffort
function calculateTractionUnitResistance(v::AbstractFloat, vehicle::Vehicle)
# this function calculates and returns the traction units vehicle resistance dependend on the velocity
return vehicle.f_Rtd0/1000*vehicle.m_td*g+vehicle.f_Rtc0/1000*vehicle.m_tc*g+vehicle.F_Rt2*((v+vehicle.Δv_t)/v00)^2 # /1000 because of the unit ‰
"""
calculate and return the traction units vehicle resistance dependend on the velocity
"""
function calculateTractionUnitResistance(v::AbstractFloat, train::Train)
return train.f_Rtd0/1000*train.m_td*g+train.f_Rtc0/1000*train.m_tc*g+train.F_Rt2*((v+train.Δv_t)/v00)^2 # /1000 because of the unit ‰
end #function calculateTractionUnitResistance
function calculateWagonsResistance(v::AbstractFloat, vehicle::Vehicle)
# this function calculates and returns the wagons vehicle resistance dependend on the velocity
return vehicle.m_w*g*(vehicle.f_Rw0/1000+vehicle.f_Rw1/1000*v/v00+vehicle.f_Rw2/1000*((v+vehicle.Δv_w)/v00)^2) # /1000 because of the unit ‰
"""
calculate and return the wagons vehicle resistance dependend on the velocity
"""
function calculateWagonsResistance(v::AbstractFloat, train::Train)
return train.m_w*g*(train.f_Rw0/1000+train.f_Rw1/1000*v/v00+train.f_Rw2/1000*((v+train.Δv_w)/v00)^2) # /1000 because of the unit ‰
end #function calculateWagonsResistance
function calculatePathResistance(s::AbstractFloat, massModel::String, vehicle::Vehicle, allCs::Vector{CharacteristicSection})
# looking for the characteristic section with the unions head position
"""
calculate and return the path resistance dependend on the trains position and mass model
"""
function calculatePathResistance(s::AbstractFloat, massModel::String, train::Train, allCs::Vector{CharacteristicSection})
# looking for the characteristic section with the trains head position
id=length(allCs)
while s<allCs[id].s_start
id=id-1
@ -45,15 +54,15 @@ function calculatePathResistance(s::AbstractFloat, massModel::String, vehicle::V
end #while
if massModel=="mass point"
pathResistance=allCs[id].f_Rp/1000*vehicle.m_union*g # /1000 because of the unit ‰
pathResistance=allCs[id].f_Rp/1000*train.m_union*g # /1000 because of the unit ‰
elseif massModel=="homogeneous strip"
pathResistance=0.0
while id>0 && s-vehicle.l_union<allCs[id].s_end
pathResistance=pathResistance+(min(s, allCs[id].s_end)-max(s-vehicle.l_union, allCs[id].s_start))/vehicle.l_union*(allCs[id].f_Rp/1000*vehicle.m_union*g) # /1000 because of the unit ‰
while id>0 && s-train.l_union<allCs[id].s_end
pathResistance=pathResistance+(min(s, allCs[id].s_end)-max(s-train.l_union, allCs[id].s_start))/train.l_union*(allCs[id].f_Rp/1000*train.m_union*g) # /1000 because of the unit ‰
id=id-1
if id==0
# TODO: currently for values < movingSection.s_start the values of movingSection.s_start will be used
return pathResistance+(allCs[1].s_start-(s-vehicle.l_union))/vehicle.l_union*(allCs[1].f_Rp/1000*vehicle.m_union*g) # /1000 because of the unit ‰
return pathResistance+(allCs[1].s_start-(s-train.l_union))/train.l_union*(allCs[1].f_Rp/1000*train.m_union*g) # /1000 because of the unit ‰
end #if
end #while
else
@ -63,12 +72,33 @@ function calculatePathResistance(s::AbstractFloat, massModel::String, vehicle::V
return pathResistance
end #function pathResistance
"""
calculate and return tractive and resisting forces for a waypoint
"""
function calculateForces!(waypoint::Waypoint, train::Train, massModel::String, allCs::Vector{CharacteristicSection}, bsType::String)
# calculate resisting forces
waypoint.F_Rt=calculateTractionUnitResistance(waypoint.v, train)
waypoint.F_Rw=calculateWagonsResistance(waypoint.v, train)
waypoint.F_Runion=waypoint.F_Rt+waypoint.F_Rw
waypoint.F_Rp=calculatePathResistance(waypoint.s, massModel, train, allCs)
waypoint.F_R=waypoint.F_Runion+waypoint.F_Rp
#calculate tractive effort
if bsType == "acceleration"
waypoint.F_T = calculateTractiveEffort(waypoint.v, train.tractiveEffortArray)
elseif bsType == "cruising"
waypoint.F_T = min(max(0.0, waypoint.F_R), calculateTractiveEffort(waypoint.v, train.tractiveEffortArray))
else
waypoint.F_T = 0.0
end
return waypoint
end #function calculateForces
## This function calculates the waypoints of the starting phase.
# Therefore it gets its first waypoint and the characteristic section and returns the characteristic section including the behavior section for starting if needed.
# TODO: currently the values of the starting phase will be calculated like in the acceleration phase
function addStartingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCs::Vector{CharacteristicSection})
# Info: currently the values of the starting phase will be calculated like in the acceleration phase
function addStartingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection})
if drivingCourse[end].v==0.0 && drivingCourse[end].s<characteristicSection.s_end
startingSection=BehaviorSection()
startingSection.type="starting" # type of behavior section
@ -76,16 +106,19 @@ function addStartingPhase!(characteristicSection::CharacteristicSection, driving
startingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(startingSection.waypoints, drivingCourse[end].i) # list of containing waypoints
# traction effort and resisting forces (in N):
drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, vehicle.tractiveEffortArray)
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration")) # currently the tractive effort is calculated like in the acceleration phase
#07/16 drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, train.tractiveEffortArray)
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/vehicle.m_union/vehicle.ξ_union
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
if drivingCourse[end].a<0.0
error("ERROR: a<0 m/s^2 in the starting phase !")
elseif drivingCourse[end].a==0.0
@ -141,27 +174,27 @@ end #function addStartingPhase!
## This function calculates the waypoints of the acceleration phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section
function addAccelerationPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCs::Vector{CharacteristicSection})
function addAccelerationPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection})
if drivingCourse[end].v==0.0
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, vehicle, allCs)
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
end #if
# if the tail of the vehicle is still in a former characteristic section it has to be checked if its speed limit can be kept
# if the tail of the train is still in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits=[]
if characteristicSection.id>1 && drivingCourse[end].s-vehicle.l_union<characteristicSection.s_start
if characteristicSection.id>1 && drivingCourse[end].s-train.l_union<characteristicSection.s_start
if abs(allCs[characteristicSection.id-1].v_limit-drivingCourse[end].v)<0.000001
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, vehicle.l_union)
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, train.l_union)
if s_cruisingBeforeAcceleration>0.0
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, vehicle, allCs, "cruisingBeforeAcceleration")
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, train, allCs, "cruisingBeforeAcceleration")
else
error("ERROR: cruisingBeforeAcceleration <=0.0 although it has to be >0.0 in CS ",characteristicSection.id)
end
else # detecting the lower speed limits of former sections
csId=characteristicSection.id-1
while csId>0 && drivingCourse[end].s-vehicle.l_union<allCs[csId].s_end
if allCs[csId].v_limit<characteristicSection.v_limit # TODO: is the position of vehicles tail < movingSection.s_start, v_limit of the first CS is used
while csId>0 && drivingCourse[end].s-train.l_union<allCs[csId].s_end
if allCs[csId].v_limit<characteristicSection.v_limit # TODO: is the position of trains tail < movingSection.s_start, v_limit of the first CS is used
push!(formerSpeedLimits, [allCs[csId].s_end, allCs[csId].v_limit])
for i in 1:length(formerSpeedLimits)-1
if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2]
@ -186,15 +219,18 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
# in the fifth cycle the interpolated values are corrected in case v_reach is still to high although s==s_end
while length(formerSpeedLimits)>0 && drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0
push!(accelerationSection.waypoints, drivingCourse[end].i)
drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, vehicle.tractiveEffortArray)
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
#07/16 drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, train.tractiveEffortArray)
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/vehicle.m_union/vehicle.ξ_union
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
if drivingCourse[end].a==0.0
error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
end
@ -207,7 +243,7 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
if settings.stepVariable=="s in m" # distance step method
drivingCourse[end].Δs=currentStepSize # step size (in m)
if ((drivingCourse[end-1].v/drivingCourse[end-1].a)^2+2*drivingCourse[end].Δs/drivingCourse[end-1].a)<0.0 || (drivingCourse[end-1].v^2+2*drivingCourse[end].Δs*drivingCourse[end-1].a)<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -231,7 +267,7 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
drivingCourse[end].ΔE=drivingCourse[end].ΔW_T # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
while length(formerSpeedLimits)>0 && drivingCourse[end].s-vehicle.l_union>=formerSpeedLimits[end][1]
while length(formerSpeedLimits)>0 && drivingCourse[end].s-train.l_union>=formerSpeedLimits[end][1]
pop!(formerSpeedLimits)
end
@ -247,11 +283,11 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
end
# creating a cruisingBeforeAcceleration section
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-vehicle.l_union))
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train.l_union))
if s_cruisingBeforeAcceleration>0.0
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, vehicle, allCs, "cruisingBeforeAcceleration")
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, train, allCs, "cruisingBeforeAcceleration")
else
error("ERROR: cruisingBeforeAcceleration <=0.0 although it has to be >0.0 in CS ",characteristicSection.id)
end
@ -269,22 +305,23 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
end
end
# from here on the head and tail of the union are located in the current characteristic section
# from here on the head and tail of the train are located in the current characteristic section
# acceleration with all parts of the vehicle in the current characteristic section
# acceleration with all parts of the train inside the current characteristic section
while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0
push!(accelerationSection.waypoints, drivingCourse[end].i)
# traction effort and resisting forces (in N):
drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, vehicle.tractiveEffortArray)
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
#07/16 drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, train.tractiveEffortArray)
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/vehicle.m_union/vehicle.ξ_union
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
if drivingCourse[end].a==0.0
error("ERROR: a=0.0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
end
@ -297,7 +334,7 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
if settings.stepVariable=="s in m" # distance step method
drivingCourse[end].Δs=currentStepSize # step size (in m)
if ((drivingCourse[end-1].v/drivingCourse[end-1].a)^2+2*drivingCourse[end].Δs/drivingCourse[end-1].a)<0.0 || (drivingCourse[end-1].v^2+2*drivingCourse[end].Δs*drivingCourse[end-1].a)<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -330,7 +367,7 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
elseif cycle==3 || cycle==4 # new step size is calculated with interpolation
currentStepSize=abs((characteristicSection.v_reach-drivingCourse[end-1].v)*(drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)) # step size (in m/s)
elseif cycle==5
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -442,27 +479,27 @@ end #function addAccelerationPhase!
## This function calculates the waypoints of the acceleration phase.
function addAccelerationPhaseWithIntersection!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCs::Vector{CharacteristicSection})
function addAccelerationPhaseUntilBraking!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection})
if drivingCourse[end].v==0.0
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, vehicle, allCs)
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
end #if
# if the tail of the vehicle is still in a former characteristic section it has to be checked if its speed limit can be kept
# if the tail of the train is still in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits=[]
if characteristicSection.id>1 && drivingCourse[end].s-vehicle.l_union<characteristicSection.s_start
if characteristicSection.id>1 && drivingCourse[end].s-train.l_union<characteristicSection.s_start
if abs(allCs[characteristicSection.id-1].v_limit-drivingCourse[end].v)<0.000001
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, vehicle.l_union)
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, train.l_union)
if s_cruisingBeforeAcceleration>0.0
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, vehicle, allCs, "cruisingBeforeAcceleration")
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, train, allCs, "cruisingBeforeAcceleration")
else
error("ERROR: cruisingBeforeAcceleration <=0.0 although it has to be >0.0 in CS ",characteristicSection.id)
end
else # detecting the lower speed limits of former sections
csId=characteristicSection.id-1
while csId>0 && drivingCourse[end].s-vehicle.l_union<allCs[csId].s_end
if allCs[csId].v_limit<characteristicSection.v_limit # TODO: is the position of vehicles end < movingSection.s_start, v_limit of the first CS is used
while csId>0 && drivingCourse[end].s-train.l_union<allCs[csId].s_end
if allCs[csId].v_limit<characteristicSection.v_limit # TODO: is the position of trains end < movingSection.s_start, v_limit of the first CS is used
push!(formerSpeedLimits, [allCs[csId].s_end, allCs[csId].v_limit])
for i in 1:length(formerSpeedLimits)-1
if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2]
@ -484,21 +521,22 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
for cycle in 1:5 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size. fourth and fith are needed in case the velocity approaches 0.0 or v_reach
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10))
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10))
while length(formerSpeedLimits)>0 && drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0
push!(accelerationSection.waypoints, drivingCourse[end].i)
# traction effort and resisting forces (in N):
drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, vehicle.tractiveEffortArray)
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
#07/16 drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, train.tractiveEffortArray)
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/vehicle.m_union/vehicle.ξ_union
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
if drivingCourse[end].a==0.0
error("ERROR: a=0.0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
end
@ -511,7 +549,7 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
if settings.stepVariable=="s in m" # distance step method
drivingCourse[end].Δs=currentStepSize # step size (in m)
if ((drivingCourse[end-1].v/drivingCourse[end-1].a)^2+2*drivingCourse[end].Δs/drivingCourse[end-1].a)<0.0 || (drivingCourse[end-1].v^2+2*drivingCourse[end].Δs*drivingCourse[end-1].a)<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -531,7 +569,7 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s)
drivingCourse[end].v=drivingCourse[end-1].v+drivingCourse[end].Δv # velocity (in m/s)
if drivingCourse[end].v<=0.0
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -540,7 +578,7 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
drivingCourse[end].ΔE=drivingCourse[end].ΔW_T # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
while length(formerSpeedLimits)>0 && drivingCourse[end].s-vehicle.l_union>=formerSpeedLimits[end][1]
while length(formerSpeedLimits)>0 && drivingCourse[end].s-train.l_union>=formerSpeedLimits[end][1]
pop!(formerSpeedLimits)
end
if length(formerSpeedLimits)>0 && drivingCourse[end].v>formerSpeedLimits[end][2]
@ -553,11 +591,11 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
delete!(characteristicSection.behaviorSections, "cruisingBeforeAcceleration")
end
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-vehicle.l_union))
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train.l_union))
if s_cruisingBeforeAcceleration>0.0
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, vehicle, allCs, "cruisingBeforeAcceleration")
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, train, allCs, "cruisingBeforeAcceleration")
else
println("Error: cruisingBeforeAcceleration <=0.0 ")
end
@ -573,25 +611,26 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
return (characteristicSection, drivingCourse)
end
end
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10))
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10))
end
# from here on the head and tail of the union are located in the current characteristic section
# from here on the head and tail of the train are located in the current characteristic section
# acceleration with all parts of the vehicle in the current characteristic section
# acceleration with all parts of the train in the current characteristic section
while drivingCourse[end].v<characteristicSection.v_reach && (drivingCourse[end].s+s_braking)<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
push!(accelerationSection.waypoints, drivingCourse[end].i)
# traction effort and resisting forces (in N):
drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, vehicle.tractiveEffortArray)
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
#07/16 drivingCourse[end].F_T=calculateTractiveEffort(drivingCourse[end].v, train.tractiveEffortArray)
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/vehicle.m_union/vehicle.ξ_union
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
if drivingCourse[end].a==0.0
error("ERROR: a=0.0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
end
@ -604,7 +643,7 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
if settings.stepVariable=="s in m" # distance step method
drivingCourse[end].Δs=currentStepSize # step size (in m)
if ((drivingCourse[end-1].v/drivingCourse[end-1].a)^2+2*drivingCourse[end].Δs/drivingCourse[end-1].a)<0.0 || (drivingCourse[end-1].v^2+2*drivingCourse[end].Δs*drivingCourse[end-1].a)<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -628,7 +667,7 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
drivingCourse[end].ΔE=drivingCourse[end].ΔW_T # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10))
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10))
end #while
# checking which limit was reached and adjusting the currentStepSize for the next cycle
@ -638,7 +677,7 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
elseif cycle==3 || cycle==4 # new step size is calculated with interpolation
currentStepSize=abs((characteristicSection.v_reach-drivingCourse[end-1].v)*(drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)) # step size (in m/s)
elseif cycle==5
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -653,9 +692,9 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
elseif cycle==3
## for the intersection:
# correcting the step size for the last waypoint
v_intersection=vehicle.a_braking*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))+sign(drivingCourse[end].v-drivingCourse[end-1].v)*sqrt(vehicle.a_braking^2*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))^2-2*vehicle.a_braking*(characteristicSection.s_end-drivingCourse[end-1].s+drivingCourse[end-1].v*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)))+characteristicSection.v_exit^2)
v_intersection=train.a_braking*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))+sign(drivingCourse[end].v-drivingCourse[end-1].v)*sqrt(train.a_braking^2*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))^2-2*train.a_braking*(characteristicSection.s_end-drivingCourse[end-1].s+drivingCourse[end-1].v*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)))+characteristicSection.v_exit^2)
s_intersection=characteristicSection.s_end-(characteristicSection.v_exit^2-v_intersection^2)/2/vehicle.a_braking
s_intersection=characteristicSection.s_end-(characteristicSection.v_exit^2-v_intersection^2)/2/train.a_braking
# s_intersection_2=(v_intersection-drivingCourse[end-1].v)*(drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)+drivingCourse[end-1].s
drivingCourse[end].v=v_intersection
@ -729,12 +768,12 @@ function addAccelerationPhaseWithIntersection!(characteristicSection::Characteri
merge!(characteristicSection.behaviorSections, Dict("acceleration"=>accelerationSection))
end # else: just return the given waypoint number without changes due to the acceleration phase
return (characteristicSection, drivingCourse)
end #function addAccelerationPhaseWithIntersection!
end #function addAccelerationPhaseUntilBraking!
## This function calculates the waypoints of the cruising phase.
# Therefore it gets its first waypoint and the characteristic section and returns the characteristic section including the behavior section for cruising if needed.
function addCruisingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, s_cruising::AbstractFloat, settings::Settings, vehicle::Vehicle, allCs::Vector{CharacteristicSection}, cruisingType::String)
function addCruisingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, s_cruising::AbstractFloat, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}, cruisingType::String)
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
cruisingSection=BehaviorSection()
cruisingSection.type=cruisingType # type of behavior section
@ -752,12 +791,13 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving
push!(cruisingSection.waypoints, drivingCourse[end].i)
# traction effort and resisting forces (in N)
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end].F_T=min(max(0.0, drivingCourse[end].F_R), calculateTractiveEffort(drivingCourse[end].v, vehicle.tractiveEffortArray))
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")) # TODO: or give cruisingSection.type instead of "cruising"?
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
#07/16 drivingCourse[end].F_T=min(max(0.0, drivingCourse[end].F_R), calculateTractiveEffort(drivingCourse[end].v, train.tractiveEffortArray))
if drivingCourse[end].F_T>=drivingCourse[end].F_R
@ -780,7 +820,7 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving
drivingCourse[end].ΔE=drivingCourse[end].ΔW_T # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
else
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/vehicle.m_union/vehicle.ξ_union
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
# creating the next waypoint
push!(drivingCourse, Waypoint())
@ -821,7 +861,7 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving
if currentStepSize>settings.stepSize/100.0
currentStepSize=currentStepSize/10.0
else
error("ERROR: The vehicle stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during the acceleration phase in CS",characteristicSection.id," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
end
@ -852,7 +892,7 @@ end #function addCruisingPhase!
## This function calculates the waypoints of the coasting phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
function addCoastingPhaseWithIntersection!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, vehicle::Vehicle, allCs::Vector{CharacteristicSection})
function addCoastingPhaseUntilBraking!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection})
if drivingCourse[end].v>characteristicSection.v_exit && drivingCourse[end].s<characteristicSection.s_end
coastingSection=BehaviorSection()
coastingSection.type="coasting" # type of behavior section
@ -861,20 +901,21 @@ function addCoastingPhaseWithIntersection!(characteristicSection::Characteristic
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
for cycle in 1:3 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size
s_braking=ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking, digits=10)
s_braking=ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10)
while drivingCourse[end].v>characteristicSection.v_exit && drivingCourse[end].v<=characteristicSection.v_reach && (drivingCourse[end].s+s_braking)<characteristicSection.s_end # as long as s_i + s_braking < s_CSend
push!(coastingSection.waypoints, drivingCourse[end].i)
# traction effort and resisting forces (in N):
drivingCourse[end].F_T=0
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, coastingSection.type))
#07/16 drivingCourse[end].F_T=0
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, settings.massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/vehicle.m_union/vehicle.ξ_union
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
# creating the next waypoint
push!(drivingCourse, Waypoint())
@ -896,7 +937,7 @@ function addCoastingPhaseWithIntersection!(characteristicSection::Characteristic
end #if
drivingCourse[end].v=drivingCourse[end-1].v+drivingCourse[end].Δv # velocity (in m/s)
if drivingCourse[end].v>characteristicSection.v_reach # if the vehicle gets to fast, it will brake
if drivingCourse[end].v>characteristicSection.v_reach # if the train gets to fast, it will brake
drivingCourse[end].v=characteristicSection.v_reach
drivingCourse[end].Δv=characteristicSection.v_reach-drivingCourse[end-1].v # step size (in m/s)
if drivingCourse[end].Δv==0.0
@ -921,7 +962,7 @@ function addCoastingPhaseWithIntersection!(characteristicSection::Characteristic
drivingCourse[end].ΔE=drivingCourse[end].ΔW_T # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
s_braking=ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/vehicle.a_braking)
s_braking=ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking)
end # while
# checking which limit was reached and adjusting the currentStepSize for the next cycle
@ -931,9 +972,9 @@ function addCoastingPhaseWithIntersection!(characteristicSection::Characteristic
pop!(drivingCourse)
pop!(coastingSection.waypoints) # TODO: hier soll wohl ein leeres Array gepoppt werden ..
elseif cycle==3
v_intersection=vehicle.a_braking*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))+sign(drivingCourse[end].v-drivingCourse[end-1].v)*sqrt(vehicle.a_braking^2*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))^2-2*vehicle.a_braking*(characteristicSection.s_end-drivingCourse[end-1].s+drivingCourse[end-1].v*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)))+characteristicSection.v_exit^2)
v_intersection=train.a_braking*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))+sign(drivingCourse[end].v-drivingCourse[end-1].v)*sqrt(train.a_braking^2*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v))^2-2*train.a_braking*(characteristicSection.s_end-drivingCourse[end-1].s+drivingCourse[end-1].v*((drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)))+characteristicSection.v_exit^2)
s_intersection=characteristicSection.s_end-(characteristicSection.v_exit^2-v_intersection^2)/2/vehicle.a_braking
s_intersection=characteristicSection.s_end-(characteristicSection.v_exit^2-v_intersection^2)/2/train.a_braking
# s_intersection_2=(v_intersection-drivingCourse[end-1].v)*(drivingCourse[end].s-drivingCourse[end-1].s)/(drivingCourse[end].v-drivingCourse[end-1].v)+drivingCourse[end-1].s
drivingCourse[end].v=v_intersection
@ -998,11 +1039,11 @@ function addCoastingPhaseWithIntersection!(characteristicSection::Characteristic
merge!(characteristicSection.behaviorSections, Dict("coasting"=>coastingSection))
end ## else: just return the given waypoint number without changes due to the coasting phase
return (characteristicSection, drivingCourse)
end #function addCoastingPhaseWithIntersection!
end #function addCoastingPhaseUntilBraking!
## This function calculates the waypoints of the braking phase.
# Therefore it gets its first waypoint and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, massModel::String, vehicle::Vehicle, allCs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat)
function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{Waypoint}, massModel::String, train::Train, allCs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat)
if drivingCourse[end].v>characteristicSection.v_exit && drivingCourse[end].s<characteristicSection.s_end
brakingSection=BehaviorSection()
brakingSection.type="braking" # type of behavior section
@ -1012,12 +1053,13 @@ function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingC
push!(brakingSection.waypoints, drivingCourse[end].i) # refering from the breaking section to the first of its waypoints
# traction effort and resisting forces (in N)
drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, vehicle)
drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, massModel, vehicle, allCs)
drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
drivingCourse[end].F_T=0.0
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, massModel, allCs, brakingSection.type))
#07/16 drivingCourse[end].F_Rt=calculateTractionUnitResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Rw=calculateWagonsResistance(drivingCourse[end].v, train)
#07/16 drivingCourse[end].F_Runion=drivingCourse[end].F_Rt+drivingCourse[end].F_Rw
#07/16 drivingCourse[end].F_Rp=calculatePathResistance(drivingCourse[end].s, massModel, train, allCs)
#07/16 drivingCourse[end].F_R=drivingCourse[end].F_Runion+drivingCourse[end].F_Rp
#07/16 drivingCourse[end].F_T=0.0
push!(drivingCourse, Waypoint())
drivingCourse[end].i=drivingCourse[end-1].i+1 # incrementing the number of the waypoint
@ -1029,8 +1071,8 @@ function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingC
drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s)
drivingCourse[end-1].a=round((drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs, digits=10) # acceleration (in m/s^2) (rounding because it should not be less than a_braking
if drivingCourse[end-1].a<vehicle.a_braking || drivingCourse[end-1].a>=0.0
println("Warning: a_braking gets to high in CS ",characteristicSection.id, " with a=",drivingCourse[end-1].a ," > ",vehicle.a_braking)
if drivingCourse[end-1].a<train.a_braking || drivingCourse[end-1].a>=0.0
println("Warning: a_braking gets to high in CS ",characteristicSection.id, " with a=",drivingCourse[end-1].a ," > ",train.a_braking)
end
drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s)
drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s)
@ -1055,4 +1097,4 @@ function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingC
end #function addBrakingPhase!
end #module
end #module MovingPhases

344
src/OperationModes.jl Normal file
View File

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

View File

@ -1,4 +1,4 @@
module RailwayDrivingDynamicsOutput
module Output
using ..types
using Plots
@ -7,26 +7,26 @@ using CSV, DataFrames, Dates
export createOutput
export plotDrivingCourse, printImportantValues, printSectionInformation # functions for showing results during the development
function createOutput(settings::Settings, pathName::String, vehicleName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
function createOutput(settings::Settings, pathName::String, trainName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
# method of function createOutput for one operation mode
if settings.typeOfOutput == "CSV"
return createOutputCsv(settings, pathName, vehicleName, drivingCourse, movingSection)
return createOutputCsv(settings, pathName, trainName, drivingCourse, movingSection)
else
return createOutputDict(settings, pathName, vehicleName, drivingCourse, movingSection)
return createOutputDict(settings, pathName, trainName, drivingCourse, movingSection)
end
end # funtion createOutput
function createOutput(settings::Settings, pathName::String, vehicleName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
function createOutput(settings::Settings, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
# method of function createOutput for two operation modes
if settings.typeOfOutput == "CSV"
return createOutputCsv(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
return createOutputCsv(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
else
return createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
return createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
end
end # funtion createOutput
function createOutputDict(settings::Settings, pathName::String, vehicleName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
function createOutputDict(settings::Settings, pathName::String, trainName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
# method of function createOutputDict for one operation mode
if settings.operationModeMinimumRunningTime
if settings.operationModeMinimumEnergyConsumption
@ -44,7 +44,7 @@ function createOutputDict(settings::Settings, pathName::String, vehicleName::Str
end
end
outputDict=Dict([("path name", pathName), ("vehicle name", vehicleName), ("operation mode", operationMode), ("mass model", settings.massModel), ("step variable", settings.stepVariable), ("step size", settings.stepSize)])
outputDict=Dict([("path name", pathName), ("train name", trainName), ("operation mode", operationMode), ("mass model", settings.massModel), ("step variable", settings.stepVariable), ("step size", settings.stepSize)])
# creating an output array
outputArray=Array{Any, 1}[]
@ -72,10 +72,10 @@ function createOutputDict(settings::Settings, pathName::String, vehicleName::Str
return outputDict
end # function createOutputDict
function createOutputDict(settings::Settings, pathName::String, vehicleName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
function createOutputDict(settings::Settings, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
# method of function createOutputDict for two operation modes
if settings.operationModeMinimumRunningTime
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
if settings.operationModeMinimumEnergyConsumption
# creating the second output array
@ -95,7 +95,7 @@ function createOutputDict(settings::Settings, pathName::String, vehicleName::Str
merge!(outputDict, Dict("outputArrayMinimumEnergyConsumption"=>outputArrayMinimumEnergyConsumption))
end
else
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
end
# println("The output dictionary has been created for minimum running time and minimum energy consumption.")
@ -103,9 +103,9 @@ function createOutputDict(settings::Settings, pathName::String, vehicleName::Str
end # function createOutputDict
function createOutputCsv(settings::Settings, pathName::String, vehicleName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
function createOutputCsv(settings::Settings, pathName::String, trainName::String, drivingCourse::Vector{Waypoint}, movingSection::MovingSection)
# method of function createOutputDict for one operation mode
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourse, movingSection)
outputDict=createOutputDict(settings, pathName, trainName, drivingCourse, movingSection)
if length(movingSection.energySavingModifications)>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption
operationMode="minimum energy consumption"
@ -123,8 +123,8 @@ function createOutputCsv(settings::Settings, pathName::String, vehicleName::Stri
# creating information block
infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "vehicle name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, vehicleName, operationMode, settings.massModel, settings.stepVariable, string(settings.stepSize), ""])
push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, trainName, operationMode, settings.massModel, settings.stepVariable, string(settings.stepSize), ""])
for column in 3:length(outputDict[outputArray][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
end # for
@ -156,16 +156,16 @@ function createOutputCsv(settings::Settings, pathName::String, vehicleName::Stri
return outputDict
end #function createOutputCsv
function createOutputCsv(settings::Settings, pathName::String, vehicleName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
function createOutputCsv(settings::Settings, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Waypoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{Waypoint}, movingSectionMinimumEnergyConsumption::MovingSection)
# method of function createOutputDict for two operation modes
outputDict=createOutputDict(settings, pathName, vehicleName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
if settings.operationModeMinimumRunningTime
#creating information block
infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "vehicle name", "operation mode", "mass model", "step variable", "step size", ""])
#push!(infoColumns, [pathName, vehicleName, "minimum running time", settings.massModel, settings.stepVariable, settings.stepSize, ""])
push!(infoColumns, [pathName, vehicleName, "minimum running time", settings.massModel, settings.stepVariable, string(settings.stepSize), ""])
push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
#push!(infoColumns, [pathName, trainName, "minimum running time", settings.massModel, settings.stepVariable, settings.stepSize, ""])
push!(infoColumns, [pathName, trainName, "minimum running time", settings.massModel, settings.stepVariable, string(settings.stepSize), ""])
for column in 3:length(outputDict["outputArrayMinimumRunningTime"][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
@ -204,8 +204,8 @@ function createOutputCsv(settings::Settings, pathName::String, vehicleName::Stri
if settings.operationModeMinimumEnergyConsumption
#creating information block
infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "vehicle name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, vehicleName, "minimum energy consumption", settings.massModel, settings.stepVariable, settings.stepSize, ""])
push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, trainName, "minimum energy consumption", settings.massModel, settings.stepVariable, settings.stepSize, ""])
for column in 3:length(outputDict["outputArrayMinimumEnergyConsumption"][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
end # for
@ -287,15 +287,16 @@ function plotDrivingCourse(drivingCourse::Vector{Waypoint})
p2=plot([t], [v], title = "v in m/s", label = ["v"], xlabel = "t in s")
p3=plot([s], [t], title = "t in s", label = ["t"], xlabel = "s in m")
# 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")
# p4=plot([t], [s], title = "s in m", label = ["s"], xlabel = "t in s")
p5=plot([s], [E], title = "E in Ws", label = ["E"], xlabel = "s in m")
p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s")
all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
all=plot(p1, p2, p5, p6, layout = (2, 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
@ -339,17 +340,17 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{Waypoint},dri
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")
# 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")
# 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],
@ -363,9 +364,10 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{Waypoint},dri
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, 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
end # module RailwayDrivingDynamicsOutput
end # module Output

View File

@ -1,21 +1,22 @@
module RailwayDrivingDynamicsPreparation
module Preparation
using ..types
include("./RailwayDrivingDynamicsMovingPhases.jl")
using .RailwayDrivingDynamicsMovingPhases
include("./MovingPhases.jl")
using .MovingPhases
export preparateSections
## creating a moving section and its containing characteristic sections which braking and acceleration behavior is secured
function preparateSections(path::Path, vehicle::Vehicle, settings::Settings)
movingSection=createMovingSection(path, vehicle.v_limit)
movingSection=secureBrakingBehavior!(movingSection, vehicle.a_braking)
movingSection=secureAccelerationBehavior!(movingSection, settings, vehicle)
## create a moving section and its containing characteristic sections with securedd braking, acceleration and cruising behavior
function preparateSections(path::Path, train::Train, settings::Settings)
movingSection=createMovingSection(path, train.v_limit)
movingSection=secureBrakingBehavior!(movingSection, train.a_braking)
movingSection=secureAccelerationBehavior!(movingSection, settings, train)
movingSection=secureCruisingBehavior!(movingSection, settings, train)
return movingSection
end #function preparateSections
## creating a moving section containing characteristic sections
function createMovingSection(path::Path, v_vehicleLimit::AbstractFloat)
## create a moving section containing characteristic sections
function createMovingSection(path::Path, v_trainLimit::AbstractFloat)
# this function creates and returns a moving section dependent on the paths attributes
movingSection=MovingSection()
@ -30,19 +31,19 @@ function createMovingSection(path::Path, v_vehicleLimit::AbstractFloat)
s_csStart=movingSection.s_start
csId=1
for row in 2:length(path.sections)
if min(path.sections[row-1].v_limit, v_vehicleLimit) != min(path.sections[row].v_limit, v_vehicleLimit) || path.sections[row-1].f_Rp != path.sections[row].f_Rp
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[row-1], min(path.sections[row-1].v_limit, v_vehicleLimit)))
if min(path.sections[row-1].v_limit, v_trainLimit) != min(path.sections[row].v_limit, v_trainLimit) || path.sections[row-1].f_Rp != path.sections[row].f_Rp
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[row-1], min(path.sections[row-1].v_limit, v_trainLimit)))
s_csStart=path.sections[row].s_start
csId=csId+1
end #if
end #for
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end].v_limit, v_vehicleLimit)))
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end].v_limit, v_trainLimit)))
return movingSection
end #function createMovingSection
##
## create a characteristic section for a path section
function createCharacteristicSection(csId::Integer, s_csStart::AbstractFloat, section::PathSection, v_csLimit::AbstractFloat)
# this function creates and returns a characteristic section dependent on the paths attributes
characteristicSection=CharacteristicSection()
@ -64,9 +65,9 @@ function createCharacteristicSection(csId::Integer, s_csStart::AbstractFloat, se
return characteristicSection
end #function createCharacteristicSection
## defining the intersection velocities between the characterisitc sections
## define the intersection velocities between the characterisitc sections to secure braking behavior
function secureBrakingBehavior!(movingSection::MovingSection, a_braking::AbstractFloat)
# this function limits the entry and exit velocity of the characteristic sections to secure that the vehicle stops at the moving sections end
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
csId=length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_exit=0.0 # the exit velocity of the last characteristic section is 0.0 m/s
while csId >= 1
@ -83,9 +84,74 @@ function secureBrakingBehavior!(movingSection::MovingSection, a_braking::Abstrac
return movingSection
end #function secureBrakingBehavior!
##
function secureAccelerationBehavior!(movingSection::MovingSection, settings::Settings, vehicle::Vehicle)
# this function limits the entry and exit velocity of the characteristic sections for case that the vehicle accelerates in every section and cruises aterwards
## define the intersection velocities between the characterisitc sections to secure acceleration behavior
function secureAccelerationBehavior!(movingSection::MovingSection, settings::Settings, train::Train)
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
movingSection.characteristicSections[1].v_entry=0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint=Waypoint()
startingPoint.i=1
previousCSv_exit=movingSection.characteristicSections[1].v_entry
for csId in 1:length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_entry, previousCSv_exit)
startingPoint.s=movingSection.characteristicSections[csId].s_start
startingPoint.v=movingSection.characteristicSections[csId].v_entry
accelerationCourse=[startingPoint] # List of waypoints
if movingSection.characteristicSections[csId].v_entry<movingSection.characteristicSections[csId].v_reach
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, train, movingSection.characteristicSections) # this function changes the accelerationCourse
movingSection.characteristicSections[csId].v_reach=accelerationCourse[end].v
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, movingSection.characteristicSections[csId].v_reach)
else #movingSection.characteristicSections[csId].v_entry==movingSection.characteristicSections[csId].v_reach
# v_exit stays the same
end #if
previousCSv_exit=movingSection.characteristicSections[csId].v_exit
end #for
return movingSection
end #function secureAccelerationBehavior!
## define the intersection velocities between the characterisitc sections to secure cruising behavior
function secureCruisingBehavior!(movingSection::MovingSection, settings::Settings, train::Train)
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_reach
startingPoint=Waypoint()
startingPoint.i=1
previousCSv_exit=movingSection.characteristicSections[1].v_entry
for csId in 1:length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_entry, previousCSv_exit)
startingPoint.s=movingSection.characteristicSections[csId].s_start
startingPoint.v=movingSection.characteristicSections[csId].v_reach
cruisingCourse=[startingPoint] # List of waypoints
(movingSection.characteristicSections[csId], cruisingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], cruisingCourse, movingSection.characteristicSections[csId].s_total, settings, train, movingSection.characteristicSections, "cruising") # this function changes the cruisingCourse
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, cruisingCourse[end].v)
previousCSv_exit=movingSection.characteristicSections[csId].v_exit
end #for
return movingSection
end #function secureCruisingBehavior!
end #module Preparation
#= 22.06.2021: acceleration an cruising behavior seperated in two functions
## define the intersection velocities between the characterisitc sections to secure acceleration behavior
function secureAccelerationBehavior!(movingSection::MovingSection, settings::Settings, train::Train)
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
movingSection.characteristicSections[1].v_entry=0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint=Waypoint()
startingPoint.i=1
@ -97,15 +163,15 @@ function secureAccelerationBehavior!(movingSection::MovingSection, settings::Set
startingPoint.s=movingSection.characteristicSections[csId].s_start
startingPoint.v=movingSection.characteristicSections[csId].v_entry
accelerationCourse=[startingPoint] # List of waypoints
cruisingCourse=[startingPoint] # List of waypoints
if movingSection.characteristicSections[csId].v_entry<movingSection.characteristicSections[csId].v_reach
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, vehicle, movingSection.characteristicSections) # this function changes the accelerationCourse
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, train, movingSection.characteristicSections) # this function changes the accelerationCourse
movingSection.characteristicSections[csId].v_reach=accelerationCourse[end].v
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, movingSection.characteristicSections[csId].v_reach)
if settings.stepVariable=="v in m/s" # with the new v_reach the calculation will be defferent a second time. Therefore the CS has to be calculated again for velocity step method to refresh the length of the acceleration section for further simulation
if settings.stepVariable=="v in m/s" # with the new v_reach the calculation will be different a second time. Therefore the CS has to be calculated again for velocity step method to refresh the length of the acceleration section for further simulation
delete!(movingSection.characteristicSections[csId].behaviorSections, "starting")
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration")
delete!(movingSection.characteristicSections[csId].behaviorSections, "acceleration")
@ -113,19 +179,19 @@ function secureAccelerationBehavior!(movingSection::MovingSection, settings::Set
movingSection.characteristicSections[csId].t_total=0.0
accelerationCourse=[startingPoint] # List of waypoints
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, vehicle, movingSection.characteristicSections) # this function changes the accelerationCourse
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, train, movingSection.characteristicSections) # this function changes the accelerationCourse
end
else #movingSection.characteristicSections[csId].v_entry==movingSection.characteristicSections[csId].v_reach
# v_exit stays the same
end #if
# securing cruising behavior
# is need if the path resistance is too high, the vehicle can not cruise at v_reach and is getting slower
s_cruisingMax=movingSection.characteristicSections[csId].s_end-accelerationCourse[end].s
if s_cruisingMax>0.0
(movingSection.characteristicSections[csId], accelerationCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], accelerationCourse, s_cruisingMax, settings, vehicle, movingSection.characteristicSections, "cruising")
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, accelerationCourse[end].v)
end
# securing cruising behavior
# is need if the path resistance is too high, the train can not cruise at v_reach and is getting slower
s_cruisingMax=movingSection.characteristicSections[csId].s_end-accelerationCourse[end].s
if s_cruisingMax>0.0
(movingSection.characteristicSections[csId], accelerationCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], accelerationCourse, s_cruisingMax, settings, train, movingSection.characteristicSections, "cruising")
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, accelerationCourse[end].v)
end
previousCSv_exit=movingSection.characteristicSections[csId].v_exit
# println("CS",csId,": s_start: ",movingSection.characteristicSections[csId].s_start," v_entry: ", round(movingSection.characteristicSections[csId].v_entry*3.6, digits=5), ", v_reach: ", round(movingSection.characteristicSections[csId].v_reach*3.6, digits=5), " v_exit: ", round(movingSection.characteristicSections[csId].v_exit*3.6, digits=5))
@ -133,5 +199,4 @@ function secureAccelerationBehavior!(movingSection::MovingSection, settings::Set
return movingSection
end #function secureAccelerationBehavior!
end #module RailwayDrivingDynamicsPreparation
=#

View File

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

View File

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

View File

@ -1,37 +1,45 @@
module RailwayDrivingDynamics
module TrainRun
include("./types.jl")
include("./RailwayDrivingDynamicsInput.jl")
include("./RailwayDrivingDynamicsPreparation.jl")
include("./RailwayDrivingDynamicsOperationModes.jl")
include("./RailwayDrivingDynamicsOutput.jl")
include("./Input.jl")
include("./Preparation.jl")
include("./OperationModes.jl")
include("./Output.jl")
using .types
using .RailwayDrivingDynamicsInput
using .RailwayDrivingDynamicsPreparation
using .RailwayDrivingDynamicsOperationModes
using .RailwayDrivingDynamicsOutput
using .Input
using .Preparation
using .OperationModes
using .Output
export calculateDrivingDynamics
function calculateDrivingDynamics(vehicleFilePath::String, pathFilePath::String, settingsFilePath::String)
# main function for calculating the driving dynamics
println("")
println("")
println("")
"""
calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
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 `trainFilePath`, `pathFilePath`, `settingsFilePath`.
# Examples
```julia-repl
julia> calculateDrivingDynamics(C:\\folder\\train.yaml, C:\\folder\\path.yaml, C:\\folder\\settings.yaml)
todo !!!
```
"""
function calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
print("\n\n\n")
# input
(vehicle, path, settings)=readInput(vehicleFilePath, pathFilePath, settingsFilePath)
(train, path, settings)=readInput(trainFilePath, pathFilePath, settingsFilePath)
println("The input has been saved.")
# preparing the input data
movingSection=preparateSections(path, vehicle, settings)
println("The moving section has been preparated.")
movingSection=preparateSections(path, train, settings)
println("The moving section has been prepared.")
if settings.operationModeMinimumRunningTime==true || settings.operationModeMinimumEnergyConsumption==true
(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=simulateMinimumRunningTime!(movingSection, settings, vehicle)
(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=simulateMinimumRunningTime!(movingSection, settings, train)
# println("t_total=", drivingCourseMinimumRunningTime[end].t)
# printSectionInformation(movingSectionMinimumRunningTime)
println("The driving course for the shortest running time has been calculated.")
@ -40,25 +48,25 @@ function calculateDrivingDynamics(vehicleFilePath::String, pathFilePath::String,
# oparation mode "minimum energy consumption"
if settings.operationModeMinimumEnergyConsumption==true
(movingSectionMinimumEnergyConsumption, drivingCourseMinimumEnergyConsumption)=simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime, settings, vehicle)
(movingSectionMinimumEnergyConsumption, drivingCourseMinimumEnergyConsumption)=simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime, settings, train)
# printSectionInformation(movingSectionMinimumEnergyConsumption)
println("The driving course for the energy consumption has been calculated.")
println("The driving course for lowest the energy consumption has been calculated.")
end #if
#output
if settings.operationModeMinimumRunningTime==true && settings.operationModeMinimumEnergyConsumption==true
plotDrivingCourse(drivingCourseMinimumRunningTime, drivingCourseMinimumEnergyConsumption)
return createOutput(settings, path.name, vehicle.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
return createOutput(settings, path.name, train.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
elseif settings.operationModeMinimumRunningTime==true
plotDrivingCourse(drivingCourseMinimumRunningTime)
return createOutput(settings, path.name, vehicle.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
return createOutput(settings, path.name, train.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
elseif settings.operationModeMinimumEnergyConsumption==true
plotDrivingCourse(drivingCourseMinimumEnergyConsumption)
return createOutput(settings, path.name, vehicle.name, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
return createOutput(settings, path.name, train.name, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
else
println("No Output was demanded. So no output is created.")
return Dict()
end
end # function calculateDrivingDynamics
end # module RailwayDrivingDynamics
end # module TrainRun

View File

@ -1,6 +1,6 @@
module types
# definition of all the additional types and their constructors
export Settings, Vehicle, PathSection, Path, Waypoint, BehaviorSection, CharacteristicSection, EnergySavingModification, MovingSection
export Settings, Train, PathSection, Path, Waypoint, BehaviorSection, CharacteristicSection, EnergySavingModification, MovingSection # tried to insert copy on 15.07.2021 , copy
## settings for the simulation
mutable struct Settings
@ -17,16 +17,16 @@ end # mutable struct Settings
Settings()=Settings("", "", 0.0, false, false, "", "", "")
## vehicle
mutable struct Vehicle
name::String # vehicles name
id # vehicles identifier
vehicleType::String # type of vehicle "passenger" or "freight" or "motor coach train"
## train
mutable struct Train
name::String # trains name
id # trains identifier
trainType::String # type of train "passenger" or "freight" or "motor coach train"
l_union::AbstractFloat # total length (in m)
v_limit::AbstractFloat # vehicles speed limit (in m/s)
v_limit::AbstractFloat # trains speed limit (in m/s)
a_braking::AbstractFloat # braking acceleration (in m/s^2)
m_union::AbstractFloat # total mass (in kg)
ξ_union::AbstractFloat # rotation mass factor of the whole vehicle union (without unit)
ξ_union::AbstractFloat # rotation mass factor of the whole train union (without unit)
# if not available use ξ_t and ξ_w
# traction unit
@ -51,8 +51,8 @@ mutable struct Vehicle
f_Rw1::AbstractFloat # coefficient for resistance to rolling of the set of wagons (in ‰)
f_Rw2::AbstractFloat # coefficient for air resistance of the set of wagons (in ‰)
Δv_w::AbstractFloat # coefficient for velocitiy difference between set of wagons and outdoor air (in m/s)
end # mutable struct Vehicle
Vehicle()=Vehicle("", 0, "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
end # mutable struct Train
Train()=Train("", 0, "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
## path separated in smaler sections
@ -100,6 +100,7 @@ mutable struct Waypoint
F_Rw::AbstractFloat # set of wagons resistance (in N)
end # mutable struct Waypoint
Waypoint()=Waypoint(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
# tried to insert copy on 15.07.2021 copy(original::Waypoint)=Waypoint(original.i, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W_T, original.ΔW_T, original.E, original.ΔE, original.F_T, original.F_R, original.F_Rp, original.F_Runion, original.F_Rt, original.F_Rw)
Waypoint(original::Waypoint)=Waypoint(original.i, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W_T, original.ΔW_T, original.E, original.ΔE, original.F_T, original.F_R, original.F_Rp, original.F_Runion, original.F_Rt, original.F_Rw)

View File

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