Refactor the call for adding breakFree and diminshing sections

development
Max Kannenberg 2022-03-04 02:20:33 +01:00
parent be54089917
commit 1dc6f8345a
4 changed files with 195 additions and 347 deletions

View File

@ -10,7 +10,7 @@ module Behavior
include("./DrivingDynamics.jl")
using .DrivingDynamics
export addAcceleratingSection!, addCruisingSection!, addCoastingSection!, addBrakingSection!, addStandstill!,
export addBreakFreeSection!, addAcceleratingSection!, addCruisingSection!, addDiminishingSection!, addCoastingSection!, addBrakingSection!, addStandstill!,
# addBrakingSectionInOneStep! is not used in the current version of the tool
calculateForces!, createDataPoint,
@ -92,13 +92,14 @@ function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bs
dataPoint[:F_R] = dataPoint[:R_train] + dataPoint[:R_path]
# calculate tractive effort
if bsType == "accelerating" || bsType == "diminishing"
dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train[:tractiveEffortVelocityPairs])
if bsType == "braking" || bsType == "coasting"
dataPoint[:F_T] = 0.0
elseif bsType == "cruising"
dataPoint[:F_T] = min(max(0.0, dataPoint[:F_R]), calculateTractiveEffort(dataPoint[:v], train[:tractiveEffortVelocityPairs]))
else
dataPoint[:F_T] = 0.0
else # bsType == "accelerating" || bsType == "diminishing" || 'default'
dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train[:tractiveEffortVelocityPairs])
end
return dataPoint
end #function calculateForces!
@ -168,74 +169,6 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
end #function moveAStep
"""
# if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
"""
#=
function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer, currentPoint::Dict, trainLength::Real)
formerSpeedLimits=[]
if csWithTrainHeadId > 1 && currentPoint[:s] - trainLength < CSs[csWithTrainHeadId][:s_entry]
formerCsId=csWithTrainHeadId-1
while formerCsId > 0 && currentPoint[:s] - trainLength < CSs[formerCsId][:s_exit]
if CSs[formerCsId][:v_limit] < CSs[csWithTrainHeadId][:v_limit] # TODO: is the position of train's rear < movingSection[:s_entry], v_limit of the first CS is used
push!(formerSpeedLimits, [CSs[formerCsId][:s_exit], CSs[formerCsId][:v_limit]])
for i in 1:length(formerSpeedLimits)-1
if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2]
pop!(formerSpeedLimits)
break
end
end
end
formerCsId=formerCsId-1
end
end
return formerSpeedLimits
end # function detectFormerSpeedLimits
function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, acceleratingSection::Dict)
# TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, acceleratingSection::Dict)
# would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, acceleratingSection::Dict)
if length(formerSpeedLimits) > 0
# if a former speed limit has been exceeded the accelerating steps of this CS will be removed and a clearing section will be inserted before accelerating
if drivingCourse[end][:v] > formerSpeedLimits[end][2]
while drivingCourse[end][:s] > get(CS[:behaviorSections], :clearing, acceleratingSection)[:s_entry]
pop!(drivingCourse)
end
if haskey(CS[:behaviorSections], :clearing)
CS[:t] = CS[:t]-CS[:behaviorSections][:clearing][:t] # reducing the total running time (in s)
CS[:E] = CS[:E]-CS[:behaviorSections][:clearing][:E] # reducing the total energy consumption (in Ws)
delete!(CS[:behaviorSections], :clearing)
end
# create a (new and longer) clearing section
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end][:s]-train[:length]))
if s_clearing > 0.0
(CS, drivingCourse) = addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
else
error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id])
end
# 09/22: if drivingCourse[end][:s] < CS[:s_exit]
if drivingCourse[end][:s] < CS[:s_exit] - s_braking
# reset the acceleratingSection
acceleratingSection = createBehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
else
return (CS, drivingCourse, formerSpeedLimits, acceleratingSection, true)
end
end
# remove former speed limits of characteristic sections the train has left during the last step from the list
while length(formerSpeedLimits) > 0 && drivingCourse[end][:s] - train[:length] >= formerSpeedLimits[end][1]
pop!(formerSpeedLimits)
end
end
return (CS, drivingCourse, formerSpeedLimits, acceleratingSection, false)
end # function considerFormerSpeedLimits!
=#
function considerFormerSpeedLimit!(CS::Dict, drivingCourse::Vector{Dict}, acceleratingSection::Dict, settings::Dict, train::Dict, CSs::Vector{Dict}, currentSpeedLimit::Dict)
# if a former speed limit has been exceeded the accelerating steps of this CS will be removed and a clearing section will be inserted before accelerating
if drivingCourse[end][:v] > currentSpeedLimit[:v]
@ -254,7 +187,7 @@ function considerFormerSpeedLimit!(CS::Dict, drivingCourse::Vector{Dict}, accele
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, currentSpeedLimit[:s_end] - drivingCourse[end][:s])
if s_clearing > 0.0
(CS, drivingCourse) = addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
(CS, drivingCourse, brakingStartReached) = addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
else
error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id])
end
@ -272,6 +205,9 @@ function considerFormerSpeedLimit!(CS::Dict, drivingCourse::Vector{Dict}, accele
return (CS, drivingCourse, acceleratingSection)
end # function considerFormerSpeedLimit!
"""
# if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
"""
function getCurrentSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::Real, trainLength::Real)
v_limit = CSs[csWithTrainHeadId][:v_limit]
s_exit = CSs[csWithTrainHeadId][:s_exit]
@ -301,66 +237,35 @@ end #function getNextPointOfInterest
## This function calculates the data points of the breakFree section.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed.
# Info: currently the values of the breakFree section will be calculated like in the accelerating section
function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
if settings[:stepVariable] == "v in m/s"
println("WARNING: ! ! ! TrainRun.jl doesn't work reliably for the step variable v. Therefore v should not be used ! ! !")
end
function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, ignoreBraking::Bool)
if drivingCourse[end][:v]==0.0 && drivingCourse[end][:s]<CS[:s_exit]
BS = createBehaviorSection("breakFree", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
# traction effort and resisting forces (in N):
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel]) # currently the tractive effort is calculated like in the accelerating section
# acceleration (in m/s^2):
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 section !")
elseif drivingCourse[end][:a] == 0.0
error("ERROR: a=0 m/s^2 in the breakFree section !")
# calculate the breakFree section with calculating the accelerating section and just using the first step and removing the rest
try (CS, drivingCourse, brakingStartReached) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false)
catch(acceleratingError)
println("This error happened during the break free phase that is using the accelerating function:")
rethrow(acceleratingError)
end
brokenFree = false
calculationCycle = 1
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
while !brokenFree
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id]))
drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i])
# delete every dataPoint except the first two
while drivingCourse[end][:i] > drivingCourse[BS[:dataPoints][1]][:i] +1
pop!(drivingCourse)
end
# check if a point of interest was missed
if drivingCourse[end][:s] > nextPointOfInterest
if settings[:stepVariable] == "s in m"
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
# change the accelerating data to break free
drivingCourse[end-1][:behavior] = BS[:type]
drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i])
if calculationCycle <= approximationLevel
calculationCycle = calculationCycle +1
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(BS[:dataPoints])
else
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
brokenFree = true
break#free
end
elseif drivingCourse[end][:v] > CS[:v_peak]
if settings[:stepVariable] == "v in m/s"
currentStepSize = CS[:v_peak]-drivingCourse[end-1][:v]
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
else #if drivingCourse[end][:s] == nextPointOfInterest || drivingCourse[end][:v] == CS[:v_peak]
brokenFree = true
break#free
end #if
end #while
# remove the accelerating section from the CS
CS[:t] = CS[:t] - get(CS[:behaviorSections], :accelerating, Dict(:t=>0.0))[:t] # total running time (in s)
CS[:E] = CS[:E] - get(CS[:behaviorSections], :accelerating, Dict(:E=>0.0))[:E] # total energy consumption (in Ws)
delete!(CS[:behaviorSections], :accelerating)
# calculate the accumulated breakFree section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
@ -386,33 +291,30 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
CS = CSs[csId]
drivingCourse = movingSection[:drivingCourse]=#
if drivingCourse[end][:v] == 0.0
(CS, drivingCourse) = addBreakFreeSection!(CS, drivingCourse, settings, train, CSs)
end #if
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel])
if drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
(CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel])
end
if ignoreBraking
s_braking = 0.0
else
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
# # if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
# formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length])
# conditions for accelerating section
# conditions for the accelerating section
targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak]
trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit]
tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
if ignoreBraking
s_braking = 0.0
else
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
# use the conditions for the accelerating section
if !targetSpeedReached && !trainAtEnd && tractionSurplus
BS = createBehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
brakingStartReached = false
while !targetSpeedReached && !trainAtEnd && tractionSurplus && !brakingStartReached
currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
@ -423,7 +325,8 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && drivingCourse[end][:s] +s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit
while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit
# 03/02 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && drivingCourse[end][:s] +s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit
# 02/23 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s] +s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit
if drivingCourse[end][:s] >= currentSpeedLimit[:s_end]
# could be asked after creating an data point. This way here prevents even a minimal exceedance of speed limit will be noticed. On the other hand the train cruises possibly a little to long
@ -439,37 +342,31 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i])
# if length(formerSpeedLimits) > 0 # If the rear 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
# return (CS, drivingCourse)
# end
# # TODO: do the following that was done here in addAcceleratingSection_without_Braking! ? currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections
# end
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
if !ignoreBraking
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
end
end #while
if CS[:id]==0
testFlag = true
else
testFlag = false # for testing
end
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end][:v] <= 0.0
#println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," <= 0.0") # for testing
currentStepSize = settings[:stepSize] / 10.0^cycle
# TODO 01/21 should not be needed anymore with diminishing.
elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
#println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing
if drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit]
#println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:s] > nextPointOfInterest
#println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing
if settings[:stepVariable] == "s in m"
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
else
@ -477,7 +374,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
end
elseif drivingCourse[end][:v] > CS[:v_peak]
#println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing
if settings[:stepVariable] == "v in m/s"
currentStepSize = CS[:v_peak]-drivingCourse[end-1][:v]
else
@ -485,34 +382,26 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
end
elseif drivingCourse[end][:v] > currentSpeedLimit[:v]
#if drivingCourse[end][:s] < currentSpeedLimit[:s_end]
#if drivingCourse[end][:s] - train[:length] < currentSpeedLimit[:s_end]
#println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing
(CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit)
#end
break
# TODO: think about alternative: handle the the position where the rear of the train leaves a CS similar to a POI. Then it will be calculated exactly and even a minimal exceedance of speed limit will be noticed
elseif drivingCourse[end][:s] +s_braking == CS[:s_exit]
#println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing
brakingStartReached = true
if s_braking == 0.0
trainAtEnd = true
end
break
elseif drivingCourse[end][:s] == CS[:s_exit]
#println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == s_exit=",CS[:s_exit]) # for testing
trainAtEnd = true
break
elseif drivingCourse[end][:v] == CS[:v_peak]
#println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_peak=",CS[:v_peak]) # for testing
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_peak=",CS[:v_peak]) # for testing
targetSpeedReached = true
break
elseif drivingCourse[end][:s] == nextPointOfInterest
#println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing
break
else
@ -525,23 +414,20 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(BS[:dataPoints])
brakingStartReached = false
else # if the level of approximation is reached
if drivingCourse[end][:v] <= 0.0
# 01/21 should not be needed anymore with diminishing.
# push!(BS[:dataPoints], drivingCourse[end][:i])
error("ERROR: The train stops during the accelerating section in CS",CS[:id]," between the positions ",drivingCourse[end-1][:s]," m and ",drivingCourse[end][:s]," m because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2",
" F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.")
elseif drivingCourse[end][:v] > CS[:v_peak]
if drivingCourse[end][:v] > CS[:v_peak]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing
targetSpeedReached = true
pop!(drivingCourse)
pop!(BS[:dataPoints])
brakingStartReached = false
elseif drivingCourse[end][:s] + s_braking > CS[:s_exit]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
brakingStartReached = true
if s_braking > 0.0
brakingStartReached = true
pop!(drivingCourse)
pop!(BS[:dataPoints])
else
@ -550,22 +436,24 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
end
elseif drivingCourse[end][:s] > nextPointOfInterest
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:s]," > nextPointOfInterest",nextPointOfInterest) # for testing
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing
tractionSurplus = false
(CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
elseif drivingCourse[end][:v] > currentSpeedLimit[:v]
#if drivingCourse[end][:s] - train[:length] < currentSpeedLimit[:s_end]
(CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit)
# end
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing
(CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit)
# TODO: think about alternative: handle the the position where the rear of the train leaves a CS similar to a POI. Then it will be calculated exactly and the train start accelerating immediately and not only at the next data point.
else
if drivingCourse[end][:s] + s_braking == CS[:s_exit]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," else case and there: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
brakingStartReached = true
end
end
# TODO is it possible to put this into to the if-fork?
@ -592,11 +480,11 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:accelerating => BS))
mergeBehaviorSection!(CS[:behaviorSections], BS)
end
end
return (CS, drivingCourse)
return (CS, drivingCourse, brakingStartReached)
end #function addAcceleratingSection!
@ -606,18 +494,11 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
if drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
(CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs)
# 01/08 old with DataPoint as struct: old drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]))
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking # may not work with EnergySaving when decreasing the length of cruising and adding coasting
# s_cruising = max(0.0, CS[:s_exit] - drivingCourse[end][:s] - s_braking) # may not work with EnergySaving when decreasing the length of cruising and adding coasting
# 02/25 old:s_cruising = max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(:length=>0.0))[:length])
end
if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit] && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && !brakingStartReached && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
# old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]<CS[:s_exit] && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
BS = createBehaviorSection(cruisingType, drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
@ -712,10 +593,6 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::
break
elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
tractionSurplus = false
(CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
# s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(length=>0.0))[:length])
else
@ -733,10 +610,9 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::
# calculate the remaining cruising way
#s_cruisingRemaining=BS[:s_entry] + s_cruising-drivingCourse[end][:s]
s_cruisingRemaining = nextPointOfInterest - drivingCourse[end][:s]
s_cruisingRemaining = min(nextPointOfInterest -drivingCourse[end][:s], BS[:s_entry] +s_cruising -drivingCourse[end][:s])
# create the next data point
# 02/18 old push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id]))
push!(drivingCourse, moveAStep(drivingCourse[end], "s in m", s_cruisingRemaining, CS[:id]))
drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i])
@ -744,6 +620,10 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
end #while
# TODO: realize this better inside the upper loops?
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
# calculate the accumulated cruising 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)
@ -754,10 +634,10 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(Symbol(BS[:type]) => BS))
mergeBehaviorSection!(CS[:behaviorSections], BS)
end # else: return the characteristic section without a cruising section
return (CS, drivingCourse)
return (CS, drivingCourse, brakingStartReached)
end #function addCruisingSection!
@ -769,11 +649,13 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit]
tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
# use the conditions for the diminishing section
if !tractionSurplus && !targetSpeedReached && !trainAtEnd
BS = createBehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
brakingStartReached = false
while !tractionSurplus && !targetSpeedReached && !trainAtEnd && !brakingStartReached
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
@ -781,7 +663,9 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
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 = 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][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end
#while drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:s] + s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end
#while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && drivingCourse[end][:s] + s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end
while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end
# acceleration (in m/s^2):
drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train])
@ -791,9 +675,16 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
push!(BS[:dataPoints], drivingCourse[end][:i])
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
end #while
if CS[:id]==0
testFlag = true
else
testFlag = false # for testing
end
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end][:v] < 0.0
@ -803,15 +694,15 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
currentStepSize = settings[:stepSize] / 10.0^cycle
end
elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
#println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," > F_R=",drivingCourse[end][:F_R]) # for testing
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," > F_R=",drivingCourse[end][:F_R]) # for testing
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit]
#println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:s] > nextPointOfInterest
#println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing
if settings[:stepVariable] == "s in m"
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
else
@ -819,12 +710,17 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
end
elseif drivingCourse[end][:s] + s_braking == CS[:s_exit]
#println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing
brakingStartReached = true
break
elseif drivingCourse[end][:s] == nextPointOfInterest
#println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing
break
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R]
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," == F_R=",drivingCourse[end][:F_R]) # for testing
tractionSurplus = true
break
elseif drivingCourse[end][:v] == 0.0
@ -839,9 +735,11 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(BS[:dataPoints])
brakingStartReached = false
else # if the level of approximation is reached
if drivingCourse[end][:v] <= 0.0
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: v=", drivingCourse[end][:v]," <= 0.0") # for testing
targetSpeedReached = true
# push!(BS[:dataPoints], drivingCourse[end][:i])
error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.",
@ -849,20 +747,29 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
" F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.")
elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit]
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing
brakingStartReached = true
pop!(drivingCourse)
pop!(BS[:dataPoints])
elseif drivingCourse[end][:s] > nextPointOfInterest
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
elseif drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," >= F_R=", drivingCourse[end][:F_R]) # for testing
tractionSurplus = true
break
else
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: else with v=", drivingCourse[end][:v]," > 0.0 and F_T=", drivingCourse[end][:F_T]," <= F_R=", drivingCourse[end][:F_R]) # for testing
#println(" and s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing
#println(" and s=", drivingCourse[end][:s]," <= nextPointOfInterest=",nextPointOfInterest) # for testing
if drivingCourse[end][:s] + s_braking == CS[:s_exit]
brakingStartReached = true
end
end #if
# TODO is it possible to put this into to the if-fork?
@ -884,11 +791,11 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings:
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:diminishing=>BS))
mergeBehaviorSection!(CS[:behaviorSections], BS)
end
end
return (CS, drivingCourse)
return (CS, drivingCourse, brakingStartReached)
end #function addDiminishingSection!
@ -902,11 +809,13 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit]
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
# use the conditions for the coasting section
if !targetSpeedReached && !trainAtEnd
BS = createBehaviorSection("coasting", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
brakingStartReached = false
while !targetSpeedReached && !trainAtEnd && !brakingStartReached
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
@ -914,7 +823,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di
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 = 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] && drivingCourse[end][:s] < nextPointOfInterest # as long as s_i + s_braking < s_end
while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest # as long as s_i + s_braking < s_end
# traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
@ -927,6 +836,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di
push!(BS[:dataPoints], drivingCourse[end][:i])
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
end # while
# check which limit was reached and adjust the currentStepSize for the next cycle
@ -971,6 +881,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(BS[:dataPoints])
brakingStartReached = false
else # if the level of approximation is reached
if drivingCourse[end][:v] <= 0.0
@ -1004,7 +915,9 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
else
if drivingCourse[end][:s] + s_braking == CS[:s_exit]
brakingStartReached = true
end
end
end
end #for
@ -1023,14 +936,13 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di
merge!(CS[:behaviorSections], Dict(:coasting=>BS))
end
return (CS, drivingCourse)
return (CS, drivingCourse, brakingStartReached)
end #function addCoastingSection!
## This function calculates the data points of the braking section. # 09/07 new braking section with more than two data points
## This function calculates the data points of the braking section.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
#function addBrakingSectionStepwise!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
# conditions for braking section
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit]
@ -1054,16 +966,12 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dic
# TODO or: drivingCourse[end][:a] = calcBrakingAcceleration(drivingCourse[end][:v], CS[:v_exit], CS[:s_exit]-drivingCourse[end][:s])
if settings[:stepVariable] == "s in m" && ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0
# targetSpeedReached = true
# create empty data point and set it for the values of s_exit and v_exit
push!(drivingCourse, createDataPoint())
drivingCourse[end][:i] = drivingCourse[end-1][:i]+1
drivingCourse[end][:behavior] = BS[:type]
push!(BS[:dataPoints], drivingCourse[end][:i])
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
# break
# end
else
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
@ -1082,12 +990,6 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dic
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
#=elseif drivingCourse[end][:s] > CS[:s_exit]
if settings[:stepVariable] == "s in m"
currentStepSize = CS[:s_exit] - drivingCourse[end-1][:s]
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end=#
elseif drivingCourse[end][:s] > nextPointOfInterest
if settings[:stepVariable] == "s in m"
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
@ -1210,6 +1112,20 @@ function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, t
return (CS, drivingCourse)
end #function addStandstill!
function mergeBehaviorSection!(BSs::Dict, BS::Dict)
if !haskey(BSs, Symbol(BS[:type]))
merge!(BSs, Dict(Symbol(BS[:type]) => BS))
else
number = "2"
while haskey(BSs, Symbol(BS[:type]*number))
number = string(parse(Int, number)+1)
end
merge!(BSs, Dict(Symbol(BS[:type]*number) => BS))
println("INFO: The ",number,". ",BS[:type]," section has been created. ! ! ! ! ! ! ! ! !")
end
return BSs
end #function mergeBehaviorSection!
function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
BS= Dict(#:type => behavior, # type of behavior section: breakFree, clearing, accelerating, cruising, diminishing, coasting, braking or standstill
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "standstill"

View File

@ -137,6 +137,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train:
acceleratingCourse::Vector{Dict} = [startingPoint] # List of data points
if CS[:v_entry] < CS[:v_peak]
(CS, acceleratingCourse) = addBreakFreeSection!(CS, acceleratingCourse, settings, train, CSs, true)
(CS, acceleratingCourse) = addAcceleratingSection!(CS, acceleratingCourse, settings, train, CSs, true) # this function changes the acceleratingCourse
CS[:v_peak] = max(CS[:v_entry], acceleratingCourse[end][:v])
CS[:v_exit] = min(CS[:v_exit], CS[:v_peak], acceleratingCourse[end][:v])

View File

@ -228,7 +228,8 @@ function calcBrakingDistance(v_start::Real, v_end::Real, a_braking::Real)
# 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
# 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
return max(0.0, ceil(s_braking, digits=approximationLevel +1)) # 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)
@ -238,7 +239,8 @@ function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real)
# 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)
# return floor(v_start, digits=approximationLevel)
return floor(v_start, digits=approximationLevel +1)
end #function calcBrakingStartVelocity
function calcBrakingAcceleration(v_start::Real, v_end::Real, s_braking::Real)

