Divide MovingPhases into Behavior and DrivingDynamics
parent
05c1bd8d52
commit
9ec48ec7cb
|
@ -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.")
|
||||
|
|
|
@ -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
|
||||
"""
|
||||
|
@ -91,31 +62,29 @@ function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::V
|
|||
end #while
|
||||
|
||||
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"
|
||||
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 ‰
|
||||
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_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]
|
||||
|
@ -152,7 +121,6 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
|
|||
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[: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.",
|
||||
|
@ -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.")
|
||||
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)
|
||||
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]=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)
|
||||
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]=((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[:Δ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] = 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]=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)
|
||||
|
||||
|
||||
|
@ -226,7 +193,7 @@ 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_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
|
||||
|
@ -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
|
||||
|
||||
# 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
|
||||
|
@ -274,34 +241,6 @@ function addBreakFreePhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dic
|
|||
# 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
|
||||
|
@ -354,7 +293,7 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::
|
|||
# 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
|
||||
|
@ -430,7 +368,7 @@ 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)
|
||||
: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
|
||||
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
|
||||
# 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]
|
||||
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
|
||||
|
@ -662,12 +600,9 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Re
|
|||
pop!(drivingCourse)
|
||||
pop!(BS[:dataPoints])
|
||||
end
|
||||
# 11/21 |->
|
||||
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)
|
||||
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
|
||||
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
|
||||
# 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):
|
||||
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
|
||||
|
||||
|
@ -785,7 +712,7 @@ 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)
|
||||
: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
|
||||
# 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)
|
||||
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,11 +802,20 @@ 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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
# 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])
|
||||
|
@ -1004,7 +941,7 @@ 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
|
||||
|
@ -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][:Δv] = drivingCourse[end][:v] - drivingCourse[end-1][:v] # step size (in m/s)
|
||||
|
||||
#drivingCourse[end-1][:a]=round((drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs], digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
|
||||
drivingCourse[end-1][:a]=(drivingCourse[end][:v]^2-drivingCourse[end-1][:v]^2)/2/drivingCourse[end][:Δs] # acceleration (in m/s^2)
|
||||
|
||||
#drivingCourse[end-1][:a]=round(calcBrakingAcceleration(drivingCourse[end-1][:v], drivingCourse[end][:v], drivingCourse[end][:Δs]), digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
|
||||
drivingCourse[end-1][:a] = calcBrakingAcceleration(drivingCourse[end-1][:v], drivingCourse[end][:v], drivingCourse[end][:Δs])
|
||||
# if drivingCourse[end-1][:a]<train[:a_braking] || drivingCourse[end-1][:a]>=0.0
|
||||
# println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1][:a] ," > ",train[:a_braking])
|
||||
# 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-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
|
||||
|
@ -1052,7 +988,6 @@ 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)
|
||||
|
@ -1111,4 +1046,4 @@ function createDataPoint()
|
|||
return dataPoint
|
||||
end #function createDataPoint
|
||||
|
||||
end #module MovingPhases
|
||||
end #module Behavior
|
|
@ -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
|
|
@ -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_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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Preparation
|
||||
|
||||
include("./MovingPhases.jl")
|
||||
using .MovingPhases
|
||||
include("./Behavior.jl")
|
||||
using .Behavior
|
||||
|
||||
export preparateSections
|
||||
|
||||
|
@ -26,9 +26,11 @@ 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]
|
||||
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
|
||||
|
@ -73,8 +75,8 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
|
|||
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]
|
||||
|
@ -104,7 +106,7 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train:
|
|||
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]
|
||||
|
@ -136,7 +138,7 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
|
|||
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], 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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue