Refactor modules for diminishing run and tractive effort velocity pairs

pull/1/head v0.5
Max Kannenberg 2021-12-08 22:44:35 +01:00
parent fb942260d2
commit 7eed749d49
9 changed files with 646 additions and 366 deletions

View File

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

View File

@ -23,18 +23,28 @@ See folder examples.
# History
## Version 0.5
Refactor modules for diminishing run and tractive effort velocity pairs
- Add the seperate moving phase "diminishing run" for steep ascents where a train runs with maximum tractive effort while the driving resistances are even higher
- Refactor tractiveEffortArray to tractiveEffortVelocityPairs
- Rename file path and folder path to directory
## Version 0.4.1
Rename waypoints
- rename "waypoints" to "dataPoints" and "Waypoint" to "DataPoint"
## Version 0.4
Refactor and fix modules EnergySaving, OperationModes and MovingPhases
- add the general used level of accuracy from v0.3 to EnergySaving and OperationModes.
- fix OperationModes and MovingPhases for steep ascents where a train runs with maximum tractive effort while the driving resistances are even higher.
- add the general used level of accuracy from v0.3 to EnergySaving and OperationModes
- fix OperationModes and MovingPhases for steep ascents where a train runs with maximum tractive effort while the driving resistances are even higher
## Version 0.3
@ -42,7 +52,7 @@ Refactor and fix modules EnergySaving, OperationModes and MovingPhases
Refactor module MovingPhases
- extract repeatedly occuring code lines and create smaller functions (e.g. the function moveAStep)
- integrate a new approach for calculating the waypoints near intersections (e.g. including an editable level of accuracy).
- integrate a new approach for calculating the waypoints near intersections (e.g. including an editable level of accuracy)
## Version 0.2

View File