View File

@ -26,10 +26,6 @@ export calculateDrivingDynamics
approximationLevel = 6 # value for approximation to intersections and precisely calculated digits
# TODO: define it here and give it to each function? (Behavior, ...)
# INFO for diminishing and cruising: if v decreases to a value where F_T-F_R is positive the train could accelerate to a value of v where F_T-F_R is negative and so forth and so on. In Behavior.jl it is realized not oscillating with accelerating and diminishing but just with cruising instead of accelerating und therefore keeping the velocity value where F_T-F_R>0.
# 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`.
"""
@ -76,9 +72,14 @@ end # function calculateDrivingDynamics
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
CSs::Vector{Dict} = movingSection[:characteristicSections]
if settings[:massModel] == "homogeneous strip"
println("WARNING: ! ! ! TrainRun.jl doesn't work reliably for the mass model homogeneous strip. This mass model should not be used ! ! !")
end
startingPoint=createDataPoint()
startingPoint[:i]=1
startingPoint[:s]=CSs[1][:s_entry]
calculateForces!(startingPoint, CSs, 1, "default", train, settings[:massModel]) # traction effort and resisting forces (in N)
drivingCourse::Vector{Dict} = [startingPoint] # List of data points
for csId in 1:length(CSs)
@ -92,21 +93,48 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_entry=",CS[:v_entry])
end
if drivingCourse[end][:v] < CS[:v_peak]
(CS, drivingCourse) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false)
end #if
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
if drivingCourse[end][:v] == 0.0
(CS, drivingCourse) = addBreakFreeSection!(CS, drivingCourse, settings, train, CSs, false)
end #if
if s_cruising > 0.0 # TODO: define a minimum cruising length?
(CS, drivingCourse) = addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
end
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking == CS[:s_exit]
testFlag = false # for testing
if drivingCourse[end][:v] > CS[:v_exit]
(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs)
end #if
while !brakingStartReached && drivingCourse[end][:s] +s_braking < CS[:s_exit]
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel]) # traction effort and resisting forces (in N)
if drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
if drivingCourse[end][:v] < CS[:v_peak] - 1/10^approximationLevel * settings[:stepSize] # TODO: check if multiplying with stepSize is necessary
(CS, drivingCourse, brakingStartReached) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false)
#s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
# testFlag && println("in CS",CS[:id]," after accelerating s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing
else
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
if s_cruising > 0.0 # TODO: define a minimum cruising length?
(CS, drivingCourse, brakingStartReached) = addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
testFlag && println("in CS",CS[:id]," after cruising s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing
# TODO: add downhillBraking as a special cruising Section:
# (CS, drivingCourse, brakingStartReached) = addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "downhillBraking")
end
end #if
else
(CS, drivingCourse, brakingStartReached) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs)
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
# testFlag && println("in CS",CS[:id]," after diminishing s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing
end
end
if drivingCourse[end][:v] > CS[:v_exit]
(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs)
end #if
# for testing:
@ -127,102 +155,3 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end #function calculateMinimumRunningTime
end # module TrainRunCalc
#=
# calculate a train run focussing on using the minimum possible running time
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
CSs::Vector{Dict} = movingSection[:characteristicSections]
startingPoint=createDataPoint()
startingPoint[:i]=1
startingPoint[:s]=CSs[1][:s_entry]
drivingCourse::Vector{Dict} = [startingPoint] # List of data points
for csId in 1:length(CSs)
CS = CSs[csId]
BSs = CS[:behaviorSections]
# for testing:
if drivingCourse[end][:s] != CS[:s_entry]
println("ERROR: In CS", csId," the train run starts at s=",drivingCourse[end][:s]," and not s_entry=",CS[:s_entry])
end
if drivingCourse[end][:v] > CS[:v_entry]
println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_entry=",CS[:v_entry])
end
# check if the CS has a cruising section
s_breakFree = get(BSs, :breakFree, Dict(:length=>0.0))[:length]
s_clearing = get(BSs, :clearing, Dict(:length=>0.0))[:length]
s_accelerating = get(BSs, :accelerating, Dict(:length=>0.0))[:length]
s_braking = calcBrakingDistance(CS[:v_peak], CS[:v_exit], train[:a_braking])
# old: s_braking = max(0.0, ceil((CS[:v_exit]^2-CS[:v_peak]^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
# calculate the cruising sections length
s_cruising = max(0.0, CS[:length] - s_breakFree - s_clearing - s_accelerating - s_braking)
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
CS[:behaviorSections] = Dict()
CS[:E] = 0.0
CS[:t] = 0.0
# TODO 02/09: could there be a better structure for processing the different moving phases? (this if fork was added on 2022/09/02)
if s_clearing > 0.0 && s_breakFree + s_accelerating == 0.0
(CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
end
if s_cruising == CS[:length]
(CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
elseif s_cruising > 0.0 || s_braking == 0.0
if drivingCourse[end][:v] < CS[:v_peak]
(CS, drivingCourse) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false) # TODO or better ignoreBraking = true?
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
println("ERROR: After accelerating in CS ",csId," the braking distance is too short!")
println(" before accelerating in CS",csId, " with s=",drivingCourse[end][:s]," s_braking=",((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking])," s_exit=",CS[:s_exit])
println(" and v=",drivingCourse[end][:v]," v_peak=",CS[:v_peak]," v_exit=",CS[:v_exit])
end
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
s_cruising=CS[:s_exit]-drivingCourse[end][:s]-s_braking
if s_cruising > 0.0
(CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
end
else
if CS[:v_entry] < CS[:v_peak] || s_accelerating > 0.0 # or instead of " || s_accelerating > 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]
# old 02/22 (CS, drivingCourse)=addAcceleratingSectionUntilBraking!(CS, drivingCourse, settings, train, CSs)
(CS, drivingCourse) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false)
end #if
end #if
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
if drivingCourse[end][:v] > CS[:v_exit]
#(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings[:massModel], train, CSs)
(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs)
end #if
# for testing:
if drivingCourse[end][:s] != CS[:s_exit]
println("ERROR: In CS", csId," the train run ends at s=",drivingCourse[end][:s]," and not s_exit=",CS[:s_exit])
end
if drivingCourse[end][:v] > CS[:v_exit]
println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_exit=",CS[:v_exit])
end
end #for
(CSs[end], drivingCourse) = addStandstill!(CSs[end], drivingCourse, settings, train, CSs)
movingSection[:t] = drivingCourse[end][:t] # total running time (in s)
movingSection[:E] = drivingCourse[end][:E] # total energy consumption (in Ws)
return (movingSection, drivingCourse)
end #function calculateMinimumRunningTime
end # module TrainRunCalc
=#