Compare commits

..

No commits in common. "7d56c707c1dea4b9f40dab0524a6a14a86d661ff" and "fff168964e59504ffcf2728d7e8f2d2da4ca82f7" have entirely different histories.

5 changed files with 189 additions and 313 deletions

View File

@ -146,12 +146,12 @@ function printSectionInformation(movingSection::Dict)
CSs::Vector{Dict} = movingSection[:characteristicSections]
println("MS with length=", movingSection[:length]," with t=", movingSection[:t])
allBs=[:breakFree, :clearing, :accelerating, :clearing2, :accelerating2, :clearing3, :accelerating3, :cruising, :downhillBraking, :diminishing, :coasting, :braking, :standstill]
allBs=[:breakFree, :clearing, :accelerating, :cruising, :diminishing, :coasting, :braking, :standstill]
for csId in 1:length(CSs)
println("CS ",csId," with length=", CSs[csId][:length]," with t=", CSs[csId][:t])
for bs in 1: length(allBs)
if haskey(CSs[csId][:behaviorSections], allBs[bs])
println("BS ",allBs[bs], " with s_entry=", CSs[csId][:behaviorSections][allBs[bs]][:s_entry], " and length=",CSs[csId][:behaviorSections][allBs[bs]][:length]) # and t=", CSs[csId][:behaviorSections][allBs[bs]][:t])
println("BS ",allBs[bs], " with s_entry=", CSs[csId][:behaviorSections][allBs[bs]][:s_entry], " and t=", CSs[csId][:behaviorSections][allBs[bs]][:t])
# for point in 1:length(CSs[csId][:behaviorSections][allBs[bs]][:dataPoints])
# println(CSs[csId][:behaviorSections][allBs[bs]][:dataPoints][point])
# end

View File