@ -90,6 +90,214 @@ function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, train::
end #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if (haskey(csOriginal.behaviorSections, "cruising") || haskey(csOriginal.behaviorSections, "diminishing")) && haskey(csOriginal.behaviorSections, "braking")
# check if cruising or diminishing should be reduced for coasting
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "diminishing")
if get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[1] > get(csOriginal.behaviorSections, "diminishing", BehaviorSection()).dataPoints[1]
reduceCruising=true
reduceDiminishing=false
else
reduceDiminishing=true
reduceCruising=false
end
elseif haskey(csOriginal.behaviorSections, "cruising")
reduceCruising=true
reduceDiminishing=false
elseif haskey(csOriginal.behaviorSections, "diminishing")
reduceDiminishing=true
reduceCruising=false
end
if reduceCruising
cruisingReduction=settings.stepSize
while cruisingReduction>=settings.stepSize/10^approximationLevel
#while cruisingReduction>=settings.stepSize/100
while cruisingReduction>=settings.stepSize/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_end) -> see below at the end of the while loop
# create a copy for the characteristic sections drivingCourse
energySavingStartId=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[1]
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
# copy the driving course till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}()
for i in 1:energySavingStartId
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of data points till the start of energy saving
end
# calculating the new length of the cruising section
if settings.stepVariable=="s in m" # distance step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction
elseif settings.stepVariable=="t in s" # time step method
# 09/20 old: doesn't work for non constant cruising
# t_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).t_total-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v
wayReduction=drivingCourse(get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[end]).v*cruisingReduction
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-wayReduction
elseif settings.stepVariable=="v in m/s" # velocity step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction*10 # TODO: or better: *100 ?
end #if
s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "starting")
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("starting"=>startingSection))
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 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
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).t_total
end
if haskey(csOriginal.behaviorSections, "acceleration")
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total
end
if haskey(csOriginal.behaviorSections, "diminishing")
diminishingSection=BehaviorSection(get(csOriginal.behaviorSections, "diminishing", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t_total
end
# calculate the new and now shorter cruising section
if s_cruising>0.0
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end
# calculate the coasting phase until the point the train needs to brake
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
if drivingCourseModified[end].v < csModified.v_exit || drivingCourseModified[end].s > csModified.s_end
# 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
end
end # while cruisingReduction
# calculate the moving phase between coasting and the end of the CS
if drivingCourseModified[end].v > csModified.v_exit
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_end
# v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end
if t_recoveryAvailable < csModified.t_total-csOriginal.t_total || drivingCourseModified[end].v != csModified.v_exit || drivingCourseModified[end].s != csModified.s_end # time loss is to high and the CS has to be calculated again with larger cruising section (so with a smaller reduction of the cruising section) or v_exit or s_end are not reached excatly
cruisingReduction=cruisingReduction/10
else
return (csModified, drivingCourseModified, true)
end
end #while
elseif reduceDiminishing
# TODO: At the moment diminishing is reduced like the acceleration in decreaseMaximumVelocity. To reduce code, the methods for reducing cruising phase an reducing the diminishing pahse can be combined in some parts.
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "starting")
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("starting"=>startingSection))
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 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
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).t_total
end
if haskey(csOriginal.behaviorSections, "acceleration")
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total
end
if haskey(csOriginal.behaviorSections, "cruising")
cruisingSection=BehaviorSection(get(csOriginal.behaviorSections, "cruising", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("cruising"=>cruisingSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "cruising", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruising", BehaviorSection()).t_total
end
diminishingSection=BehaviorSection(get(csOriginal.behaviorSections, "diminishing", BehaviorSection()))
if length(diminishingSection.dataPoints) > 2
# remove the last diminishing waypoint
pop!(diminishingSection.dataPoints)
diminishingSection.v_exit=drivingCourse[diminishingSection.dataPoints[end]].v # exit speed (in m/s)
diminishingSection.s_end=drivingCourse[diminishingSection.dataPoints[end]].s # last position (in m)
diminishingSection.s_total=diminishingSection.s_end-diminishingSection.s_start # total length (in m)
diminishingSection.t_total=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E_total=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t_total
energySavingStartId=diminishingSection.dataPoints[end]
else
# The diminishing section is only one step. This step is removed and if there is a cruisingBeforeAcceleration section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", get(csOriginal.behaviorSections, "diminishing", BehaviorSection())).dataPoints[1]
end
# copy the driving course till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}()
for i in 1:energySavingStartId
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
end
# calculate the coasting phase until the point the train needs to brake
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
# calculate the moving phase between coasting and the end of the CS
if drivingCourseModified[end].v > csModified.v_exit
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_end
# v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end
if t_recoveryAvailable>=(csModified.t_total-csOriginal.t_total)
return (csModified, drivingCourseModified, true)
else # time loss is to high. so there is no energy saving modification for this CS with the available recovery time
# TODO: just return false or take smaller steps?
return (CharacteristicSection(), [], false)
end
end
# there is no energy saving modification for this CS with the available recovery time
return (CharacteristicSection(), [], false)
else
# there is no energy saving modification for this CS because a cruising section AND a braking section are needed to be transformed into a coasting section
return (CharacteristicSection(), [], false)
end
end # function increaseCoastingSection
#= 12/03 old without diminishing: function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, 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/10^approximationLevel
@ -101,11 +309,13 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
# TODO: tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])]
drivingCourseModified=[DataPoint(drivingCourse[1])]
# TODO: tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])]
for i in 2:energySavingStartId
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of data points till the start of energy saving
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of data points till the start of energy saving
end
# calculating the new length of the cruising section
@ -182,6 +392,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end
end # function increaseCoastingSection
=#
# method 2 with shortening the acceleration by stepsize
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
@ -228,7 +439,7 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
energySavingStartId=accelerationSection.dataPoints[end]
else
# The acceleration section is only one step. This step is removed and if ther ist a cruisingBeforeAcceleration section it will be combined with the new cruising section.
# The acceleration section is only one step. This step is removed and if there is a cruisingBeforeAcceleration section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", get(csOriginal.behaviorSections, "acceleration", BehaviorSection())).dataPoints[1]
end

View File

@ -8,10 +8,10 @@ export readInput
"""
Read the input information from YAML files for train, path and settings, save it in different objects and return them.
"""
function readInput(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
train=inputTrain(trainFilePath)
path=inputPath(pathFilePath)
settings=inputSettings(settingsFilePath)
function readInput(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
train=inputTrain(trainDirectory)
path=inputPath(pathDirectory)
settings=inputSettings(settingsDirectory)
return (train, path, settings)
end #function readInput
@ -19,8 +19,8 @@ function readInput(trainFilePath::String, pathFilePath::String, settingsFilePath
"""
Read the train information from a YAML file, save it in a Train object and return it.
"""
function inputTrain(trainFilePath::String)
data = YAML.load(open(trainFilePath))
function inputTrain(trainDirectory::String)
data = YAML.load(open(trainDirectory))
collect(keys(data))
collect(values(data))
@ -56,8 +56,6 @@ function inputTrain(trainFilePath::String)
end
# speed limit: # trains speed limit (in m/s)
v_limit_temp=0.0
v_limit_kmh_temp=0.0
@ -189,11 +187,13 @@ function inputTrain(trainFilePath::String)
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?
# pairs of velocity and tractive effort
if haskey(data["train"],"F_T_pairs") && data["train"]["F_T_pairs"]!=nothing
F_T_pairs=data["train"]["F_T_pairs"]
train.tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs, 1.0)
#= old 2021-11-04: now it is pairs and no scope
# check if the elements of the array have the correct type
errorDetected=false
for row in 1:length(F_T_pairs)
@ -207,17 +207,33 @@ function inputTrain(trainFilePath::String)
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
if row>=2 && F_T_pairs[row][1] <= F_T_pairs[row-1][1]
errorDetected=true
println("ERROR at reading the train yaml file: The speed value of F_T_pairs in row ", row ," (v=",F_T_pairs[row][1]," m/s) is not higher than the speed value in the previous row (v=",F_T_pairs[row-1][1]," m/s).")
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.")
error("ERROR at reading the train yaml file: Only real floating point number >=0.0 are allowed for speed and tractive effort. The speed values have to be listed from low to high.")
end
# create tractiveEffortVelocityPairs
if F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first known value is used
push!(train.tractiveEffortVelocityPairs, [0.0, 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." )
end
for row in 1:length(F_T_pairs)
push!(train.tractiveEffortVelocityPairs, [F_T_pairs[row][1]], F_T_pairs[row][2]])
end # for
# 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]])
push!(train.tractiveEffortArray, [0.0, F_T_pairs[1][1], 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.")
@ -234,9 +250,11 @@ function inputTrain(trainFilePath::String)
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." )
@ -245,6 +263,9 @@ function inputTrain(trainFilePath::String)
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"]
train.tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs_kmh, 1000/3600)
#= old 2021-11-04: now it is pairs and no scope
# check if the elements of the array have the correct type
errorDetected=false
for row in 1:length(F_T_pairs_kmh)
@ -285,6 +306,7 @@ function inputTrain(trainFilePath::String)
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
@ -398,10 +420,53 @@ function inputTrain(trainFilePath::String)
return train
end #function inputTrain
function checkAndDefineTractiveEffortInput(F_T_pairs, velocityMultiplier::AbstractFloat)
# TODO: check if its numbers are real ? function checkAndDefineTractiveEffortInput(F_T_pairs::Array{Array{Real,1},1}, velocityMultiplier::AbstractFloat)
# 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
function inputPath(pathFilePath::String)
if row>=2 && F_T_pairs[row][1] <= F_T_pairs[row-1][1]
errorDetected=true
println("ERROR at reading the train yaml file: The speed value of F_T_pairs in row ", row ," (v=",F_T_pairs[row][1]," m/s) is not higher than the speed value in the previous row (v=",F_T_pairs[row-1][1]," m/s).")
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. The speed values have to be listed from low to high.")
end
# create tractiveEffortVelocityPairs
tractiveEffortVelocityPairs=[]
if F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first known value is used
push!(tractiveEffortVelocityPairs, [0.0, 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." )
end
for row in 1:length(F_T_pairs)
push!(tractiveEffortVelocityPairs, [F_T_pairs[row][1]*velocityMultiplier, F_T_pairs[row][2]])
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
return tractiveEffortVelocityPairs
end #function checkAndDefineTractiveEffortInput
function inputPath(pathDirectory::String)
# this function reads path information from a YAML file, saves it in a Path object and returns it
data = YAML.load(open(pathFilePath))
data = YAML.load(open(pathDirectory))
collect(keys(data))
collect(values(data))
@ -504,9 +569,9 @@ end # function inputPath
function inputSettings(settingsFilePath::String)
function inputSettings(settingsDirectory::String)
# this function reads setting information from a YAML file, saves it in a Setting object and returns it
data = YAML.load(open(settingsFilePath))
data = YAML.load(open(settingsDirectory))
collect(keys(data))
collect(values(data))
@ -594,16 +659,16 @@ function inputSettings(settingsFilePath::String)
# 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"]
if haskey(data["settings"],"csvDirectory")
if typeof(data["settings"]["csvDirectory"])==String
settings.csvDirectory=data["settings"]["csvDirectory"]
else
error("ERROR at reading the settings yaml file: The value of csvFolderPath is wrong. It has to be of type String.")
error("ERROR at reading the settings yaml file: The value of csvDirectory 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.")
error("ERROR at reading the settings yaml file: The keyword csvDirectory is missing. It has to be added.")
end
delete!(data["settings"], "csvFolderPath")
delete!(data["settings"], "csvDirectory")
end # if

View File

@ -11,16 +11,15 @@ approximationLevel = 6 # value for approximation to intersections TODO further
# TODO: define it in TrainRun and give it to each function?
## functions for calculating tractive effort and resisting forces
#TODO: change tractiveEffortArray to tractiveEffortVelocityPairs ?? Currently the example doesn't fit to the function
"""
calculateTractiveEffort(v, tractiveEffortArray)
calculateTractiveEffort(v, tractiveEffortVelocityPairs)
Calculate the trains tractive effort from the `tractiveEffortArray` dependend on the velocity `v`.
Calculate the trains tractive effort with the `tractiveEffortVelocityPairs` dependend on the velocity `v`.
...
# Arguments
- `v::AbstractFloat`: the current velocity in m/s.
- `tractiveEffortArray::Array{Array{AbstractFloat,1},1}`: the trains pairs for velocity in m/s and tractive effort in N as one array containing an array for each pair.
- `tractiveEffortVelocityPairs::Array{Array{AbstractFloat,1},1}`: the trains pairs for velocity in m/s and tractive effort in N as one array containing an array for each pair.
...
# Examples
@ -32,25 +31,42 @@ julia> calculateTractiveEffort(30.0, [[0.0, 180000], [20.0, 100000], [40.0, 6000
80000
```
"""
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortArray)
for row in 1:length(tractiveEffortArray)
if tractiveEffortArray[row][1]<=v && v<=tractiveEffortArray[row][2]
return tractiveEffortArray[row][3]
elseif tractiveEffortArray[row][1]>v
if row>1
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-_(row-1))/(v_row-v_(row-1))+F_(row-1)
F_T_interpolation=(v-tractiveEffortArray[row-1][2])*(tractiveEffortArray[row][3]-tractiveEffortArray[row-1][3])/(tractiveEffortArray[row][1]-tractiveEffortArray[row-1][2])+tractiveEffortArray[row-1][3]
return F_T_interpolation
else
return tractiveEffortArray[1][3]
end #if
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs)
for row in 1:length(tractiveEffortVelocityPairs)
if tractiveEffortVelocityPairs[row][1]==v
return tractiveEffortVelocityPairs[row][2]
elseif tractiveEffortVelocityPairs[row][1]>v
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-F_(row-1))/(v_row-v_(row-1))+F_(row-1)
F_T_interpolation=(v-tractiveEffortVelocityPairs[row-1][1])*(tractiveEffortVelocityPairs[row][2]-tractiveEffortVelocityPairs[row-1][2])/(tractiveEffortVelocityPairs[row][1]-tractiveEffortVelocityPairs[row-1][1])+tractiveEffortVelocityPairs[row-1][2]
return F_T_interpolation
end #if
end #for
# if v gets higher than the velocities in tractiveEffortArray the last tractive effort will be used
# if v gets higher than the velocities in tractiveEffortVelocityPairs the last tractive effort will be used
# TODO: also an extrapolation could be used
return tractiveEffortArray[end][3]
return tractiveEffortVelocityPairs[end][2]
end #function calculateTractiveEffort
#= old 2021-11-04: now with easier tractiveEffortVelocityPairs than previous tractiveEffortArray
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortArray)
for row in 1:length(tractiveEffortArray)
if tractiveEffortArray[row][1]<=v && v<=tractiveEffortArray[row][2]
return tractiveEffortArray[row][3]
elseif tractiveEffortArray[row][1]>v
if row>1
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-_(row-1))/(v_row-v_(row-1))+F_(row-1)
F_T_interpolation=(v-tractiveEffortArray[row-1][2])*(tractiveEffortArray[row][3]-tractiveEffortArray[row-1][3])/(tractiveEffortArray[row][1]-tractiveEffortArray[row-1][2])+tractiveEffortArray[row-1][3]
return F_T_interpolation
else
return tractiveEffortArray[1][3]
end #if
end #if
end #for
# if v gets higher than the velocities in tractiveEffortArray the last tractive effort will be used
# TODO: also an extrapolation could be used
return tractiveEffortArray[end][3]
end #function calculateTractiveEffort
=#
#TODO: choose an explanation and replace the ? ? ?
"""
@ -125,12 +141,14 @@ function calculateForces!(dataPoint::DataPoint, train::Train, massModel::String,
dataPoint.F_Rp=calculatePathResistance(dataPoint.s, massModel, train, allCs)
dataPoint.F_R=dataPoint.F_Runion+dataPoint.F_Rp
#calculate tractive effort
if bsType == "acceleration"
dataPoint.F_T = calculateTractiveEffort(dataPoint.v, train.tractiveEffortArray)
# calculate tractive effort
if bsType == "acceleration" || bsType == "diminishing"
# 12/03 test: if bsType == "acceleration" || bsType == "diminishing" || bsType == "maximumTraction"
# 11/21 old without diminishing: if bsType == "acceleration"
dataPoint.F_T = calculateTractiveEffort(dataPoint.v, train.tractiveEffortVelocityPairs)
# println(" F_T:",dataPoint.F_T )
elseif bsType == "cruising"
# 09/22 println("s=",dataPoint.s, " v=",dataPoint.v, " F_R=",dataPoint.F_R, " F_T=",calculateTractiveEffort(dataPoint.v, train.tractiveEffortArray))
dataPoint.F_T = min(max(0.0, dataPoint.F_R), calculateTractiveEffort(dataPoint.v, train.tractiveEffortArray))
dataPoint.F_T = min(max(0.0, dataPoint.F_R), calculateTractiveEffort(dataPoint.v, train.tractiveEffortVelocityPairs))
else
dataPoint.F_T = 0.0
end
@ -144,6 +162,7 @@ TODO
function moveAStep(previousPoint::DataPoint, stepVariable::String, stepSize::AbstractFloat, csId::Integer)
# stepSize is the currentStepSize depending on the accessing function
# TODO: csId is only for error messages. Should it be removed?
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =#
# creating the next data point
newPoint=DataPoint()
@ -156,14 +175,15 @@ function moveAStep(previousPoint::DataPoint, stepVariable::String, stepSize::Abs
newPoint.Δv=0.0 # step size (in m/s)
elseif stepVariable=="s in m" # distance step method
newPoint.Δs=stepSize # step size (in m)
# TODO: is this if correct and necessary?
#if ((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)<0.0 || (previousPoint.v^2+2*newPoint.Δs*previousPoint.a)<0.0 # checking if the parts of the following square roots will be <0.0
# error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.",
# " Before the stop the last point has the values s=",previousPoint.s," m, v=",previousPoint.v," m/s, a=",previousPoint.a," m/s^2,",
# " F_T=",previousPoint.F_T," N, F_Rt=",previousPoint.F_Rt," N, F_Rw=",previousPoint.F_Rw," N, F_Rp=",previousPoint.F_Rp," N.")
#end
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies.
=#
# 11/21 |->
if previousPoint.a<0.0
if ((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)<0.0 || (previousPoint.v^2+2*newPoint.Δs*previousPoint.a)<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",previousPoint.s," m, v=",previousPoint.v," m/s, a=",previousPoint.a," m/s^2,",
" F_T=",previousPoint.F_T," N, F_Rt=",previousPoint.F_Rt," N, F_Rw=",previousPoint.F_Rw," N, F_Rp=",previousPoint.F_Rp," N.")
end
end
# 11/21 ->|
newPoint.Δt=sign(previousPoint.a)*sqrt((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)-previousPoint.v/previousPoint.a # step size (in s)
newPoint.Δv=sqrt(previousPoint.v^2+2*newPoint.Δs*previousPoint.a)-previousPoint.v # step size (in m/s)
elseif stepVariable=="t in s" # time step method
@ -179,17 +199,12 @@ function moveAStep(previousPoint::DataPoint, stepVariable::String, stepSize::Abs
newPoint.s=previousPoint.s+newPoint.Δs # position (in m)
newPoint.t=previousPoint.t+newPoint.Δt # point in time (in s)
newPoint.v=previousPoint.v+newPoint.Δv # velocity (in m/s)
# 08/23 the following will be checked later
#if newPoint.v<=0.0
# error("ERROR: The train stops during the acceleration phase in CS",csId," m because the tractive effort is lower than the resistant forces.",
# " Before the stop the last point has the values s=",previousPoint.s," v=",previousPoint.v," m/s a=",previousPoint.a," m/s^2",
# " F_T=",previousPoint.F_T," N F_Rt=",previousPoint.F_Rt," N F_Rw=",previousPoint.F_Rw," N F_Rp=",previousPoint.F_Rp," N.")
#end
newPoint.ΔW_T=previousPoint.F_T*newPoint.Δs # mechanical work in this step (in Ws)
newPoint.W_T=previousPoint.W_T+newPoint.ΔW_T # mechanical work (in Ws)
newPoint.ΔE=newPoint.ΔW_T # energy consumption in this step (in Ws)
newPoint.E=previousPoint.E+newPoint.ΔE # energy consumption (in Ws)
return newPoint
end #function moveAStep
@ -343,11 +358,23 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
end #if
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration")
if drivingCourse[end].F_T < drivingCourse[end].F_R
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration"))
end
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_union)
if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s <characteristicSection.s_end
# 09/09 new (for steep gradients "<=" is necessary but only in accelertion until breaking due to Operation modes) TODO
# conditions for acceleration phase
targetSpeedReached = drivingCourse[end].v >= characteristicSection.v_reach
trainAtEnd = drivingCourse[end].s >= characteristicSection.s_end
tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R
# use the conditions for the acceleration phase
if !targetSpeedReached && !trainAtEnd && tractionSurplus
#11/23 old without F_T > F_R: if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s <characteristicSection.s_end && drivingCourse[end].F_T > drivingCourse[end].F_R
accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section
accelerationSection.s_start=drivingCourse[end].s # first position (in m)
@ -355,28 +382,20 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
push!(accelerationSection.dataPoints, drivingCourse[end].i)
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
#= 08/23 old version for intersection approximation
for cycle in 1:5 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size and fourth cycle with the last step size calculated till the intersection
# in the fifth cycle the interpolated values are corrected in case v_reach is still to high although s==s_end
=#
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
# while characteristicSection.v_reach - drivingCourse[end].v > 0.000001 && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0
while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0
# 09/09 new (for steep gradients "<=" is necessary but only in accelertion until braking due to Operation modes) TODO
while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].F_T > drivingCourse[end].F_R
# 12/03 old with v>0.0: while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R
# traction effort and resisting forces (in N)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
# 11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
# acceleration (in m/s^2):
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
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
push!(accelerationSection.dataPoints, drivingCourse[end].i)
# drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
(characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection)
@ -385,6 +404,7 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
end #if
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
end #if
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
@ -411,6 +431,8 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
elseif drivingCourse[end].v==characteristicSection.v_reach
break
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
currentStepSize = settings.stepSize / 10.0^cycle
else
error("ERROR at acceleration phase: With the step variable ",settings.stepVariable," the while loop will be left although v<v_reach and s<s_end in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
@ -432,30 +454,33 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
elseif drivingCourse[end].s>characteristicSection.s_end
drivingCourse[end].s=characteristicSection.s_end # rounding s down to s_end
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
else
end
end
end #for
# if length(accelerationSection.dataPoints) > 1 # 09/09 new: it is possible that the acceleration starts at v_reach, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section. | It should only be used in addAccelerationUntilBreaking! due to Operation Modes TODO
if length(accelerationSection.dataPoints) > 1 # 11/21 new: it is possible that the acceleration starts at v_reach, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
# calculate the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
accelerationSection.s_end=drivingCourse[end].s # last position (in m)
accelerationSection.s_total=accelerationSection.s_end-accelerationSection.s_start # total length (in m)
accelerationSection.t_total=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
accelerationSection.E_total=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
characteristicSection.t_total=characteristicSection.t_total+accelerationSection.t_total # total running time (in s)
characteristicSection.E_total=characteristicSection.E_total+accelerationSection.E_total # total energy consumption (in Ws)
# calculation the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
accelerationSection.s_end=drivingCourse[end].s # last position (in m)
accelerationSection.s_total=accelerationSection.s_end-accelerationSection.s_start # total length (in m)
accelerationSection.t_total=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
accelerationSection.E_total=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
characteristicSection.t_total=characteristicSection.t_total+accelerationSection.t_total # total running time (in s)
characteristicSection.E_total=characteristicSection.E_total+accelerationSection.E_total # total energy consumption (in Ws)
# TODO: this warning schould not be needed. just for testing
if characteristicSection.v_reach < drivingCourse[end].v
println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_reach=",characteristicSection.v_reach)
end
# TODO: this warning schould not be needed. just for testing
if characteristicSection.v_reach<drivingCourse[end].v
println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_reach=",characteristicSection.v_reach)
merge!(characteristicSection.behaviorSections, Dict("acceleration"=>accelerationSection))
end
merge!(characteristicSection.behaviorSections, Dict("acceleration"=>accelerationSection))
# end
end # else: just return the given data point number without changes due to the acceleration phase
return (characteristicSection, drivingCourse)
@ -468,48 +493,18 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
end #if
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration")
if drivingCourse[end].F_T < drivingCourse[end].F_R
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration"))
end
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_union)
#(formerSpeedLimits, s_cruisingBeforeAcceleration) = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_union)
#if s_cruisingBeforeAcceleration > 0.0
# (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 ",csWithTrainHeadId)
#end
#= 07/30 *** TODO
# 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-train.l_union<characteristicSection.s_start
if abs(allCs[characteristicSection.id-1].v_limit-drivingCourse[end].v)<0.000001
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, train.l_union)
if s_cruisingBeforeAcceleration>0.0
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, 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-train.l_union<allCs[csId].s_end
if allCs[csId].v_limit<characteristicSection.v_limit # TODO: is the position of trains end < movingSection.s_start, v_limit of the first CS is used
push!(formerSpeedLimits, [allCs[csId].s_end, allCs[csId].v_limit])
for i in 1:length(formerSpeedLimits)-1
if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2]
pop!(formerSpeedLimits)
break
end
end
end
csId=csId-1
end
end
end
=#
# 09/09 old (for steep gradients <= is necessary): if drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
if drivingCourse[end].v <= characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
# 11/23 old without F_T>F_R: if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].F_T > drivingCourse[end].F_R
accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section
accelerationSection.s_start=drivingCourse[end].s # first position (in m)
@ -517,24 +512,23 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
push!(accelerationSection.dataPoints, drivingCourse[end].i)
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
# 08/23 : old for cycle in 1:5 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size. fourth and fith are needed in case the velocity approaches 0.0 or v_reach
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
while drivingCourse[end].v <= characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
# 09/09 old (for steep gradients <= is necessary): while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
while drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend
# 12/03 old with v>0 while drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
#11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
# acceleration (in m/s^2):
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
# 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
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
push!(accelerationSection.dataPoints, drivingCourse[end].i)
# 12/03: was moved behind considerFormerSpeedLimits: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
(characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection)
@ -542,7 +536,7 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
return (characteristicSection, drivingCourse)
end
end
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
end #while
@ -567,6 +561,9 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
elseif drivingCourse[end].v==characteristicSection.v_reach
break
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
currentStepSize = settings.stepSize / 10.0^cycle
else
error("ERROR at acceleration until braking phase: With the step variable ",settings.stepVariable," the while loop will be left although v<v_reach and s<s_end in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end
@ -587,6 +584,11 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
elseif drivingCourse[end].s + s_braking > characteristicSection.s_end
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
else
end
@ -594,7 +596,7 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
end #for
if length(accelerationSection.dataPoints) > 1 # 09/09 new: it is possible that the acceleration starts at v_reach, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
# calculation the accumulated acceleration section information
# calculate the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
accelerationSection.s_end=drivingCourse[end].s # last position (in m)
accelerationSection.s_total=accelerationSection.s_end-accelerationSection.s_start # total length (in m)
@ -615,11 +617,20 @@ end #function addAccelerationPhaseUntilBraking!
## This function calculates the data points of the cruising phase.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed.
function addCruisingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, s_cruising::AbstractFloat, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}, cruisingType::String)
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"?
if drivingCourse[end].F_T < drivingCourse[end].F_R
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
s_cruising=max(0.0, s_cruising-get(characteristicSection.behaviorSections, "diminishing", BehaviorSection()).s_total)
end
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].F_T >= drivingCourse[end].F_R
# 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
cruisingSection=BehaviorSection()
cruisingSection.type=cruisingType # type of behavior section
cruisingSection.s_start=drivingCourse[end].s # first position (in m)
cruisingSection.s_end=min(drivingCourse[end].s+s_cruising, characteristicSection.s_end) # last position (in m)
# 11/22: now it is at the end of the BS: cruisingSection.s_end=min(drivingCourse[end].s+s_cruising, characteristicSection.s_end) # last position (in m)
cruisingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(cruisingSection.dataPoints, drivingCourse[end].i)
@ -627,241 +638,113 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving
s_cruising=min(s_cruising, characteristicSection.s_end-cruisingSection.s_start)
# traction effort and resisting forces (in N)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")) # TODO: or give cruisingSection.type instead of "cruising"?
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"?
# 11/05 old: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")) # TODO: or give cruisingSection.type instead of "cruising"?
currentStepSize=settings.stepSize
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end].s<cruisingSection.s_start+s_cruising && (drivingCourse[end].F_T < drivingCourse[end].F_R || (settings.massModel=="homogeneous strip" && characteristicSection.id > 1 && drivingCourse[end].s < allCs[characteristicSection.id].s_start + train.l_union)) && drivingCourse[end].v>0.0 #&& drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
#TODO: maybe just consider former CS with different path resistance?
#TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_reach could make problems for energy saving by shortening the acceleration phase
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_reach OR the mass model homogeneous strip is used and parts of the train are still in former CS
if settings.massModel=="homogeneous strip" && characteristicSection.id > 1
currentStepSize=settings.stepSize
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end].s < characteristicSection.s_start + train.l_union && drivingCourse[end].s<cruisingSection.s_start+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
# TODO: whithout allCs should work as well, no? while drivingCourse[end].s < allCs[characteristicSection.id].s_start + train.l_union && drivingCourse[end].s<cruisingSection.s_start+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_reach OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance?
#TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_reach could make problems for energy saving by shortening the acceleration phase
#09/22: neu ist der Teil beim if. alt ist der Teil beim else TODO
if drivingCourse[end].F_T >= drivingCourse[end].F_R
# acceleration (in m/s^2):
drivingCourse[end].a=0.0
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train.l_union/(10.0^cycle), characteristicSection.id)) # TODO welche Schrittweite nehm ich hier?
push!(cruisingSection.dataPoints, drivingCourse[end].i)
else
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
push!(cruisingSection.dataPoints, drivingCourse[end].i)
end
# traction effort and resisting forces (in N)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end].v<=0.0
currentStepSize = settings.stepSize / 10.0^cycle
elseif drivingCourse[end].s>cruisingSection.s_start+s_cruising # TODO also the following? drivingCourse[end].s > allCs[characteristicSection.id].s_start + train.l_union))
if settings.stepVariable == "s in m"
currentStepSize=cruisingSection.s_start+s_cruising-drivingCourse[end-1].s
if settings.stepVariable=="s in m"
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", currentStepSize, characteristicSection.id))
else
currentStepSize = settings.stepSize / 10.0^cycle
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train.l_union/(10.0^cycle), characteristicSection.id)) # TODO which step size should be used?
end
#elseif drivingCourse[end].s>characteristicSection.s_end #TODO: is this necesaary if s_cruising is known? # now s_cruising will be limited to the end of CS at the beginning of this function
# if settings.stepVariable == "s in m"
# currentStepSize=characteristicSection.s_end-drivingCourse[end-1].s
# else
# currentStepSize = settings.stepSize / 10.0^cycle
# end
#elseif drivingCourse[end].v>characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip? #TODO: now, the train can't get faster in the cruising section. so v_reach can not be exceeded
# if settings.stepVariable=="v in m/s"
# currentStepSize=characteristicSection.v_reach-drivingCourse[end-1].v
# else
# currentStepSize = settings.stepSize / 10.0^cycle
# end
elseif drivingCourse[end].s==cruisingSection.s_start+s_cruising # || drivingCourse[end].s==characteristicSection.s_end
break
#elseif drivingCourse[end].v==characteristicSection.v_reach # copied from addAccelerationPhase. TODO 08/24 should it be used otherwise for homogeneous strip?
# break
elseif drivingCourse[end].F_T>=drivingCourse[end].F_R # TODO should not be necessary: && (settings.massModel=="mass point" || characteristicSection.id == 1 || drivingCourse[end].s >= allCs[characteristicSection.id].s_start+train.l_union)
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way
s_cruisingRemaining=cruisingSection.s_start+s_cruising-drivingCourse[end].s
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, characteristicSection.id))
push!(cruisingSection.dataPoints, drivingCourse[end].i)
break
else # TODO copied from addAccelerationPhase -> probably not needed here !?
error("ERROR at cruising phase: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(cruisingSection.dataPoints)
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 # copied from addAccelerationPhase TODO: change error message?
error("ERROR: The train stops during the cruising phase in CS",characteristicSection.id," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m 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.")
#elseif drivingCourse[end].v > characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip?
# pop!(drivingCourse)
# pop!(cruisingSection.dataPoints)
#elseif drivingCourse[end].s>characteristicSection.s_end
# drivingCourse[end].s=characteristicSection.s_end # round s down to s_end
elseif drivingCourse[end].s>cruisingSection.s_start+s_cruising
if cruisingSection.type == "cruisingBeforeAcceleration"
else
pop!(drivingCourse)
pop!(cruisingSection.dataPoints)
# for testing
if drivingCourse[end].F_T > drivingCourse[end].F_R && drivingCourse[end].F_R > 0.0
error("In the cruising phase of CS",cruisingSection.id,": F_T=",drivingCourse[end].F_T," != F_R=",drivingCourse[end].F_R)
end
elseif drivingCourse[end].F_T>=drivingCourse[end].F_R # TODO should not be necessary: && (settings.massModel=="mass point" || characteristicSection.id == 1 || drivingCourse[end].s >= allCs[characteristicSection.id].s_start + train.l_union)
# it is calculated the same as for the other cycles
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way
s_cruisingRemaining=cruisingSection.s_start+s_cruising-drivingCourse[end].s
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, characteristicSection.id))
push!(cruisingSection.dataPoints, drivingCourse[end].i)
break
else
end
end
end #for
#= 09/21 old. homogenous strip has to be added
if drivingCourse[end].F_T>=drivingCourse[end].F_R
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
push!(drivingCourse, DataPoint())
drivingCourse[end].i=drivingCourse[end-1].i+1 # incrementing the number of the data point
push!(cruisingSection.dataPoints, drivingCourse[end].i)
# calculate s, t, v, E
drivingCourse[end].Δs=min(s_cruising, characteristicSection.s_end-drivingCourse[end-1].s) # step size (in m)
drivingCourse[end].Δt=drivingCourse[end].Δs/drivingCourse[end-1].v # step size (in s)
drivingCourse[end].Δv=0.0 # step size (in m/s)
# TODO moveAStep can not be used at the moment because of 1/a in the formulars. It has to be changed and then used with stepVariable="s in m", stepSize=min(s_cruising, characteristicSection.s_end-drivingCourse[end-1].s) -> see the three lines above
drivingCourse[end].s=drivingCourse[end-1].s+drivingCourse[end].Δs # position (in m)
drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s)
drivingCourse[end].v=drivingCourse[end-1].v # velocity (in m/s)
drivingCourse[end].ΔW_T=drivingCourse[end-1].F_T*drivingCourse[end].Δs # mechanical work in this step (in Ws)
drivingCourse[end].W_T=drivingCourse[end-1].W_T+drivingCourse[end].ΔW_T # mechanical work (in Ws)
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 # the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_reach
currentStepSize=settings.stepSize
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0 # TODO: <= v_reach was inserted -> probably needed for homogeneous strip
# traction effort and resisting forces (in N)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
if drivingCourse[end].a==0.0
# TODO: this part is important for mass strip
end
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
push!(cruisingSection.dataPoints, drivingCourse[end].i)
#= TODO: the following has probably to be considered with homogeneous strip:
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
(characteristicSection, drivingCourse, formerSpeedLimits, cruisingSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection)
if endOfCsReached
return (characteristicSection, drivingCourse)
end #if
end #if
=#
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end].v<=0.0
currentStepSize = settings.stepSize / 10.0^cycle
elseif drivingCourse[end].s>characteristicSection.s_end
if drivingCourse[end].s>cruisingSection.s_start+s_cruising # TODO also the following? drivingCourse[end].s > allCs[characteristicSection.id].s_start + train.l_union))
if settings.stepVariable == "s in m"
currentStepSize=characteristicSection.s_end-drivingCourse[end-1].s
currentStepSize=cruisingSection.s_start+s_cruising-drivingCourse[end-1].s
else
currentStepSize = settings.stepSize / 10.0^cycle
end
elseif drivingCourse[end].v>characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip?
if settings.stepVariable=="v in m/s"
currentStepSize=characteristicSection.v_reach-drivingCourse[end-1].v
else
currentStepSize = settings.stepSize / 10.0^cycle
end
elseif drivingCourse[end].s==characteristicSection.s_end
elseif drivingCourse[end].s==cruisingSection.s_start+s_cruising # || drivingCourse[end].s==characteristicSection.s_end
break
elseif drivingCourse[end].F_T < drivingCourse[end].F_R
# if settings.stepVariable == "s in m"
# currentStepSize=cruisingSection.s_start+s_cruising-drivingCourse[end-1].s
# else
currentStepSize = settings.stepSize / 10.0^cycle
# end
elseif drivingCourse[end].s >= characteristicSection.s_start + train.l_union
# TODO: whithout allCs should work as well, no? elseif drivingCourse[end].s >= allCs[characteristicSection.id].s_start + train.l_union
break
#elseif drivingCourse[end].v==characteristicSection.v_reach # copied from addAccelerationPhase. TODO should it be used otherwise for homogeneous strip?
# break
else # TODO copied from addAccelerationPhase -> probably not needed here !?
error("ERROR at cruising phase: With the step variable ",settings.stepVariable," the while loop will be left although v<v_reach and s<s_end in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
error("ERROR at cruising phase: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(cruisingSection.dataPoints)
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 # copied from addAccelerationPhase TODO: change error message?
error("ERROR: The train stops during the crusing phase in CS",characteristicSection.id," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m 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.")
elseif drivingCourse[end].v > characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip?
pop!(drivingCourse)
pop!(cruisingSection.dataPoints)
elseif drivingCourse[end].s>characteristicSection.s_end
drivingCourse[end].s=characteristicSection.s_end # round s down to s_end
if drivingCourse[end].s>cruisingSection.s_start+s_cruising
if cruisingSection.type == "cruisingBeforeAcceleration"
else
pop!(drivingCourse)
pop!(cruisingSection.dataPoints)
end
# 11/21 |->
elseif drivingCourse[end].s==cruisingSection.s_start+s_cruising
break
# 11/21 ->|
elseif drivingCourse[end].F_T < drivingCourse[end].F_R
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
# s_cruising=max(0.0, s_cruising-get(characteristicSection.behaviorSections, "diminishing", BehaviorSection()).s_total)
else
end
end
end #for
end
=#
end #if
# TODO oder soll das lieber nach oben in den else des letzten Durchlaufs. Noch mal genauer ansehen, ob hier was doppelt gemoppelt ist
# if drivingCourse[end].s<cruisingSection.s_start+s_cruising
if drivingCourse[end].s<cruisingSection.s_start+s_cruising && drivingCourse[end].F_T >= drivingCourse[end].F_R
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way
s_cruisingRemaining=cruisingSection.s_start+s_cruising-drivingCourse[end].s
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, characteristicSection.id))
push!(cruisingSection.dataPoints, drivingCourse[end].i)
end
# 08/24 old push!(cruisingSection.dataPoints, drivingCourse[end].i)
## new 09/06 TODO: if no acceleration is following the cruising it could be called cruising
#if cruisingSection.type == "cruisingBeforeAcceleration" && drivingCourse[end].s == characteristicSection.s_end
# cruisingSection.type = "cruising"
#end
# calculation the accumulated cruising section information
cruisingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
cruisingSection.s_total=cruisingSection.s_end-cruisingSection.s_start # total length (in m)
# calculate the accumulated cruising section information
cruisingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
cruisingSection.s_end=drivingCourse[end].s # last position (in m)
cruisingSection.s_total=cruisingSection.s_end-cruisingSection.s_start # total length (in m)
cruisingSection.t_total=drivingCourse[end].t-drivingCourse[cruisingSection.dataPoints[1]].t # total running time (in s)
cruisingSection.E_total=drivingCourse[end].E-drivingCourse[cruisingSection.dataPoints[1]].E # total energy consumption (in Ws)
@ -976,7 +859,7 @@ function addCoastingPhaseUntilBraking!(characteristicSection::CharacteristicSect
end
end #for
# calculation the accumulated coasting section information
# calculate the accumulated coasting section information
coastingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
coastingSection.s_end=drivingCourse[end].s # last position (in m)
coastingSection.s_total=coastingSection.s_end-coastingSection.s_start # total length (in m)
@ -1062,9 +945,7 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
velocityIsPositive=true
# println("Bremsphase")
while drivingCourse[end].v>characteristicSection.v_exit && drivingCourse[end].s < characteristicSection.s_end && velocityIsPositive
# println(" while-Durchlauf mit v=",drivingCourse[end].v," und v_exit=",characteristicSection.v_exit)
# traction effort and resisting forces (in N):
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, brakingSection.type))
@ -1096,7 +977,7 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
#drivingCourse[end-1].a=round((drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs, digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
drivingCourse[end-1].a=(drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs # acceleration (in m/s^2)
println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train.a_braking)
# println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train.a_braking)
# if drivingCourse[end-1].a<train.a_braking || drivingCourse[end-1].a>=0.0
# println("Warning: a_braking gets to high in CS ",characteristicSection.id, " with a=",drivingCourse[end-1].a ," > ",train.a_braking)
@ -1114,7 +995,7 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
end
# calculation the accumulated coasting section information
# calculate the accumulated coasting section information
brakingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
brakingSection.s_end=drivingCourse[end].s # last position (in m)
brakingSection.s_total=brakingSection.s_end-brakingSection.s_start # total length (in m)
@ -1130,4 +1011,99 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
end #function addBrakingPhaseStepwise!
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower
function addDiminishingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection})
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "diminishing"))
if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<characteristicSection.s_end
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
diminishingSection=BehaviorSection()
diminishingSection.type="diminishing" # type of behavior section
diminishingSection.s_start=drivingCourse[end].s # first position (in m)
diminishingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(diminishingSection.dataPoints, drivingCourse[end].i)
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
# 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
#11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, diminishingSection.type))
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
# 11/21: old, only for cruising:
#if drivingCourse[end].a==0.0
# error("ERROR: a=0 m/s^2 in the diminishing 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
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
push!(diminishingSection.dataPoints, drivingCourse[end].i)
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, diminishingSection.type))
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end].v<=0.0
currentStepSize = settings.stepSize / 10.0^cycle
elseif drivingCourse[end].s + s_braking > characteristicSection.s_end
currentStepSize = settings.stepSize / 10.0^cycle
elseif drivingCourse[end].s + s_braking==characteristicSection.s_end
# 11/21 old without s_braking: elseif drivingCourse[end].s==characteristicSection.s_end
break
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
currentStepSize = settings.stepSize / 10.0^cycle
else
error("ERROR during diminishing run: With the step variable ",settings.stepVariable," the while loop will be left although s+s_braking<s_end && v>0.0 in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# push!(diminishingSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during diminishing run in CS",characteristicSection.id," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m 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.")
elseif drivingCourse[end].s + s_braking > characteristicSection.s_end
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
break
else
end
end
end #for
if length(diminishingSection.dataPoints) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start
# calculate the accumulated diminishing section information
diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
diminishingSection.s_end=drivingCourse[end].s # last position (in m)
diminishingSection.s_total=diminishingSection.s_end-diminishingSection.s_start # total length (in m)
diminishingSection.t_total=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E_total=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
characteristicSection.t_total=characteristicSection.t_total+diminishingSection.t_total # total running time (in s)
characteristicSection.E_total=characteristicSection.E_total+diminishingSection.E_total # total energy consumption (in Ws)
merge!(characteristicSection.behaviorSections, Dict("diminishing"=>diminishingSection))
end
end
return (characteristicSection, drivingCourse)
end #function addDiminishingPhase!
end #module MovingPhases

View File

@ -11,13 +11,15 @@ export simulateMinimumRunningTime!, simulateMinimumEnergyConsumption
approximationLevel = 6 # TODO: define it in TrainRun and give it to each function?
# simulate a train run focussing on using the minimum possible running time
function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Settings, train::Train)
# simulate a train run focussing on using the minimum possible running time
# CSs=movingSection.characteristicSections
startingPoint=DataPoint()
startingPoint.i=1
startingPoint.s=movingSection.characteristicSections[1].s_start
drivingCourse=[startingPoint] # List of data points
# for CS in CSs
for csId in 1:length(movingSection.characteristicSections)
# println("CS",csId)
# check if the CS has a cruising section
@ -33,6 +35,7 @@ function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Set
delete!(movingSection.characteristicSections[csId].behaviorSections, "starting")
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration")
delete!(movingSection.characteristicSections[csId].behaviorSections, "acceleration")
delete!(movingSection.characteristicSections[csId].behaviorSections, "diminishing") # 11/22 added new
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruising")
movingSection.characteristicSections[csId].E_total=0.0
movingSection.characteristicSections[csId].t_total=0.0
@ -98,7 +101,7 @@ end #function simulateMinimumRunningTime
function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumRunningTime::Vector{DataPoint}, settings::Settings, train::Train)
# simulate a train run focussing on using the minimum possible energy consumption
# simulate a train run focussing on using the minimum possible energy consumption
# booleans for choosing which methods are used for saving energy
doMethod1=true
#doMethod1=false

View File

@ -112,13 +112,13 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
outputArray="outputArrayMinimumEnergyConsumption"
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_MinimumEnergyConsumption.csv"
csvFilePath=settings.csvDirectory*"\\"*dateString*"_MinimumEnergyConsumption.csv"
else
operationMode="minimum running time"
outputArray="outputArrayMinimumRunningTime"
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_MinimumRunningTime.csv"
csvFilePath=settings.csvDirectory*"\\"*dateString*"_MinimumRunningTime.csv"
end
# creating information block
@ -144,7 +144,7 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
end # for
# combining the columns in a data frame and saving it as a CSV-file at csvFolderPath
# combining the columns in a data frame and saving it as a CSV-file at csvDirectory
if settings.detailOfOutput=="reduced"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course"
@ -187,7 +187,7 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
push!(allColumns, infoColumns[column])
end # for
#combining the columns in a data frame and saving it as a CSV-file at csvFolderPath
#combining the columns in a data frame and saving it as a CSV-file at csvDirectory
if settings.detailOfOutput=="reduced"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course"
@ -195,7 +195,7 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
end
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_dataMinimumRunningTime.csv"
csvFilePath=settings.csvDirectory*"\\"*dateString*"_dataMinimumRunningTime.csv"
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for minimum running time at ",csvFilePath)
end #if settings.operationModeMinimumRunningTime
@ -232,10 +232,10 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18])
end
# creating a CSV-file at csvFolderPath
# creating a CSV-file at csvDirectory
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_dataMinimumEnergyConsumption.csv"
csvFilePath=settings.csvDirectory*"\\"*dateString*"_dataMinimumEnergyConsumption.csv"
CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for minimum energy consumption at ",csvFilePath)
end # if settings.operationModeMinimumEnergyConsumption
@ -255,7 +255,7 @@ end #function printImportantValues
function printSectionInformation(movingSection::MovingSection)
println("MS mit s_total=", movingSection.s_total," mit t_total=", movingSection.t_total)
allBs=["starting", "cruisingBeforeAcceleration","acceleration", "cruising", "coasting","cruisingAfterCoasting", "braking"]
allBs=["starting", "cruisingBeforeAcceleration","acceleration", "cruising", "diminishing", "coasting","cruisingAfterCoasting", "braking"]
for csId in 1:length(movingSection.characteristicSections)
println("CS ",csId," mit s_total=", movingSection.characteristicSections[csId].s_total," mit t_total=", movingSection.characteristicSections[csId].t_total)
for bs in 1: length(allBs)

View File

@ -19,9 +19,9 @@ export calculateDrivingDynamics
# TODO: define it here and give it to each function? (MovingPhases, EnergySaving)
"""
calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
calculateDrivingDynamics(trainDirectory::String, pathDirectory::String, settingsDirectory::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`.
Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
# Examples
```julia-repl
@ -29,11 +29,11 @@ julia> calculateDrivingDynamics(C:\\folder\\train.yaml, C:\\folder\\path.yaml, C
todo !!!
```
"""
function calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
function calculateDrivingDynamics(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
print("\n\n\n")
# input
(train, path, settings)=readInput(trainFilePath, pathFilePath, settingsFilePath)
(train, path, settings)=readInput(trainDirectory, pathDirectory, settingsDirectory)
println("The input has been saved.")
@ -53,7 +53,7 @@ function calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, s
if settings.operationModeMinimumEnergyConsumption==true
(movingSectionMinimumEnergyConsumption, drivingCourseMinimumEnergyConsumption)=simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime, settings, train)
# printSectionInformation(movingSectionMinimumEnergyConsumption)
println("The driving course for lowest the energy consumption has been calculated.")
println("The driving course for the lowest energy consumption has been calculated.")
end #if
#output

View File

@ -11,7 +11,7 @@ mutable struct Settings
operationModeMinimumEnergyConsumption::Bool # operation mode "minimum energy consumption"
# output:
typeOfOutput::String # output as "julia dictionary" or as "CSV"
csvFolderPath::String # path of the folder in which the CSV fiiles willl be saved
csvDirectory::String # directory in which the CSV files will be saved
detailOfOutput::String # detail of output "reduced" or "everything"
end # mutable struct Settings
Settings()=Settings("", "", 0.0, false, false, "", "", "")
@ -26,8 +26,10 @@ mutable struct Train
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)
# m_train
ξ_union::AbstractFloat # rotation mass factor of the whole train union (without unit)
# if not available use ξ_t and ξ_w
# ξ_train
# traction unit
m_t::AbstractFloat # mass of the traction unit (in kg)
@ -35,7 +37,7 @@ mutable struct Train
m_tc::AbstractFloat # mass on the traction units carrying axles (in kg)
ξ_t::AbstractFloat # rotation mass factor of the traction unit (without unit)
# in case ξ_union is not available
tractiveEffortArray # list values for tractive effort (in [m/s , N])
tractiveEffortVelocityPairs # list of velocities and their corresponding tractive effort (in [m/s , N])
f_Rtd0::AbstractFloat # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0::AbstractFloat # coefficient for basic resistance due to the traction units carring axles (in ‰)
@ -89,15 +91,21 @@ mutable struct DataPoint
Δv::AbstractFloat # step size (in m/s)
a::AbstractFloat # acceleration (in m/s^2)
W_T::AbstractFloat # mechanical work (in Ws)
# W
ΔW_T::AbstractFloat # mechanical work in this step (in Ws)
# ΔW
E::AbstractFloat # energy consumption (in Ws)
ΔE::AbstractFloat # energy consumption in this step (in Ws)
F_T::AbstractFloat # tractive effort (in N)
F_R::AbstractFloat # resisting force (in N)
F_Rp::AbstractFloat # line resistanc (in N)
F_Runion::AbstractFloat # vehicle resistance (in N)
F_Rp::AbstractFloat # path resistance (in N)
# R_path
F_Runion::AbstractFloat # train resistance (in N)
# R_train
F_Rt::AbstractFloat # traction unit resistance (in N)
# R_traction
F_Rw::AbstractFloat # set of wagons resistance (in N)
# R_consist
end # mutable struct DataPoint
DataPoint()=DataPoint(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::DataPoint)=DataPoint(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)
@ -109,6 +117,7 @@ DataPoint(original::DataPoint)=DataPoint(original.i, original.s, original.Δs, o
## smallest section of the path is the behavior section. It relates to the containing data points via their identifier.
mutable struct BehaviorSection
type::String # type of behavior section: "starting", "cruisingBeforeAcceleration", "acceleration", "cruising", "coasting", "cruisingAfterCoasting" or "braking"
# enum-type. breakFree, clearing, diminishing, standStill, "acceleration", "cruising", "coasting", "braking"
s_total::AbstractFloat # total length (in m)
s_start::AbstractFloat # first position (in m)
s_end::AbstractFloat # last position (in m)
@ -131,15 +140,21 @@ end
mutable struct CharacteristicSection
id::Integer # identifier
s_total::AbstractFloat # total length (in m)
# length::AbstractFloat # total length (in m)
s_start::AbstractFloat # first position (in m)
# s_entry
s_end::AbstractFloat # last position (in m)
# s_exit
t_total::AbstractFloat # total running time (in s)
# t
E_total::AbstractFloat # total energy consumption (in Ws)
# E
v_limit::AbstractFloat # speed limit (in m/s)
v_reach::AbstractFloat # maximum reachable speed (in m/s)
# v_target
v_entry::AbstractFloat # maximum entry speed (in m/s)
v_exit::AbstractFloat # maximum exit speed (in m/s)
f_Rp::AbstractFloat # spedific line resistance (in ‰)
f_Rp::AbstractFloat # spedific path resistance (in ‰)
behaviorSections::AbstractDict{String, BehaviorSection} # list of containing behavior sections
end # mutable struct CharacteristicSection
CharacteristicSection()=CharacteristicSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Dict{String, BehaviorSection}())