From a57944b1664d18aade6e4e98880aac929db3a6d1 Mon Sep 17 00:00:00 2001 From: Max Kannenberg <95709892+MaxKannenberg@users.noreply.github.com> Date: Wed, 8 Dec 2021 13:35:25 +0100 Subject: [PATCH] Rename modules and variables --- Project.toml | 4 +- README.md | 7 +- data/settings.yaml | 2 +- .../train_freight_V90withOreConsist.yaml} | 4 +- .../train_passenger_IC2.yaml} | 4 +- ...train_passenger_SiemensDesiroClassic.yaml} | 4 +- examples/MinimalWorkingExample.jl | 50 +- ...ynamicsEnergySaving.jl => EnergySaving.jl} | 114 ++-- src/Input.jl | 634 ++++++++++++++++++ ...ynamicsMovingPhases.jl => MovingPhases.jl} | 300 +++++---- src/OperationModes.jl | 344 ++++++++++ ...lwayDrivingDynamicsOutput.jl => Output.jl} | 78 +-- ...gDynamicsPreparation.jl => Preparation.jl} | 129 +++- src/RailwayDrivingDynamicsInput.jl | 600 ----------------- src/RailwayDrivingDynamicsOperationModes.jl | 478 ------------- ...{RailwayDrivingDynamics.jl => TrainRun.jl} | 56 +- src/types.jl | 21 +- test/runtests.jl | 94 +-- 18 files changed, 1462 insertions(+), 1461 deletions(-) rename data/{vehicles/vehicle_freight.yaml => trains/train_freight_V90withOreConsist.yaml} (96%) rename data/{vehicles/vehicle_passenger_intercity.yaml => trains/train_passenger_IC2.yaml} (97%) rename data/{vehicles/vehicle_passenger_suburban.yaml => trains/train_passenger_SiemensDesiroClassic.yaml} (97%) rename src/{RailwayDrivingDynamicsEnergySaving.jl => EnergySaving.jl} (77%) create mode 100644 src/Input.jl rename src/{RailwayDrivingDynamicsMovingPhases.jl => MovingPhases.jl} (82%) create mode 100644 src/OperationModes.jl rename src/{RailwayDrivingDynamicsOutput.jl => Output.jl} (79%) rename src/{RailwayDrivingDynamicsPreparation.jl => Preparation.jl} (55%) delete mode 100644 src/RailwayDrivingDynamicsInput.jl delete mode 100644 src/RailwayDrivingDynamicsOperationModes.jl rename src/{RailwayDrivingDynamics.jl => TrainRun.jl} (53%) diff --git a/Project.toml b/Project.toml index 01a8066..3122b10 100644 --- a/Project.toml +++ b/Project.toml @@ -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" diff --git a/README.md b/README.md index 954bed4..0045e69 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/data/settings.yaml b/data/settings.yaml index 8e6c2b7..9f2ea28 100644 --- a/data/settings.yaml +++ b/data/settings.yaml @@ -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" diff --git a/data/vehicles/vehicle_freight.yaml b/data/trains/train_freight_V90withOreConsist.yaml similarity index 96% rename from data/vehicles/vehicle_freight.yaml rename to data/trains/train_freight_V90withOreConsist.yaml index 2846c82..755f8ce 100644 --- a/data/vehicles/vehicle_freight.yaml +++ b/data/trains/train_freight_V90withOreConsist.yaml @@ -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) diff --git a/data/vehicles/vehicle_passenger_intercity.yaml b/data/trains/train_passenger_IC2.yaml similarity index 97% rename from data/vehicles/vehicle_passenger_intercity.yaml rename to data/trains/train_passenger_IC2.yaml index e0acdf6..f84fe10 100644 --- a/data/vehicles/vehicle_passenger_intercity.yaml +++ b/data/trains/train_passenger_IC2.yaml @@ -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) diff --git a/data/vehicles/vehicle_passenger_suburban.yaml b/data/trains/train_passenger_SiemensDesiroClassic.yaml similarity index 97% rename from data/vehicles/vehicle_passenger_suburban.yaml rename to data/trains/train_passenger_SiemensDesiroClassic.yaml index 85da9ee..6692927 100644 --- a/data/vehicles/vehicle_passenger_suburban.yaml +++ b/data/trains/train_passenger_SiemensDesiroClassic.yaml @@ -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) diff --git a/examples/MinimalWorkingExample.jl b/examples/MinimalWorkingExample.jl index 8cf54be..1eb8f38 100644 --- a/examples/MinimalWorkingExample.jl +++ b/examples/MinimalWorkingExample.jl @@ -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 diff --git a/src/RailwayDrivingDynamicsEnergySaving.jl b/src/EnergySaving.jl similarity index 77% rename from src/RailwayDrivingDynamicsEnergySaving.jl rename to src/EnergySaving.jl index 9115347..caf813c 100644 --- a/src/RailwayDrivingDynamicsEnergySaving.jl +++ b/src/EnergySaving.jl @@ -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].vcsModified.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].scsOriginal.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].v0.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].s0.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 (Δt0.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 diff --git a/src/RailwayDrivingDynamicsMovingPhases.jl b/src/MovingPhases.jl similarity index 82% rename from src/RailwayDrivingDynamicsMovingPhases.jl rename to src/MovingPhases.jl index 26d045b..4361660 100644 --- a/src/RailwayDrivingDynamicsMovingPhases.jl +++ b/src/MovingPhases.jl @@ -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 s0 && s-vehicle.l_union0 && s-train.l_union1 && drivingCourse[end].s-vehicle.l_union1 && drivingCourse[end].s-train.l_union0.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_union0 && drivingCourse[end].s-train.l_union0 && drivingCourse[end].v0.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].v0.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_union1 && drivingCourse[end].s-train.l_union0.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_union0 && drivingCourse[end].s-train.l_union0 && drivingCourse[end].v0.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].v0.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=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].scharacteristicSection.v_exit && drivingCourse[end].v<=characteristicSection.v_reach && (drivingCourse[end].s+s_braking)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=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=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 diff --git a/src/OperationModes.jl b/src/OperationModes.jl new file mode 100644 index 0000000..0fc6538 --- /dev/null +++ b/src/OperationModes.jl @@ -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 diff --git a/src/RailwayDrivingDynamicsOutput.jl b/src/Output.jl similarity index 79% rename from src/RailwayDrivingDynamicsOutput.jl rename to src/Output.jl index 420f907..7acbecf 100644 --- a/src/RailwayDrivingDynamicsOutput.jl +++ b/src/Output.jl @@ -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 diff --git a/src/RailwayDrivingDynamicsPreparation.jl b/src/Preparation.jl similarity index 55% rename from src/RailwayDrivingDynamicsPreparation.jl rename to src/Preparation.jl index 357c25b..42368ac 100644 --- a/src/RailwayDrivingDynamicsPreparation.jl +++ b/src/Preparation.jl @@ -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_entry0.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 +=# diff --git a/src/RailwayDrivingDynamicsInput.jl b/src/RailwayDrivingDynamicsInput.jl deleted file mode 100644 index 9d9d547..0000000 --- a/src/RailwayDrivingDynamicsInput.jl +++ /dev/null @@ -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_startNext3 - 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 diff --git a/src/RailwayDrivingDynamicsOperationModes.jl b/src/RailwayDrivingDynamicsOperationModes.jl deleted file mode 100644 index cd446a8..0000000 --- a/src/RailwayDrivingDynamicsOperationModes.jl +++ /dev/null @@ -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].vmovingSection.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 diff --git a/src/RailwayDrivingDynamics.jl b/src/TrainRun.jl similarity index 53% rename from src/RailwayDrivingDynamics.jl rename to src/TrainRun.jl index 9f28387..e4a0ff5 100644 --- a/src/RailwayDrivingDynamics.jl +++ b/src/TrainRun.jl @@ -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 diff --git a/src/types.jl b/src/types.jl index 1afa8fc..8a0dcb1 100644 --- a/src/types.jl +++ b/src/types.jl @@ -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) diff --git a/test/runtests.jl b/test/runtests.jl index 9919bad..2e9512a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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.