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)
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.")

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 createDataPoint
export createDataPoint, calcBrakingStartVelocity
# 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)
# 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)
for row in 1:length(tractiveEffortVelocityPairs)
if tractiveEffortVelocityPairs[row][1]==v
return tractiveEffortVelocityPairs[row][2]
elseif tractiveEffortVelocityPairs[row][1]>v
nextPair = tractiveEffortVelocityPairs[row]
if nextPair[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)
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
end #if
end #for
@ -46,37 +48,6 @@ function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs)
return tractiveEffortVelocityPairs[end][2]
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
"""
@ -90,35 +61,33 @@ function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::V
end
end #while
if massModel=="mass point"
pathResistance=CSs[id][:r_path]/1000*train[:m_train]*g # /1000 because of the unit ‰
elseif massModel=="homogeneous strip"
pathResistance=0.0
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 ‰
id=id-1
if id==0
if massModel == "mass point"
pathResistance = calcPathResistance(CSs[id][:r_path], train[:m_train])
elseif massModel == "homogeneous strip"
pathResistance = 0.0
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] * calcPathResistance(CSs[id][:r_path], train[:m_train])
id = id-1
if id == 0
# 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 #while
else
error("ERROR at the calculation of path resistance: settings[:massModel]!=mass point && settings[:massModel]!=homogeneous strip")
end #if
return pathResistance
end #function pathResistance
end #function calculatePathResistance
"""
calculate and return tractive and resisting forces for a data point
"""
function calculateForces!(dataPoint::Dict, train::Dict, massModel::String, CSs::Vector{Dict}, bsType::String)
# calculate resisting forces
dataPoint[:R_traction]=calculateTractionUnitResistance(dataPoint[:v], train)
dataPoint[:R_wagons]=calculateWagonsResistance(dataPoint[:v], train)
dataPoint[:R_train]=dataPoint[:R_traction]+dataPoint[:R_wagons]
dataPoint[:R_path]=calculatePathResistance(dataPoint[:s], massModel, train, CSs)
dataPoint[:F_R]=dataPoint[:R_train]+dataPoint[:R_path]
dataPoint[:R_traction] = calcTractionUnitResistance(dataPoint[:v], train)
dataPoint[:R_wagons] = calcWagonsResistance(dataPoint[:v], train)
dataPoint[:R_train] = dataPoint[:R_traction] + dataPoint[:R_wagons]
dataPoint[:R_path] = calculatePathResistance(dataPoint[:s], massModel, train, CSs)
dataPoint[:F_R] = dataPoint[:R_train] + dataPoint[:R_path]
# calculate tractive effort
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. =#
# creating the next data point
newPoint=createDataPoint()
newPoint[:i]=previousPoint[:i]+1 # identifier
newPoint = createDataPoint()
newPoint[:i] = previousPoint[:i]+1 # identifier
# calculate s, t, v, E
if previousPoint[:a]==0.0 # TODO: or better stepVariable=="s_cruising in m" ?
newPoint[:Δs]=stepSize # step size (in m)
newPoint[:Δt]=newPoint[:Δs]/previousPoint[:v] # step size (in s)
newPoint[:Δv]=0.0 # step size (in m/s)
elseif stepVariable=="s in m" # distance step method
newPoint[:Δs]=stepSize # step size (in m)
# 11/21 |->
if previousPoint[:a]<0.0
if previousPoint[:a] == 0.0 # TODO: or better stepVariable=="s_cruising in m" ?
newPoint[:Δs] = stepSize # step size (in m)
newPoint[:Δt] = newPoint[:Δs]/previousPoint[:v] # step size (in s)
newPoint[:Δv] = 0.0 # step size (in m/s)
elseif stepVariable == "s in m" # distance step method
newPoint[:Δs] = stepSize # step size (in m)
if previousPoint[:a] < 0.0
if ((previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a])<0.0 || (previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a])<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,",
" F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.")
end
end
# 11/21 ->|
newPoint[:Δt]=sign(previousPoint[:a])*sqrt((previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a])-previousPoint[:v]/previousPoint[:a] # step size (in s)
newPoint[:Δv]=sqrt(previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a])-previousPoint[:v] # step size (in m/s)
elseif stepVariable=="t in s" # time step method
newPoint[:Δt]=stepSize # step size (in s)
newPoint[:Δs]=newPoint[:Δt]*(2*previousPoint[:v]+newPoint[:Δt]*previousPoint[:a])/2 # step size (in m)
newPoint[:Δv]=newPoint[:Δt]*previousPoint[:a] # step size (in m/s)
elseif stepVariable=="v in m/s" # velocity step method
newPoint[:Δv]=stepSize*sign(previousPoint[:a]) # step size (in m/s)
newPoint[:Δs]=((previousPoint[:v]+newPoint[:Δv])^2-previousPoint[:v]^2)/2/previousPoint[:a] # step size (in m)
newPoint[:Δt]=newPoint[:Δv]/previousPoint[:a] # step size (in s)
newPoint[:Δt] = calc_Δt_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in s)
newPoint[:Δv] = calc_Δv_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m/s)
elseif stepVariable =="t in s" # time step method
newPoint[:Δt] =stepSize # step size (in s)
newPoint[:Δs] = calc_Δs_with_Δt(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m)
newPoint[:Δv] = calc_Δv_with_Δt(newPoint[:Δs], previousPoint[:a]) # step size (in m/s)
elseif stepVariable =="v in m/s" # velocity step method
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[:Δt] = calc_Δt_with_Δv(newPoint[:Δs], previousPoint[:a]) # step size (in s)
end #if
newPoint[:s]=previousPoint[:s]+newPoint[:Δs] # position (in m)
newPoint[:t]=previousPoint[:t]+newPoint[:Δt] # point in time (in s)
newPoint[:v]=previousPoint[:v]+newPoint[:Δv] # velocity (in m/s)
newPoint[:ΔW]=previousPoint[:F_T]*newPoint[:Δs] # mechanical work in this step (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]=previousPoint[:E]+newPoint[:ΔE] # energy consumption (in Ws)
newPoint[:s] = previousPoint[:s] + newPoint[:Δs] # position (in m)
newPoint[:t] = previousPoint[:t] + newPoint[:Δt] # point in time (in s)
newPoint[:v] = previousPoint[:v] + newPoint[:Δv] # velocity (in m/s)
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[:ΔE] = calc_ΔE(newPoint[:ΔW]) # energy consumption in this step (in Ws)
newPoint[:E] = previousPoint[:E] + newPoint[:ΔE] # energy consumption (in Ws)
return newPoint
@ -226,17 +193,17 @@ function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, setti
end
# 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_clearing=min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end][:s]-train[:length]))
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]))
if s_clearing>0.0
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
if s_clearing > 0.0
(CS, drivingCourse) = addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
else
error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id])
end
# 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
accelerationSection = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
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
# 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
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 !")
end
# creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id]))
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])
# 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)
: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)
: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)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:breakFree => BS))
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
function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end][:v]==0.0
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
(CS, drivingCourse) = addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
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")
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
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)
# 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# 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
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])
# 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
(CS, drivingCourse, formerSpeedLimits, BS, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, BS)
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
if cycle < approximationLevel+1
if drivingCourse[end][:v]<=0.0
if drivingCourse[end][:v] <= 0.0
currentStepSize = settings[:stepSize] / 10.0^cycle
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
end
elseif drivingCourse[end][:v]>CS[:v_peak]
if settings[:stepVariable]=="v in m/s"
elseif drivingCourse[end][:v] > CS[:v_peak]
if settings[:stepVariable] == "v in m/s"
currentStepSize=CS[:v_peak]-drivingCourse[end-1][:v]
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
elseif drivingCourse[end][:s]==CS[:s_exit]
elseif drivingCourse[end][:s] == CS[:s_exit]
break
elseif drivingCourse[end][:v]==CS[:v_peak]
elseif drivingCourse[end][:v] == CS[:v_peak]
break
elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
currentStepSize = settings[:stepSize] / 10.0^cycle
@ -408,20 +346,20 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
pop!(BS[:dataPoints])
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])
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",
" 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!(BS[:dataPoints])
elseif drivingCourse[end][:s]>CS[:s_exit]
drivingCourse[end][:s]=CS[:s_exit] # rounding s down to s_exit
elseif drivingCourse[end][:s] > CS[:s_exit]
drivingCourse[end][:s] = CS[:s_exit] # rounding s down to s_exit
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])
else
@ -430,16 +368,16 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
end
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
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)
: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)
: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)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
# TODO: this warning schould not be needed. just for testing
if CS[:v_peak] < drivingCourse[end][:v]
@ -457,12 +395,12 @@ end #function addAccelerationPhase!
## This function calculates the data points of the acceleration phase.
function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end][:v]==0.0
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
(CS, drivingCourse) = addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
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")
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]
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])
drivingCourse[end][:behavior] = BS[:type]
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
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel))
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
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
# 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])
# acceleration (in m/s^2):
drivingCourse[end][:a]=(drivingCourse[end][:F_T]-drivingCourse[end][:F_R])/train[:m_train]/train[:ξ_train]
# if drivingCourse[end][:a]==0.0
drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
# 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])
# end
@ -502,7 +440,7 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}
end
end
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
# 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])
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])
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?
# 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)
: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)
: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)
: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[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
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[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:acceleration=>BS))
end
@ -597,7 +535,7 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
drivingCourse[end][:behavior] = BS[:type]
# 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)
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
currentStepSize=settings[:stepSize]
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end][:s] < 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]
# 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: 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):
drivingCourse[end][:a]=0.0
drivingCourse[end][:a] = 0.0
# create the next data point
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
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"
currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1][:s]
currentStepSize=BS[:s_entry] + s_cruising-drivingCourse[end-1][:s]
else
currentStepSize = settings[:stepSize] / 10.0^cycle
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
elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
# if settings[:stepVariable] == "s in m"
@ -656,19 +594,16 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
pop!(BS[:dataPoints])
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"
else
pop!(drivingCourse)
pop!(BS[:dataPoints])
end
# 11/21 |->
elseif drivingCourse[end][:s]==BS[:s_entry]+s_cruising
elseif drivingCourse[end][:s] == BS[:s_entry]+s_cruising
break
# 11/21 ->|
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")
# 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
# 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]
drivingCourse[end][:a]=0.0 # acceleration (in m/s^2)
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)
# 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
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
# 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)
: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)
: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)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(Symbol(BS[:type]) => BS))
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})
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])
drivingCourse[end][:behavior] = BS[:type]
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
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:s]+s_braking<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])
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
# acceleration (in m/s^2):
drivingCourse[end][:a]=(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
drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type]
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])
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end][:v]<=0.0
if drivingCourse[end][:v] <= 0.0
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:s] + s_braking > CS[:s_exit]
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]
break
@ -766,7 +693,7 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::D
pop!(BS[:dataPoints])
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])
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",
@ -785,16 +712,16 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::D
end
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
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)
: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)
: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)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:diminishing=>BS))
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
# 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
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)
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
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
# traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# 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
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type]
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
@ -875,19 +802,28 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, se
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
# 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)
drivingCourse[end-1][:a]=0.0
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end-1][:v]^2)/2/train[:a_braking])
drivingCourse[end][:a] = 0.0
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
# 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]=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][:Δv]=0.0 # step size (in m/s)
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][:Δv] = 0.0 # step size (in m/s)
drivingCourse[end][:s]=drivingCourse[end-1][:s]+drivingCourse[end][:Δs] # position (in m)
drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s)
drivingCourse[end][:v]=drivingCourse[end-1][:v] # velocity (in m/s)
drivingCourse[end][:s] = drivingCourse[end-1][:s] + drivingCourse[end][:Δs] # position (in m)
drivingCourse[end][:t] = drivingCourse[end-1][:t] + drivingCourse[end][:Δt] # point in time (in s)
drivingCourse[end][:v] = drivingCourse[end-1][:v] # velocity (in m/s)
drivingCourse[end][:ΔW]=drivingCourse[end-1][:F_T]*drivingCourse[end][:Δs] # mechanical work in this step (in Ws)
# =0.0
@ -897,6 +833,7 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, se
# =0.0
drivingCourse[end][:E]=drivingCourse[end-1][:E]+drivingCourse[end][:ΔE] # energy consumption (in Ws)
# =drivingCourse[end-1][:E]
=#
else
end
@ -904,14 +841,14 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, se
end #for
# 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)
: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)
: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)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:coasting=>BS))
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)
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[:s_exit]=CS[:s_exit] # last position (in m)
BS[:s_exit] = CS[:s_exit] # last position (in m)
drivingCourse[end][:behavior] = BS[:type]
# 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
# calculate s, t, v
drivingCourse[end][:s]=BS[:s_exit] # position (in m)
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][:Δv]=drivingCourse[end][:v]-drivingCourse[end-1][:v] # step size (in m/s)
drivingCourse[end][:s] = BS[:s_exit] # position (in m)
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][:Δ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)
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
println("")
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("")
end =#
drivingCourse[end][:Δt]=drivingCourse[end][:Δv]/drivingCourse[end-1][:a] # step size (in s)
drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s)
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][:Δ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][:Δ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][:Δ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][:Δ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)
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)
:t => drivingCourse[end][:Δt], # total running time (in s)
:E => drivingCourse[end][:ΔE], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:braking=>BS))
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]
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
# traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2):
drivingCourse[end][:a]=train[:a_braking]
drivingCourse[end][:a] = train[:a_braking]
# 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
#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
velocityIsPositive=false
break
@ -1004,44 +941,43 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{Dict}, setting
drivingCourse[end][:behavior] = BS[:type]
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
if drivingCourse[end][:v] < CS[:v_exit] || !velocityIsPositive
# calculate s, t, v
drivingCourse[end][:s]=CS[:s_exit] # position (in m)
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][:Δ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][:s] = CS[:s_exit] # position (in m)
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][:Δv] = drivingCourse[end][:v] - drivingCourse[end-1][:v] # step size (in m/s)
#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
# println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1][:a] ," > ",train[:a_braking])
# end
drivingCourse[end][:Δt]=drivingCourse[end][:Δv]/drivingCourse[end-1][:a] # step size (in s)
drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s)
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][:Δ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][:Δ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][:Δ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][:Δ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)
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
end
# 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)
: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)
: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)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:braking=>BS))
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.
# 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})
if drivingCourse[end][:v] == 0.0
BS = createBehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
merge!(BS, Dict(:length => 0.0, # total length (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:s_exit => drivingCourse[end][:s], # last position (in m)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
drivingCourse[end][:behavior] = BS[:type]
@ -1111,4 +1046,4 @@ function createDataPoint()
return dataPoint
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.
# 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: 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
# include modules of TrainRunCalc
include("./MovingPhases.jl")
include("./Behavior.jl")
# use modules of TrainRunCalc
using .MovingPhases
using .Behavior
export addOperationModeEnergySaving!
@ -596,11 +597,11 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
# calculate the new and now shorter cruising section
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
# 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]
# 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
if drivingCourseModified[end][:v] > csModified[:v_exit]
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
#(csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings, train, allCSs)
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
@ -729,11 +730,11 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict},
# calculate the new and now shorter cruising section
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
# 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]
# 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
if drivingCourseModified[end][:v] > csModified[:v_exit]
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
#(csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings, train, allCSs)
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
@ -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
# 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
if drivingCourseModified[end][:v] > csModified[:v_exit]
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
(csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings, train, allCSs)
end
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
drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving
#s_braking=max(0.0, ceil((csModified[:v_exit]^2-csModified[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_braking=max(0.0, ceil((csModified[:v_exit]^2-drivingCourseModified[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_cruising=csModified[:s_exit]-drivingCourseModified[end][:s]-s_braking
s_braking = calcBrakingDistance(drivingCourseModified[end][:v], csModified[:v_exit], train[:a_braking])
s_cruising = csModified[:s_exit]-drivingCourseModified[end][:s]-s_braking
if s_cruising > 1/10^approximationLevel
# 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
# s_brakingAfterCruising=ceil((csModified[:v_exit]^2-drivingCourseModified[end][:v]^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end][:v]>csModified[:v_exit]
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
#(csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingSection!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end][:s]<csModified[:s_exit]
if (csModified[:s_exit]-drivingCourseModified[end][:s])>0.001

View File

@ -1,7 +1,7 @@
module Preparation
include("./MovingPhases.jl")
using .MovingPhases
include("./Behavior.jl")
using .Behavior
export preparateSections
@ -26,10 +26,12 @@ function createMovingSection(path::Dict, v_trainLimit::Real)
s_csStart=s_entry
csId=1
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]
push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][row-1], min(path[:sections][row-1][:v_limit], v_trainLimit)))
s_csStart=path[:sections][row][:s_start]
csId=csId+1
previousSection = path[:sections][row-1]
currentSection = path[:sections][row]
if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit)))
s_csStart = currentSection[:s_start]
csId = csId+1
end #if
end #for
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
CSs = movingSection[:characteristicSections]
csId=length(CSs)
CSs[csId][:v_exit]=0.0 # the exit velocity of the last characteristic section is 0.0 m/s
csId = length(CSs)
CSs[csId][:v_exit] = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s
while csId >= 1
v_entryMax=sqrt(CSs[csId][:v_exit]^2-2*a_braking*CSs[csId][:length])
v_entryMax=floor(v_entryMax, digits=12)
v_entryMax = calcBrakingStartVelocity(CSs[csId][:v_exit], a_braking, CSs[csId][:length])
#v_entryMax=floor(v_entryMax, digits=12)
CSs[csId][:v_entry]=min(CSs[csId][:v_limit], v_entryMax)
CSs[csId][:v_peak]=CSs[csId][:v_entry]
csId=csId-1
CSs[csId][:v_entry] = min(CSs[csId][:v_limit], v_entryMax)
CSs[csId][:v_peak] = CSs[csId][:v_entry]
csId = csId - 1
if csId >= 1
CSs[csId][:v_exit]=min(CSs[csId][:v_limit], CSs[csId+1][:v_entry])
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
CSs = movingSection[:characteristicSections]
CSs[1][:v_entry]=0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint=createDataPoint()
startingPoint[:i]=1
CSs[1][:v_entry] = 0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint = createDataPoint()
startingPoint[:i] = 1
previousCSv_exit=CSs[1][:v_entry]
previousCSv_exit = CSs[1][:v_entry]
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[:v]=CSs[csId][:v_entry]
startingPoint[:s] = CSs[csId][:s_entry]
startingPoint[:v] = CSs[csId][:v_entry]
accelerationCourse::Vector{Dict} = [startingPoint] # List of data points
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_exit] = min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end][:v])
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
CSs = movingSection[:characteristicSections]
startingPoint=createDataPoint()
startingPoint[:i]=1
startingPoint = createDataPoint()
startingPoint[:i] = 1
previousCSv_exit=CSs[1][:v_entry]
previousCSv_exit = CSs[1][:v_entry]
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[:v]=CSs[csId][:v_peak]
startingPoint[:s] = CSs[csId][:s_entry]
startingPoint[:v] = CSs[csId][:v_peak]
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][:v_exit]=min(CSs[csId][:v_exit], cruisingCourse[end][:v])
(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])
previousCSv_exit=CSs[csId][:v_exit]
previousCSv_exit = CSs[csId][:v_exit]
end #for
return movingSection

View File

@ -5,22 +5,22 @@ include("./TrainRunCalc.jl")
# include additional modules
include("./Import.jl")
include("./EnergySaving.jl")
include("./Export.jl")
# include additional modules that are not recommended to use in this state
include("./AdditionalOutput.jl")
include("./EnergySaving.jl")
# use main module TrainRunCalc
using .TrainRunCalc
# use additional modules
using .Import
using .EnergySaving
using .Export
# use additional modules that are not recommended to use in this state
using .AdditionalOutput
using .EnergySaving
# main function
export calculateDrivingDynamics,
@ -28,7 +28,7 @@ export calculateDrivingDynamics,
# import functions
importYamlFiles, importYamlFile,
# functions for saving energy
# functions for saving energy that are not recommended to use in this state
addOperationModeEnergySaving!,
# export functions
@ -38,6 +38,11 @@ exportToCsv,
plotResults, plotDrivingCourse, printImportantValues, printSectionInformation
# 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

View File

@ -3,21 +3,21 @@ module TrainRunCalc
# include modules of TrainRunCalc
include("./Input.jl")
include("./Preparation.jl")
include("./MovingPhases.jl")
include("./Behavior.jl")
include("./Output.jl")
# use modules of TrainRunCalc
using .Input
using .Preparation
using .MovingPhases
using .Behavior
using .Output
# export main function
export calculateDrivingDynamics
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`.
@ -90,15 +90,15 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
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")
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
# 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)=addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
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
# 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)
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
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
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
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"
# 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
@ -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
if drivingCourse[end][:v] > CS[:v_exit]
#(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings[:massModel], train, CSs)
(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings, train, CSs)
#(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings[:massModel], train, CSs)
(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs)
end #if
#= 09/20 old and should never be used:
@ -134,7 +134,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
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])
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 #for