Refactor the mutable struct DataPoint as a Dictionary

development
Max Kannenberg 2022-01-10 06:43:19 +01:00
parent f590206226
commit 0b15ba343d
7 changed files with 859 additions and 582 deletions

View File

@ -96,7 +96,8 @@ function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict)
end # if train[:type] end # if train[:type]
end #function calculateRecoveryTime end #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) # TODO: a refactoring caused worse drivingsCourses. see the commented function below
function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections] BSsOriginal = csOriginal[:behaviorSections]
if (haskey(BSsOriginal, :cruising) || haskey(BSsOriginal, :diminishing)) && haskey(BSsOriginal, :braking) if (haskey(BSsOriginal, :cruising) || haskey(BSsOriginal, :diminishing)) && haskey(BSsOriginal, :braking)
# check if cruising or diminishing should be reduced for coasting # check if cruising or diminishing should be reduced for coasting
@ -121,7 +122,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
# 01/07 test for a better calculation time: cruisingReduction = settings[:stepSize]*100 # 01/07 test for a better calculation time: cruisingReduction = settings[:stepSize]*100
while cruisingReduction>=settings[:stepSize]/10^approximationLevel while cruisingReduction>=settings[:stepSize]/10^approximationLevel
#while cruisingReduction>=settings[:stepSize]/100 #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_exit]) -> see below at the end of the while loop 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_exit]) -> see below at the end of the while loop
# create a copy for the characteristic sections drivingCourse # create a copy for the characteristic sections drivingCourse
energySavingStartId=get(BSsOriginal, :cruising, Dict(:dataPoints=>[0]))[:dataPoints][1] energySavingStartId=get(BSsOriginal, :cruising, Dict(:dataPoints=>[0]))[:dataPoints][1]
@ -130,11 +131,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
end end
# copy the driving course till the beginning of energy saving # copy the driving course till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}() drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving
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 # calculating the new length of the cruising section
if settings[:stepVariable]=="s in m" # distance step method if settings[:stepVariable]=="s in m" # distance step method
@ -142,8 +139,8 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
elseif settings[:stepVariable]=="t in s" # time step method elseif settings[:stepVariable]=="t in s" # time step method
# 09/20 old: doesn't work for non constant cruising -> TODO: should work now # 09/20 old: doesn't work for non constant cruising -> TODO: should work now
# t_cruising=BSsOriginal[:cruising][:t]-cruisingReduction # t_cruising=BSsOriginal[:cruising][:t]-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v # s_cruising=t_cruising*drivingCourseModified[end][:v]
distanceReduction = drivingCourse[BSsOriginal[:cruising][:dataPoints][end]].v*cruisingReduction distanceReduction = drivingCourse[BSsOriginal[:cruising][:dataPoints][end]][:v]*cruisingReduction
s_cruising = BSsOriginal[:cruising][:length]-distanceReduction s_cruising = BSsOriginal[:cruising][:length]-distanceReduction
elseif settings[:stepVariable]=="v in m/s" # velocity step method elseif settings[:stepVariable]=="v in m/s" # velocity step method
@ -202,7 +199,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
# calculate the coasting phase until the point the train needs to brake # calculate the coasting phase until the point the train needs to brake
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
if drivingCourseModified[end].v < csModified[:v_exit] || drivingCourseModified[end].s > csModified[:s_exit] if drivingCourseModified[end][:v] < csModified[:v_exit] || drivingCourseModified[end][:s] > csModified[:s_exit]
# the train reaches v_exit before reaching s_exit. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section) # the train reaches v_exit before reaching s_exit. 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 cruisingReduction=cruisingReduction/10
else else
@ -211,16 +208,16 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
end # while cruisingReduction end # while cruisingReduction
# calculate the moving phase between coasting and the end of the CS # calculate the moving phase between coasting and the end of the CS
if drivingCourseModified[end].v > csModified[:v_exit] if drivingCourseModified[end][:v] > csModified[:v_exit]
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs) #(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified[:v_exit] && drivingCourseModified[end].s < csModified[:s_exit] elseif drivingCourseModified[end][:v] == csModified[:v_exit] && drivingCourseModified[end][:s] < csModified[:s_exit]
# v_exit is already reached. Now cruise till the end of the CS # v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end].s s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end][:s]
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting") (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end end
if t_recoveryAvailable < csModified[:t]-csOriginal[:t] || drivingCourseModified[end].v != csModified[:v_exit] || drivingCourseModified[end].s != csModified[:s_exit] # 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_exit are not reached excatly if t_recoveryAvailable < csModified[:t]-csOriginal[:t] || drivingCourseModified[end][:v] != csModified[:v_exit] || drivingCourseModified[end][:s] != csModified[:s_exit] # 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_exit are not reached excatly
cruisingReduction=cruisingReduction/10 cruisingReduction=cruisingReduction/10
else else
return (csModified, drivingCourseModified, true) return (csModified, drivingCourseModified, true)
@ -277,11 +274,11 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
# remove the last diminishing waypoint # remove the last diminishing waypoint
pop!(diminishingSection[:dataPoints]) pop!(diminishingSection[:dataPoints])
diminishingSection[:v_exit]=drivingCourse[diminishingSection[:dataPoints][end]].v # exit speed (in m/s) diminishingSection[:v_exit]=drivingCourse[diminishingSection[:dataPoints][end]][:v] # exit speed (in m/s)
diminishingSection[:s_exit]=drivingCourse[diminishingSection[:dataPoints][end]].s # last position (in m) diminishingSection[:s_exit]=drivingCourse[diminishingSection[:dataPoints][end]][:s] # last position (in m)
diminishingSection[:length]=diminishingSection[:s_exit]-diminishingSection[:s_entry] # total length (in m) diminishingSection[:length]=diminishingSection[:s_exit]-diminishingSection[:s_entry] # total length (in m)
diminishingSection[:t]=drivingCourse[diminishingSection[:dataPoints][end]].t-drivingCourse[diminishingSection[:dataPoints][1]].t # total running time (in s) diminishingSection[:t]=drivingCourse[diminishingSection[:dataPoints][end]][:t]-drivingCourse[diminishingSection[:dataPoints][1]][:t] # total running time (in s)
diminishingSection[:E]=drivingCourse[diminishingSection[:dataPoints][end]].E-drivingCourse[diminishingSection[:dataPoints][1]].E # total energy consumption (in Ws) diminishingSection[:E]=drivingCourse[diminishingSection[:dataPoints][end]][:E]-drivingCourse[diminishingSection[:dataPoints][1]][:E] # total energy consumption (in Ws)
merge!(BSsModified, Dict(:diminishing => diminishingSection)) merge!(BSsModified, Dict(:diminishing => diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E] csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E]
@ -294,20 +291,17 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
end end
# copy the driving course till the beginning of energy saving # copy the driving course till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}() drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving
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 # calculate the coasting phase until the point the train needs to brake
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
# calculate the moving phase between coasting and the end of the CS # calculate the moving phase between coasting and the end of the CS
if drivingCourseModified[end].v > csModified[:v_exit] if drivingCourseModified[end][:v] > csModified[:v_exit]
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified[:v_exit] && drivingCourseModified[end].s < csModified[:s_exit] elseif drivingCourseModified[end][:v] == csModified[:v_exit] && drivingCourseModified[end][:s] < csModified[:s_exit]
# v_exit is already reached. Now cruise till the end of the CS # v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end].s s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end][:s]
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting") (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end end
@ -331,14 +325,200 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
return (csOriginal, drivingCourse, false) return (csOriginal, drivingCourse, false)
end end
end # function increaseCoastingSection end # function increaseCoastingSection
#=
function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections]
if (haskey(BSsOriginal, :cruising) || (haskey(BSsOriginal, :diminishing) && get(BSsOriginal, :diminishing, Dict(:dataPoints =>[0]))[:dataPoints][1] > get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0]))[:dataPoints][1])) && haskey(BSsOriginal, :braking)
# check if cruising or diminishing should be reduced for coasting
if haskey(BSsOriginal, :cruising) && haskey(BSsOriginal, :diminishing)
if BSsOriginal[:cruising][:dataPoints][1] > BSsOriginal[:diminishing][:dataPoints][1]
reduceCruising=true
reduceDiminishing=false
else
reduceDiminishing=true
reduceCruising=false
end
elseif haskey(BSsOriginal, :cruising)
reduceCruising=true
reduceDiminishing=false
elseif haskey(BSsOriginal, :diminishing)
reduceDiminishing=true
reduceCruising=false
else
error("in increaseCoastingSection") #TODO
end
# method 2 with shortening the acceleration by stepsize # copy csOriginal to csModifiedInitial
csModifiedInitial = copyCharacteristicSection(csOriginal)
BSsModified = csModifiedInitial[:behaviorSections]
# delete bahavior sections that will be recalculated except breakFree, clearing, acceleration, diminishing
# and rest total running time and energy consumption
if haskey(BSsModified, :coasting)
csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:coasting][:E]
csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:coasting][:t]
delete!(BSsModified, :coasting)
end
if haskey(BSsModified, :cruisingAfterCoasting)
csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:cruisingAfterCoasting][:E]
csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:cruisingAfterCoasting][:t]
delete!(BSsModified, :cruisingAfterCoasting)
end
if haskey(BSsModified, :braking)
csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:braking][:E]
csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:braking][:t]
delete!(BSsModified, :braking)
end
if haskey(BSsModified, :standstill)
csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:standstill][:E]
csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:standstill][:t]
delete!(BSsModified, :standstill)
end
if reduceCruising
cruisingReduction = settings[:stepSize]
# 01/07 test for a better calculation time: cruisingReduction = settings[:stepSize]*100
# remove old cruising section
csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:cruising][:E]
csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:cruising][:t]
delete!(BSsModified, :cruising)
# determine the starting point of saving energy (needed for copying the characteristic section's drivingCourse)
energySavingStartId=get(BSsOriginal, :cruising, Dict(:dataPoints=>[0]))[:dataPoints][1]
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
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_exit]) -> see below at the end of the while loop
# copy the characteristic section for being modified
csModified = copyCharacteristicSection(csModifiedInitial)
# copy the driving course till the beginning of energy saving
drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving
# calculating the new length of the cruising section
if settings[:stepVariable]=="s in m" # distance step method
s_cruising = BSsOriginal[:cruising][:length] - cruisingReduction
elseif settings[:stepVariable]=="t in s" # time step method
# 09/20 old: doesn't work for non constant cruising -> TODO: should work now
# t_cruising=BSsOriginal[:cruising][:t]-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end][:v]
distanceReduction = drivingCourse[BSsOriginal[:cruising][:dataPoints][end]][:v] * cruisingReduction
s_cruising = BSsOriginal[:cruising][:length]-distanceReduction
elseif settings[:stepVariable]=="v in m/s" # velocity step method
s_cruising=BSsOriginal[:cruising][:length]-cruisingReduction*10 # TODO: or better: *100 ?
end #if
s_cruising=max(0.0, s_cruising)
# 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_exit]
# the train reaches v_exit before reaching s_exit. 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_exit]
# v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end][:s]
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end
if t_recoveryAvailable < csModified[:t]-csOriginal[:t] || drivingCourseModified[end][:v] != csModified[:v_exit] || drivingCourseModified[end][:s] != csModified[:s_exit] # 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_exit are not reached excatly
cruisingReduction=cruisingReduction/10
else
return (csModified, drivingCourseModified, true)
end
end #while
elseif reduceDiminishing
# TODO: At the moment diminishing is reduced similar to the acceleration in decreaseMaximumVelocity. To reduce code the methods for reducing cruising phase and reducing the diminishing phase can be combined in some parts.
csModified = csModifiedInitial
diminishingSection = BSsModified[:diminishing]
# remove the last diminishing waypoint
t_diff = drivingCourse[diminishingSection[:dataPoints][end]][:t] - drivingCourse[diminishingSection[:dataPoints][end-1]][:t]
E_diff = drivingCourse[diminishingSection[:dataPoints][end]][:E] - drivingCourse[diminishingSection[:dataPoints][end-1]][:E]
pop!(diminishingSection[:dataPoints])
diminishingSection[:v_exit] = drivingCourse[diminishingSection[:dataPoints][end]][:v] # exit speed (in m/s)
diminishingSection[:s_exit] = drivingCourse[diminishingSection[:dataPoints][end]][:s] # last position (in m)
diminishingSection[:length] = diminishingSection[:s_exit] - diminishingSection[:s_entry] # total length (in m)
diminishingSection[:t] = diminishingSection[:t] - t_diff # total running time (in s)
diminishingSection[:E] = diminishingSection[:E] - E_diff # total energy consumption (in Ws)
# merge!(BSsModified, Dict(:diminishing => diminishingSection))
csModified[:E] = csModified[:E] - t_diff
csModified[:t] = csModified[:t] - E_diff
energySavingStartId = diminishingSection[:dataPoints][end]
if length(diminishingSection[:dataPoints]) == 2 # The diminishing section was only one step. This step is removed and so the complette diminishing section.
delete!(BSsModified, :diminishing)
end
# copy the driving course till the beginning of energy saving
drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving
# 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_exit]
# v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end][:s]
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end
if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t])
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?
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end
end
# there is no energy saving modification for this CS with the available recovery time
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, 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
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end
end # function increaseCoastingSection
=#
# TODO: with changing DataPoint to Dict and trying to use copy() there occured calculation errors that can't be corrected at the moment. see the code down below
function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections] BSsOriginal = csOriginal[:behaviorSections]
if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit] if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit]
accelerationSection = copyBehaviorSection(BSsOriginal[:acceleration]) accelerationSection = copyBehaviorSection(BSsOriginal[:acceleration])
if drivingCourse[accelerationSection[:dataPoints][end]-1].v < csOriginal[:v_exit] if drivingCourse[accelerationSection[:dataPoints][end]-1][:v] < csOriginal[:v_exit]
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false) return (csOriginal, drivingCourse, false)
# TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size. # TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size.
@ -379,11 +559,11 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict
# remove the last acceleration waypoint # remove the last acceleration waypoint
pop!(accelerationSection[:dataPoints]) pop!(accelerationSection[:dataPoints])
accelerationSection[:v_exit]=drivingCourse[accelerationSection[:dataPoints][end]].v # exit speed (in m/s) accelerationSection[:v_exit]=drivingCourse[accelerationSection[:dataPoints][end]][:v] # exit speed (in m/s)
accelerationSection[:s_exit]=drivingCourse[accelerationSection[:dataPoints][end]].s # last position (in m) accelerationSection[:s_exit]=drivingCourse[accelerationSection[:dataPoints][end]][:s] # last position (in m)
accelerationSection[:length]=accelerationSection[:s_exit]-accelerationSection[:s_entry] # total length (in m) accelerationSection[:length]=accelerationSection[:s_exit]-accelerationSection[:s_entry] # total length (in m)
accelerationSection[:t]=drivingCourse[accelerationSection[:dataPoints][end]].t-drivingCourse[accelerationSection[:dataPoints][1]].t # total running time (in s) accelerationSection[:t]=drivingCourse[accelerationSection[:dataPoints][end]][:t]-drivingCourse[accelerationSection[:dataPoints][1]][:t] # total running time (in s)
accelerationSection[:E]=drivingCourse[accelerationSection[:dataPoints][end]].E-drivingCourse[accelerationSection[:dataPoints][1]].E # total energy consumption (in Ws) accelerationSection[:E]=drivingCourse[accelerationSection[:dataPoints][end]][:E]-drivingCourse[accelerationSection[:dataPoints][1]][:E] # total energy consumption (in Ws)
merge!(BSsModified, Dict(:acceleration=>accelerationSection)) merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E] csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E]
@ -396,39 +576,36 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict
end end
# TODO: should v_peak be reduced or is it enough to pop the data points? # TODO: should v_peak be reduced or is it enough to pop the data points?
# characteristicSection[:v_peak]=drivingCourse[end].v # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section # characteristicSection[:v_peak]=drivingCourse[end][:v] # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section
# copy the drivingCourse till the beginning of energy saving # copy the drivingCourse till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}() drivingCourseModified = drivingCourse[1:energySavingStartId] # List of data points till the start of energy saving
for i in 1:energySavingStartId
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
end
#s_braking=max(0.0, ceil((csModified[:v_exit]^2-csModified[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors #s_braking=max(0.0, ceil((csModified[:v_exit]^2-csModified[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_braking=max(0.0, ceil((csModified[:v_exit]^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors s_braking=max(0.0, ceil((csModified[:v_exit]^2-drivingCourseModified[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_cruising=csModified[:s_exit]-drivingCourseModified[end].s-s_braking s_cruising=csModified[:s_exit]-drivingCourseModified[end][:s]-s_braking
if s_cruising >0.001 if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if end #if
# s_brakingAfterCruising=ceil((csModified[:v_exit]^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same # s_brakingAfterCruising=ceil((csModified[:v_exit]^2-drivingCourseModified[end][:v]^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified[:v_exit] if drivingCourseModified[end][:v]>csModified[:v_exit]
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs) #(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].s<csModified[:s_exit] elseif drivingCourseModified[end][:s]<csModified[:s_exit]
if (csModified[:s_exit]-drivingCourseModified[end].s)>0.001 if (csModified[:s_exit]-drivingCourseModified[end][:s])>0.001
# if (csModified[:s_exit]-drivingCourseModified[end].s)>10^(-approximationLevel) # if (csModified[:s_exit]-drivingCourseModified[end][:s])>10^(-approximationLevel)
# println("INFO: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.") # println("INFO: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.")
# println(" Therefore the calculation of this method can not continue for this CS.") # println(" Therefore the calculation of this method can not continue for this CS.")
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false) return (csOriginal, drivingCourse, false)
end end
println("WARNING: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.") println("WARNING: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.")
println(" Therefore s=",drivingCourseModified[end].s," will be set s_exit=",csModified[:s_exit]," because the difference is only ",csModified[:s_exit]-drivingCourseModified[end].s," m.") println(" Therefore s=",drivingCourseModified[end][:s]," will be set s_exit=",csModified[:s_exit]," because the difference is only ",csModified[:s_exit]-drivingCourseModified[end][:s]," m.")
println(" v=",drivingCourseModified[end].v," m/s v_exit=",csOriginal[:v_exit] ," m/s") println(" v=",drivingCourseModified[end][:v]," m/s v_exit=",csOriginal[:v_exit] ," m/s")
drivingCourseModified[end].s=csModified[:s_exit] # rounding up to s_exit drivingCourseModified[end][:s]=csModified[:s_exit] # rounding up to s_exit
end #if end #if
if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t]) if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t])
@ -455,39 +632,150 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict
return (csOriginal, drivingCourse, false) return (csOriginal, drivingCourse, false)
end #if haskey end #if haskey
end # function decreaseMaximumVelocity end # function decreaseMaximumVelocity
#=
# combination of method 1 and method 2 # method 2 with shortening the acceleration by stepsize
function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
# TODO doesn't work that well alone. works better with combineEnergySavingMethods. why? does a while loop end to early or something like this?
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections] BSsOriginal = csOriginal[:behaviorSections]
# if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && csOriginal[:v_peak]>csOriginal[:v_entry] && csOriginal[:v_peak]>csOriginal[:v_exit] if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit]
if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && drivingCourse[get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0]))[:dataPoints][end]].v > max(csOriginal[:v_entry], csOriginal[:v_exit]) accelerationSection = copyBehaviorSection(BSsOriginal[:acceleration])
# 12/28 old: csCombined=CharacteristicSection(csOriginal)
#TODO after removing the mutable structs: Is it possible to just "copy"? if drivingCourse[accelerationSection[:dataPoints][end]-1][:v] < csOriginal[:v_exit]
csCombined=Dict(:id => csOriginal[:id], # identifier # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
# TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size.
end
# copy csOriginal to csModified
# 12/28 old: csModified=CharacteristicSection(csOriginal[:id], csOriginal[:length], csOriginal[:s_entry], csOriginal[:s_exit], 0.0, 0.0, csOriginal[:v_limit], csOriginal[:v_peak], csOriginal[:v_entry], csOriginal[:v_exit], csOriginal[:r_path], Dict{Symbol, Dict}())
csModified=Dict(:id => csOriginal[:id], # identifier
:s_entry => csOriginal[:s_entry], # first position (in m) :s_entry => csOriginal[:s_entry], # first position (in m)
:s_exit => csOriginal[:s_exit], # last position (in m) :s_exit => csOriginal[:s_exit], # last position (in m)
:length => csOriginal[:length], # total length (in m) :length => csOriginal[:length], # total length (in m)
:r_path => csOriginal[:r_path], # path resistance (in ‰) :r_path => csOriginal[:r_path], # path resistance (in ‰)
:behaviorSections => Dict(), # empty list of containing behavior sections :behaviorSections => Dict(), # empty list of containing behavior sections
:t => csOriginal[:t], # total running time (in s) :t => 0.0, # total running time (in s)
:E => csOriginal[:E], # total energy consumption (in Ws) :E => 0.0, # total energy consumption (in Ws)
:v_limit => csOriginal[:v_limit], # speed limit (in m/s) :v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s) :v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s) :v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s) :v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
BSsModified = csModified[:behaviorSections]
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] if haskey(BSsOriginal, :breakFree)
for bs in 1: length(allBs) breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])
if haskey(BSsOriginal, allBs[bs]) merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
merge!(csCombined[:behaviorSections], Dict(allBs[bs] => copyBehaviorSection(BSsOriginal[allBs[bs]]))) csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E]
end #if csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t]
end #for
drivingCourseCombined=Vector{DataPoint}()
for i in 1:length(drivingCourse)
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseCombined, copy(drivingCourse[i]))
push!(drivingCourseCombined, DataPoint(drivingCourse[i]))
end end
if haskey(BSsOriginal, :diminishing) && BSsModified[:diminishing][:dataPoints][1] < BSsModified[:acceleration][:dataPoints][1]
diminishingSection=copyBehaviorSection(BSsOriginal[:diminishing])
merge!(BSsModified, Dict(:diminishing=>diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E]
csModified[:t] = csModified[:t] + BSsModified[:diminishing][:t]
end
if length(accelerationSection[:dataPoints]) > 2
if haskey(BSsOriginal, :clearing)
clearingSection=copyBehaviorSection(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing][:E]
csModified[:t] = csModified[:t] + BSsModified[:clearing][:t]
end
# remove the last acceleration waypoint from the accelerationSection
pop!(accelerationSection[:dataPoints])
energySavingStartId=accelerationSection[:dataPoints][end]
accelerationSection[:v_exit]=drivingCourse[energySavingStartId][:v] # exit speed (in m/s)
accelerationSection[:s_exit]=drivingCourse[energySavingStartId][:s] # last position (in m)
accelerationSection[:length]=accelerationSection[:s_exit]-accelerationSection[:s_entry] # total length (in m)
accelerationSection[:t]=drivingCourse[energySavingStartId][:t]-drivingCourse[accelerationSection[:dataPoints][1]][:t] # total running time (in s)
accelerationSection[:E]=drivingCourse[energySavingStartId][:E]-drivingCourse[accelerationSection[:dataPoints][1]][:E] # total energy consumption (in Ws)
merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + accelerationSection[:E]
csModified[:t] = csModified[:t] + accelerationSection[:t]
else
# The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0])))[:dataPoints][1]
end
# TODO: should v_peak be reduced or is it enough to pop the data points?
# characteristicSection[:v_peak]=drivingCourse[end][:v] # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section
# copy the drivingCourse till the beginning of energy saving
drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving
#s_braking=max(0.0, ceil((csModified[:v_exit]^2-csModified[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_braking=max(0.0, ceil((csModified[:v_exit]^2-drivingCourseModified[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_cruising=csModified[:s_exit]-drivingCourseModified[end][:s]-s_braking
if s_cruising > 1/10^approximationLevel
# old if s_cruising > 0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if
# s_brakingAfterCruising=ceil((csModified[:v_exit]^2-drivingCourseModified[end][:v]^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end][:v]>csModified[:v_exit]
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end][:s]<csModified[:s_exit]
if (csModified[:s_exit]-drivingCourseModified[end][:s])>0.001
# if (csModified[:s_exit]-drivingCourseModified[end][:s])>10^(-approximationLevel)
# println("INFO: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.")
# println(" Therefore the calculation of this method can not continue for this CS.")
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end
println("WARNING: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.")
println(" Therefore s=",drivingCourseModified[end][:s]," will be set s_exit=",csModified[:s_exit]," because the difference is only ",csModified[:s_exit]-drivingCourseModified[end][:s]," m.")
println(" v=",drivingCourseModified[end][:v]," m/s v_exit=",csOriginal[:v_exit] ," m/s")
drivingCourseModified[end][:s]=csModified[:s_exit] # rounding up to s_exit
end #if
if t_recoveryAvailable >= csModified[:t] - csOriginal[:t]
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
# 09/06 old: else # time loss is to high and the CS has to be calculated again with larger acceleration section (so with a smaller reduction of the acceleration section)
# 09/06 old: accelerationReduction=min(accelerationReduction/10, csModified[:v_peak]-csModified[:v_entry], csModified[:v_peak]-csModified[:v_exit])
# TODO: just return false or take smaller steps?
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end
# 09/06 old: end #while
#
# 09/06 old: # there is no energy saving modification for this CS with the available recovery time
# old: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
# 12/29 new, now not with empty but with original CS and DC: return (csOriginal, drivingCourse, false)
else
# there is no energy saving modification for this CS because v_peak can not be lowered below v_entry or v_exit or because there is no acceleration section that can be transformed into a cruising section
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end #if haskey
end # function decreaseMaximumVelocity
=#
# combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections]
# if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && csOriginal[:v_peak]>csOriginal[:v_entry] && csOriginal[:v_peak]>csOriginal[:v_exit]
if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && drivingCourse[get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0]))[:dataPoints][end]][:v] > max(csOriginal[:v_entry], csOriginal[:v_exit])
# copy the characteristic section
csCombined = copyCharacteristicSection(csOriginal)
# copy the drivingCourse
drivingCourseCombined = copy(drivingCourse)
ΔE=0.0 # saved energy (in Ws) ΔE=0.0 # saved energy (in Ws)
Δt=0.0 # time loss (in s) Δt=0.0 # time loss (in s)
#while (Δt<t_recoveryAvailable && ΔE<=0.0) #while (Δt<t_recoveryAvailable && ΔE<=0.0)

File diff suppressed because it is too large Load Diff

View File

@ -15,10 +15,10 @@ approximationLevel = 6 # TODO: define it in TrainRun and give it to each fu
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict) function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
CSs::Vector{Dict} = movingSection[:characteristicSections] CSs::Vector{Dict} = movingSection[:characteristicSections]
startingPoint=DataPoint() startingPoint=createDataPoint()
startingPoint.i=1 startingPoint[:i]=1
startingPoint.s=CSs[1][:s_entry] startingPoint[:s]=CSs[1][:s_entry]
drivingCourse=[startingPoint] # List of data points drivingCourse::Vector{Dict} = [startingPoint] # List of data points
# for CS in CSs # for CS in CSs
for csId in 1:length(CSs) for csId in 1:length(CSs)
@ -53,18 +53,18 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
elseif s_cruising > 0.0 || s_braking == 0.0 elseif s_cruising > 0.0 || s_braking == 0.0
# 09/21 elseif s_cruising > 0.0 # 09/21 elseif s_cruising > 0.0
# 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0) # 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0)
if drivingCourse[end].v < CS[:v_peak] if drivingCourse[end][:v] < CS[:v_peak]
(CS, drivingCourse)=addAccelerationPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addAccelerationPhase!(CS, drivingCourse, settings, train, CSs)
end #if end #if
if CS[:s_exit]-drivingCourse[end].s-max(0.0, (CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors if CS[:s_exit]-drivingCourse[end][:s]-max(0.0, (CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
println("ERROR: After accelerating in CS ",csId," the braking distance is too short!") println("ERROR: After accelerating in CS ",csId," the braking distance is too short!")
println(" before acceleration in CS",csId, " with s=",drivingCourse[end].s," s_braking=",((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])," s_exit=",CS[:s_exit]) println(" before acceleration in CS",csId, " with s=",drivingCourse[end][:s]," s_braking=",((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking])," s_exit=",CS[:s_exit])
println(" and v=",drivingCourse[end].v," v_peak=",CS[:v_peak]," v_exit=",CS[:v_exit]) println(" and v=",drivingCourse[end][:v]," v_peak=",CS[:v_peak]," v_exit=",CS[:v_exit])
end end
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
s_cruising=CS[:s_exit]-drivingCourse[end].s-s_braking s_cruising=CS[:s_exit]-drivingCourse[end][:s]-s_braking
if s_cruising > 0.0 if s_cruising > 0.0
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
@ -78,17 +78,17 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end #if end #if
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
if drivingCourse[end].v > CS[:v_exit] if drivingCourse[end][:v] > CS[:v_exit]
#(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings[:massModel], train, CSs) #(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings[:massModel], train, CSs)
(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings, train, CSs)
end #if end #if
#= 09/20 old and should never be used: #= 09/20 old and should never be used:
if drivingCourse[end].s < CS[:s_exit] if drivingCourse[end][:s] < CS[:s_exit]
if haskey(BSs, :cruising) if haskey(BSs, :cruising)
println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CS[:s_exit]) println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end][:s]," to s_exit=",CS[:s_exit])
end end
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
end =# end =#
@ -96,35 +96,34 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
(CSs[end], drivingCourse)=addStandstill!(CSs[end], drivingCourse, settings, train, CSs) (CSs[end], drivingCourse)=addStandstill!(CSs[end], drivingCourse, settings, train, CSs)
movingSection[:t] = drivingCourse[end].t # total running time (in s) movingSection[:t] = drivingCourse[end][:t] # total running time (in s)
movingSection[:E] = drivingCourse[end].E # total energy consumption (in Ws) movingSection[:E] = drivingCourse[end][:E] # total energy consumption (in Ws)
return (movingSection, drivingCourse) return (movingSection, drivingCourse)
end #function calculateMinimumRunningTime end #function calculateMinimumRunningTime
function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict, drivingCourseMinimumRunningTime::Vector{DataPoint}, settings::Dict, train::Dict) function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict, drivingCourseMinimumRunningTime::Vector{Dict}, settings::Dict, train::Dict)
# calculate a train run focussing on using the minimum possible energy consumption # calculate a train run focussing on using the minimum possible energy consumption
# booleans for choosing which methods are used for saving energy # booleans for choosing which methods are used for saving energy
doMethod1=true doMethod1=true
#doMethod1=false #doMethod1=false
#doMethod2=false
doMethod2=true doMethod2=true
#doMethod2=false
doCombinationOfMethods=true doCombinationOfMethods=true
#doCombinationOfMethods=false #doCombinationOfMethods=false
# create a new driving course for the minimum energy consumption
drivingCourseOriginal = copy(drivingCourseMinimumRunningTime)
#create a new moving section for the minimum energy consumption #create a new moving section for the minimum energy consumption
movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime) movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime)
# 01/01 new when Datapoint is a Dict: movingSectionOriginal=copy(movingSectionMinimumRunningTime) # 01/09 old not sure if just copy is enough.. : movingSectionOriginal=copy(movingSectionMinimumRunningTime)
CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections] CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections]
merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications
# create a new driving course for the minimum energy consumption
drivingCourseOriginal=DataPoint[]
for i in 1:length(drivingCourseMinimumRunningTime)
push!(drivingCourseOriginal, DataPoint(drivingCourseMinimumRunningTime[i])) # List of data points till the start of energy saving
end
# calculate the recovery time # calculate the recovery time
t_recovery=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train) t_recovery=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train)
merge!(movingSectionOriginal, Dict(:t_recovery=>t_recovery)) # total recovery time for energy-saving modifications (in s) merge!(movingSectionOriginal, Dict(:t_recovery=>t_recovery)) # total recovery time for energy-saving modifications (in s)
@ -158,12 +157,9 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end #if end #if
end # for end # for
# testNr=0
# 01/03 old wit too long calculation time: while movingSectionOriginal[:t_recoveryAvailable] > 0.0 # 01/03 old wit too long calculation time: while movingSectionOriginal[:t_recoveryAvailable] > 0.0
while movingSectionOriginal[:t_recoveryAvailable] >= 1/(10^approximationLevel) while movingSectionOriginal[:t_recoveryAvailable] >= 1/(10^approximationLevel)
# testNr=testNr+1 # compare modifications
# println("while in OpModes: ", testNr, " mit t_recoveryAvailable=",movingSectionOriginal[:t_recoveryAvailable])
# comparison of modifications
ratioMax=0.0 ratioMax=0.0
csIdMax=0 csIdMax=0
typeMax="none" typeMax="none"
@ -207,39 +203,36 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end end
# create new driving course # create new driving course
drivingCourseNew=DataPoint[] drivingCourseNew = copy(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified])
for i in 1:length(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified])
push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified][i]))
end
#fill up the rest of the driving course with information from the original course #fill up the rest of the driving course with information from the original course
drivingCourseNew[end].F_T=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_T drivingCourseNew[end][:F_T]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:F_T]
drivingCourseNew[end].R_traction=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_traction drivingCourseNew[end][:R_traction]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_traction]
drivingCourseNew[end].R_wagons=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_wagons drivingCourseNew[end][:R_wagons]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_wagons]
drivingCourseNew[end].R_train=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_train drivingCourseNew[end][:R_train]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_train]
drivingCourseNew[end].R_path=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_path drivingCourseNew[end][:R_path]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_path]
drivingCourseNew[end].F_R=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_R drivingCourseNew[end][:F_R]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:F_R]
drivingCourseNew[end].a=drivingCourseOriginal[lastIdOfSelectedCsOriginal].a drivingCourseNew[end][:a]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:a]
endOfModificationId=drivingCourseNew[end].i # is needed for updating the other modified driving courses endOfModificationId=drivingCourseNew[end][:i] # is needed for updating the other modified driving courses
difference=endOfModificationId-lastIdOfSelectedCsOriginal difference=endOfModificationId-lastIdOfSelectedCsOriginal
i=lastIdOfSelectedCsOriginal+1 i=lastIdOfSelectedCsOriginal+1
while i <= length(drivingCourseOriginal) while i <= length(drivingCourseOriginal)
push!(drivingCourseNew, DataPoint(drivingCourseOriginal[i])) push!(drivingCourseNew, copy(drivingCourseOriginal[i]))
drivingCourseNew[end].i=length(drivingCourseNew) drivingCourseNew[end][:i]=length(drivingCourseNew)
drivingCourseNew[end].t=drivingCourseNew[end-1].t+drivingCourseNew[end].Δt drivingCourseNew[end][:t]=drivingCourseNew[end-1][:t]+drivingCourseNew[end][:Δt]
drivingCourseNew[end].E=drivingCourseNew[end-1].E+drivingCourseNew[end].ΔE drivingCourseNew[end][:E]=drivingCourseNew[end-1][:E]+drivingCourseNew[end][:ΔE]
drivingCourseNew[end].W=drivingCourseNew[end-1].W+drivingCourseNew[end].ΔW drivingCourseNew[end][:W]=drivingCourseNew[end-1][:W]+drivingCourseNew[end][:ΔW]
i=i+1 i=i+1
end # while end # while
# replace the original driving course and CS with the new modified ones # replace the original driving course and CS with the new modified ones
drivingCourseOriginal=drivingCourseNew drivingCourseOriginal=drivingCourseNew
CSsOrig[csIdMax]=copy(movingSectionOriginal[:energySavingModifications][end][:csModified]) CSsOrig[csIdMax]=copyCharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified])
# 01/07 old without copy: CSsOrig[csIdMax]=copyCharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified]) # 01/09 old with copy: CSsOrig[csIdMax]=copy(movingSectionOriginal[:energySavingModifications][end][:csModified])
movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s) movingSectionOriginal[:t]=drivingCourseOriginal[end][:t] # total running time (in s)
movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws) movingSectionOriginal[:E]=drivingCourseOriginal[end][:E] # total energy consumption (in Ws)
# update all the data point references in the behaviour sections of the following characteristic sections and the other modified characteristic sections # update all the data point references in the behaviour sections of the following characteristic sections and the other modified characteristic sections
if difference!= 0 if difference!= 0
@ -291,7 +284,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end #function calculateMinimumEnergyConsumption end #function calculateMinimumEnergyConsumption
function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict) function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{Dict}, csId::Integer, modificationType::String, settings::Dict, train::Dict)
# TODO: refactor and sort this function # TODO: refactor and sort this function
CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections] CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections]
@ -301,6 +294,7 @@ function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{Dat
elseif modificationType == "decreasing maximum velocity" elseif modificationType == "decreasing maximum velocity"
# method 2: accelerate to a lower v_peak # method 2: accelerate to a lower v_peak
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable]) (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
elseif modificationType == "combination of energy saving methods" elseif modificationType == "combination of energy saving methods"
# calculate the combination of the previous methods # calculate the combination of the previous methods
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable]) (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
@ -368,24 +362,7 @@ function createEnergySavingModification()
:drivingCourseModified => []) # drivingCourse for the modified characteristic section :drivingCourseModified => []) # drivingCourse for the modified characteristic section
end #createEnergySavingModification end #createEnergySavingModification
function copyEnergySavingModification(original::Dict) function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{Dict}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
copy = Dict(:csId => original[:csId], # identifier of the characteristic section
:type => original[:type], # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
:ΔE => original[:ΔE], # saved energy (in Ws)
:Δt => original[:Δt], # time loss (in s)
:ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s)
:csModified => copy(original[:csModified])) # the modified characteristic section
# 01/07 old without copy: csModified => copyCharacteristicSection(original[:csModified])) # the modified characteristic section
drivingCourseModified = DataPoint[]
for i in 1:length(original[:drivingCourseModified])
push!(drivingCourseModified, DataPoint(original[:drivingCourseModified][i]))
end
merge!(copy, Dict(:drivingCourseModified => drivingCourseModified)) # drivingCourse for the modified characteristic section
return copy
end #function copyEnergySavingModification
function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
difference = endOfModificationId-lastIdOfSelectedCsOriginal difference = endOfModificationId-lastIdOfSelectedCsOriginal
for modNr in csIdMax+1:length(energySavingModifications) for modNr in csIdMax+1:length(energySavingModifications)
@ -401,17 +378,16 @@ function updateEnergySavingModifications!(energySavingModifications::Vector{Dict
end #for end #for
# correct the points of previous CS in the modified driving course. Copy the new driving course till the beginning of the current CS and change total values of the current modified CS data points accordingly # correct the points of previous CS in the modified driving course. Copy the new driving course till the beginning of the current CS and change total values of the current modified CS data points accordingly
drivingCourseModifiedNew=Vector{DataPoint}() drivingCourseModifiedNew = copy(drivingCourseNew[1:endOfModificationId])
for i in 1:endOfModificationId
push!(drivingCourseModifiedNew, DataPoint(drivingCourseNew[i]))
end # for
i=lastIdOfSelectedCsOriginal+1 i=lastIdOfSelectedCsOriginal+1
while i <= length(energySavingModifications[modNr][:drivingCourseModified]) while i <= length(energySavingModifications[modNr][:drivingCourseModified])
push!(drivingCourseModifiedNew, DataPoint(energySavingModifications[modNr][:drivingCourseModified][i])) push!(drivingCourseModifiedNew, copy(energySavingModifications[modNr][:drivingCourseModified][i]))
drivingCourseModifiedNew[end].i=length(drivingCourseModifiedNew)
drivingCourseModifiedNew[end].t=drivingCourseModifiedNew[end-1].t+drivingCourseModifiedNew[end].Δt drivingCourseModifiedNew[end][:i]=length(drivingCourseModifiedNew)
drivingCourseModifiedNew[end].E=drivingCourseModifiedNew[end-1].E+drivingCourseModifiedNew[end].ΔE drivingCourseModifiedNew[end][:t]=drivingCourseModifiedNew[end-1][:t]+drivingCourseModifiedNew[end][:Δt]
drivingCourseModifiedNew[end].W=drivingCourseModifiedNew[end-1].W+drivingCourseModifiedNew[end].ΔW drivingCourseModifiedNew[end][:E]=drivingCourseModifiedNew[end-1][:E]+drivingCourseModifiedNew[end][:ΔE]
drivingCourseModifiedNew[end][:W]=drivingCourseModifiedNew[end-1][:W]+drivingCourseModifiedNew[end][:ΔW]
i=i+1 i=i+1
end # while end # while
@ -425,10 +401,10 @@ end #function updateEnergySavingModifications!
function copyMovingSection(original::Dict) function copyMovingSection(original::Dict)
#TODO after removing the mutable structs: Is it possible to just "copy"? #TODO after removing the mutable structs: Is it possible to just "copy"?
CSsCopy = Vector{Dict}() copiedCSs = Vector{Dict}()
for csId in 1:length(original[:characteristicSections]) for csId in 1:length(original[:characteristicSections])
push!(CSsCopy, copy(original[:characteristicSections][csId])) push!(copiedCSs, copyCharacteristicSection(original[:characteristicSections][csId]))
# 01/07 old without copy: push!(CSsCopy, copyCharacteristicSection(original[:characteristicSections][csId])) # 01/07 old without copy: push!(copiedCSs, copyCharacteristicSection(original[:characteristicSections][csId]))
end #for end #for
copiedMS = Dict(:id => original[:id], # identifier copiedMS = Dict(:id => original[:id], # identifier
@ -437,15 +413,14 @@ function copyMovingSection(original::Dict)
:s_exit => original[:s_exit], # last position (in m) :s_exit => original[:s_exit], # last position (in m)
:t => original[:t], # total running time (in s) :t => original[:t], # total running time (in s)
:E => original[:E], # total energy consumption (in Ws) :E => original[:E], # total energy consumption (in Ws)
:characteristicSections => CSsCopy) # list of containing characteristic sections :characteristicSections => copiedCSs) # list of containing characteristic sections
if haskey(original, :energySavingModifications) # list of containing all the used energy saving modifications if haskey(original, :energySavingModifications) # list of containing all the used energy saving modifications
ModificationsCopy = Dict[] copiedModifications = Dict[]
for modId in 1:length(original[:energySavingModifications]) for modId in 1:length(original[:energySavingModifications])
push!(ModificationsCopy, copyEnergySavingModification(original[:energySavingModifications][modId])) # TODO or should it be copyEnergySavingModification push!(copiedModifications, copyEnergySavingModification(original[:energySavingModifications][modId]))
# 01/07 new when DataPoint is a Dict: push!(ModificationsCopy, copy(original[:energySavingModifications][modId]))
end #for end #for
merge!(copiedMS, Dict(:energySavingModifications => ModificationsCopy)) merge!(copiedMS, Dict(:energySavingModifications => copiedModifications))
end end
if haskey(original, :t_recovery) # total recovery time for energy-saving modifications (in s) if haskey(original, :t_recovery) # total recovery time for energy-saving modifications (in s)
@ -457,30 +432,17 @@ function copyMovingSection(original::Dict)
end end
return copiedMS return copiedMS
end #function copyMovingSection end #function copyMovingSection
#=
function copyCharacteristicSection(original::Dict)
#TODO after removing the mutable structs: Is it possible to just "copy"?
copiedCS = Dict(:id => original[:id], # identifier
:s_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last position (in m)
:length => original[:length], # total length (in m)
:r_path => original[:r_path], # path resistance (in ‰)
:behaviorSections => Dict(), # empty list of containing behavior sections
:t => original[:t], # total running time (in s)
:E => original[:E], # total energy consumption (in Ws)
:v_limit => original[:v_limit], # speed limit (in m/s)
:v_peak => original[:v_peak], # maximum reachable speed (in m/s)
:v_entry => original[:v_entry], # maximum entry speed (in m/s)
:v_exit => original[:v_exit]) # maximum exit speed (in m/s)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] function copyEnergySavingModification(modificaionOriginal::Dict)
for bs in 1: length(allBs) modificaionCopy = Dict(:csId => modificaionOriginal[:csId], # identifier of the characteristic section
if haskey(original[:behaviorSections], allBs[bs]) :type => modificaionOriginal[:type], # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
#merge!(copiedCS[:behaviorSections], Dict(allBs[bs] => copyBehaviorSection(original[:behaviorSections][allBs[bs]]))) :ΔE => modificaionOriginal[:ΔE], # saved energy (in Ws)
merge!(copiedCS[:behaviorSections], Dict(allBs[bs] => copy(original[:behaviorSections][allBs[bs]]))) :Δt => modificaionOriginal[:Δt], # time loss (in s)
end #if :ratio => modificaionOriginal[:ratio], # ratio of ΔE and Δt (in Ws/s)
end #for :csModified => copyCharacteristicSection(modificaionOriginal[:]), # the modified characteristic section
return copiedCS :drivingCourseModified => copy(modificaionOriginal[:drivingCourseModified])) # drivingCourse for the modified characteristic section
end #function copyCharacteristicSection
=# return modificaionCopy
end # copyEnergySavingModification
end #module OperationModes end #module OperationModes

View File

@ -7,7 +7,7 @@ using CSV, DataFrames, Dates
export createOutput export createOutput
export plotDrivingCourse, printImportantValues, printSectionInformation # functions for showing results during the development export plotDrivingCourse, printImportantValues, printSectionInformation # functions for showing results during the development
function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict) function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{Dict}, movingSection::Dict)
# method of function createOutput for one operation mode # method of function createOutput for one operation mode
if settings[:typeOfOutput] == "CSV" if settings[:typeOfOutput] == "CSV"
return createOutputCsv(settings, pathName, trainName, drivingCourse, movingSection) return createOutputCsv(settings, pathName, trainName, drivingCourse, movingSection)
@ -16,7 +16,7 @@ function createOutput(settings::Dict, pathName::String, trainName::String, drivi
end end
end # funtion createOutput end # funtion createOutput
function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict) function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Dict}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{Dict}, movingSectionMinimumEnergyConsumption::Dict)
# method of function createOutput for two operation modes # method of function createOutput for two operation modes
if settings[:typeOfOutput] == "CSV" if settings[:typeOfOutput] == "CSV"
return createOutputCsv(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) return createOutputCsv(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
@ -26,7 +26,7 @@ function createOutput(settings::Dict, pathName::String, trainName::String, drivi
end # funtion createOutput end # funtion createOutput
function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict) function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{Dict}, movingSection::Dict)
# method of function createOutputDict for one operation mode # method of function createOutputDict for one operation mode
if settings[:operationModeMinimumRunningTime] if settings[:operationModeMinimumRunningTime]
if settings[:operationModeMinimumEnergyConsumption] if settings[:operationModeMinimumEnergyConsumption]
@ -58,7 +58,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d
elseif settings[:detailOfOutput]=="driving course" elseif settings[:detailOfOutput]=="driving course"
push!(outputArray, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray push!(outputArray, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray
for point in drivingCourse for point in drivingCourse
row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a] row=[point[:i], point[:behavior], point[:Δs], point[:s], point[:Δt], point[:t], point[:Δv], point[:v], point[:F_T], point[:F_R], point[:R_path], point[:R_train], point[:R_traction], point[:R_wagons], point[:ΔW], point[:W], point[:ΔE], point[:E], point[:a]]
push!(outputArray, row) # push row to outputArray push!(outputArray, row) # push row to outputArray
end end
end end
@ -73,7 +73,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d
return outputDict return outputDict
end # function createOutputDict end # function createOutputDict
function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict) function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Dict}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{Dict}, movingSectionMinimumEnergyConsumption::Dict)
# method of function createOutputDict for two operation modes # method of function createOutputDict for two operation modes
if settings[:operationModeMinimumRunningTime] if settings[:operationModeMinimumRunningTime]
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime) outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
@ -88,7 +88,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d
elseif settings[:detailOfOutput]=="driving course" elseif settings[:detailOfOutput]=="driving course"
push!(outputArrayMinimumEnergyConsumption, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption push!(outputArrayMinimumEnergyConsumption, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption
for point in drivingCourseMinimumEnergyConsumption for point in drivingCourseMinimumEnergyConsumption
row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a] row=[point[:i], point[:behavior], point[:Δs], point[:s], point[:Δt], point[:t], point[:Δv], point[:v], point[:F_T], point[:F_R], point[:R_path], point[:R_train], point[:R_traction], point[:R_wagons], point[:ΔW], point[:W], point[:ΔE], point[:E], point[:a]]
push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption
end end
end end
@ -104,7 +104,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d
end # function createOutputDict end # function createOutputDict
function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict) function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{Dict}, movingSection::Dict)
# method of function createOutputDict for one operation mode # method of function createOutputDict for one operation mode
outputDict=createOutputDict(settings, pathName, trainName, drivingCourse, movingSection) outputDict=createOutputDict(settings, pathName, trainName, drivingCourse, movingSection)
@ -157,7 +157,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr
return outputDict return outputDict
end #function createOutputCsv end #function createOutputCsv
function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict) function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Dict}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{Dict}, movingSectionMinimumEnergyConsumption::Dict)
# method of function createOutputDict for two operation modes # method of function createOutputDict for two operation modes
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
@ -246,10 +246,10 @@ end #function createOutputCsv
function printImportantValues(drivingCourse::Vector{DataPoint}) function printImportantValues(drivingCourse::Vector{Dict})
println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh") println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh")
for i in 1:length(drivingCourse) for i in 1:length(drivingCourse)
println(drivingCourse[i].i,". ",drivingCourse[i].s," ",drivingCourse[i].v*3.6," ",drivingCourse[i].t/60," ",drivingCourse[i].a," ",drivingCourse[i].F_R/1000," ",drivingCourse[i].F_T/1000," ",drivingCourse[i].E/3600/1000) println(drivingCourse[i][:i],". ",drivingCourse[i][:s]," ",drivingCourse[i][:v]*3.6," ",drivingCourse[i][:t]/60," ",drivingCourse[i][:a]," ",drivingCourse[i][:F_R]/1000," ",drivingCourse[i][:F_T]/1000," ",drivingCourse[i][:E]/3600/1000)
end #for end #for
println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh") println("i behavior s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh")
end #function printImportantValues end #function printImportantValues
@ -272,18 +272,18 @@ function printSectionInformation(movingSection::Dict)
end #for end #for
end #function printSectionInformation end #function printSectionInformation
function plotDrivingCourse(drivingCourse::Vector{DataPoint}) function plotDrivingCourse(drivingCourse::Vector{Dict})
a=[] a=[]
E=[] E=[]
s=[] s=[]
t=[] t=[]
v=[] v=[]
for i in 1:length(drivingCourse) for i in 1:length(drivingCourse)
push!(a, drivingCourse[i].a) push!(a, drivingCourse[i][:a])
push!(E, drivingCourse[i].E) push!(E, drivingCourse[i][:E])
push!(s, drivingCourse[i].s) push!(s, drivingCourse[i][:s])
push!(t, drivingCourse[i].t) push!(t, drivingCourse[i][:t])
push!(v, drivingCourse[i].v) push!(v, drivingCourse[i][:v])
end #for end #for
p1=plot([s], [v], title = "v in m/s", label = ["v"], xlabel = "s in m") p1=plot([s], [v], title = "v in m/s", label = ["v"], xlabel = "s in m")
@ -304,18 +304,18 @@ function plotDrivingCourse(drivingCourse::Vector{DataPoint})
println("Plots for different variables have been created.") println("Plots for different variables have been created.")
end #function plotDrivingCourse end #function plotDrivingCourse
function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},drivingCourseMinimumEnergyConsumption::Vector{DataPoint}) function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{Dict},drivingCourseMinimumEnergyConsumption::Vector{Dict})
a_minTime=[] a_minTime=[]
E_minTime=[] E_minTime=[]
s_minTime=[] s_minTime=[]
t_minTime=[] t_minTime=[]
v_minTime=[] v_minTime=[]
for i in 1:length(drivingCourseMinimumRunningTime) for i in 1:length(drivingCourseMinimumRunningTime)
push!(a_minTime, drivingCourseMinimumRunningTime[i].a) push!(a_minTime, drivingCourseMinimumRunningTime[i][:a])
push!(E_minTime, drivingCourseMinimumRunningTime[i].E) push!(E_minTime, drivingCourseMinimumRunningTime[i][:E])
push!(s_minTime, drivingCourseMinimumRunningTime[i].s) push!(s_minTime, drivingCourseMinimumRunningTime[i][:s])
push!(t_minTime, drivingCourseMinimumRunningTime[i].t) push!(t_minTime, drivingCourseMinimumRunningTime[i][:t])
push!(v_minTime, drivingCourseMinimumRunningTime[i].v) push!(v_minTime, drivingCourseMinimumRunningTime[i][:v])
end #for end #for
a_minEnergy=[] a_minEnergy=[]
@ -324,11 +324,11 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},dr
t_minEnergy=[] t_minEnergy=[]
v_minEnergy=[] v_minEnergy=[]
for i in 1:length(drivingCourseMinimumEnergyConsumption) for i in 1:length(drivingCourseMinimumEnergyConsumption)
push!(a_minEnergy, drivingCourseMinimumEnergyConsumption[i].a) push!(a_minEnergy, drivingCourseMinimumEnergyConsumption[i][:a])
push!(E_minEnergy, drivingCourseMinimumEnergyConsumption[i].E) push!(E_minEnergy, drivingCourseMinimumEnergyConsumption[i][:E])
push!(s_minEnergy, drivingCourseMinimumEnergyConsumption[i].s) push!(s_minEnergy, drivingCourseMinimumEnergyConsumption[i][:s])
push!(t_minEnergy, drivingCourseMinimumEnergyConsumption[i].t) push!(t_minEnergy, drivingCourseMinimumEnergyConsumption[i][:t])
push!(v_minEnergy, drivingCourseMinimumEnergyConsumption[i].v) push!(v_minEnergy, drivingCourseMinimumEnergyConsumption[i][:v])
end #for end #for
p1=plot([s_minTime,s_minEnergy], p1=plot([s_minTime,s_minEnergy],

View File

@ -93,21 +93,21 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train:
CSs = movingSection[:characteristicSections] CSs = movingSection[:characteristicSections]
CSs[1][:v_entry]=0.0 # the entry velocity of the first characteristic section is 0.0 m/s CSs[1][:v_entry]=0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint=DataPoint() startingPoint=createDataPoint()
startingPoint.i=1 startingPoint[:i]=1
previousCSv_exit=CSs[1][:v_entry] previousCSv_exit=CSs[1][:v_entry]
for csId in 1:length(CSs) for csId in 1:length(CSs)
CSs[csId][:v_entry]=min(CSs[csId][:v_entry], previousCSv_exit) CSs[csId][:v_entry]=min(CSs[csId][:v_entry], previousCSv_exit)
startingPoint.s=CSs[csId][:s_entry] startingPoint[:s]=CSs[csId][:s_entry]
startingPoint.v=CSs[csId][:v_entry] startingPoint[:v]=CSs[csId][:v_entry]
accelerationCourse=[startingPoint] # List of data points accelerationCourse::Vector{Dict} = [startingPoint] # List of data points
if CSs[csId][:v_entry] < CSs[csId][:v_peak] if CSs[csId][:v_entry] < CSs[csId][:v_peak]
(CSs[csId], accelerationCourse) = addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse (CSs[csId], accelerationCourse) = addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse
CSs[csId][:v_peak] = max(CSs[csId][:v_entry], accelerationCourse[end].v) CSs[csId][:v_peak] = max(CSs[csId][:v_entry], accelerationCourse[end][:v])
CSs[csId][:v_exit] = min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end].v) CSs[csId][:v_exit] = min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end][:v])
else #CSs[csId][:v_entry]==CSs[csId][:v_peak] else #CSs[csId][:v_entry]==CSs[csId][:v_peak]
# v_exit stays the same # v_exit stays the same
end #if end #if
@ -125,20 +125,20 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak # limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak
CSs = movingSection[:characteristicSections] CSs = movingSection[:characteristicSections]
startingPoint=DataPoint() startingPoint=createDataPoint()
startingPoint.i=1 startingPoint[:i]=1
previousCSv_exit=CSs[1][:v_entry] previousCSv_exit=CSs[1][:v_entry]
for csId in 1:length(CSs) for csId in 1:length(CSs)
CSs[csId][:v_entry]=min(CSs[csId][:v_entry], previousCSv_exit) CSs[csId][:v_entry]=min(CSs[csId][:v_entry], previousCSv_exit)
startingPoint.s=CSs[csId][:s_entry] startingPoint[:s]=CSs[csId][:s_entry]
startingPoint.v=CSs[csId][:v_peak] startingPoint[:v]=CSs[csId][:v_peak]
cruisingCourse=[startingPoint] # List of data points cruisingCourse::Vector{Dict} = [startingPoint] # List of data points
(CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId][:length], settings, train, CSs, "cruising") # this function changes the cruisingCourse (CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId][:length], settings, train, CSs, "cruising") # this function changes the cruisingCourse
CSs[csId][:v_exit]=min(CSs[csId][:v_exit], cruisingCourse[end].v) CSs[csId][:v_exit]=min(CSs[csId][:v_exit], cruisingCourse[end][:v])
previousCSv_exit=CSs[csId][:v_exit] previousCSv_exit=CSs[csId][:v_exit]
end #for end #for

View File

@ -41,7 +41,7 @@ function calculateDrivingDynamics(trainDirectory::String, pathDirectory::String,
if settings[:operationModeMinimumRunningTime] ==true || settings[:operationModeMinimumEnergyConsumption] ==true if settings[:operationModeMinimumRunningTime] ==true || settings[:operationModeMinimumEnergyConsumption] ==true
(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=calculateMinimumRunningTime!(movingSection, settings, train) (movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=calculateMinimumRunningTime!(movingSection, settings, train)
# println("t=", drivingCourseMinimumRunningTime[end].t) # println("t=", drivingCourseMinimumRunningTime[end][:t])
# printSectionInformation(movingSectionMinimumRunningTime) # printSectionInformation(movingSectionMinimumRunningTime)
println("The driving course for the shortest running time has been calculated.") println("The driving course for the shortest running time has been calculated.")
end #if end #if

View File

@ -1,38 +1,10 @@
module types module types
# definition of all the additional types and their constructors
export DataPoint#, BehaviorSection export copyCharacteristicSection, copyBehaviorSection
export copyBehaviorSection # TODO is it still necessary if there is no more mutable struct? can just copy(original) be used?
#export trainType #export trainType
#@enum trainType passenger=1 freight=2 motorCoachTrain=3 #@enum trainType passenger=1 freight=2 motorCoachTrain=3
#@enum behavior breakFree=1 clearing=2 acceleration=3 cruising=4diminishing=6 coasting=7 cruisingAfterCoasting=8 braking=9 standstill=10 #@enum behavior breakFree=1 clearing=2 acceleration=3 cruising=4diminishing=6 coasting=7 cruisingAfterCoasting=8 braking=9 standstill=10
## a data point is the smallest element of the driving course. One step of the step approach is between two data points
mutable struct DataPoint
i::Integer # identifier and counter variable of the dricing course
behavior::String # type of behavior section the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting", "braking" or "standstill")
# a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
s::AbstractFloat # position (in m)
Δs::AbstractFloat # step size (in m)
t::AbstractFloat # point in time (in s)
Δt::AbstractFloat # step size (in s)
v::AbstractFloat # velocity (in m/s)
Δv::AbstractFloat # step size (in m/s)
a::AbstractFloat # acceleration (in m/s^2)
W::AbstractFloat # mechanical work (in Ws)
ΔW::AbstractFloat # mechanical work in this step (in Ws)
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)
R_path::AbstractFloat # path resistance (in N)
R_train::AbstractFloat # train resistance (in N)
R_traction::AbstractFloat # traction unit resistance (in N)
R_wagons::AbstractFloat # set of wagons resistance (in N)
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, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_wagons)
DataPoint(original::DataPoint)=DataPoint(original.i, original.behavior, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_wagons)
## different sections the whole path can be devided in the following ## different sections the whole path can be devided in the following
## smallest section of the path is the behavior section. It relates to the containing data points via their identifier. ## smallest section of the path is the behavior section. It relates to the containing data points via their identifier.
@ -54,4 +26,30 @@ function copyBehaviorSection(original::Dict)
return copiedBS return copiedBS
end end
function copyCharacteristicSection(originalCS::Dict)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
copiedBSs = Dict()
for bs in 1: length(allBs)
if haskey(originalCS[:behaviorSections], allBs[bs])
merge!(copiedBSs, Dict(allBs[bs] => originalCS[:behaviorSections][allBs[bs]]))
end #if
end #for
copiedCS=Dict(:id => originalCS[:id], # identifier
:s_entry => originalCS[:s_entry], # first position (in m)
:s_exit => originalCS[:s_exit], # last position (in m)
:length => originalCS[:length], # total length (in m)
:r_path => originalCS[:r_path], # path resistance (in ‰)
# :behaviorSections => copy(originalCS[:behaviorSections]), # list of containing behavior sections
:behaviorSections => copiedBSs, # list of containing behavior sections
:t => originalCS[:t], # total running time (in s)
:E => originalCS[:E], # total energy consumption (in Ws)
:v_limit => originalCS[:v_limit], # speed limit (in m/s)
:v_peak => originalCS[:v_peak], # maximum reachable speed (in m/s)
:v_entry => originalCS[:v_entry], # maximum entry speed (in m/s)
:v_exit => originalCS[:v_exit]) # maximum exit speed (in m/s)
return copiedCS
end # CharacteristicSection
end #module end #module