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
""" """
@ -91,31 +62,29 @@ function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::V
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]
@ -152,7 +121,6 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
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.",
@ -160,25 +128,24 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
" 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]=newPoint[:Δt]*(2*previousPoint[:v]+newPoint[:Δt]*previousPoint[:a])/2 # step size (in m) newPoint[:Δs] = calc_Δs_with_Δt(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m)
newPoint[:Δv]=newPoint[:Δt]*previousPoint[:a] # step size (in m/s) newPoint[:Δv] = calc_Δv_with_Δt(newPoint[:Δs], 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]=((previousPoint[:v]+newPoint[:Δv])^2-previousPoint[:v]^2)/2/previousPoint[:a] # step size (in m) newPoint[:Δs] = calc_Δs_with_Δv(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m)
newPoint[:Δt]=newPoint[:Δv]/previousPoint[:a] # step size (in s) newPoint[:Δt] = calc_Δt_with_Δv(newPoint[:Δs], 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)
@ -226,7 +193,7 @@ 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
@ -264,7 +231,7 @@ 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
@ -274,34 +241,6 @@ function addBreakFreePhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dic
# 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
@ -354,7 +293,7 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
# 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
@ -430,7 +368,7 @@ 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)
@ -477,14 +415,14 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}
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
@ -662,12 +600,9 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
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")
@ -721,25 +656,17 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::D
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
@ -785,7 +712,7 @@ 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)
@ -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,11 +802,20 @@ 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)
@ -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
@ -943,7 +880,7 @@ function addBrakingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict,
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])
@ -1004,7 +941,7 @@ 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
@ -1014,9 +951,8 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{Dict}, setting
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]=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]=(drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs] # acceleration (in m/s^2) 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
@ -1028,7 +964,7 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{Dict}, setting
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
@ -1052,7 +988,6 @@ 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)
@ -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,9 +26,11 @@ 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]
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit)))
s_csStart = currentSection[:s_start]
csId = csId+1 csId = csId+1
end #if end #if
end #for end #for
@ -73,8 +75,8 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
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]
@ -104,7 +106,7 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train:
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]
@ -136,7 +138,7 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
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]

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