Divide MovingPhases into Behavior and DrivingDynamics

development
Max Kannenberg 2022-01-20 13:37:55 +01:00
parent 05c1bd8d52
commit 9ec48ec7cb
7 changed files with 492 additions and 328 deletions

View File

@ -16,4 +16,5 @@ setting_directory = "data/settings.yaml"
train_run = calculateDrivingDynamics(train, running_path, settings) train_run = calculateDrivingDynamics(train, running_path, settings)
runtime = train_run[:movingSectionMinimumRunningTime][:t] runtime = train_run[:movingSectionMinimumRunningTime][:t]
exportToCsv(train_run)
println("The V 90 with 10 ore wagons needs $runtime seconds for 10 km with no gradient.") println("The V 90 with 10 ore wagons needs $runtime seconds for 10 km with no gradient.")

View File

@ -1,12 +1,12 @@
module MovingPhases module Behavior
include("./DrivingDynamics.jl")
using .DrivingDynamics
export addAccelerationPhase!, addAccelerationPhaseUntilBraking!, addCruisingPhase!, addCoastingPhaseUntilBraking!, addBrakingPhase!, addBrakingPhaseStepwise!, addStandstill!, calculateForces! export addAccelerationPhase!, addAccelerationPhaseUntilBraking!, addCruisingPhase!, addCoastingPhaseUntilBraking!, addBrakingPhase!, addBrakingPhaseStepwise!, addStandstill!, calculateForces!
export createDataPoint export createDataPoint, calcBrakingStartVelocity
# addBrakingPhaseStepwise! is not used in the current version of the tool # addBrakingPhaseStepwise! is not used in the current version of the tool
v00=100/3.6 # velocity constant (in m/s)
g=9.81 # acceleration due to gravity (in m/s^2) # TODO: should more digits of g be used? g=9,80665 m/s^2
approximationLevel = 6 # value for approximation to intersections TODO further explanation (e.g. approximationLevel = 3 -> with stepSize 10 m the approximation will be calculated accurate on 10 mm ; 1s -> 1 ms; 1 km/h -> 3.6 mm/s) approximationLevel = 6 # value for approximation to intersections TODO further explanation (e.g. approximationLevel = 3 -> with stepSize 10 m the approximation will be calculated accurate on 10 mm ; 1s -> 1 ms; 1 km/h -> 3.6 mm/s)
# TODO: define it in TrainRun and give it to each function? # TODO: define it in TrainRun and give it to each function?
@ -33,11 +33,13 @@ julia> calculateTractiveEffort(30.0, [[0.0, 180000], [20.0, 100000], [40.0, 6000
""" """
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs) function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs)
for row in 1:length(tractiveEffortVelocityPairs) for row in 1:length(tractiveEffortVelocityPairs)
if tractiveEffortVelocityPairs[row][1]==v nextPair = tractiveEffortVelocityPairs[row]
return tractiveEffortVelocityPairs[row][2] if nextPair[1] == v
elseif tractiveEffortVelocityPairs[row][1]>v return nextPair[2]
elseif nextPair[1] > v
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-F_(row-1))/(v_row-v_(row-1))+F_(row-1) # interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-F_(row-1))/(v_row-v_(row-1))+F_(row-1)
F_T_interpolation=(v-tractiveEffortVelocityPairs[row-1][1])*(tractiveEffortVelocityPairs[row][2]-tractiveEffortVelocityPairs[row-1][2])/(tractiveEffortVelocityPairs[row][1]-tractiveEffortVelocityPairs[row-1][1])+tractiveEffortVelocityPairs[row-1][2] previousPair = tractiveEffortVelocityPairs[row-1]
F_T_interpolation = (v-previousPair[1]) * (nextPair[2]-previousPair[2]) / (nextPair[1]-previousPair[1]) + previousPair[2]
return F_T_interpolation return F_T_interpolation
end #if end #if
end #for end #for
@ -46,37 +48,6 @@ function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs)
return tractiveEffortVelocityPairs[end][2] return tractiveEffortVelocityPairs[end][2]
end #function calculateTractiveEffort end #function calculateTractiveEffort
#TODO: choose an explanation and replace the ? ? ?
"""
calculateTractionUnitResistance(v, train)
Calculate the traction units vehicle resistance dependend on the velocity `v`.
Calculate the vehicle resistance for the traction unit of the `train` dependend on the velocity `v`.
...
# Arguments
- `v::AbstractFloat`: the current velocity in m/s.
- `train::Dict`: ? ? ?
...
# Examples
```julia-repl
julia> calculateTractionUnitResistance(30.0, ? ? ?)
? ? ?
```
"""
function calculateTractionUnitResistance(v::AbstractFloat, train::Dict)
return train[:f_Rtd0]/1000*train[:m_td]*g+train[:f_Rtc0]/1000*train[:m_tc]*g+train[:F_Rt2]*((v+train[:Δv_t])/v00)^2 # /1000 because of the unit ‰
end #function calculateTractionUnitResistance
"""
calculate and return the wagons vehicle resistance dependend on the velocity
"""
function calculateWagonsResistance(v::AbstractFloat, train::Dict)
return train[:m_w]*g*(train[:f_Rw0]/1000+train[:f_Rw1]/1000*v/v00+train[:f_Rw2]/1000*((v+train[:Δv_w])/v00)^2) # /1000 because of the unit ‰
end #function calculateWagonsResistance
""" """
calculate and return the path resistance dependend on the trains position and mass model calculate and return the path resistance dependend on the trains position and mass model
""" """
@ -90,35 +61,33 @@ function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::V
end end
end #while end #while
if massModel=="mass point" if massModel == "mass point"
pathResistance=CSs[id][:r_path]/1000*train[:m_train]*g # /1000 because of the unit ‰ pathResistance = calcPathResistance(CSs[id][:r_path], train[:m_train])
elseif massModel=="homogeneous strip" elseif massModel == "homogeneous strip"
pathResistance=0.0 pathResistance = 0.0
while id>0 && s-train[:length]<CSs[id][:s_exit] while id > 0 && s-train[:length] < CSs[id][:s_exit]
pathResistance=pathResistance+(min(s, CSs[id][:s_exit])-max(s-train[:length], CSs[id][:s_entry]))/train[:length]*(CSs[id][:r_path]/1000*train[:m_train]*g) # /1000 because of the unit ‰ pathResistance = pathResistance + (min(s, CSs[id][:s_exit]) - max(s-train[:length], CSs[id][:s_entry])) / train[:length] * calcPathResistance(CSs[id][:r_path], train[:m_train])
id=id-1 id = id-1
if id==0 if id == 0
# TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used # TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used
return pathResistance+(CSs[1][:s_entry]-(s-train[:length]))/train[:length]*(CSs[1][:r_path]/1000*train[:m_train]*g) # /1000 because of the unit ‰ return pathResistance + (CSs[1][:s_entry] - (s-train[:length])) / train[:length] * calcPathResistance(CSs[1][:r_path], train[:m_train])
end #if end #if
end #while end #while
else
error("ERROR at the calculation of path resistance: settings[:massModel]!=mass point && settings[:massModel]!=homogeneous strip")
end #if end #if
return pathResistance return pathResistance
end #function pathResistance end #function calculatePathResistance
""" """
calculate and return tractive and resisting forces for a data point calculate and return tractive and resisting forces for a data point
""" """
function calculateForces!(dataPoint::Dict, train::Dict, massModel::String, CSs::Vector{Dict}, bsType::String) function calculateForces!(dataPoint::Dict, train::Dict, massModel::String, CSs::Vector{Dict}, bsType::String)
# calculate resisting forces # calculate resisting forces
dataPoint[:R_traction]=calculateTractionUnitResistance(dataPoint[:v], train) dataPoint[:R_traction] = calcTractionUnitResistance(dataPoint[:v], train)
dataPoint[:R_wagons]=calculateWagonsResistance(dataPoint[:v], train) dataPoint[:R_wagons] = calcWagonsResistance(dataPoint[:v], train)
dataPoint[:R_train]=dataPoint[:R_traction]+dataPoint[:R_wagons] dataPoint[:R_train] = dataPoint[:R_traction] + dataPoint[:R_wagons]
dataPoint[:R_path]=calculatePathResistance(dataPoint[:s], massModel, train, CSs) dataPoint[:R_path] = calculatePathResistance(dataPoint[:s], massModel, train, CSs)
dataPoint[:F_R]=dataPoint[:R_train]+dataPoint[:R_path] dataPoint[:F_R] = dataPoint[:R_train] + dataPoint[:R_path]
# calculate tractive effort # calculate tractive effort
if bsType == "acceleration" || bsType == "diminishing" if bsType == "acceleration" || bsType == "diminishing"
@ -142,44 +111,42 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =# #= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =#
# creating the next data point # creating the next data point
newPoint=createDataPoint() newPoint = createDataPoint()
newPoint[:i]=previousPoint[:i]+1 # identifier newPoint[:i] = previousPoint[:i]+1 # identifier
# calculate s, t, v, E # calculate s, t, v, E
if previousPoint[:a]==0.0 # TODO: or better stepVariable=="s_cruising in m" ? if previousPoint[:a] == 0.0 # TODO: or better stepVariable=="s_cruising in m" ?
newPoint[:Δs]=stepSize # step size (in m) newPoint[:Δs] = stepSize # step size (in m)
newPoint[:Δt]=newPoint[:Δs]/previousPoint[:v] # step size (in s) newPoint[:Δt] = newPoint[:Δs]/previousPoint[:v] # step size (in s)
newPoint[:Δv]=0.0 # step size (in m/s) newPoint[:Δv] = 0.0 # step size (in m/s)
elseif stepVariable=="s in m" # distance step method elseif stepVariable == "s in m" # distance step method
newPoint[:Δs]=stepSize # step size (in m) newPoint[:Δs] = stepSize # step size (in m)
# 11/21 |-> if previousPoint[:a] < 0.0
if previousPoint[:a]<0.0
if ((previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a])<0.0 || (previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a])<0.0 # checking if the parts of the following square roots will be <0.0 if ((previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a])<0.0 || (previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a])<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.", error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,", " Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,",
" F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.") " F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.")
end end
end end
# 11/21 ->| newPoint[:Δt] = calc_Δt_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in s)
newPoint[:Δt]=sign(previousPoint[:a])*sqrt((previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a])-previousPoint[:v]/previousPoint[:a] # step size (in s) newPoint[:Δv] = calc_Δv_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m/s)
newPoint[:Δv]=sqrt(previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a])-previousPoint[:v] # step size (in m/s) elseif stepVariable =="t in s" # time step method
elseif stepVariable=="t in s" # time step method newPoint[:Δt] =stepSize # step size (in s)
newPoint[:Δt]=stepSize # step size (in s) newPoint[:Δs] = calc_Δs_with_Δt(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m)
newPoint[:Δs]=newPoint[:Δt]*(2*previousPoint[:v]+newPoint[:Δt]*previousPoint[:a])/2 # step size (in m) newPoint[:Δv] = calc_Δv_with_Δt(newPoint[:Δs], previousPoint[:a]) # step size (in m/s)
newPoint[:Δv]=newPoint[:Δt]*previousPoint[:a] # step size (in m/s) elseif stepVariable =="v in m/s" # velocity step method
elseif stepVariable=="v in m/s" # velocity step method newPoint[:Δv] = stepSize * sign(previousPoint[:a]) # step size (in m/s)
newPoint[:Δv]=stepSize*sign(previousPoint[:a]) # step size (in m/s) newPoint[:Δs] = calc_Δs_with_Δv(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m)
newPoint[:Δs]=((previousPoint[:v]+newPoint[:Δv])^2-previousPoint[:v]^2)/2/previousPoint[:a] # step size (in m) newPoint[:Δt] = calc_Δt_with_Δv(newPoint[:Δs], previousPoint[:a]) # step size (in s)
newPoint[:Δt]=newPoint[:Δv]/previousPoint[:a] # step size (in s)
end #if end #if
newPoint[:s]=previousPoint[:s]+newPoint[:Δs] # position (in m) newPoint[:s] = previousPoint[:s] + newPoint[:Δs] # position (in m)
newPoint[:t]=previousPoint[:t]+newPoint[:Δt] # point in time (in s) newPoint[:t] = previousPoint[:t] + newPoint[:Δt] # point in time (in s)
newPoint[:v]=previousPoint[:v]+newPoint[:Δv] # velocity (in m/s) newPoint[:v] = previousPoint[:v] + newPoint[:Δv] # velocity (in m/s)
newPoint[:ΔW]=previousPoint[:F_T]*newPoint[:Δs] # mechanical work in this step (in Ws) newPoint[:ΔW] = calc_ΔW(previousPoint[:F_T], newPoint[:Δs]) # mechanical work in this step (in Ws)
newPoint[:W]=previousPoint[:W]+newPoint[:ΔW] # mechanical work (in Ws) newPoint[:W] = previousPoint[:W] + newPoint[:ΔW] # mechanical work (in Ws)
newPoint[:ΔE]=newPoint[:ΔW] # energy consumption in this step (in Ws) newPoint[:ΔE] = calc_ΔE(newPoint[:ΔW]) # energy consumption in this step (in Ws)
newPoint[:E]=previousPoint[:E]+newPoint[:ΔE] # energy consumption (in Ws) newPoint[:E] = previousPoint[:E] + newPoint[:ΔE] # energy consumption (in Ws)
return newPoint return newPoint
@ -226,17 +193,17 @@ function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, setti
end end
# create a (new and longer) clearing section # create a (new and longer) clearing section
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_clearing=min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end][:s]-train[:length])) s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end][:s]-train[:length]))
if s_clearing>0.0 if s_clearing > 0.0
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") (CS, drivingCourse) = addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
else else
error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id]) error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id])
end end
# 09/22: if drivingCourse[end][:s] < CS[:s_exit] # 09/22: if drivingCourse[end][:s] < CS[:s_exit]
if drivingCourse[end][:s] < CS[:s_exit]-s_braking if drivingCourse[end][:s] < CS[:s_exit] - s_braking
# reset the accelerationSection # reset the accelerationSection
accelerationSection = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) accelerationSection = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
else else
@ -264,55 +231,27 @@ function addBreakFreePhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dic
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") # currently the tractive effort is calculated like in the acceleration phase calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") # currently the tractive effort is calculated like in the acceleration phase
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a]=(drivingCourse[end][:F_T]-drivingCourse[end][:F_R])/train[:m_train]/train[:ξ_train] drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
if drivingCourse[end][:a]<0.0 if drivingCourse[end][:a]<0.0
error("ERROR: a<0 m/s^2 in the breakFree phase !") error("ERROR: a<0 m/s^2 in the breakFree phase !")
elseif drivingCourse[end][:a]==0.0 elseif drivingCourse[end][:a] == 0.0
error("ERROR: a=0 m/s^2 in the breakFree phase !") error("ERROR: a=0 m/s^2 in the breakFree phase !")
end end
# creating the next data point # creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
#= 07/30 TODO: the calculation is easier with these lines because the values that are 0 in the first step are not used in calculation but all in all the code gets easier without these lines:
push!(drivingCourse, createDataPoint())
drivingCourse[end][:i]=drivingCourse[end-1][:i]+1 # incrementing the number of the data point
# calculate s, t, v, E
if settings[:stepVariable]=="s in m" # distance step method
drivingCourse[end][:Δs]=settings[:stepSize] # step size (in m)
drivingCourse[end][:Δt]=sqrt(2*drivingCourse[end][:Δs]/drivingCourse[end-1][:a]) # step size (in s) (in this formula drivingCourse[end-1][:v] is missing because it is 0.0)
drivingCourse[end][:Δv]=sqrt(2*drivingCourse[end][:Δs]*drivingCourse[end-1][:a]) # step size (in m/s) (in this formula drivingCourse[end-1][:v] is missing because it is 0.0)
elseif settings[:stepVariable]=="t in s" # time step method
drivingCourse[end][:Δt]=settings[:stepSize] # step size (in s)
drivingCourse[end][:Δs]=drivingCourse[end][:Δt]*(drivingCourse[end][:Δt]*drivingCourse[end-1][:a])/2 # step size (in m)
drivingCourse[end][:Δv]=drivingCourse[end][:Δt]*drivingCourse[end-1][:a] # step size (in m/s)
elseif settings[:stepVariable]=="v in m/s" # velocity step method
drivingCourse[end][:Δv]=settings[:stepSize]*sign(drivingCourse[end-1][:a]) # step size (in m/s)
drivingCourse[end][:Δs]=drivingCourse[end][:Δv]^2/2/drivingCourse[end-1][:a] # step size (in m)
drivingCourse[end][:Δt]=drivingCourse[end][:Δv]/drivingCourse[end-1][:a] # step size (in s)
end #if
#drivingCourse[end][:s]=ceil(drivingCourse[end-1][:s]+drivingCourse[end][:Δs], digits=approximationLevel) # position (in m) # rounded -> exact to 1 nm
drivingCourse[end][:s]=drivingCourse[end-1][:s]+drivingCourse[end][:Δs] # position (in m)
drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s)
drivingCourse[end][:v]=drivingCourse[end-1][:v]+drivingCourse[end][:Δv] # velocity (in m/s)
drivingCourse[end][:ΔW]=drivingCourse[end-1][:F_T]*drivingCourse[end][:Δs] # mechanical work in this step (in Ws)
drivingCourse[end][:W]=drivingCourse[end-1][:W]+drivingCourse[end][:ΔW] # mechanical work (in Ws)
drivingCourse[end][:ΔE]=drivingCourse[end][:ΔW] # energy consumption in this step (in Ws)
drivingCourse[end][:E]=drivingCourse[end-1][:E]+drivingCourse[end][:ΔE] # energy consumption (in Ws)
=#
push!(BS[:dataPoints], drivingCourse[end][:i]) push!(BS[:dataPoints], drivingCourse[end][:i])
# calculate the accumulated breakFree section information # calculate the accumulated breakFree section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:breakFree => BS)) merge!(CS[:behaviorSections], Dict(:breakFree => BS))
end # else: return the characteristic section without a breakFree section end # else: return the characteristic section without a breakFree section
@ -324,12 +263,12 @@ end #function addBreakFreePhase!
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section # Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section
function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end][:v]==0.0 if drivingCourse[end][:v]==0.0
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] if drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
end end
@ -349,12 +288,12 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end][:v]<CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
# 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) # 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a]=(drivingCourse[end][:F_T]-drivingCourse[end][:F_R])/train[:m_train]/train[:ξ_train] drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
@ -362,7 +301,6 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
push!(BS[:dataPoints], drivingCourse[end][:i]) push!(BS[:dataPoints], drivingCourse[end][:i])
# calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) # calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
(CS, drivingCourse, formerSpeedLimits, BS, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, BS) (CS, drivingCourse, formerSpeedLimits, BS, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, BS)
if endOfCsReached if endOfCsReached
@ -375,7 +313,7 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1 if cycle < approximationLevel+1
if drivingCourse[end][:v]<=0.0 if drivingCourse[end][:v] <= 0.0
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:s]>CS[:s_exit] elseif drivingCourse[end][:s]>CS[:s_exit]
@ -385,17 +323,17 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end][:v]>CS[:v_peak] elseif drivingCourse[end][:v] > CS[:v_peak]
if settings[:stepVariable]=="v in m/s" if settings[:stepVariable] == "v in m/s"
currentStepSize=CS[:v_peak]-drivingCourse[end-1][:v] currentStepSize=CS[:v_peak]-drivingCourse[end-1][:v]
else else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end][:s]==CS[:s_exit] elseif drivingCourse[end][:s] == CS[:s_exit]
break break
elseif drivingCourse[end][:v]==CS[:v_peak] elseif drivingCourse[end][:v] == CS[:v_peak]
break break
elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
@ -408,20 +346,20 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
pop!(BS[:dataPoints]) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end][:v]<=0.0 if drivingCourse[end][:v] <= 0.0
# push!(BS[:dataPoints], drivingCourse[end][:i]) # push!(BS[:dataPoints], drivingCourse[end][:i])
error("ERROR: The train stops during the acceleration phase in CS",CS[:id]," because the tractive effort is lower than the resistant forces.", error("ERROR: The train stops during the acceleration phase in CS",CS[:id]," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2",
" F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.") " F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.")
elseif drivingCourse[end][:v]>CS[:v_peak] elseif drivingCourse[end][:v] > CS[:v_peak]
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints]) pop!(BS[:dataPoints])
elseif drivingCourse[end][:s]>CS[:s_exit] elseif drivingCourse[end][:s] > CS[:s_exit]
drivingCourse[end][:s]=CS[:s_exit] # rounding s down to s_exit drivingCourse[end][:s] = CS[:s_exit] # rounding s down to s_exit
elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
else else
@ -430,16 +368,16 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
end end
end #for end #for
if length(BS[:dataPoints]) > 1 # 11/21 new: it is possible that the acceleration starts at v_peak, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section. if length(BS[:dataPoints]) > 1 # it is possible that the acceleration starts at v_peak, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
# calculate the accumulated acceleration section information # calculate the accumulated acceleration section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
# TODO: this warning schould not be needed. just for testing # TODO: this warning schould not be needed. just for testing
if CS[:v_peak] < drivingCourse[end][:v] if CS[:v_peak] < drivingCourse[end][:v]
@ -457,12 +395,12 @@ end #function addAccelerationPhase!
## This function calculates the data points of the acceleration phase. ## This function calculates the data points of the acceleration phase.
function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end][:v]==0.0 if drivingCourse[end][:v]==0.0
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] if drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
end end
@ -471,21 +409,21 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}
# 11/23 old without F_T>F_R: if drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit] # 11/23 old without F_T>F_R: if drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit]
if drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] if drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
BS = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) BS = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s]+s_braking<CS[:s_exit] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSend while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s] + s_braking<CS[:s_exit] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSend
# 12/03 old with v>0 while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s]+s_braking<CS[:s_exit] && drivingCourse[end][:v]>0.0 && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSend # 12/03 old with v>0 while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s]+s_braking<CS[:s_exit] && drivingCourse[end][:v]>0.0 && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSend
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a]=(drivingCourse[end][:F_T]-drivingCourse[end][:F_R])/train[:m_train]/train[:ξ_train] drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
# if drivingCourse[end][:a]==0.0 # if drivingCourse[end][:a] == 0.0
# error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end][:F_T]," R_traction=",drivingCourse[end][:R_traction]," R_wagons=",drivingCourse[end][:R_wagons]," R_path=",drivingCourse[end][:R_path]) # error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end][:F_T]," R_traction=",drivingCourse[end][:R_traction]," R_wagons=",drivingCourse[end][:R_wagons]," R_path=",drivingCourse[end][:R_path])
# end # end
@ -502,7 +440,7 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}
end end
end end
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end #while end #while
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
@ -551,7 +489,7 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}
pop!(BS[:dataPoints]) pop!(BS[:dataPoints])
elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
else else
@ -562,15 +500,15 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}
if length(BS[:dataPoints]) > 1 # TODO: is it still possible that it is <=1 although there is a separate diminishing phase? if length(BS[:dataPoints]) > 1 # TODO: is it still possible that it is <=1 although there is a separate diminishing phase?
# calculate the accumulated acceleration section information # calculate the accumulated acceleration section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:v_peak]=max(drivingCourse[end][:v], CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances CS[:v_peak] = max(drivingCourse[end][:v], CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:acceleration=>BS)) merge!(CS[:behaviorSections], Dict(:acceleration=>BS))
end end
@ -597,7 +535,7 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
# TODO: necessary? # TODO: necessary?
s_cruising=min(s_cruising, CS[:s_exit]-BS[:s_entry]) s_cruising = min(s_cruising, CS[:s_exit]-BS[:s_entry])
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give BS[:type] instead of "cruising"? calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give BS[:type] instead of "cruising"?
@ -606,14 +544,14 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
if settings[:massModel]=="homogeneous strip" && CS[:id] > 1 if settings[:massModel]=="homogeneous strip" && CS[:id] > 1
currentStepSize=settings[:stepSize] currentStepSize=settings[:stepSize]
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end][:s] < CS[:s_entry] + train[:length] && drivingCourse[end][:s]<BS[:s_entry]+s_cruising && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R] #&& drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit] while drivingCourse[end][:s] < CS[:s_entry] + train[:length] && drivingCourse[end][:s] < BS[:s_entry]+s_cruising && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R] #&& drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit]
# TODO: whithout CSs should work as well, no? while drivingCourse[end][:s] < CSs[CS[:id]][:s_entry] + train[:length] && drivingCourse[end][:s]<BS[:s_entry]+s_cruising && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R] #&& drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit] # TODO: whithout CSs should work as well, no? while drivingCourse[end][:s] < CSs[CS[:id]][:s_entry] + train[:length] && drivingCourse[end][:s]<BS[:s_entry]+s_cruising && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R] #&& drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit]
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS # the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance? #TODO: maybe just consider former CS with different path resistance?
#TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_peak could make problems for energy saving by shortening the acceleration phase #TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_peak could make problems for energy saving by shortening the acceleration phase
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a]=0.0 drivingCourse[end][:a] = 0.0
# create the next data point # create the next data point
if settings[:stepVariable]=="s in m" if settings[:stepVariable]=="s in m"
@ -630,13 +568,13 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1 if cycle < approximationLevel+1
if drivingCourse[end][:s]>BS[:s_entry]+s_cruising # TODO also the following? drivingCourse[end][:s] > CSs[CS[:id]][:s_entry] + train[:length])) if drivingCourse[end][:s] > BS[:s_entry]+s_cruising # TODO also the following? drivingCourse[end][:s] > CSs[CS[:id]][:s_entry] + train[:length]))
if settings[:stepVariable] == "s in m" if settings[:stepVariable] == "s in m"
currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1][:s] currentStepSize=BS[:s_entry] + s_cruising-drivingCourse[end-1][:s]
else else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end][:s]==BS[:s_entry]+s_cruising # || drivingCourse[end][:s]==CS[:s_exit] elseif drivingCourse[end][:s] == BS[:s_entry]+s_cruising # || drivingCourse[end][:s]==CS[:s_exit]
break break
elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R] elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
# if settings[:stepVariable] == "s in m" # if settings[:stepVariable] == "s in m"
@ -656,19 +594,16 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
pop!(BS[:dataPoints]) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end][:s]>BS[:s_entry]+s_cruising if drivingCourse[end][:s] > BS[:s_entry]+s_cruising
if BS[:type] == "clearing" if BS[:type] == "clearing"
else else
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints]) pop!(BS[:dataPoints])
end end
# 11/21 |-> elseif drivingCourse[end][:s] == BS[:s_entry]+s_cruising
elseif drivingCourse[end][:s]==BS[:s_entry]+s_cruising
break break
# 11/21 ->|
elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R] elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
(CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")
# s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(length=>0.0))[:length]) # s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(length=>0.0))[:length])
@ -682,11 +617,11 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
# TODO oder soll das lieber nach oben in den else des letzten Durchlaufs. Noch mal genauer ansehen, ob hier was doppelt gemoppelt ist # TODO oder soll das lieber nach oben in den else des letzten Durchlaufs. Noch mal genauer ansehen, ob hier was doppelt gemoppelt ist
# if drivingCourse[end][:s]<BS[:s_entry]+s_cruising # if drivingCourse[end][:s]<BS[:s_entry]+s_cruising
if drivingCourse[end][:s]<BS[:s_entry]+s_cruising && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] if drivingCourse[end][:s] < BS[:s_entry]+s_cruising && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
drivingCourse[end][:a]=0.0 # acceleration (in m/s^2) drivingCourse[end][:a] = 0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way # calculate the remaining cruising way
s_cruisingRemaining=BS[:s_entry]+s_cruising-drivingCourse[end][:s] s_cruisingRemaining=BS[:s_entry] + s_cruising-drivingCourse[end][:s]
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id]))
@ -695,14 +630,14 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
end end
# calculate the accumulated cruising section information # calculate the accumulated cruising section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(Symbol(BS[:type]) => BS)) merge!(CS[:behaviorSections], Dict(Symbol(BS[:type]) => BS))
end # else: return the characteristic section without a cruising section end # else: return the characteristic section without a cruising section
@ -715,43 +650,35 @@ end #function addCruisingPhase!
function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing")
if drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:v] > 0.0 && drivingCourse[end][:s]<CS[:s_exit] if drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:v] > 0.0 && drivingCourse[end][:s] < CS[:s_exit]
BS = createBehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) BS = createBehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
while drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:s]+s_braking<CS[:s_exit] && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_CSend while drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:s] + s_braking < CS[:s_exit] && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_CSend
# 11/22 old without F_T<=F_R while drivingCourse[end][:s]+s_braking<CS[:s_exit] && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_CSend
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a]=(drivingCourse[end][:F_T]-drivingCourse[end][:F_R])/train[:m_train]/train[:ξ_train] drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
# 11/21: old, only for cruising:
#if drivingCourse[end][:a]==0.0
# error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end][:F_T]," R_traction=",drivingCourse[end][:R_traction]," R_wagons=",drivingCourse[end][:R_wagons]," R_path=",drivingCourse[end][:R_path])
#end
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i]) push!(BS[:dataPoints], drivingCourse[end][:i])
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
end #while end #while
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1 if cycle < approximationLevel+1
if drivingCourse[end][:v]<=0.0 if drivingCourse[end][:v] <= 0.0
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] elseif drivingCourse[end][:s] + s_braking > CS[:s_exit]
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:s] + s_braking==CS[:s_exit] elseif drivingCourse[end][:s] + s_braking == CS[:s_exit]
# 11/21 old without s_braking: elseif drivingCourse[end][:s]==CS[:s_exit] # 11/21 old without s_braking: elseif drivingCourse[end][:s]==CS[:s_exit]
break break
@ -766,7 +693,7 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::D
pop!(BS[:dataPoints]) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end][:v]<=0.0 if drivingCourse[end][:v] <= 0.0
# push!(BS[:dataPoints], drivingCourse[end][:i]) # push!(BS[:dataPoints], drivingCourse[end][:i])
error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.", error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2",
@ -785,16 +712,16 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::D
end end
end #for end #for
if length(BS[:dataPoints]) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start if length(BS[:dataPoints]) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start?
# calculate the accumulated diminishing section information # calculate the accumulated diminishing section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:diminishing=>BS)) merge!(CS[:behaviorSections], Dict(:diminishing=>BS))
end end
@ -817,20 +744,20 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, se
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
# 08/24 old for cycle in 1:3 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size # 08/24 old for cycle in 1:3 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
while drivingCourse[end][:v]>CS[:v_exit] && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s] + s_braking < CS[:s_exit] # as long as s_i + s_braking < s_CSend while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && drivingCourse[end][:s] + s_braking < CS[:s_exit] # as long as s_i + s_braking < s_CSend
# traction effort and resisting forces (in N): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a]=(drivingCourse[end][:F_T]-drivingCourse[end][:F_R])/train[:m_train]/train[:ξ_train] drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
# creating the next data point # creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i]) push!(BS[:dataPoints], drivingCourse[end][:i])
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking]) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end # while end # while
@ -875,19 +802,28 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, se
pop!(BS[:dataPoints]) pop!(BS[:dataPoints])
elseif drivingCourse[end][:v] > CS[:v_peak] # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different elseif drivingCourse[end][:v] > CS[:v_peak] # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different
# delete last data point because it went to far
pop!(drivingCourse)
pop!(BS[:dataPoints])
# while coasting the train brakes to hold v_peak (only one data point in the end of coasting is calculated like cruising at v_peak) # while coasting the train brakes to hold v_peak (only one data point in the end of coasting is calculated like cruising at v_peak)
drivingCourse[end-1][:a]=0.0 drivingCourse[end][:a] = 0.0
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end-1][:v]^2)/2/train[:a_braking]) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
# recalculate s, t, v, E # recalculate s, t, v, E
s_constantCoasting = min(currentStepSize, CS[:s_exit] - (drivingCourse[end-1][:s] + s_braking)) # TODO: if settings[:stepVariable]=="s in m"
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], s_constantCoasting, CS[:id]))
drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i])
#=
#drivingCourse[end][:Δs]= CS[:s_exit]-drivingCourse[end-1][:s] - s_braking # step size (in m) # TODO: the coasting section is currently realised with using distance steps. For example t_braking could also be used #drivingCourse[end][:Δs]= CS[:s_exit]-drivingCourse[end-1][:s] - s_braking # step size (in m) # TODO: the coasting section is currently realised with using distance steps. For example t_braking could also be used
drivingCourse[end][:Δs]=min(currentStepSize, CS[:s_exit]-(drivingCourse[end-1][:s]+s_braking)) # TODO: if settings[:stepVariable]=="s in m" drivingCourse[end][:Δs] = min(currentStepSize, CS[:s_exit] - (drivingCourse[end-1][:s] + s_braking)) # TODO: if settings[:stepVariable]=="s in m"
drivingCourse[end][:Δt]=drivingCourse[end][:Δs]/drivingCourse[end-1][:v] # step size (in s) drivingCourse[end][:Δt] = drivingCourse[end][:Δs]/drivingCourse[end-1][:v] # step size (in s)
drivingCourse[end][:Δv]=0.0 # step size (in m/s) drivingCourse[end][:Δv] = 0.0 # step size (in m/s)
drivingCourse[end][:s]=drivingCourse[end-1][:s]+drivingCourse[end][:Δs] # position (in m) drivingCourse[end][:s] = drivingCourse[end-1][:s] + drivingCourse[end][:Δs] # position (in m)
drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s) drivingCourse[end][:t] = drivingCourse[end-1][:t] + drivingCourse[end][:Δt] # point in time (in s)
drivingCourse[end][:v]=drivingCourse[end-1][:v] # velocity (in m/s) drivingCourse[end][:v] = drivingCourse[end-1][:v] # velocity (in m/s)
drivingCourse[end][:ΔW]=drivingCourse[end-1][:F_T]*drivingCourse[end][:Δs] # mechanical work in this step (in Ws) drivingCourse[end][:ΔW]=drivingCourse[end-1][:F_T]*drivingCourse[end][:Δs] # mechanical work in this step (in Ws)
# =0.0 # =0.0
@ -897,6 +833,7 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, se
# =0.0 # =0.0
drivingCourse[end][:E]=drivingCourse[end-1][:E]+drivingCourse[end][:ΔE] # energy consumption (in Ws) drivingCourse[end][:E]=drivingCourse[end-1][:E]+drivingCourse[end][:ΔE] # energy consumption (in Ws)
# =drivingCourse[end-1][:E] # =drivingCourse[end-1][:E]
=#
else else
end end
@ -904,14 +841,14 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, se
end #for end #for
# calculate the accumulated coasting section information # calculate the accumulated coasting section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:coasting=>BS)) merge!(CS[:behaviorSections], Dict(:coasting=>BS))
end ## else: just return the given data point number without changes due to the coasting phase end ## else: just return the given data point number without changes due to the coasting phase
@ -925,7 +862,7 @@ function addBrakingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict,
# function addBrakingPhase!(CS::Dict, drivingCourse::Vector{Dict}, massModel::String, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat) # function addBrakingPhase!(CS::Dict, drivingCourse::Vector{Dict}, massModel::String, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat)
if drivingCourse[end][:v]>CS[:v_exit] && drivingCourse[end][:s]<CS[:s_exit] if drivingCourse[end][:v]>CS[:v_exit] && drivingCourse[end][:s]<CS[:s_exit]
BS = createBehaviorSection("braking", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) BS = createBehaviorSection("braking", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
BS[:s_exit]=CS[:s_exit] # last position (in m) BS[:s_exit] = CS[:s_exit] # last position (in m)
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
@ -937,13 +874,13 @@ function addBrakingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict,
push!(BS[:dataPoints], drivingCourse[end][:i]) # refering from the breaking section to the last of its data points push!(BS[:dataPoints], drivingCourse[end][:i]) # refering from the breaking section to the last of its data points
# calculate s, t, v # calculate s, t, v
drivingCourse[end][:s]=BS[:s_exit] # position (in m) drivingCourse[end][:s] = BS[:s_exit] # position (in m)
drivingCourse[end][:v]=CS[:v_exit] # velocity (in m/s) drivingCourse[end][:v] = CS[:v_exit] # velocity (in m/s)
drivingCourse[end][:Δs]=drivingCourse[end][:s]-drivingCourse[end-1][:s] # step size (in m) drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s] # step size (in m)
drivingCourse[end][:Δv]=drivingCourse[end][:v]-drivingCourse[end-1][:v] # step size (in m/s) drivingCourse[end][:Δv] = drivingCourse[end][:v] - drivingCourse[end-1][:v] # step size (in m/s)
# 09/21 old: rounding is not necessary. drivingCourse[end-1][:a]=round((drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs], digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking) # 09/21 old: rounding is not necessary. drivingCourse[end-1][:a]=round((drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs], digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
drivingCourse[end-1][:a]=(drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs] drivingCourse[end-1][:a] = calcBrakingAcceleration(drivingCourse[end-1][:v], drivingCourse[end][:v], drivingCourse[end][:Δs])
#= if drivingCourse[end-1][:a]<train[:a_braking] || drivingCourse[end-1][:a]>=0.0 #= if drivingCourse[end-1][:a]<train[:a_braking] || drivingCourse[end-1][:a]>=0.0
println("") println("")
println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1][:a] ," > ",train[:a_braking]) println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1][:a] ," > ",train[:a_braking])
@ -951,22 +888,22 @@ function addBrakingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict,
println(" v_exit=",CS[:v_exit]) println(" v_exit=",CS[:v_exit])
println("") println("")
end =# end =#
drivingCourse[end][:Δt]=drivingCourse[end][:Δv]/drivingCourse[end-1][:a] # step size (in s) drivingCourse[end][:Δt] = drivingCourse[end][:Δv] / drivingCourse[end-1][:a] # step size (in s)
drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s) drivingCourse[end][:t] = drivingCourse[end-1][:t] + drivingCourse[end][:Δt] # point in time (in s)
drivingCourse[end][:ΔW]=0.0 # mechanical work in this step (in Ws) drivingCourse[end][:ΔW] = 0.0 # mechanical work in this step (in Ws)
drivingCourse[end][:W]=drivingCourse[end-1][:W]+drivingCourse[end][:ΔW] # mechanical work (in Ws) drivingCourse[end][:W] = drivingCourse[end-1][:W] + drivingCourse[end][:ΔW] # mechanical work (in Ws)
drivingCourse[end][:ΔE]=drivingCourse[end][:ΔW] # energy consumption in this step (in Ws) drivingCourse[end][:ΔE] = drivingCourse[end][:ΔW] # energy consumption in this step (in Ws)
drivingCourse[end][:E]=drivingCourse[end-1][:E]+drivingCourse[end][:ΔE] # energy consumption (in Ws) drivingCourse[end][:E] = drivingCourse[end-1][:E] + drivingCourse[end][:ΔE] # energy consumption (in Ws)
merge!(BS, Dict(:length => drivingCourse[end][:Δs], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:Δs], # total length (in m)
#:s_exit => drivingCourse[end][:s], # last position (in m) #:s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:Δt], # total running time (in s) :t => drivingCourse[end][:Δt], # total running time (in s)
:E => drivingCourse[end][:ΔE], # total energy consumption (in Ws) :E => drivingCourse[end][:ΔE], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:braking=>BS)) merge!(CS[:behaviorSections], Dict(:braking=>BS))
end # else: return the characteristic section without a braking section end # else: return the characteristic section without a braking section
@ -982,19 +919,19 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{Dict}, setting
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
velocityIsPositive=true velocityIsPositive = true
while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:s] < CS[:s_exit] && velocityIsPositive while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:s] < CS[:s_exit] && velocityIsPositive
# traction effort and resisting forces (in N): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a]=train[:a_braking] drivingCourse[end][:a] = train[:a_braking]
# creating the next data point # creating the next data point
#TODO moveAStep should give back true or false for success or failure e.g. with dropping below v=0 m/s #TODO moveAStep should give back true or false for success or failure e.g. with dropping below v=0 m/s
#at the moment it is only for stepVariable=="s in m" #at the moment it is only for stepVariable=="s in m"
if settings[:stepVariable]=="s in m" if settings[:stepVariable] == "s in m"
if ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0 if ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0
velocityIsPositive=false velocityIsPositive=false
break break
@ -1004,44 +941,43 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{Dict}, setting
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i]) push!(BS[:dataPoints], drivingCourse[end][:i])
# s_braking=ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking]) # s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end # while end # while
if drivingCourse[end][:v] < CS[:v_exit] || !velocityIsPositive if drivingCourse[end][:v] < CS[:v_exit] || !velocityIsPositive
# calculate s, t, v # calculate s, t, v
drivingCourse[end][:s]=CS[:s_exit] # position (in m) drivingCourse[end][:s] = CS[:s_exit] # position (in m)
drivingCourse[end][:v]=CS[:v_exit] # velocity (in m/s) drivingCourse[end][:v] = CS[:v_exit] # velocity (in m/s)
drivingCourse[end][:Δs]=drivingCourse[end][:s]-drivingCourse[end-1][:s] # step size (in m) drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s] # step size (in m)
drivingCourse[end][:Δv]=drivingCourse[end][:v]-drivingCourse[end-1][:v] # step size (in m/s) drivingCourse[end][:Δv] = drivingCourse[end][:v] - drivingCourse[end-1][:v] # step size (in m/s)
#drivingCourse[end-1][:a]=round((drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs], digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
drivingCourse[end-1][:a]=(drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs] # acceleration (in m/s^2)
#drivingCourse[end-1][:a]=round(calcBrakingAcceleration(drivingCourse[end-1][:v], drivingCourse[end][:v], drivingCourse[end][:Δs]), digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
drivingCourse[end-1][:a] = calcBrakingAcceleration(drivingCourse[end-1][:v], drivingCourse[end][:v], drivingCourse[end][:Δs])
# if drivingCourse[end-1][:a]<train[:a_braking] || drivingCourse[end-1][:a]>=0.0 # if drivingCourse[end-1][:a]<train[:a_braking] || drivingCourse[end-1][:a]>=0.0
# println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1][:a] ," > ",train[:a_braking]) # println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1][:a] ," > ",train[:a_braking])
# end # end
drivingCourse[end][:Δt]=drivingCourse[end][:Δv]/drivingCourse[end-1][:a] # step size (in s) drivingCourse[end][:Δt] = drivingCourse[end][:Δv] / drivingCourse[end-1][:a] # step size (in s)
drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s) drivingCourse[end][:t] = drivingCourse[end-1][:t] + drivingCourse[end][:Δt] # point in time (in s)
drivingCourse[end][:ΔW]=0.0 # mechanical work in this step (in Ws) drivingCourse[end][:ΔW] = 0.0 # mechanical work in this step (in Ws)
drivingCourse[end][:W]=drivingCourse[end-1][:W]+drivingCourse[end][:ΔW] # mechanical work (in Ws) drivingCourse[end][:W] = drivingCourse[end-1][:W] + drivingCourse[end][:ΔW] # mechanical work (in Ws)
drivingCourse[end][:ΔE]=drivingCourse[end][:ΔW] # energy consumption in this step (in Ws) drivingCourse[end][:ΔE] = drivingCourse[end][:ΔW] # energy consumption in this step (in Ws)
drivingCourse[end][:E]=drivingCourse[end-1][:E]+drivingCourse[end][:ΔE] # energy consumption (in Ws) drivingCourse[end][:E] = drivingCourse[end-1][:E] + drivingCourse[end][:ΔE] # energy consumption (in Ws)
elseif drivingCourse[end][:s] > CS[:s_exit] elseif drivingCourse[end][:s] > CS[:s_exit]
error("Beim Bremsen wurde das CS-Ende überschritten, aber nicht v_exit unterschritten !!") error("At the end of braking: s>s_exit but v>v_exit")
else else
end end
# calculate the accumulated coasting section information # calculate the accumulated coasting section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:braking=>BS)) merge!(CS[:behaviorSections], Dict(:braking=>BS))
end # else: return the characteristic section without a braking section end # else: return the characteristic section without a braking section
@ -1052,12 +988,11 @@ end #function addBrakingPhaseStepwise!
## This function calculates the data point of the standstill. ## This function calculates the data point of the standstill.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed.
function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end][:v] == 0.0 if drivingCourse[end][:v] == 0.0
BS = createBehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) BS = createBehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
merge!(BS, Dict(:length => 0.0, # total length (in m) merge!(BS, Dict(:length => 0.0, # total length (in m)
:t => 0.0, # total running time (in s) :t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws) :E => 0.0, # total energy consumption (in Ws)
:s_exit => drivingCourse[end][:s], # last position (in m) :s_exit => drivingCourse[end][:s], # last position (in m)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) :v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = BS[:type]
@ -1111,4 +1046,4 @@ function createDataPoint()
return dataPoint return dataPoint
end #function createDataPoint end #function createDataPoint
end #module MovingPhases end #module Behavior

221
src/DrivingDynamics.jl Normal file
View File

@ -0,0 +1,221 @@
module DrivingDynamics
# export resisting forces and acceleration
export calcTractionUnitResistance, calcWagonsResistance, calcForceFromCoefficient, calcAcceleration,
# export step sizes in different units
calc_Δs_with_Δt, calc_Δs_with_Δv,
calc_Δt_with_Δs, calc_Δt_with_Δv, calc_Δt_with_constant_v,
calc_Δv_with_Δs, calc_Δv_with_Δt,
calc_ΔW, calc_ΔE,
# export braking information
calcBrakingDistance, calcBrakingStartVelocity, calcBrakingAcceleration
# literature the driving dynamics equations are based on:
# - Brünger, Olaf and Dahlhaus, Elias. 2014. Running Time Estimation. [book authors] Ingo Arne Hansen and Jörn Pachl. Railway Timetabling & Operations. Analysis Modelling Optimisation Simulation Performance Evaluation. Hamburg : Eurailpress DVV Media Group, 2014, edtition 2, chapter 4.
# - Jaekel, Birgit and Albrecht, Thomas. 2014. Comparative analysis of algorithms and models for train running simulation. Journal of Rail Transport Planning & Management. 2014.
# - Wende, Dietrich. 2003. Fahrdynamik des Schienenverkehrs. Wiesbaden : Vieweg + Teubner, 2003. edition 1.
v00 = 100/3.6 # velocity constant (in m/s)
g = 9.81 # acceleration due to gravity (in m/s^2) # TODO: should more digits of g be used? g=9,80665 m/s^2
approximationLevel = 6 # value for approximation to intersections TODO further explanation (e.g. approximationLevel = 3 -> with stepSize 10 m the approximation will be calculated accurate on 10 mm ; 1s -> 1 ms; 1 km/h -> 3.6 mm/s)
# TODO: necessary here?
## calculate forces
#TODO: replace the ? ? ?
"""
calcTractionUnitResistance(v, train)
Calculate the vehicle resistance for the traction unit of the `train` dependend on the velocity `v`.
...
# Arguments
- `v::AbstractFloat`: the current velocity in m/s.
- `train::Dict`: ? ? ?
...
# Examples
```julia-repl
julia> calcTractionUnitResistance(30.0, ? ? ?)
? ? ?
```
"""
function calcTractionUnitResistance(v::AbstractFloat, train::Dict)
# equation is based on Wende, page 151
f_Rtd0 = train[:f_Rtd0] # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0 = train[:f_Rtc0] # coefficient for basic resistance due to the traction units carring axles (in ‰)
F_Rt2 = train[:F_Rt2] # coefficient for air resistance of the traction units (in N)
m_td = train[:m_td] # mass on the traction unit's driving axles (in kg)
m_tc = train[:m_tc] # mass on the traction unit's carrying axles (in kg)
Δv_t = train[:Δv_t] # coefficient for velocitiy difference between traction unit and outdoor air (in m/s)
F_R_tractionUnit = f_Rtd0/1000 * m_td * g + f_Rtc0/1000 * m_tc * g + F_Rt2 * ((v + Δv_t) /v00)^2 # vehicle resistance of the traction unit (in N) # /1000 because of the unit ‰
# TODO: use calcForceFromCoefficient? F_R_tractionUnit = calcForceFromCoefficient(f_Rtd0, m_td) + calcForceFromCoefficient(f_Rtc0, m_tc) + F_Rt2 * ((v + Δv_t) /v00)^2 # vehicle resistance of the traction unit (in N)
return F_R_tractionUnit
#TODO: same variable name like in the rest of the tool? return R_traction
#TODO: just one line? return train[:f_Rtd0]/1000*train[:m_td]*g+train[:f_Rtc0]/1000*train[:m_tc]*g+train[:F_Rt2]*((v+train[:Δv_t])/v00)^2 # /1000 because of the unit ‰
end #function calcTractionUnitResistance
"""
TODO
calculate and return the wagons vehicle resistance dependend on the velocity
"""
function calcWagonsResistance(v::AbstractFloat, train::Dict)
# equation is based on a combination of the equations of Strahl and Sauthoff (Wende, page 153) with more detailled factors (Lehmann, page 135)
f_Rw0 = train[:f_Rw0] # coefficient for basic resistance of the set of wagons (consist) (in ‰)
f_Rw1 = train[:f_Rw1] # coefficient for the consists resistance to rolling (in ‰)
f_Rw2 = train[:f_Rw2] # coefficient fo the consistsr air resistance (in ‰)
m_w = train[:m_w] # mass of the set of wagons (consist) (in kg)
Δv_w = train[:Δv_w] # coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s)
F_R_wagons = m_w *g *(f_Rw0/1000 + f_Rw1/1000 *v /v00 + f_Rw2/1000 * ((v + Δv_w) /v00)^2) # vehicle resistance of the wagons (in N) # /1000 because of the unit ‰
# TODO: use calcForceFromCoefficient? F_R_wagons = calcForceFromCoefficient(f_Rw0, m_w) + calcForceFromCoefficient(f_Rw1, m_w) *v /v00 + calcForceFromCoefficient(f_Rw2, m_w) * ((v + Δv_w) /v00)^2 # vehicle resistance of the wagons (in N)
return F_R_wagons
end #function calcWagonsResistance
function calcForceFromCoefficient(f_R::Real, m::Real)
# equation is based on Wende, page 8
# f_R: specific resistance (in ‰)
# m: vehicle's mass (in kg)
F_R = f_R /1000 *m *g # Resisting Force (in N) # /1000 because of the unit ‰
return F_R
end #function calcForceFromCoefficient
function calcAcceleration(F_T::Real, F_R::Real, m_train::Real, ξ_train::Real)
# equation is based on Brünger et al., page 72 with a=dv/dt
# F_T: tractive effort (in N)
# F_R: resisting forces (in N)
# m_train: train's mass (in kg)
# ξ_train: train's rotation mass factor (without unit)
a = (F_T - F_R) /m_train /ξ_train # acceleration (in m/s)
return a
end #function calcAcceleration
function calc_Δs_with_Δt(Δt::Real, a_prev::Real, v_prev::Real)
# equation is based on Wende, page 37
# Δt: time step (in s)
# a_prev: acceleration from previous data point
# v_prev: velocitiy from previous data point
Δs = Δt * (2*v_prev + Δt*a_prev) /2 # step size (in m)
return Δs
end #function calc_Δs_with_Δt
function calc_Δs_with_Δv(Δv::Real, a_prev::Real, v_prev::Real)
# equation is based on Wende, page 37
# Δv: velocity step (in m/s)
# a_prev: acceleration from previous data point
# v_prev: velocitiy from previous data point
Δs = ((v_prev + Δv)^2 - v_prev^2)/2/a_prev # step size (in m)
return Δs
end #function calc_Δs_with_Δv
function calc_Δt_with_Δs(Δs::Real, a_prev::Real, v_prev::Real)
# equation is based on Wende, page 37
# Δs: distance step (in m)
# a_prev: acceleration from previous data point
# v_prev: velocitiy from previous data point
Δt = sign(a_prev) *sqrt((v_prev /a_prev)^2 + 2 *Δs /a_prev) - v_prev /a_prev # step size (in m/s)
return Δt
end #function calc_Δt_with_Δs
function calc_Δt_with_Δv(Δv::Real, a_prev::Real)
# equation is based on Wende, page 37
# Δv: velocity step (in m/s)
# a_prev: acceleration from previous data point
Δt = Δv /a_prev # step size (in s)
return Δt
end #function calc_Δt_with_Δv
function calc_Δt_with_constant_v(Δs::Real, v::Real)
# equation is based on Wende, page 37
# Δs: distance step (in m)
# v: constant velocity (in m/s)
Δt = Δs /v # step size (in s)
return Δt
end #function calc_Δt_with_constant_v
function calc_Δv_with_Δs(Δs::Real, a_prev::Real, v_prev::Real)
# equation is based on Wende, page 37
# Δs: distance step (in m)
# a_prev: acceleration from previous data point
# v_prev: velocitiy from previous data point
Δv = sqrt(v_prev^2 + 2*Δs*a_prev) - v_prev # step size (in m/s)
return Δv
end #function calc_Δv_with_Δs
function calc_Δv_with_Δt(Δt::Real, a_prev::Real)
# equation is based on Wende, page 37
# Δt: time step (in s)
# a_prev: acceleration from previous data point
# v_prev: velocitiy from previous data point
Δv = Δt * a_prev # step size (in m/s)
return Δv
end #function calc_Δv_with_Δt
function calc_ΔW(F_T_prev::Real, Δs::Real)
# equation is based on Wende, page 17
# F_T_prev: tractive force from previous data point
# Δs: distance step
ΔW = F_T_prev * Δs # mechanical work in this step (in Ws)
return ΔW
end #function calc_ΔW
function calc_ΔE(ΔW::Real)
# simplified equation is based on Jaekel et al., page 6
# ΔW: mechanical work in this step (in Ws)
ΔE = ΔW # energy consumption in this step (in Ws)
return ΔE
end #function calc_ΔW
function calcBrakingDistance(v_start::Real, v_end::Real, a_braking::Real)
# equation is based on Wende, page 37
# v_start: velocity at the start of braking (in m/s)
# v_end: target velocity at the end of braking (in m/s)
# a_braking: constant braking acceleration (in m/s^2)
s_braking = (v_end^2 - v_start^2) /2 /a_braking # braking distance (in m)
# TODO: also possible: calc_Δs_with_Δv(v_end-v_start, a_braking, v_start)
return max(0.0, ceil(s_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
end #function calcBrakingDistance
function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real)
# equation is based on Wende, page 37
# v_end: target velocity at the end of braking (in m/s)
# a_braking: constant braking acceleration (in m/s^2)
# s_braking: braking distance (in Ws)
v_start = sqrt(v_end^2 - 2*a_braking *s_braking) # braking start velocity (in m/s)
return floor(v_start, digits=approximationLevel)
end #function calcBrakingStartVelocity
function calcBrakingAcceleration(v_start::Real, v_end::Real, s_braking::Real)
# equation is based on Wende, page 37
# v_start: braking start velocity (in m/s)
# v_end: target velocity at the end of braking (in m/s)
# s_braking: braking distance (in Ws)
a_braking = (v_end^2 - v_start^2) /2 /s_braking # constant braking acceleration (in m/s^2)
return a_braking
end #function calcBrakingAcceleration
end #module DrivingDynamics

View File

@ -1,16 +1,17 @@
# INFO: EnergySaving should not be used because it is not completed yet. It was used to show the possiility of calculating different operation modes. # INFO: EnergySaving should not be used because it is not completed yet. It was used to show the possiility of calculating different operation modes.
# TODO: It has to be optimized so that each ernergy saving merhode is working individually for every train on every path. # TODO: It has to be optimized so that each ernergy saving method is working individually for every train on every path.
# TODO: calculation time for passenger trains on path1 is very long and should be reduced # TODO: calculation time for passenger trains on path1 is very long and should be reduced
#TODO: Test if enum trainType is working correctly in function calculateRecoveryTime or if only the else-pathis taken # TODO from 2022/01/18: Test if enum trainType is working correctly in function calculateRecoveryTime or if only the else-pathis taken
# TODO from 2022/01/19: Are here calculations that should be transferred to DrivingDynamics.jl?
module EnergySaving module EnergySaving
# include modules of TrainRunCalc # include modules of TrainRunCalc
include("./MovingPhases.jl") include("./Behavior.jl")
# use modules of TrainRunCalc # use modules of TrainRunCalc
using .MovingPhases using .Behavior
export addOperationModeEnergySaving! export addOperationModeEnergySaving!
@ -596,11 +597,11 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
# calculate the new and now shorter cruising section # calculate the new and now shorter cruising section
if s_cruising>0.0 if s_cruising>0.0
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") (csModified, drivingCourseModified)=addCruisingSection!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end 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)=addCoastingSectionUntilBraking!(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)
@ -612,8 +613,8 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
# 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)=addBrakingSection!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings, train, allCSs)
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
@ -729,11 +730,11 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
# calculate the new and now shorter cruising section # calculate the new and now shorter cruising section
if s_cruising>0.0 if s_cruising>0.0
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") (csModified, drivingCourseModified)=addCruisingSection!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end 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)=addCoastingSectionUntilBraking!(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)
@ -745,8 +746,8 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
# 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)=addBrakingSection!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings, train, allCSs)
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
@ -826,11 +827,11 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start 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 # calculate the coasting phase until the point the train needs to brake
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addCoastingSectionUntilBraking!(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)=addBrakingSection!(csModified, drivingCourseModified, settings, train, allCSs)
end end
if t_recoveryAvailable >= csModified[:t] - csOriginal[:t] if t_recoveryAvailable >= csModified[:t] - csOriginal[:t]
@ -928,20 +929,19 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict
# copy the drivingCourse till the beginning of energy saving # copy the drivingCourse till the beginning of energy saving
drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start 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 = calcBrakingDistance(drivingCourseModified[end][:v], csModified[:v_exit], train[:a_braking])
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 > 1/10^approximationLevel if s_cruising > 1/10^approximationLevel
# 01/09 old if s_cruising > 0.001 # 01/09 old if s_cruising > 0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") (csModified, drivingCourseModified)=addCruisingSection!(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)=addBrakingSection!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingSection!(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

View File

@ -1,7 +1,7 @@
module Preparation module Preparation
include("./MovingPhases.jl") include("./Behavior.jl")
using .MovingPhases using .Behavior
export preparateSections export preparateSections
@ -26,10 +26,12 @@ function createMovingSection(path::Dict, v_trainLimit::Real)
s_csStart=s_entry s_csStart=s_entry
csId=1 csId=1
for row in 2:length(path[:sections]) for row in 2:length(path[:sections])
if min(path[:sections][row-1][:v_limit], v_trainLimit) != min(path[:sections][row][:v_limit], v_trainLimit) || path[:sections][row-1][:f_Rp] != path[:sections][row][:f_Rp] previousSection = path[:sections][row-1]
push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][row-1], min(path[:sections][row-1][:v_limit], v_trainLimit))) currentSection = path[:sections][row]
s_csStart=path[:sections][row][:s_start] if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
csId=csId+1 push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit)))
s_csStart = currentSection[:s_start]
csId = csId+1
end #if end #if
end #for end #for
push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][end], min(path[:sections][end][:v_limit], v_trainLimit))) push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][end], min(path[:sections][end][:v_limit], v_trainLimit)))
@ -70,15 +72,15 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end # this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
CSs = movingSection[:characteristicSections] CSs = movingSection[:characteristicSections]
csId=length(CSs) csId = length(CSs)
CSs[csId][:v_exit]=0.0 # the exit velocity of the last characteristic section is 0.0 m/s CSs[csId][:v_exit] = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s
while csId >= 1 while csId >= 1
v_entryMax=sqrt(CSs[csId][:v_exit]^2-2*a_braking*CSs[csId][:length]) v_entryMax = calcBrakingStartVelocity(CSs[csId][:v_exit], a_braking, CSs[csId][:length])
v_entryMax=floor(v_entryMax, digits=12) #v_entryMax=floor(v_entryMax, digits=12)
CSs[csId][:v_entry]=min(CSs[csId][:v_limit], v_entryMax) CSs[csId][:v_entry] = min(CSs[csId][:v_limit], v_entryMax)
CSs[csId][:v_peak]=CSs[csId][:v_entry] CSs[csId][:v_peak] = CSs[csId][:v_entry]
csId=csId-1 csId = csId - 1
if csId >= 1 if csId >= 1
CSs[csId][:v_exit]=min(CSs[csId][:v_limit], CSs[csId+1][:v_entry]) CSs[csId][:v_exit]=min(CSs[csId][:v_limit], CSs[csId+1][:v_entry])
end #if end #if
@ -91,20 +93,20 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train:
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards # this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
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=createDataPoint() 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::Vector{Dict} = [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) = addAccelerationSection!(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]
@ -124,22 +126,22 @@ 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=createDataPoint() 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::Vector{Dict} = [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) = addCruisingSection!(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
return movingSection return movingSection

View File

@ -5,22 +5,22 @@ include("./TrainRunCalc.jl")
# include additional modules # include additional modules
include("./Import.jl") include("./Import.jl")
include("./EnergySaving.jl")
include("./Export.jl") include("./Export.jl")
# include additional modules that are not recommended to use in this state # include additional modules that are not recommended to use in this state
include("./AdditionalOutput.jl") include("./AdditionalOutput.jl")
include("./EnergySaving.jl")
# use main module TrainRunCalc # use main module TrainRunCalc
using .TrainRunCalc using .TrainRunCalc
# use additional modules # use additional modules
using .Import using .Import
using .EnergySaving
using .Export using .Export
# use additional modules that are not recommended to use in this state # use additional modules that are not recommended to use in this state
using .AdditionalOutput using .AdditionalOutput
using .EnergySaving
# main function # main function
export calculateDrivingDynamics, export calculateDrivingDynamics,
@ -28,7 +28,7 @@ export calculateDrivingDynamics,
# import functions # import functions
importYamlFiles, importYamlFile, importYamlFiles, importYamlFile,
# functions for saving energy # functions for saving energy that are not recommended to use in this state
addOperationModeEnergySaving!, addOperationModeEnergySaving!,
# export functions # export functions
@ -38,6 +38,11 @@ exportToCsv,
plotResults, plotDrivingCourse, printImportantValues, printSectionInformation plotResults, plotDrivingCourse, printImportantValues, printSectionInformation
# approximationLevel = 6 # value for approximation to intersections # approximationLevel = 6 # value for approximation to intersections
# TODO: define it here and give it to each function? (MovingPhases, EnergySaving, ..) # TODO: define it here and give it to each function? (Behavior, EnergySaving, ..)
"""
TODO: Package description
"""
end # module TrainRun end # module TrainRun

View File

@ -3,21 +3,21 @@ module TrainRunCalc
# include modules of TrainRunCalc # include modules of TrainRunCalc
include("./Input.jl") include("./Input.jl")
include("./Preparation.jl") include("./Preparation.jl")
include("./MovingPhases.jl") include("./Behavior.jl")
include("./Output.jl") include("./Output.jl")
# use modules of TrainRunCalc # use modules of TrainRunCalc
using .Input using .Input
using .Preparation using .Preparation
using .MovingPhases using .Behavior
using .Output using .Output
# export main function # export main function
export calculateDrivingDynamics export calculateDrivingDynamics
approximationLevel = 6 # value for approximation to intersections and precisely calculated digits approximationLevel = 6 # value for approximation to intersections and precisely calculated digits
# TODO: define it here and give it to each function? (MovingPhases, ...) # TODO: define it here and give it to each function? (Behavior, ...)
# Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`. # Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
@ -90,15 +90,15 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
if s_clearing == CS[:length] if s_clearing == CS[:length]
# 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "cruising") # 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "cruising")
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") (CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
elseif s_cruising == CS[:length] elseif s_cruising == CS[:length]
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") (CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
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)=addAccelerationSection!(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
@ -111,13 +111,13 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
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)=addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
end end
else else
if CS[:v_entry] < CS[:v_peak] || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_peak" or "v_i <= v_peak" if CS[:v_entry] < CS[:v_peak] || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_peak" or "v_i <= v_peak"
# 09/09 old (not sufficient for steep gradients): if CS[:v_entry] < CS[:v_peak] # 09/09 old (not sufficient for steep gradients): if CS[:v_entry] < CS[:v_peak]
(CS, drivingCourse)=addAccelerationPhaseUntilBraking!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addAccelerationSectionUntilBraking!(CS, drivingCourse, settings, train, CSs)
end #if end #if
end #if end #if
@ -125,8 +125,8 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
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)=addBrakingSection!(CS, drivingCourse, settings[:massModel], train, CSs)
(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addBrakingSection!(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:
@ -134,7 +134,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
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)=addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
end =# end =#
end #for end #for