@ -10,7 +10,7 @@ module Behavior
include("./DrivingDynamics.jl")
using .DrivingDynamics
export addBreakFreeSection!, addClearingSection!, addAcceleratingSection!, addCruisingSection!, addDiminishingSection!, addCoastingSection!, addBrakingSection!, addStandstill!,
export addBreakFreeSection!, addAcceleratingSection!, addCruisingSection!, addDiminishingSection!, addCoastingSection!, addBrakingSection!, addStandstill!,
# addBrakingSectionInOneStep! is not used in the current version of the tool
calculateForces!, createDataPoint,
@ -171,6 +171,43 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs
return newPoint
end #function moveAStep
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]
# delete existing clearing section that is not long enough
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, currentSpeedLimit[:s_end] - drivingCourse[end][:s])
if s_clearing > 0.0
(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
calculateForces!(drivingCourse[end], CSs, CS[:id], acceleratingSection[:type], train, settings[:massModel])
# reset the acceleratingSection
acceleratingSection = createBehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
if drivingCourse[end][:s] + s_braking >= CS[:s_exit]
CS[:v_peak] = drivingCourse[end][:v]
end
end
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
"""
@ -203,12 +240,12 @@ 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}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, ignoreBraking::Bool)
# conditions for the break free section
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached]
targetPositionReached = drivingCourse[end][:s] >= CS[:s_exit]
trainIsHalting = drivingCourse[end][:v] == 0.0
if trainIsHalting && !endOfCSReached
if trainIsHalting && !targetPositionReached
BS = createBehaviorSection("breakFree", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
@ -216,7 +253,7 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel]) # currently the tractive effort is calculated like in the accelerating section
# calculate the breakFree section with calculating the accelerating section and just using the first step and removing the rest
try (CS, drivingCourse, stateFlags) = addAcceleratingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
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)
@ -249,97 +286,41 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:
merge!(CS[:behaviorSections], Dict(:breakFree => BS))
end # else: return the characteristic section without a breakFree section
# determine state flags
if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics]
s_braking = 0.0
else
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
# reset state flags
stateFlags[:endOfCSReached] = drivingCourse[end][:s] >= CS[:s_exit]
stateFlags[:brakingStartReached] = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
stateFlags[:tractionDeficit] = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] # or add another flag for equal forces?
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
stateFlags[:previousSpeedLimitReached] = false
stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_limit]
stateFlags[:error] = !(stateFlags[:endOfCSReached] || stateFlags[:brakingStartReached] || stateFlags[:tractionDeficit] || stateFlags[:previousSpeedLimitReached] || stateFlags[:speedLimitReached])
return (CS, drivingCourse, stateFlags)
return (CS, drivingCourse)
end #function addBreakFreeSection!
## This function calculates the data points of the clearing section.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the clearing section.
function addClearingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
if stateFlags[:previousSpeedLimitReached]
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train[:length])
if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics]
ignoreBraking = true
s_braking = 0.0
else
ignoreBraking = false
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, currentSpeedLimit[:s_end] - drivingCourse[end][:s])
if s_clearing > 0.0
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_clearing, settings, train, CSs, "clearing")
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel])
# stateFlags[:brakingStartReached] = brakingStartReached
# stateFlags[:endOfCSReached] = stateFlags[:endOfCSReached] || drivingCourse[end][:s] == CS[:s_exit]
else
error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id])
end
#stateFlags[:previousSpeedLimitReached] = false
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train[:length])
stateFlags[:previousSpeedLimitReached] = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v]
else
stateFlags[:error] = true
end
return (CS, drivingCourse, stateFlags)
end #function addClearingSection
## This function calculates the data points of the accelerating section.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the accelerating section
function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
#function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, ignoreBraking::Bool)
#=if drivingCourse would also be part of movingSectiong: function addAcceleratingSection!(movingSection::Dict, stateFlags::Dict, csId::Integer, settings::Dict, train::Dict)
function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, ignoreBraking::Bool)
#=if drivingCourse would also be part of movingSectiong: function addAcceleratingSection!(movingSection::Dict, csId::Integer, settings::Dict, train::Dict, ignoreBraking::Bool)
CSs = movingSection[:characteristicSections]
CS = CSs[csId]
drivingCourse = movingSection[:drivingCourse]=#
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel])
if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics]
ignoreBraking = true
if ignoreBraking
s_braking = 0.0
else
ignoreBraking = false
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
# conditions for the accelerating section
targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak] || stateFlags[:speedLimitReached]
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached]
targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak]
targetPositionReached = drivingCourse[end][:s] >= CS[:s_exit]
tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] || stateFlags[:brakingStartReached]
previousSpeedLimitReached = stateFlags[:previousSpeedLimitReached]
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
# use the conditions for the accelerating section
if !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached
if !targetSpeedReached && !targetPositionReached && tractionSurplus && !brakingStartReached
BS = createBehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train[:length])
previousSpeedLimitReached = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v]
speedLimitReached = drivingCourse[end][:v] >= CS[:v_limit]
#speedLimitReached = drivingCourse[end][:v] > currentSpeedLimit[:v]
speedLimitReached = drivingCourse[end][:v] > currentSpeedLimit[:v]
#targetSpeedReached = speedLimitReached
while !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached && !previousSpeedLimitReached
while !targetSpeedReached && !targetPositionReached && tractionSurplus && !brakingStartReached
currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
@ -349,7 +330,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
while !targetSpeedReached && !speedLimitReached && !brakingStartReached && !pointOfInterestReached && tractionSurplus && !previousSpeedLimitReached
while !targetSpeedReached && !speedLimitReached && !brakingStartReached && !pointOfInterestReached && tractionSurplus
# 03/08 old: 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
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
@ -371,8 +352,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
speedLimitReached = drivingCourse[end][:v] > CS[:v_limit]
previousSpeedLimitReached = currentSpeedLimit[:v] < CS[:v_limit] && (drivingCourse[end][:v] > currentSpeedLimit[:v] || (drivingCourse[end][:v] == currentSpeedLimit[:v] && drivingCourse[end][:s] < currentSpeedLimit[:s_end]))
speedLimitReached = drivingCourse[end][:v] > currentSpeedLimit[:v]
targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak]
#targetSpeedReached = speedLimitReached
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest # POIs include s_exit as well
@ -413,32 +393,36 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
elseif drivingCourse[end][:v] > currentSpeedLimit[:v]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing
if settings[:stepVariable] == "v in m/s"
currentStepSize = currentSpeedLimit[:v]-drivingCourse[end-1][:v]
else
currentStepSize = settings[:stepSize] / 10.0^cycle
(CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit)
# conditions for the next for cycle
if !ignoreBraking
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
end
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
speedLimitReached = false
targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak]
#targetSpeedReached = speedLimitReached
tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
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]
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
if s_braking == 0.0
endOfCSReached = true
targetPositionReached = true
end
break
elseif 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
break
elseif drivingCourse[end][:v] == currentSpeedLimit[:v] && drivingCourse[end][:s] < currentSpeedLimit[:s_end]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_limitCurrent=",currentSpeedLimit[:v]) # for testing
# targetSpeedReached = true
break
elseif drivingCourse[end][:s] == nextPointOfInterest
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing
if nextPointOfInterest == CS[:s_exit]
endOfCSReached = true
targetPositionReached = true
end
break
@ -455,67 +439,63 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
# conditions for the next for cycle
brakingStartReached = false
previousSpeedLimitReached = false
speedLimitReached = false
targetSpeedReached = false
endOfCSReached = false
targetPositionReached = false
pointOfInterestReached = false
tractionSurplus = true
else # if the level of approximation is reached
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])
# conditions for the next section
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
pop!(drivingCourse)
pop!(BS[:dataPoints])
else
drivingCourse[end][:s] = CS[:s_exit] # round s down to CS[:s_exit]
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
end
elseif drivingCourse[end][:s] > nextPointOfInterest
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing
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
elseif drivingCourse[end][:v] > currentSpeedLimit[:v]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing
previousSpeedLimitReached = true
(CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit)
speedLimitReached = false
pop!(drivingCourse)
pop!(BS[:dataPoints])
# 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
elseif drivingCourse[end][:v] == currentSpeedLimit[:v]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_limitCurrent=",currentSpeedLimit[:v]) # for testing
end
end
# TODO is it possible to put this into to the if-fork?
if drivingCourse[end][:s] == CS[:s_exit]
endOfCSReached = true
targetPositionReached = true
end
end
end #for
if drivingCourse[end][:s] == CS[:s_exit]
endOfCSReached = true
targetPositionReached = true
end
end #while
@ -528,7 +508,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
:E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
# 03/10 old: CS[:v_peak] = max(drivingCourse[end][:v], CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when running on a path with high resistances
CS[:v_peak] = max(drivingCourse[end][:v], CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when running on a path with high resistances
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws)
@ -536,38 +516,26 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
end
end
# set state flags
stateFlags[:endOfCSReached] = endOfCSReached
stateFlags[:brakingStartReached] = brakingStartReached
stateFlags[:tractionDeficit] = !(tractionSurplus || drivingCourse[end][:F_T] == drivingCourse[end][:F_R]) # or add another flag for equal forces?
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
stateFlags[:previousSpeedLimitReached] = previousSpeedLimitReached
stateFlags[:speedLimitReached] = targetSpeedReached
stateFlags[:error] = !(endOfCSReached || brakingStartReached || stateFlags[:tractionDeficit] || previousSpeedLimitReached || targetSpeedReached)
return (CS, drivingCourse, stateFlags)
return (CS, drivingCourse, brakingStartReached)
end #function addAcceleratingSection!
## This function calculates the data points of the cruising section.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed.
function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String)
function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String)
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])
# conditions for cruising section
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] || stateFlags[:brakingStartReached]
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
speedIsValid = drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak]
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
targetPositionReached = s_cruising == 0.0
tractionSurplus = drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
if speedIsValid && !brakingStartReached && !tractionDeficit && !targetPositionReached
# 03/04 old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && !brakingStartReached && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
if speedIsValid && !brakingStartReached && tractionSurplus
# 03/04 old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && !brakingStartReached && 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]
trainIsClearing = BS[:type] == "clearing"
trainIsBrakingDownhill = BS[:type] == "downhillBraking"
# TODO: necessary?
s_cruising = min(s_cruising, CS[:s_exit]-BS[:s_entry])
@ -579,16 +547,14 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# conditions for cruising section
trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train[:length]
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising
resistingForceNegative = drivingCourse[end][:F_R] < 0.0
# TODO: change? to correctCruisingType = (trainIsClearing || (trainIsBrakingDownhill == drivingCourse[end][:F_R] < 0)) # while clearing tractive or braking force can be used
# use the conditions for the cruising section
while trainInPreviousCS && !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
while trainInPreviousCS && !targetPositionReached && tractionSurplus
currentStepSize = settings[:stepSize]
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while trainInPreviousCS && targetPositionReached && !pointOfInterestReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
while trainInPreviousCS && targetPositionReached && !pointOfInterestReached && tractionSurplus
# 03/09 old: while drivingCourse[end][:s] < CS[:s_entry] + train[:length] && drivingCourse[end][:s] < BS[:s_entry] +s_cruising && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R]
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance?
@ -610,10 +576,9 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# conditions for the next while cycle
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest # POIs include s_exit as well
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
tractionSurplus = drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising
trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train[:length]
resistingForceNegative = drivingCourse[end][:F_R] < 0.0
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
@ -621,9 +586,6 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
if drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:F_R] < 0.0
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end][:s] > nextPointOfInterest
if settings[:stepVariable] == "s in m"
currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s]
@ -657,7 +619,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# conditions for the next for cycle
pointOfInterestReached = false
tractionDeficit = false
tractionSurplus = true
targetPositionReached = false
trainInPreviousCS = true
@ -674,8 +636,6 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
break
elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
break
elseif drivingCourse[end][:F_R] < 0.0
break
else
end
@ -686,10 +646,9 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# conditions for the next while cycle
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
resistingForceNegative = drivingCourse[end][:F_R] < 0.0
tractionSurplus = drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
while !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
while !targetPositionReached && tractionSurplus
# 03/09 old: while drivingCourse[end][:s] < BS[:s_entry]+s_cruising && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
nextPointOfInterest = min(BS[:s_entry]+s_cruising, getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]))
drivingCourse[end][:a] = 0.0 # acceleration (in m/s^2)
@ -707,8 +666,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# conditions for the next while cycle
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
resistingForceNegative = drivingCourse[end][:F_R] < 0
tractionSurplus = drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
end #while
# TODO: realize this better inside the upper loops?
@ -728,43 +686,33 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
mergeBehaviorSection!(CS[:behaviorSections], BS)
end # else: return the characteristic section without a cruising section
# set state flags
stateFlags[:endOfCSReached] = drivingCourse[end][:s] == CS[:s_exit]
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
stateFlags[:brakingStartReached] = brakingStartReached || drivingCourse[end][:s] + s_braking >= CS[:s_exit]
stateFlags[:tractionDeficit] = tractionDeficit
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0.0
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train[:length])
stateFlags[:previousSpeedLimitReached] = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v]
stateFlags[:error] = !(targetPositionReached || tractionDeficit || !(cruisingType == "clearing" || ((cruisingType == "downhillBraking") == resistingForceNegative)))
return (CS, drivingCourse, stateFlags)
return (CS, drivingCourse, brakingStartReached)
end #function addCruisingSection!
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower
function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
calculateForces!(drivingCourse[end], CSs, CS[:id], "diminishing", train, settings[:massModel])
# conditions for diminishing section
targetSpeedReached = drivingCourse[end][:v] <= 0.0
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached]
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] #|| stateFlags[:tractionDeficit]
targetPositionReached = 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] || stateFlags[:brakingStartReached]
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
# use the conditions for the diminishing section
if tractionDeficit && !targetSpeedReached && !endOfCSReached
if !tractionSurplus && !targetSpeedReached && !targetPositionReached
BS = createBehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached
while !tractionSurplus && !targetSpeedReached && !targetPositionReached && !brakingStartReached
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while tractionDeficit && !brakingStartReached && !pointOfInterestReached && !targetSpeedReached
while !tractionSurplus && !brakingStartReached && !pointOfInterestReached && !targetSpeedReached
# 03/09 old: 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])
@ -781,7 +729,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
targetSpeedReached = drivingCourse[end][:v] <= 0.0
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
tractionSurplus = drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
end #while
if CS[:id]==0
@ -842,7 +790,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
brakingStartReached = false
pointOfInterestReached = false
targetSpeedReached = false
tractionDeficit = true
tractionSurplus = false
else # if the level of approximation is reached
if drivingCourse[end][:v] <= 0.0
@ -859,7 +807,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
pointOfInterestReached = false
targetSpeedReached = false
tractionDeficit = true
tractionSurplus = false
elseif drivingCourse[end][:s] > nextPointOfInterest
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing
@ -882,7 +830,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
# TODO is it possible to put this into to the if-fork?
if drivingCourse[end][:s] == CS[:s_exit]
endOfCSReached = true
targetPositionReached = true
end
end #if
end #for
@ -903,37 +851,29 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
end
end
# set state flags
stateFlags[:endOfCSReached] = endOfCSReached
stateFlags[:brakingStartReached] = brakingStartReached
stateFlags[:tractionDeficit] = tractionDeficit
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_exit]
stateFlags[:error] = !(endOfCSReached || brakingStartReached || !tractionDeficit)
return (CS, drivingCourse, stateFlags)
return (CS, drivingCourse, brakingStartReached)
end #function addDiminishingSection!
## This function calculates the data points of the coasting section.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
# TODO: 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
# with getCurrentSpeedLimit
# conditions for coasting section
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached]
targetPositionReached = 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] || stateFlags[:brakingStartReached]
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit]
# use the conditions for the coasting section
if !targetSpeedReached && !endOfCSReached
if !targetSpeedReached && !targetPositionReached
BS = createBehaviorSection("coasting", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
while !targetSpeedReached && !endOfCSReached && !brakingStartReached
while !targetSpeedReached && !targetPositionReached && !brakingStartReached
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
@ -1027,20 +967,20 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle
brakingStartReached = false
pointOfInterestReached = false
targetSpeedReached = false
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])
# conditions for the next for cycle
brakingStartReached = false
pointOfInterestReached = false
targetSpeedReached = true
# 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][: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])
elseif drivingCourse[end][:s] > nextPointOfInterest
drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest
@ -1052,8 +992,6 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
end #for
end #while
stateFlags[:speedLimitReached] = false
# calculate the accumulated coasting 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)
@ -1067,36 +1005,29 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
merge!(CS[:behaviorSections], Dict(:coasting=>BS))
end
# set state flags
stateFlags[:endOfCSReached] = endOfCSReached
stateFlags[:brakingStartReached] = brakingStartReached
stateFlags[:tractionDeficit] = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
stateFlags[:error] = !(endOfCSReached || brakingStartReached || stateFlags[:tractionDeficit] || previousSpeedLimitReached || targetSpeedReached)
return (CS, drivingCourse, stateFlags)
return (CS, drivingCourse, brakingStartReached)
end #function addCoastingSection!
## 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}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict})
function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict})
# conditions for braking section
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached]
targetPositionReached = drivingCourse[end][:s] >= CS[:s_exit]
# use the conditions for the braking section
if !targetSpeedReached && !endOfCSReached
if !targetSpeedReached && !targetPositionReached
BS = createBehaviorSection("braking", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
drivingCourse[end][:behavior] = BS[:type]
while !targetSpeedReached && !endOfCSReached
while !targetSpeedReached && !targetPositionReached
currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while !targetSpeedReached && !endOfCSReached && !pointOfInterestReached
while !targetSpeedReached && !targetPositionReached && !pointOfInterestReached
# 03/09 old: while drivingCourse[end][:v] > CS[:v_exit] && !targetSpeedReached && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest
# traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel])
@ -1122,7 +1053,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
# conditions for the next while cycle
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest
endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit]
targetPositionReached = drivingCourse[end][:s] >= CS[:s_exit]
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
end # while
@ -1145,7 +1076,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
break
elseif drivingCourse[end][:v] == CS[:v_exit]
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
endOfCSReached = true
targetPositionReached = true
# println(" with a=", drivingCourse[end-1][:a]) # for testing
break
elseif drivingCourse[end][:s] == CS[:s_exit]
@ -1164,7 +1095,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
# conditions for the next for cycle
pointOfInterestReached = false
endOfCSReached = false
targetPositionReached = false
targetSpeedReached = false
else # if the level of approximation is reached
@ -1173,7 +1104,8 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
# reset last point with setting v=v_exit
# println("during braking section in CS",CS[:id],": rounding v up from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], 0.0)
endOfCSReached = true
targetPositionReached = true
# println(" with a=", drivingCourse[end-1][:a]) # for testing
break
elseif drivingCourse[end][:s] > CS[:s_exit]
# println("during braking section in CS",CS[:id],": rounding s down from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
@ -1190,17 +1122,20 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
# reset last point with setting v=v_exit
# println("during braking section in CS",CS[:id],": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
endOfCSReached = true
targetPositionReached = true
# println(" with a=", drivingCourse[end-1][:a]) # for testing
break
elseif drivingCourse[end][:v] == CS[:v_exit]
# println("during braking section in CS",CS[:id],": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
endOfCSReached = true
targetPositionReached = true
# println(" with a=", drivingCourse[end-1][:a]) # for testing
break
elseif drivingCourse[end][:s] == CS[:s_exit]
# println("during braking section in CS",CS[:id],": rounding v down from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
targetSpeedReached = true
# println(" with a=", drivingCourse[end-1][:a]) # for testing
break
else
# do nothing for example for drivingCourse[end][:s]==nextPointOfInterest
@ -1222,16 +1157,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
merge!(CS[:behaviorSections], Dict(:braking=>BS))
end # else: return the characteristic section without a braking section
# set state flags
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train[:length])
stateFlags[:previousSpeedLimitReached] = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v]
stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_exit]
stateFlags[:endOfCSReached] = endOfCSReached
stateFlags[:error] = !(endOfCSReached)
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel])
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
return (CS, drivingCourse, stateFlags)
return (CS, drivingCourse)
end #function addBrakingSection!
@ -1264,14 +1190,14 @@ function mergeBehaviorSection!(BSs::Dict, BS::Dict)
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. ! ! ! ! ! ! ! ! !")
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", "downhillBraking", "diminishing", "coasting", "braking" or "standstill"
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "standstill"
:length => 0.0, # total length (in m)
:s_entry => s_entry, # first position (in m)
:s_exit => 0.0, # last position (in m)

View File

@ -10,17 +10,17 @@ module Characteristics
include("./Behavior.jl")
using .Behavior
export determineCharacteristics
export preparateSections
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior
function determineCharacteristics(path::Dict, train::Dict, settings::Dict)
function preparateSections(path::Dict, train::Dict, settings::Dict)
movingSection = createMovingSection(path, train[:v_limit])
movingSection = secureBrakingBehavior!(movingSection, train[:a_braking])
movingSection = secureAcceleratingBehavior!(movingSection, settings, train)
movingSection = secureCruisingBehavior!(movingSection, settings, train)
return movingSection
end #function determineCharacteristics
end #function preparateSections
## create a moving section containing characteristic sections
function createMovingSection(path::Dict, v_trainLimit::Real)
@ -134,31 +134,14 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train:
previousCSv_exit = CSs[1][:v_entry]
for CS in CSs
CS[:v_entry] = min(CS[:v_entry], previousCSv_exit)
startingPoint[:s] = CS[:s_entry]
startingPoint[:v] = CS[:v_entry]
calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings[:massModel]) # traction effort and resisting forces (in N)
acceleratingCourse::Vector{Dict} = [startingPoint] # List of data points
if CS[:v_entry] < CS[:v_peak]
# conditions for entering the accelerating phase
stateFlags = Dict(:endOfCSReached => false,
:brakingStartReached => false,
:tractionDeficit => false,
:resistingForceNegative => false,
:previousSpeedLimitReached => false,
:speedLimitReached => false,
:error => false,
:usedForDefiningCharacteristics => true) # because usedForDefiningCharacteristics == true the braking distance will be ignored during securing the accelerating phase
(CS, acceleratingCourse, stateFlags) = addBreakFreeSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs)
while !stateFlags[:speedLimitReached] && !stateFlags[:endOfCSReached] && !stateFlags[:tractionDeficit]
if !stateFlags[:previousSpeedLimitReached]
(CS, acceleratingCourse, stateFlags) = addAcceleratingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function changes the acceleratingCourse
elseif stateFlags[:previousSpeedLimitReached]
(CS, acceleratingCourse, stateFlags) = addClearingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs)
end
end
(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])
else #CS[:v_entry] == CS[:v_peak]
@ -171,7 +154,6 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train:
CS[:behaviorSections] = Dict()
CS[:E] = 0.0
CS[:t] = 0.0
end #for
return movingSection
@ -190,23 +172,13 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
previousCSv_exit = CSs[1][:v_entry]
for CS in CSs
# conditions for entering the cruising phase
stateFlags = Dict(:endOfCSReached => false,
:brakingStartReached => false,
:tractionDeficit => false,
:resistingForceNegative => false,
:previousSpeedLimitReached => false,
:speedLimitReached => false,
:error => false,
:usedForDefiningCharacteristics => true) # currently only used during the definition of the accelerating characteristics
CS[:v_entry] = min(CS[:v_entry], previousCSv_exit)
startingPoint[:s] = CS[:s_entry]
startingPoint[:v] = CS[:v_peak]
cruisingCourse::Vector{Dict} = [startingPoint] # List of data points
(CS, cruisingCourse, stateFlags) = addCruisingSection!(CS, cruisingCourse, stateFlags, CS[:length], settings, train, CSs, "cruising") # this function changes the cruisingCourse
(CS, cruisingCourse) = addCruisingSection!(CS, cruisingCourse, CS[:length], settings, train, CSs, "cruising") # this function changes the cruisingCourse
CS[:v_exit] = min(CS[:v_exit], cruisingCourse[end][:v])
previousCSv_exit = CS[:v_exit]

View File

@ -12,7 +12,6 @@
# 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?
# TODO from 2022/01/22: use always copyCharacteristicSection and don't do it manually like "csModified=Dict(:id => csOriginal[:id], ..." three times
# TODO from 2022/03/18: stateFlags need to be added to functions that add behavior sections
module EnergySaving
@ -183,7 +182,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
# update all the data point references in the behaviour sections of the following characteristic sections and the other modified characteristic sections
if difference!= 0
# update the data point references in the behaviour sections of the following characteristic sections
allBs=[:breakFree, :clearing, :accelerating, :cruising, :downhillBraking, :diminishing, :coasting, :braking, :standstill]
allBs=[:breakFree, :clearing, :accelerating, :cruising, :diminishing, :coasting, :braking, :standstill]
for csId in csIdMax+1:length(CSsOrig)
for bs in 1: length(allBs)
if haskey(CSsOrig[csId][:behaviorSections], allBs[bs])
@ -264,7 +263,7 @@ function copyMovingSection(original::Dict)
end #function copyMovingSection
function copyCharacteristicSection(originalCS::Dict)
allBs=[:breakFree, :clearing, :accelerating, :cruising, :downhillBraking, :diminishing, :coasting, :braking, :standstill]
allBs=[:breakFree, :clearing, :accelerating, :cruising, :diminishing, :coasting, :braking, :standstill]
copiedBSs = Dict()
for bs in 1: length(allBs)
if haskey(originalCS[:behaviorSections], allBs[bs])
@ -321,7 +320,7 @@ function createEnergySavingModification()
end #createEnergySavingModification
function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{Dict}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
allBs=[:breakFree, :clearing, :accelerating, :cruising, :downhillBraking, :diminishing, :coasting, :braking, :standstill]
allBs=[:breakFree, :clearing, :accelerating, :cruising, :diminishing, :coasting, :braking, :standstill]
difference = endOfModificationId-lastIdOfSelectedCsOriginal
for modNr in csIdMax+1:length(energySavingModifications)
if energySavingModifications[modNr][:ratio]>0

View File

@ -51,7 +51,7 @@ function calculateDrivingDynamics(trainInput::Dict, pathInput::Dict, settingsInp
println("The input has been checked.")
# prepare the input data
movingSection = determineCharacteristics(path, train, settings)
movingSection = preparateSections(path, train, settings)
println("The moving section has been prepared.")
# calculate the train run for oparation mode "minimum running time"
@ -84,6 +84,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
for csId in 1:length(CSs)
CS = CSs[csId]
# 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])
@ -92,75 +93,53 @@ 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
# determine the different flags for switching between the states for creatinge moving phases
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel]) # tractive effort and resisting forces (in N)
if drivingCourse[end][:v] == 0.0
(CS, drivingCourse) = addBreakFreeSection!(CS, drivingCourse, settings, train, CSs, false)
end #if
previousSpeedLimitReached = false
stateFlags = Dict(:endOfCSReached => drivingCourse[end][:s] > CS[:s_exit],
:brakingStartReached => drivingCourse[end][:s] + s_braking == CS[:s_exit],
:tractionDeficit => drivingCourse[end][:F_T] < drivingCourse[end][:F_R], # or add another flag for equal forces?
:resistingForceNegative => drivingCourse[end][:F_R] < 0.0,
:previousSpeedLimitReached => false, #speedLimitReached, # check already at this position?
:speedLimitReached => drivingCourse[end][:v] > CS[:v_limit],
:error => false)
# determine the behavior sections for this characteristic section. It has to be at least one of those BS: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "standstill")
while !stateFlags[:endOfCSReached] # s < s_exit
if !stateFlags[:brakingStartReached] # s+s_braking < s_exit
if !stateFlags[:tractionDeficit]
if drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && drivingCourse[end][:v] == 0.0
(CS, drivingCourse, stateFlags) = addBreakFreeSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
brakingStartReached = drivingCourse[end][:s] + s_braking == CS[:s_exit]
drivingCourse[end][:s] + s_braking > CS[:s_exit] && error("ERROR: In CS", csId,": s +s_braking=", drivingCourse[end][:s],",+",s_braking," > ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit])
testFlag = false # for testing
elseif stateFlags[:previousSpeedLimitReached]
(CS, drivingCourse, stateFlags) = addClearingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
while !brakingStartReached
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel]) # traction effort and resisting forces (in N)
elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached] # v < v_limit
(CS, drivingCourse, stateFlags) = addAcceleratingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
elseif drivingCourse[end][:F_R] < 0 && stateFlags[:speedLimitReached] # v < v_limit
if settings[:massModel] == "mass point"
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
elseif settings[:massModel] == "homogeneous strip"
# TODO: Add downhillBraking for homogeneous strip
error("Add downhillBraking for homogeneous strip !")
# cruise until F_R >= 0.0
end
if s_cruising > 0.0 # TODO: define a minimum cruising length?
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "downhillBraking")
else
stateFlags[:brakingStartReached] = true
end
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] || stateFlags[:speedLimitReached]
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)
# 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, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising")
else
stateFlags[:brakingStartReached] = true
end
else
error()
end
elseif stateFlags[:tractionDeficit]
(CS, drivingCourse, stateFlags) = addDiminishingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
(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
error()
(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
s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking])
if drivingCourse[end][:s] +s_braking == CS[:s_exit]
brakingStartReached = true
end
else#if !stateFlags[:endOfCSReached] # s < s_exit
(CS, drivingCourse, stateFlags) = addBrakingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
#else
# error()
end
end
#if s == s_exit
# standstill
#end
if drivingCourse[end][:v] > CS[:v_exit]
(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs)
end #if
# for testing: