Merge pull request #22 from railtoolkit/development_max

Development max
master
Martin Scheidt 2022-08-09 15:43:57 +02:00 committed by GitHub
commit b8578ae49c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 236 additions and 396 deletions

View File

@ -46,15 +46,15 @@ xxx.xx # in seconds
""" """
function trainrun(train::Train, path::Path, settings=Settings()::Settings) function trainrun(train::Train, path::Path, settings=Settings()::Settings)
# prepare the input data # prepare the input data
movingSection = determineCharacteristics(path, train, settings) (characteristicSections, pointsOfInterest) = determineCharacteristics(path, train, settings)
# settings.outputDetail == :verbose && println("The moving section has been prepared.") # TODO settings.outputDetail == :verbose && println("The characteristics haven been determined.")
# calculate the train run for oparation mode "minimum running time" # calculate the train run with the minimum running time
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train) (characteristicSections, drivingCourse) = calculateMinimumRunningTime!(characteristicSections, settings, train)
# settings.outputDetail == :verbose && println("The driving course for the shortest running time has been calculated.") # TODO settings.outputDetail == :verbose && println("The driving course for the shortest running time has been calculated.")
# accumulate data and create an output dictionary # accumulate data and create an output dictionary
output = createOutput(settings, drivingCourse, movingSection[:pointsOfInterest]) output = createOutput(settings, drivingCourse, pointsOfInterest)
return output return output
end # function trainrun end # function trainrun

View File

@ -4,8 +4,8 @@
# __copyright__ = "2020-2022" # __copyright__ = "2020-2022"
# __license__ = "ISC" # __license__ = "ISC"
## This function calculates the data points of the breakFree section. ## This function calculates the support 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. # Therefore it gets its first support 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 # 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::Settings, train::Train, CSs::Vector{Dict}) function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict})
# conditions for the break free section # conditions for the break free section
@ -13,8 +13,9 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:
trainIsHalting = drivingCourse[end][:v] == 0.0 trainIsHalting = drivingCourse[end][:v] == 0.0
if trainIsHalting && !endOfCSReached if trainIsHalting && !endOfCSReached
BS = BehaviorSection("breakFree", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingMode = "breakFree"
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
startingPoint = drivingCourse[end][:i]
# 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 calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel) # currently the tractive effort is calculated like in the accelerating section
@ -26,29 +27,14 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:
rethrow(acceleratingError) rethrow(acceleratingError)
end end
# delete every dataPoint except the first two # delete every supportPoint except the first two
while drivingCourse[end][:i] > drivingCourse[BS[:dataPoints][1]][:i] +1 while drivingCourse[end][:i] > startingPoint +1
pop!(drivingCourse) pop!(drivingCourse)
end end
# change the accelerating data to break free # change the accelerating data to break free
drivingCourse[end-1][:behavior] = BS[:type] drivingCourse[end-1][:behavior] = drivingMode
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
push!(BS[:dataPoints], drivingCourse[end][:i])
# 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)
delete!(CS[:behaviorSections], :accelerating)
# calculate the accumulated breakFree 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)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
merge!(CS[:behaviorSections], Dict(:breakFree => BS))
end # else: return the characteristic section without a breakFree section end # else: return the characteristic section without a breakFree section
# determine state flags # determine state flags
@ -71,7 +57,7 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:
return (CS, drivingCourse, stateFlags) return (CS, drivingCourse, stateFlags)
end #function addBreakFreeSection! end #function addBreakFreeSection!
## This function calculates the data points of the clearing section. ## This function calculates the support 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. # 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::Settings, train::Train, CSs::Vector{Dict}) function addClearingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict})
if stateFlags[:previousSpeedLimitReached] if stateFlags[:previousSpeedLimitReached]
@ -104,14 +90,11 @@ function addClearingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
return (CS, drivingCourse, stateFlags) return (CS, drivingCourse, stateFlags)
end #function addClearingSection end #function addClearingSection
## This function calculates the data points of the accelerating section. ## This function calculates the support 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 # 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::Settings, train::Train, CSs::Vector{Dict}) function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict})
#function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Settings, train::Train, CSs::Vector{Dict}, ignoreBraking::Bool) #= TODO: instead of CS just give csId?
#=if drivingCourse would also be part of movingSectiong: function addAcceleratingSection!(movingSection::Dict, stateFlags::Dict, csId::Integer, settings::Settings, train::Train) -> CS = CSs[csId] =#
CSs = movingSection[:characteristicSections]
CS = CSs[csId]
drivingCourse = movingSection[:drivingCourse]=#
calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel)
@ -132,8 +115,8 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
# use the conditions for the accelerating section # use the conditions for the accelerating section
if !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached if !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached
BS = BehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingMode = "accelerating"
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length) currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length)
previousSpeedLimitReached = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v] previousSpeedLimitReached = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v]
@ -153,19 +136,18 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
while !targetSpeedReached && !speedLimitReached && !brakingStartReached && !pointOfInterestReached && tractionSurplus && !previousSpeedLimitReached while !targetSpeedReached && !speedLimitReached && !brakingStartReached && !pointOfInterestReached && tractionSurplus && !previousSpeedLimitReached
# 03/08 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit # 03/08 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1] && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit
if drivingCourse[end][:s] >= currentSpeedLimit[:s_end] 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 # could be asked after creating an support 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
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length) currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length)
end end
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train) drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train)
# create the next data point # create the next support point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
push!(BS[:dataPoints], drivingCourse[end][:i])
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel)
# conditions for the next while cycle # conditions for the next while cycle
if !ignoreBraking if !ignoreBraking
@ -250,9 +232,8 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
error("ERROR at accelerating section: With the step variable ",settings.stepVariable," the while loop will be left although v<v_peak and s<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s") error("ERROR at accelerating section: With the step variable ",settings.stepVariable," the while loop will be left although v<v_peak and s<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last support point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle # conditions for the next for cycle
brakingStartReached = false brakingStartReached = false
@ -267,7 +248,6 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
if 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 testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next section # conditions for the next section
brakingStartReached = false brakingStartReached = false
@ -276,17 +256,14 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
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 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 if s_braking > 0.0
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
else else
drivingCourse[end][:s] = CS[:s_exit] # round s down to CS[:s_exit] drivingCourse[end][:s] = CS[:s_exit] # round s down to CS[:s_exit]
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
end end
elseif drivingCourse[end][:s] > nextPointOfInterest[1] elseif drivingCourse[end][:s] > nextPointOfInterest[1]
testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest drivingCourse[end][:s] = nextPointOfInterest[1] # 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]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing
@ -296,7 +273,6 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
previousSpeedLimitReached = true previousSpeedLimitReached = true
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
else else
if drivingCourse[end][:s] + s_braking == CS[:s_exit] if drivingCourse[end][:s] + s_braking == CS[:s_exit]
@ -323,19 +299,6 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
end end
end #while end #while
if length(BS[:dataPoints]) > 1
# calculate the accumulated accelerating 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)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
: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[:t] = CS[:t] + BS[:t] # total running time (in s)
mergeBehaviorSection!(CS[:behaviorSections], BS)
end
end end
# set state flags # set state flags
@ -351,14 +314,14 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
end #function addAcceleratingSection! end #function addAcceleratingSection!
## This function calculates the data points of the cruising section. ## This function calculates the support 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. # Therefore it gets its first support 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::Settings, train::Train, CSs::Vector{Dict}, cruisingType::String) function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, s_cruising::Real, settings::Settings, train::Train, CSs::Vector{Dict}, cruisingType::String)
trainIsClearing = cruisingType == "clearing" trainIsClearing = cruisingType == "clearing"
trainIsBrakingDownhill = cruisingType == "downhillBraking" trainIsBrakingDownhill = cruisingType == "downhillBraking"
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
if !trainIsBrakingDownhill # TODO: or just give BS[:type] instead of "cruising"/"braking"? if !trainIsBrakingDownhill # TODO: or just give drivingMode instead of "cruising"/"braking"?
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
else else
calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel)
@ -379,17 +342,16 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
targetPositionReached = s_cruising == 0.0 targetPositionReached = s_cruising == 0.0
resistingForceNegative = drivingCourse[end][:F_R] < 0 resistingForceNegative = drivingCourse[end][:F_R] < 0
#println(" vor if speedIsValid=",speedIsValid ," brakingStartReached=", brakingStartReached," tractionDeficit=", tractionDeficit," targetPositionReached=", targetPositionReached)
if speedIsValid && !brakingStartReached && !tractionDeficit && !targetPositionReached 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] # 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 = BehaviorSection(cruisingType, drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingMode = cruisingType
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
# TODO: necessary? # TODO: necessary?
s_cruising = min(s_cruising, CS[:s_exit]-BS[:s_entry]) targetPosition = min(drivingCourse[end][:s] + s_cruising, CS[:s_exit])
# 07/12 old: s_cruising = min(s_cruising, CS[:s_exit]-drivingCourse[end][:s])
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
#03/25 calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
if !trainIsBrakingDownhill if !trainIsBrakingDownhill
calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
else else
@ -399,7 +361,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
if settings.massModel == :homogeneous_strip && CS[:id] > 1 if settings.massModel == :homogeneous_strip && CS[:id] > 1
# conditions for cruising section # conditions for cruising section
trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train.length trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train.length
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising targetPositionReached = drivingCourse[end][:s] >= targetPosition
resistingForceNegative = drivingCourse[end][:F_R] < 0.0 resistingForceNegative = drivingCourse[end][:F_R] < 0.0
# targetSpeedReached = stateFlags[:speedLimitReached] || drivingCourse[end][:v] >= CS[:v_peak] # targetSpeedReached = stateFlags[:speedLimitReached] || drivingCourse[end][:v] >= CS[:v_peak]
# TODO: change? to correctCruisingType = (trainIsClearing || (trainIsBrakingDownhill == drivingCourse[end][:F_R] < 0)) # while clearing tractive or braking force can be used # TODO: change? to correctCruisingType = (trainIsClearing || (trainIsBrakingDownhill == drivingCourse[end][:F_R] < 0)) # while clearing tractive or braking force can be used
@ -412,11 +374,9 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
for cycle in 1:settings.approxLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:settings.approxLevel+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 && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
# 03/09 old: while drivingCourse[end][:s] < CS[:s_entry] + train.length && drivingCourse[end][:s] < BS[:s_entry] +s_cruising && drivingCourse[end][:s] < nextPointOfInterest[1] && 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 # the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance? #TODO: maybe just consider former CS with different path resistance?
# tractive effort (in N): # tractive effort (in N):
#03/25 drivingCourse[end][:F_T] = min(drivingCourse[end][:F_T], max(0.0, drivingCourse[end][:F_R]))
if !trainIsBrakingDownhill if !trainIsBrakingDownhill
drivingCourse[end][:F_T] = min(drivingCourse[end][:F_T], max(0.0, drivingCourse[end][:F_R])) drivingCourse[end][:F_T] = min(drivingCourse[end][:F_T], max(0.0, drivingCourse[end][:F_R]))
else else
@ -427,14 +387,13 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a] = 0.0 drivingCourse[end][:a] = 0.0
# create the next data point # create the next support point
if settings.stepVariable == :distance || settings.stepVariable == time if settings.stepVariable == :distance || settings.stepVariable == time
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
else else
push!(drivingCourse, moveAStep(drivingCourse[end], position, train.length/(10.0^cycle), CS[:id])) # TODO which step size should be used? push!(drivingCourse, moveAStep(drivingCourse[end], position, train.length/(10.0^cycle), CS[:id])) # TODO which step size should be used?
end end
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
push!(BS[:dataPoints], drivingCourse[end][:i])
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel)
@ -448,7 +407,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# conditions for the next while cycle # conditions for the next while cycle
pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] # POIs include s_exit as well pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] # POIs include s_exit as well
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising targetPositionReached = drivingCourse[end][:s] >= targetPosition
trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train.length trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train.length
resistingForceNegative = drivingCourse[end][:F_R] < 0.0 resistingForceNegative = drivingCourse[end][:F_R] < 0.0
end #while end #while
@ -471,14 +430,14 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
currentStepSize = settings.stepSize / 10.0^cycle currentStepSize = settings.stepSize / 10.0^cycle
end end
elseif drivingCourse[end][:s] > BS[:s_entry] + s_cruising # TODO also the following? drivingCourse[end][:s] > CSs[CS[:id]][:s_entry] + train.length)) elseif drivingCourse[end][:s] > targetPosition # TODO also the following? drivingCourse[end][:s] > CSs[CS[:id]][:s_entry] + train.length))
if settings.stepVariable == :distance if settings.stepVariable == :distance
currentStepSize=BS[:s_entry] + s_cruising-drivingCourse[end-1][:s] currentStepSize = targetPosition - drivingCourse[end-1][:s]
else else
currentStepSize = settings.stepSize / 10.0^cycle currentStepSize = settings.stepSize / 10.0^cycle
end end
elseif drivingCourse[end][:s] == BS[:s_entry] + s_cruising # || drivingCourse[end][:s]==CS[:s_exit] elseif drivingCourse[end][:s] == targetPosition # || drivingCourse[end][:s]==CS[:s_exit]
break break
elseif drivingCourse[end][:s] >= CS[:s_entry] + train.length elseif drivingCourse[end][:s] >= CS[:s_entry] + train.length
@ -494,9 +453,8 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
error("ERROR at cruising section: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s") error("ERROR at cruising section: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last support point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle # conditions for the next for cycle
pointOfInterestReached = false pointOfInterestReached = false
@ -508,13 +466,11 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end][:s] > nextPointOfInterest[1] if drivingCourse[end][:s] > nextPointOfInterest[1]
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s] elseif drivingCourse[end][:s] > targetPosition
elseif drivingCourse[end][:s] > BS[:s_entry]+s_cruising if drivingMode != "clearing"
if BS[:type] != "clearing"
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
end end
elseif drivingCourse[end][:s] == BS[:s_entry]+s_cruising elseif drivingCourse[end][:s] == targetPosition
break break
elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R] elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
break break
@ -539,15 +495,15 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
end #if end #if
# conditions for the next while cycle # conditions for the next while cycle
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising targetPositionReached = drivingCourse[end][:s] >= targetPosition
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
resistingForceNegative = drivingCourse[end][:F_R] < 0.0 resistingForceNegative = drivingCourse[end][:F_R] < 0.0
while !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used while !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
# 03/09 old: while drivingCourse[end][:s] < BS[:s_entry]+s_cruising && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] # 03/09 old: while drivingCourse[end][:s] < targetPosition && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
if nextPointOfInterest[1] > BS[:s_entry]+s_cruising if nextPointOfInterest[1] > targetPosition
nextPointOfInterest = [BS[:s_entry]+s_cruising, ""] nextPointOfInterest = [targetPosition, ""]
end end
# tractive effort (in N): # tractive effort (in N):
@ -563,16 +519,15 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
drivingCourse[end][:a] = 0.0 # acceleration (in m/s^2) drivingCourse[end][:a] = 0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way # calculate the remaining cruising way
#s_cruisingRemaining=BS[:s_entry] + s_cruising-drivingCourse[end][:s] #s_cruisingRemaining=targetPosition-drivingCourse[end][:s]
s_cruisingRemaining = min(nextPointOfInterest[1] -drivingCourse[end][:s], BS[:s_entry] +s_cruising -drivingCourse[end][:s]) s_cruisingRemaining = min(nextPointOfInterest[1] -drivingCourse[end][:s], targetPosition -drivingCourse[end][:s])
# create the next data point # create the next support point
push!(drivingCourse, moveAStep(drivingCourse[end], :distance, s_cruisingRemaining, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], :distance, s_cruisingRemaining, CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
if drivingCourse[end][:s] == nextPointOfInterest[1] if drivingCourse[end][:s] == nextPointOfInterest[1]
drivingCourse[end][:label] = nextPointOfInterest[2] drivingCourse[end][:label] = nextPointOfInterest[2]
end end
push!(BS[:dataPoints], drivingCourse[end][:i])
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel)
# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) # calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel)
@ -583,23 +538,11 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
#end #end
# conditions for the next while cycle # conditions for the next while cycle
targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising targetPositionReached = drivingCourse[end][:s] >= targetPosition
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
resistingForceNegative = drivingCourse[end][:F_R] < 0 resistingForceNegative = drivingCourse[end][:F_R] < 0
end #while end #while
# TODO: realize this better inside the upper loops?
# 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)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
mergeBehaviorSection!(CS[:behaviorSections], BS)
end # else: return the characteristic section without a cruising section end # else: return the characteristic section without a cruising section
# set state flags # set state flags
@ -618,7 +561,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
end #function addCruisingSection! end #function addCruisingSection!
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower ## This function calculates the support points for diminishing run when using maximum tractive effort and still getting slower
function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict}) function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict})
calculateForces!(drivingCourse[end], CSs, CS[:id], "diminishing", train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], "diminishing", train, settings.massModel)
@ -639,8 +582,8 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
# use the conditions for the diminishing section # use the conditions for the diminishing section
if tractionDeficit && !targetSpeedReached && !endOfCSReached if tractionDeficit && !targetSpeedReached && !endOfCSReached
BS = BehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingMode = "diminishing"
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached
currentStepSize=settings.stepSize # initialize the step size that can be reduced near intersections currentStepSize=settings.stepSize # initialize the step size that can be reduced near intersections
@ -653,12 +596,11 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train) drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train)
# create the next data point # create the next support point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
push!(BS[:dataPoints], drivingCourse[end][:i])
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel)
# conditions for the next while cycle # conditions for the next while cycle
if !ignoreBraking if !ignoreBraking
@ -721,9 +663,8 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
else else
error("ERROR during diminishing run: With the step variable ",settings.stepVariable," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s") error("ERROR during diminishing run: With the step variable ",settings.stepVariable," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last support point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle # conditions for the next for cycle
brakingStartReached = false brakingStartReached = false
@ -735,7 +676,6 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end][:v] <= 0.0 if drivingCourse[end][:v] <= 0.0
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: v=", drivingCourse[end][:v]," <= 0.0") # for testing testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: v=", drivingCourse[end][:v]," <= 0.0") # for testing
# 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.", error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2", " 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.") " 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.")
@ -743,7 +683,6 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit] 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 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
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
pointOfInterestReached = false pointOfInterestReached = false
targetSpeedReached = false targetSpeedReached = false
@ -753,7 +692,6 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
elseif drivingCourse[end][:s] > nextPointOfInterest[1] elseif drivingCourse[end][:s] > nextPointOfInterest[1]
testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest drivingCourse[end][:s] = nextPointOfInterest[1] # 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 testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," >= F_R=", drivingCourse[end][:F_R]) # for testing
@ -780,18 +718,6 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
drivingCourse[end][:label] = nextPointOfInterest[2] drivingCourse[end][:label] = nextPointOfInterest[2]
end end
end #while end #while
if length(BS[:dataPoints]) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start?
# calculate the accumulated diminishing section information
merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end][:s], # last position (in m)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
mergeBehaviorSection!(CS[:behaviorSections], BS)
end
end end
# set state flags # set state flags
@ -806,7 +732,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
end #function addDiminishingSection! end #function addDiminishingSection!
## This function calculates the data points of the coasting section. ## This function calculates the support 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 # 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::Settings, train::Train, CSs::Vector{Dict}) function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, 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 # 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
@ -821,8 +747,8 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# use the conditions for the coasting section # use the conditions for the coasting section
if !targetSpeedReached && !endOfCSReached if !targetSpeedReached && !endOfCSReached
BS = BehaviorSection("coasting", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingMode = "coasting"
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
while !targetSpeedReached && !endOfCSReached && !brakingStartReached while !targetSpeedReached && !endOfCSReached && !brakingStartReached
currentStepSize=settings.stepSize # initialize the step size that can be reduced near intersections currentStepSize=settings.stepSize # initialize the step size that can be reduced near intersections
@ -833,15 +759,14 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
while !targetSpeedReached && !brakingStartReached && !pointOfInterestReached while !targetSpeedReached && !brakingStartReached && !pointOfInterestReached
# 03/09 old : while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1] # 03/09 old : while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1]
# traction effort and resisting forces (in N): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel)
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train) drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train)
# create the next data point # create the next support point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
push!(BS[:dataPoints], drivingCourse[end][:i])
# conditions for the next while cycle # conditions for the next while cycle
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
@ -897,9 +822,8 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
# TODO: not needed. just for testing # TODO: not needed. just for testing
error("ERROR at coasting until braking section: With the step variable ",settings.stepVariable," the while loop will be left although v<v_peak and s+s_braking<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s") error("ERROR at coasting until braking section: With the step variable ",settings.stepVariable," the while loop will be left although v<v_peak and s+s_braking<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last support point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle # conditions for the next for cycle
brakingStartReached = false brakingStartReached = false
@ -914,9 +838,8 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
" 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 and s_braking=",s_braking,"m.") " 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 and s_braking=",s_braking,"m.")
elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] elseif drivingCourse[end][:s] + s_braking > CS[:s_exit]
# delete last data point because it went to far # delete last support point because it went to far
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle # conditions for the next for cycle
# brakingStartReached = true # brakingStartReached = true
@ -924,9 +847,8 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
targetSpeedReached = 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 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 # delete last support point because it went to far
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle # conditions for the next for cycle
brakingStartReached = false brakingStartReached = false
@ -935,7 +857,6 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
elseif drivingCourse[end][:s] > nextPointOfInterest[1] elseif drivingCourse[end][:s] > nextPointOfInterest[1]
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
else else
# do nothing for example for drivingCourse[end][:s] + s_braking == CS[:s_exit] # do nothing for example for drivingCourse[end][:s] + s_braking == CS[:s_exit]
end end
@ -949,16 +870,6 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
end #while end #while
stateFlags[:speedLimitReached] = false 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)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
merge!(CS[:behaviorSections], Dict(:coasting=>BS))
end end
# set state flags # set state flags
@ -972,8 +883,8 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
end #function addCoastingSection! end #function addCoastingSection!
## This function calculates the data points of the braking section. ## This function calculates the support 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. # Therefore it gets its first support 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::Settings, train::Train, CSs::Vector{Dict}) function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict})
# conditions for braking section # conditions for braking section
targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit]
@ -981,8 +892,8 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
# use the conditions for the braking section # use the conditions for the braking section
if !targetSpeedReached && !endOfCSReached if !targetSpeedReached && !endOfCSReached
BS = BehaviorSection("braking", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingMode = "braking"
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
while !targetSpeedReached && !endOfCSReached while !targetSpeedReached && !endOfCSReached
currentStepSize = settings.stepSize # initialize the step size that can be reduced near intersections currentStepSize = settings.stepSize # initialize the step size that can be reduced near intersections
@ -993,24 +904,22 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
while !targetSpeedReached && !endOfCSReached && !pointOfInterestReached while !targetSpeedReached && !endOfCSReached && !pointOfInterestReached
# 03/09 old: while drivingCourse[end][:v] > CS[:v_exit] && !targetSpeedReached && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest[1] # 03/09 old: while drivingCourse[end][:v] > CS[:v_exit] && !targetSpeedReached && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest[1]
# traction effort and resisting forces (in N): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel)
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end][:a] = train.a_braking drivingCourse[end][:a] = train.a_braking
# TODO or: drivingCourse[end][:a] = brakingAcceleration(drivingCourse[end][:v], CS[:v_exit], CS[:s_exit]-drivingCourse[end][:s]) # TODO or: drivingCourse[end][:a] = brakingAcceleration(drivingCourse[end][:v], CS[:v_exit], CS[:s_exit]-drivingCourse[end][:s])
if settings.stepVariable == :distance && ((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 if settings.stepVariable == :distance && ((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
# create empty data point and set it for the values of s_exit and v_exit # create empty support point and set it for the values of s_exit and v_exit
push!(drivingCourse, DataPoint()) push!(drivingCourse, SupportPoint())
drivingCourse[end][:i] = drivingCourse[end-1][:i]+1 drivingCourse[end][:i] = drivingCourse[end-1][:i]+1
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
push!(BS[:dataPoints], drivingCourse[end][:i])
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
else else
# create the next data point # create the next support point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id]))
drivingCourse[end][:behavior] = BS[:type] drivingCourse[end][:behavior] = drivingMode
push!(BS[:dataPoints], drivingCourse[end][:i])
end end
#println(drivingCourse[end][:i],". s=",drivingCourse[end][:s]," s_exit=", CS[:s_exit]," v_exit=", CS[:v_exit]," v=",drivingCourse[end][:v]) #println(drivingCourse[end][:i],". s=",drivingCourse[end][:s]," s_exit=", CS[:s_exit]," v_exit=", CS[:v_exit]," v=",drivingCourse[end][:v])
@ -1052,9 +961,8 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
break break
end end
# delete last data point for recalculating the last step with reduced step size # delete last support point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(BS[:dataPoints])
# conditions for the next for cycle # conditions for the next for cycle
pointOfInterestReached = false pointOfInterestReached = false
@ -1076,7 +984,6 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
break break
elseif drivingCourse[end][:s] > nextPointOfInterest[1] elseif drivingCourse[end][:s] > nextPointOfInterest[1]
drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest
drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s]
break break
elseif drivingCourse[end][:v] == CS[:v_exit] && drivingCourse[end][:s] == CS[:s_exit] elseif drivingCourse[end][:v] == CS[:v_exit] && drivingCourse[end][:s] == CS[:s_exit]
break break
@ -1107,16 +1014,6 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
end end
end #while end #while
# 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)
:t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
CS[:t] = CS[:t] + BS[:t] # total running time (in s)
merge!(CS[:behaviorSections], Dict(:braking=>BS))
end # else: return the characteristic section without a braking section end # else: return the characteristic section without a braking section
# set state flags # set state flags
@ -1132,62 +1029,38 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
end #function addBrakingSection! end #function addBrakingSection!
## This function calculates the data point of the halt. ## This function calculates the support point of the halt.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the halt if needed. # Therefore it gets its first support point and the characteristic section and returns the characteristic section including the halt if needed.
function addHalt!(CS::Dict, drivingCourse::Vector{Dict}, settings::Settings, train::Train, CSs::Vector{Dict}) function addHalt!(CS::Dict, drivingCourse::Vector{Dict}, settings::Settings, train::Train, CSs::Vector{Dict})
if drivingCourse[end][:v] == 0.0 if drivingCourse[end][:v] == 0.0
BS = BehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingMode = "halt"
merge!(BS, Dict(:length => 0.0, # total length (in m) drivingCourse[end][:behavior] = drivingMode
:t => 0.0, # total running time (in s)
:s_exit => drivingCourse[end][:s], # last position (in m)
:v_exit => drivingCourse[end][:v])) # exit speed (in m/s)))
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], BS[:type], train, settings.massModel) calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel)
merge!(CS[:behaviorSections], Dict(:halt => BS))
end # else: return the characteristic section without a halt section section end # else: return the characteristic section without a halt section section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addHalt! end #function addHalt!
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 recalculateLastBrakingPoint!(drivingCourse, s_target, v_target) function recalculateLastBrakingPoint!(drivingCourse, s_target, v_target)
currentPoint = drivingCourse[end] currentPoint = drivingCourse[end]
previousPoint = drivingCourse[end-1] previousPoint = drivingCourse[end-1]
# set s and v # set s and v
currentPoint[:s] = s_target # position (in m) currentPoint[:s] = s_target # position (in m)
currentPoint[:v] = v_target # velocity (in m/s) currentPoint[:v] = v_target # velocity (in m/s)
currentPoint[:Δs] = currentPoint[:s] - previousPoint[:s] # step size (in m)
currentPoint[:Δv] = currentPoint[:v] - previousPoint[:v] # step size (in m/s)
# calculate other values # calculate other values
previousPoint[:a] = brakingAcceleration(previousPoint[:v], currentPoint[:v], currentPoint[:Δs]) previousPoint[:a] = brakingAcceleration(previousPoint[:v], currentPoint[:v], currentPoint[:s]-previousPoint[:s])
# # TODO: just for testing # # TODO: just for testing
# if previousPoint[:a]<train.a_braking || previousPoint[:a]>=0.0 # if previousPoint[:a]<train.a_braking || previousPoint[:a]>=0.0
# println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",previousPoint[:a] ," > ",train.a_braking) # println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",previousPoint[:a] ," > ",train.a_braking)
# end # end
currentPoint[:Δt] = Δt_with_Δv(currentPoint[:Δv], previousPoint[:a]) # step size (in s) currentPoint[:t] = previousPoint[:t] + Δt_with_Δv(currentPoint[:v]-previousPoint[:v], previousPoint[:a]) # point in time (in s)
currentPoint[:t] = previousPoint[:t] + currentPoint[:Δt] # point in time (in s)
end #function recalculateLastBrakingPoint end #function recalculateLastBrakingPoint
## define the intersection velocities between the characterisitc sections to secure braking behavior ## define the intersection velocities between the characterisitc sections to secure braking behavior
function secureBrakingBehavior!(movingSection::Dict, a_braking::Real, approxLevel::Integer) function secureBrakingBehavior!(CSs::Vector{Dict}, a_braking::Real, approxLevel::Integer)
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end # limit the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
CSs = movingSection[:characteristicSections]
csId = length(CSs) csId = length(CSs)
followingCSv_entry = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s followingCSv_entry = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s
@ -1201,24 +1074,18 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real, approxLeve
CS[:v_entry] = min(CS[:v_limit], v_entryMax) CS[:v_entry] = min(CS[:v_limit], v_entryMax)
CS[:v_peak] = CS[:v_entry] CS[:v_peak] = CS[:v_entry]
# 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[:t] = 0.0
followingCSv_entry = CS[:v_entry] followingCSv_entry = CS[:v_entry]
csId = csId - 1 csId = csId - 1
end #while end #while
return movingSection return CSs
end #function secureBrakingBehavior! end #function secureBrakingBehavior!
## define the intersection velocities between the characterisitc sections to secure accelerating behavior ## define the intersection velocities between the characterisitc sections to secure accelerating behavior
function secureAcceleratingBehavior!(movingSection::Dict, settings::Settings, train::Train) function secureAcceleratingBehavior!(CSs::Vector{Dict}, settings::Settings, train::Train)
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards # limit the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises afterwards
CSs = movingSection[:characteristicSections]
CSs[1][:v_entry] = 0.0 # the entry velocity of the first characteristic section is 0.0 m/s CSs[1][:v_entry] = 0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint = DataPoint() startingPoint = SupportPoint()
startingPoint[:i] = 1 startingPoint[:i] = 1
previousCSv_exit = CSs[1][:v_entry] previousCSv_exit = CSs[1][:v_entry]
@ -1227,7 +1094,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Settings, tr
startingPoint[:s] = CS[:s_entry] startingPoint[:s] = CS[:s_entry]
startingPoint[:v] = CS[:v_entry] startingPoint[:v] = CS[:v_entry]
calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings.massModel) # traction effort and resisting forces (in N) calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings.massModel) # traction effort and resisting forces (in N)
acceleratingCourse::Vector{Dict} = [startingPoint] # List of data points acceleratingCourse::Vector{Dict} = [startingPoint] # List of support points
if CS[:v_entry] < CS[:v_peak] if CS[:v_entry] < CS[:v_peak]
# conditions for entering the accelerating phase # conditions for entering the accelerating phase
@ -1267,11 +1134,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Settings, tr
end #if end #if
previousCSv_exit = CS[:v_exit] previousCSv_exit = CS[:v_exit]
# 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[:t] = 0.0
end #for end #for
return movingSection return CSs
end #function secureAcceleratingBehavior! end #function secureAcceleratingBehavior!

View File

@ -7,22 +7,21 @@
# Calculate the running time of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`. # Calculate the running time of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
# calculate a train run focussing on using the minimum possible running time # calculate a train run focussing on using the minimum possible running time
function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, train::Train) function calculateMinimumRunningTime!(CSs::Vector{Dict}, settings::Settings, train::Train)
CSs::Vector{Dict} = movingSection[:characteristicSections]
if settings.massModel == :homogeneous_strip && settings.stepVariable == speed if settings.massModel == :homogeneous_strip && settings.stepVariable == speed
println("WARNING: ! ! ! TrainRuns.jl doesn't work reliably for the mass model homogeneous strip with step size v in m/s. The calculation time can be extremely high when calcutlating paths with steep gradients ! ! !") println("WARNING: ! ! ! TrainRuns.jl doesn't work reliably for the mass model homogeneous strip with step size v in m/s. The calculation time can be extremely high when calcutlating paths with steep gradients ! ! !")
end end # TODO
startingPoint=DataPoint() startingPoint = SupportPoint()
startingPoint[:i]=1 startingPoint[:i] = 1
startingPoint[:s]=CSs[1][:s_entry] startingPoint[:s] = CSs[1][:s_entry]
calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N) calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N)
drivingCourse::Vector{Dict} = [startingPoint] # List of data points drivingCourse::Vector{Dict} = [startingPoint] # List of support points
for csId in 1:length(CSs) for csId in 1:length(CSs)
CS = CSs[csId] CS = CSs[csId]
# for testing # for testing: # TODO
if drivingCourse[end][:s] != CS[:s_entry] 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]) println("ERROR: In CS", csId," the train run starts at s=",drivingCourse[end][:s]," and not s_entry=",CS[:s_entry])
end end
@ -30,7 +29,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, t
println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_entry=",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 end
# determine the different flags for switching between the states for creatinge moving phases # determine the different flags for switching between the states for creating moving phases
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) # tractive effort and resisting forces (in N) calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) # tractive effort and resisting forces (in N)
@ -106,7 +105,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, t
#end #end
# for testing: # for testing: # TODO
if drivingCourse[end][:s] != CS[:s_exit] 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]) println("ERROR: In CS", csId," the train run ends at s=",drivingCourse[end][:s]," and not s_exit=",CS[:s_exit])
end end
@ -117,9 +116,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, t
(CSs[end], drivingCourse) = addHalt!(CSs[end], drivingCourse, settings, train, CSs) (CSs[end], drivingCourse) = addHalt!(CSs[end], drivingCourse, settings, train, CSs)
movingSection[:t] = drivingCourse[end][:t] # total running time (in s) return (CSs, drivingCourse)
return (movingSection, drivingCourse)
end #function calculateMinimumRunningTime end #function calculateMinimumRunningTime
@ -180,7 +177,7 @@ function calculatePathResistance(CSs::Vector{Dict}, csId::Integer, s::Real, mass
pathResistance = pathResistance + (min(s, CSs[csId][:s_exit]) - max(s_rear, CSs[csId][:s_entry])) / train.length * forceFromCoefficient(CSs[csId][:r_path], train.m_train_full) pathResistance = pathResistance + (min(s, CSs[csId][:s_exit]) - max(s_rear, CSs[csId][:s_entry])) / train.length * forceFromCoefficient(CSs[csId][:r_path], train.m_train_full)
csId = csId-1 csId = csId-1
if csId == 0 if csId == 0
# TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used # TODO: currently for values < s_trainrun_start the values of s_trainrun_start will be used
return pathResistance + (CSs[1][:s_entry] - s_rear) / train.length * forceFromCoefficient(CSs[1][:r_path], train.m_train_full) return pathResistance + (CSs[1][:s_entry] - s_rear) / train.length * forceFromCoefficient(CSs[1][:r_path], train.m_train_full)
end #if end #if
end #while end #while
@ -191,30 +188,30 @@ end #function calculatePathResistance
""" """
calculate and return tractive and resisting forces for a data point calculate and return tractive and resisting forces for a support point
""" """
function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Train, massModel) function calculateForces!(supportPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Train, massModel)
# calculate resisting forces # calculate resisting forces
dataPoint[:R_traction] = tractionUnitResistance(dataPoint[:v], train) supportPoint[:R_traction] = tractionUnitResistance(supportPoint[:v], train)
if train.transportType == :freight if train.transportType == :freight
dataPoint[:R_wagons] = freightWagonsResistance(dataPoint[:v], train) supportPoint[:R_wagons] = freightWagonsResistance(supportPoint[:v], train)
elseif train.transportType == :passenger elseif train.transportType == :passenger
dataPoint[:R_wagons] = passengerWagonsResistance(dataPoint[:v], train) supportPoint[:R_wagons] = passengerWagonsResistance(supportPoint[:v], train)
end end
dataPoint[:R_train] = dataPoint[:R_traction] + dataPoint[:R_wagons] supportPoint[:R_train] = supportPoint[:R_traction] + supportPoint[:R_wagons]
dataPoint[:R_path] = calculatePathResistance(CSs, csId, dataPoint[:s], massModel, train) supportPoint[:R_path] = calculatePathResistance(CSs, csId, supportPoint[:s], massModel, train)
dataPoint[:F_R] = dataPoint[:R_train] + dataPoint[:R_path] supportPoint[:F_R] = supportPoint[:R_train] + supportPoint[:R_path]
# calculate tractive effort # calculate tractive effort
if bsType == "braking" || bsType == "coasting" || bsType == "halt" if bsType == "braking" || bsType == "coasting" || bsType == "halt"
dataPoint[:F_T] = 0.0 supportPoint[:F_T] = 0.0
elseif bsType == "cruising" elseif bsType == "cruising"
dataPoint[:F_T] = min(max(0.0, dataPoint[:F_R]), calculateTractiveEffort(dataPoint[:v], train.tractiveEffort)) supportPoint[:F_T] = min(max(0.0, supportPoint[:F_R]), calculateTractiveEffort(supportPoint[:v], train.tractiveEffort))
else # bsType == "accelerating" || bsType == "diminishing" || 'default' else # bsType == "accelerating" || bsType == "diminishing" || 'default'
dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train.tractiveEffort) supportPoint[:F_T] = calculateTractiveEffort(supportPoint[:v], train.tractiveEffort)
end end
return dataPoint return supportPoint
end #function calculateForces! end #function calculateForces!
@ -226,55 +223,55 @@ function moveAStep(previousPoint::Dict, stepVariable::Symbol, stepSize::Real, cs
# TODO: csId is only for error messages. Should it be removed? # TODO: csId is only for error messages. Should it be removed?
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =# #= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =#
# create the next data point # create the next support point
newPoint = DataPoint() newPoint = SupportPoint()
newPoint[:i] = previousPoint[:i]+1 # identifier newPoint[:i] = previousPoint[:i]+1 # identifier
# calculate s, t, v, E # calculate s, t, v, E
if stepVariable == :distance # distance step method if stepVariable == :distance # distance step method
newPoint[:Δs] = stepSize # step size (in m) Δs = stepSize # step size (in m)
if previousPoint[:a] == 0.0 if previousPoint[:a] == 0.0
if previousPoint[:v] == 0.0 if previousPoint[:v] == 0.0
error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".") error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".")
end end
newPoint[:Δt] = Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s) Δt = Δt_with_constant_v(Δs, previousPoint[:v]) # step size (in s)
newPoint[:Δv] = 0.0 # step size (in m/s) Δv = 0.0 # step size (in m/s)
else else
# check if the parts of the following square roots will be <0.0 in the functions Δt_with_Δs and Δv_with_Δs # check if the parts of the following square roots will be <0.0 in the functions Δt_with_Δs and Δv_with_Δs
squareRootPartIsNegative = (previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a] < 0.0 || previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a] < 0.0 squareRootPartIsNegative = (previousPoint[:v]/previousPoint[:a])^2+2*Δs/previousPoint[:a] < 0.0 || previousPoint[:v]^2+2*Δs*previousPoint[:a] < 0.0
if previousPoint[:a] < 0.0 && squareRootPartIsNegative if previousPoint[:a] < 0.0 && squareRootPartIsNegative
error("ERROR: The train stops during the accelerating section in CS",csId," because the tractive effort is lower than the resistant forces.", error("ERROR: The train stops during the accelerating section in CS",csId," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,", " Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,",
" F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.") " F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.")
end end
newPoint[:Δt] = Δt_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in s) Δt = Δt_with_Δs(Δs, previousPoint[:a], previousPoint[:v]) # step size (in s)
newPoint[:Δv] = Δv_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m/s) Δv = Δv_with_Δs(Δs, previousPoint[:a], previousPoint[:v]) # step size (in m/s)
end end
elseif stepVariable == :time # time step method elseif stepVariable == :time # time step method
newPoint[:Δt] = stepSize # step size (in s) Δt = stepSize # step size (in s)
newPoint[:Δs] = Δs_with_Δt(newPoint[:Δt], previousPoint[:a], previousPoint[:v]) # step size (in m) Δs = Δs_with_Δt(Δt, previousPoint[:a], previousPoint[:v]) # step size (in m)
newPoint[:Δv] = Δv_with_Δt(newPoint[:Δt], previousPoint[:a]) # step size (in m/s) Δv = Δv_with_Δt(Δt, previousPoint[:a]) # step size (in m/s)
elseif stepVariable == :velocity # velocity step method elseif stepVariable == :velocity # velocity step method
if previousPoint[:a] == 0.0 if previousPoint[:a] == 0.0
if previousPoint[:v] == 0.0 if previousPoint[:v] == 0.0
error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".") error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".")
end end
newPoint[:Δs] = stepSize # step size (in m) Δs = stepSize # step size (in m)
# TODO what is the best default step size for constant v? define Δs or Δt? # TODO what is the best default step size for constant v? define Δs or Δt?
newPoint[:Δt] = Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s) Δt = Δt_with_constant_v(Δs, previousPoint[:v]) # step size (in s)
newPoint[:Δv] = 0.0 # step size (in m/s) Δv = 0.0 # step size (in m/s)
else else
newPoint[:Δv] = stepSize * sign(previousPoint[:a]) # step size (in m/s) Δv = stepSize * sign(previousPoint[:a]) # step size (in m/s)
newPoint[:Δs] = Δs_with_Δv(newPoint[:Δv], previousPoint[:a], previousPoint[:v]) # step size (in m) Δs = Δs_with_Δv(Δv, previousPoint[:a], previousPoint[:v]) # step size (in m)
newPoint[:Δt] = Δt_with_Δv(newPoint[:Δv], previousPoint[:a]) # step size (in s) Δt = Δt_with_Δv(Δv, previousPoint[:a]) # step size (in s)
end end
end #if end #if
newPoint[:s] = previousPoint[:s] + newPoint[:Δs] # position (in m) newPoint[:s] = previousPoint[:s] + Δs # position (in m)
newPoint[:t] = previousPoint[:t] + newPoint[:Δt] # point in time (in s) newPoint[:t] = previousPoint[:t] + Δt # point in time (in s)
newPoint[:v] = previousPoint[:v] + newPoint[:Δv] # velocity (in m/s) newPoint[:v] = previousPoint[:v] + Δv # velocity (in m/s)
return newPoint return newPoint
end #function moveAStep end #function moveAStep
@ -289,7 +286,7 @@ function getCurrentSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::
if csWithTrainHeadId > 1 && s -trainLength < CSs[csWithTrainHeadId][:s_entry] if csWithTrainHeadId > 1 && s -trainLength < CSs[csWithTrainHeadId][:s_entry]
formerCsId = csWithTrainHeadId-1 formerCsId = csWithTrainHeadId-1
while formerCsId > 0 && s -trainLength < CSs[formerCsId][:s_exit] while formerCsId > 0 && s -trainLength < CSs[formerCsId][:s_exit]
if CSs[formerCsId][:v_limit] < v_limit # TODO: is the position of the train's rear < movingSection[:s_entry], v_limit of the first CS is used if CSs[formerCsId][:v_limit] < v_limit # TODO: is the position of the train's rear < s_trainrun_start, v_limit of the first CS is used
v_limit = CSs[formerCsId][:v_limit] v_limit = CSs[formerCsId][:v_limit]
s_exit = CSs[formerCsId][:s_exit] s_exit = CSs[formerCsId][:s_exit]
end end
@ -314,12 +311,25 @@ function getNextPointOfInterest(pointsOfInterest::Vector{Tuple}, s::Real)
end #function getNextPointOfInterest end #function getNextPointOfInterest
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior ## create vectors with the moving section's points of interest and with the characteristic sections with secured braking and accelerating behavior
function determineCharacteristics(path::Path, train::Train, settings::Settings) function determineCharacteristics(path::Path, train::Train, settings::Settings)
movingSection = MovingSection(path, train.v_limit, train.length) # determine the positions of the points of interest depending on the interesting part of the train (front/rear) and the train's length
movingSection = secureBrakingBehavior!(movingSection, train.a_braking, settings.approxLevel) ##TODO: use a tuple with naming
movingSection = secureAcceleratingBehavior!(movingSection, settings, train) pointsOfInterest = Tuple[]
#movingSection = secureCruisingBehavior!(movingSection, settings, train) if !isempty(path.poi)
for POI in path.poi
s_poi = POI[:station]
if POI[:measure] == "rear"
s_poi += train.length
end
push!(pointsOfInterest, (s_poi, POI[:label]) )
end
sort!(pointsOfInterest, by = x -> x[1])
end
return movingSection characteristicSections = CharacteristicSections(path, train.v_limit, train.length, pointsOfInterest)
characteristicSections = secureBrakingBehavior!(characteristicSections, train.a_braking, settings.approxLevel)
characteristicSections = secureAcceleratingBehavior!(characteristicSections, settings, train)
return (characteristicSections, pointsOfInterest)
end #function determineCharacteristics end #function determineCharacteristics

View File

@ -51,7 +51,7 @@ function Settings(
"outputDetail": { "outputDetail": {
"description": "Selecting the detail of the result", "description": "Selecting the detail of the result",
"type": "string", "type": "string",
"enum": [ "running_time", "points_of_interest", "driving_course" ] "enum": [ "running_time", "points_of_interest", "data_points", "driving_course" ]
}, },
"outputFormat": { "outputFormat": {
"description": "Output format", "description": "Output format",
@ -254,9 +254,9 @@ function Path(file, type = :YAML)
if POI_PRESENT if POI_PRESENT
sort!(tmp_points, by = x -> x[1]) sort!(tmp_points, by = x -> x[1])
for elem in tmp_points for elem in tmp_points
station = elem[1] # first point of the section (in m) station = elem[1] # station in m
label = elem[2] # paths speed limt (in m/s) label = elem[2] # name
measure = elem[3] # specific path resistance of the section (in ‰) measure = elem[3] # front or rear
point = Dict(:station => station, point = Dict(:station => station,
:label => label, :label => label,
@ -613,71 +613,44 @@ function Train(file, type = :YAML)
end #function Train() # outer constructor end #function Train() # outer constructor
## create a moving section containing characteristic sections ## create the moving section's characteristic sections
function MovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real) function CharacteristicSections(path::Path, v_trainLimit::Real, s_trainLength::Real, MS_poi::Vector{Tuple})
# this function creates and returns a moving section dependent on the paths attributes # create and return the characteristic sections of a moving section dependent on the paths attributes
s_entry = path.sections[1][:s_start] # first position (in m)
s_exit = path.sections[end][:s_end] # last position (in m)
pathLength = s_exit - s_entry # total length (in m)
##TODO: use a tuple with naming
pointsOfInterest = Tuple[]
if !isempty(path.poi)
for POI in path.poi
s_poi = POI[:station]
if POI[:measure] == "rear"
s_poi += s_trainLength
end
push!(pointsOfInterest, (s_poi, POI[:label]) )
end
sort!(pointsOfInterest, by = x -> x[1])
end
CSs=Vector{Dict}() CSs=Vector{Dict}()
s_csStart=s_entry s_csStart = path.sections[1][:s_start] # first position (in m)
csId=1 csId = 1
for row in 2:length(path.sections) for row in 2:length(path.sections)
previousSection = path.sections[row-1] previousSection = path.sections[row-1]
currentSection = path.sections[row] currentSection = path.sections[row]
speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit)
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp] pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
if speedLimitIsDifferent || pathResistanceIsDifferent if speedLimitIsDifferent || pathResistanceIsDifferent
push!(CSs, CharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, pointsOfInterest)) push!(CSs, CharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, MS_poi))
s_csStart = currentSection[:s_start] s_csStart = currentSection[:s_start]
csId = csId+1 csId = csId+1
end #if end #if
end #for end #for
push!(CSs, CharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, pointsOfInterest)) push!(CSs, CharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, MS_poi))
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore return CSs
:length => pathLength, # total length (in m) end #function CharacteristicSections
:s_entry => s_entry, # first position (in m)
:s_exit => s_exit, # last position (in m)
:t => 0.0, # total running time (in s)
:characteristicSections => CSs, # list of containing characteristic sections
:pointsOfInterest => pointsOfInterest) # list of containing points of interest
return movingSection
end #function MovingSection
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections. ## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
function CharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, MS_poi::Vector{Tuple}) function CharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, MS_poi::Vector{Tuple})
# Create and return a characteristic section dependent on the paths attributes # Create and return a characteristic section dependent on the paths attributes
characteristicSection= Dict(:id => id, # identifier characteristicSection::Dict{Symbol, Any} = Dict(:id => id, # identifier
:s_entry => s_entry, # first position (in m) :s_entry => s_entry, # first position (in m)
:s_exit => section[:s_end], # last position (in m) :s_exit => section[:s_end], # last position (in m)
:length => section[:s_end] -s_entry, # total length (in m) :length => section[:s_end] -s_entry, # total length (in m)
:r_path => section[:f_Rp], # path resistance (in ‰) :r_path => section[:f_Rp], # path resistance (in ‰)
:behaviorSections => Dict(), # list of containing behavior sections :v_limit => v_limit, # speed limit (in m/s)
:t => 0.0, # total running time (in s) # initializing :v_entry, :v_peak and :v_exit with :v_limit
:v_limit => v_limit, # speed limit (in m/s) :v_peak => v_limit, # maximum reachable speed (in m/s)
# initializing :v_entry, :v_peak and :v_exit with :v_limit :v_entry => v_limit, # maximum entry speed (in m/s)
:v_peak => v_limit, # maximum reachable speed (in m/s) :v_exit => v_limit) # maximum exit speed (in m/s)
:v_entry => v_limit, # maximum entry speed (in m/s)
:v_exit => v_limit) # maximum exit speed (in m/s)
# list of positions of every point of interest (POI) in this charateristic section for which data points should be calculated # list of positions of every point of interest (POI) in this charateristic section for which support points should be calculated
s_exit = characteristicSection[:s_exit] s_exit = characteristicSection[:s_exit]
##TODO: use a tuple with naming ##TODO: use a tuple with naming
@ -699,42 +672,17 @@ function CharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limi
end #function CharacteristicSection end #function CharacteristicSection
""" """
BehaviorSection() TODO! a SupportPoint is the smallest element of the driving course. One step of the step approach is between two support points
""" """
function BehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer) function SupportPoint()
BS= Dict( supportPoint = Dict(
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "downhillBraking", "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)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_entry => v_entry, # entry speed (in m/s)
:v_exit => 0.0, # exit speed (in m/s)
:dataPoints => [startingPoint] # list of identifiers of the containing data points starting with the initial point
)
return BS
end #function BehaviorSection
"""
a DataPoint is the smallest element of the driving course. One step of the step approach is between two data points
"""
function DataPoint()
dataPoint = Dict(
:i => 0, # identifier and counter variable of the driving course :i => 0, # identifier and counter variable of the driving course
:behavior => "", # type of behavior section the data point is part of - see BehaviorSection() :behavior => "", # type of behavior section the support point is part of - see BehaviorSection()
# a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter # a support point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
:s => 0.0, # position (in m) :s => 0.0, # position (in m)
:Δs => 0.0, # step size (in m)
:t => 0.0, # point in time (in s) :t => 0.0, # point in time (in s)
:Δt => 0.0, # step size (in s)
:v => 0.0, # velocity (in m/s) :v => 0.0, # velocity (in m/s)
:Δv => 0.0, # step size (in m/s)
:a => 0.0, # acceleration (in m/s^2) :a => 0.0, # acceleration (in m/s^2)
:W => 0.0, # mechanical work (in Ws)
:ΔW => 0.0, # mechanical work in this step (in Ws)
:E => 0.0, # energy consumption (in Ws)
:ΔE => 0.0, # energy consumption in this step (in Ws)
:F_T => 0.0, # tractive effort (in N) :F_T => 0.0, # tractive effort (in N)
:F_R => 0.0, # resisting force (in N) :F_R => 0.0, # resisting force (in N)
:R_path => 0.0, # path resistance (in N) :R_path => 0.0, # path resistance (in N)
@ -743,5 +691,5 @@ function DataPoint()
:R_wagons => 0.0, # set of wagons resistance (in N) :R_wagons => 0.0, # set of wagons resistance (in N)
:label => "" # a label for important points :label => "" # a label for important points
) )
return dataPoint return supportPoint
end #function DataPoint end #function SupportPoint

View File

@ -124,8 +124,8 @@ function Δs_with_Δt(Δt::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37] # equation is based on [Wende:2003, page 37]
# Δt: time step (in s) # Δt: time step (in s)
# a_prev: acceleration from previous data point # a_prev: acceleration from previous support point
# v_prev: velocitiy from previous data point # v_prev: velocitiy from previous support point
Δs = Δt * (2*v_prev + Δt*a_prev) /2 # step size (in m) Δs = Δt * (2*v_prev + Δt*a_prev) /2 # step size (in m)
return Δs return Δs
end #function Δs_with_Δt end #function Δs_with_Δt
@ -134,8 +134,8 @@ function Δs_with_Δv(Δv::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37] # equation is based on [Wende:2003, page 37]
# Δv: velocity step (in m/s) # Δv: velocity step (in m/s)
# a_prev: acceleration from previous data point # a_prev: acceleration from previous support point
# v_prev: velocitiy from previous data point # v_prev: velocitiy from previous support point
Δs = ((v_prev + Δv)^2 - v_prev^2)/2/a_prev # step size (in m) Δs = ((v_prev + Δv)^2 - v_prev^2)/2/a_prev # step size (in m)
return Δs return Δs
end #function Δs_with_Δv end #function Δs_with_Δv
@ -144,8 +144,8 @@ function Δt_with_Δs(Δs::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37] # equation is based on [Wende:2003, page 37]
# Δs: distance step (in m) # Δs: distance step (in m)
# a_prev: acceleration from previous data point # a_prev: acceleration from previous support point
# v_prev: velocitiy from previous data point # v_prev: velocitiy from previous support point
Δt = sign(a_prev) *sqrt((v_prev /a_prev)^2 + 2 *Δs /a_prev) - v_prev /a_prev # step size (in m/s) Δt = sign(a_prev) *sqrt((v_prev /a_prev)^2 + 2 *Δs /a_prev) - v_prev /a_prev # step size (in m/s)
return Δt return Δt
@ -155,7 +155,7 @@ function Δt_with_Δv(Δv::Real, a_prev::Real)
# equation is based on [Wende:2003, page 37] # equation is based on [Wende:2003, page 37]
# Δv: velocity step (in m/s) # Δv: velocity step (in m/s)
# a_prev: acceleration from previous data point # a_prev: acceleration from previous support point
Δt = Δv /a_prev # step size (in s) Δt = Δv /a_prev # step size (in s)
return Δt return Δt
end #function Δt_with_Δv end #function Δt_with_Δv
@ -173,8 +173,8 @@ function Δv_with_Δs(Δs::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37] # equation is based on [Wende:2003, page 37]
# Δs: distance step (in m) # Δs: distance step (in m)
# a_prev: acceleration from previous data point # a_prev: acceleration from previous support point
# v_prev: velocitiy from previous data point # v_prev: velocitiy from previous support point
Δv = sqrt(v_prev^2 + 2*Δs*a_prev) - v_prev # step size (in m/s) Δv = sqrt(v_prev^2 + 2*Δs*a_prev) - v_prev # step size (in m/s)
return Δv return Δv
end #function Δv_with_Δs end #function Δv_with_Δs
@ -183,7 +183,7 @@ function Δv_with_Δt(Δt::Real, a_prev::Real)
# equation is based on [Wende:2003, page 37] # equation is based on [Wende:2003, page 37]
# Δt: time step (in s) # Δt: time step (in s)
# a_prev: acceleration from previous data point # a_prev: acceleration from previous support point
Δv = Δt * a_prev # step size (in m/s) Δv = Δt * a_prev # step size (in m/s)
return Δv return Δv
end #function Δv_with_Δt end #function Δv_with_Δt

View File

@ -8,37 +8,55 @@ function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfI
if settings.outputDetail == :running_time if settings.outputDetail == :running_time
output::Vector{Dict} = [Dict(:t => drivingCourse[end][:t])] output::Vector{Dict} = [Dict(:t => drivingCourse[end][:t])]
elseif settings.outputDetail == :points_of_interest && !isempty(pointsOfInterest) elseif settings.outputDetail == :points_of_interest
# get only the driving course's data points with POI labels # get only the driving course's support points with POI labels
# if there is no point with POI label return the information of departure and arrival (first and last points)
output = Dict[] output = Dict[]
dataPoint = 1 if isempty(pointsOfInterest)
for POI in 1:length(pointsOfInterest) push!(output, drivingCourse[1])
while dataPoint <= length(drivingCourse) push!(output, drivingCourse[end])
if pointsOfInterest[POI][1] == drivingCourse[dataPoint][:s] else
push!(output, drivingCourse[dataPoint]) supportPoint = 1
break for POI in 1:length(pointsOfInterest)
while supportPoint <= length(drivingCourse)
if pointsOfInterest[POI][1] == drivingCourse[supportPoint][:s]
push!(output, drivingCourse[supportPoint])
break
end
supportPoint += 1
end end
dataPoint += 1
end end
end end
else #if settings.outputDetail == :driving_course || (settings.outputDetail == :points_of_interest && !isempty(path.poi)) elseif settings.outputDetail == :data_points
# get the driving course's support points where a new behavior section starts and the driving mode changes
output = Dict[]
# the first support point is the first data point
push!(output, drivingCourse[1])
for supportPoint in 2:length(drivingCourse)
if drivingCourse[supportPoint-1][:behavior] != drivingCourse[supportPoint][:behavior]
push!(output, drivingCourse[supportPoint])
end
end
elseif settings.outputDetail == :driving_course
output = drivingCourse output = drivingCourse
end end
if settings.outputFormat == :dataframe if settings.outputFormat == :dataframe
return createDataFrame(output, settings.outputDetail) return createDataFrame(output, settings.outputDetail, settings.approxLevel)
elseif settings.outputFormat == :vector elseif settings.outputFormat == :vector
return output return output
end end
end end
function createDataFrame(output_vector::Vector{Dict}, outputDetail) function createDataFrame(output_vector::Vector{Dict}, outputDetail, approxLevel::Int)
if outputDetail == :running_time if outputDetail == :running_time
# create a DataFrame with running time information # create a DataFrame with running time information
dataFrame = DataFrame(t=[output_vector[end][:t]]) dataFrame = DataFrame(t=[round(output_vector[end][:t], digits=approxLevel)])
else # :points_of_interest or :driving_course else # :points_of_interest, :data_points or :driving_course
columnSymbols = [:label, :behavior, :s, :v, :t, :a, :F_T, :F_R, :R_path, :R_traction, :R_wagons] columnSymbols = [:label, :behavior, :s, :v, :t, :a, :F_T, :F_R, :R_path, :R_traction, :R_wagons]
allColumns = [] allColumns = []
@ -54,6 +72,7 @@ function createDataFrame(output_vector::Vector{Dict}, outputDetail)
for point in output_vector for point in output_vector
push!(currentRealColumn, point[columnSymbols[column]]) push!(currentRealColumn, point[columnSymbols[column]])
end end
currentRealColumn = round.(currentRealColumn, digits=approxLevel)
push!(allColumns, currentRealColumn) push!(allColumns, currentRealColumn)
end end
end # for end # for
@ -63,4 +82,4 @@ function createDataFrame(output_vector::Vector{Dict}, outputDetail)
end end
return dataFrame return dataFrame
end #createDataFrameForDrivingCourse end #createDataFrame

View File

@ -10,7 +10,7 @@ struct Settings
stepVariable::Symbol # variable of the linear multistep method: ":distance", ":time" or ":velocity". stepVariable::Symbol # variable of the linear multistep method: ":distance", ":time" or ":velocity".
stepSize::Real # step size, unit depends on stepVariable - :distance in meter, time in seconds and velocity in meter/second. stepSize::Real # step size, unit depends on stepVariable - :distance in meter, time in seconds and velocity in meter/second.
approxLevel::Int # value for approximation; used when rounding or iterating. approxLevel::Int # value for approximation; used when rounding or iterating.
outputDetail::Symbol # single Float() ":running_time", Vector() of ":points_of_interest", outputDetail::Symbol # single Float() ":running_time", Vector() of ":points_of_interest", Vector() of ":data_points"
# or complete Vector() ":driving_course" # or complete Vector() ":driving_course"
outputFormat::Symbol # output as ":dataframe" or as ":vector". outputFormat::Symbol # output as ":dataframe" or as ":vector".

View File

@ -1,4 +1,4 @@
%YAML 1.2 %YAML 1.2
--- ---
settings: settings:
outputDetail: "driving_course" # single value "running_time", list of "points_of_interest", complete "driving_course" outputDetail: "driving_course" # single value "running_time", list of "points_of_interest", list of "data_points", complete "driving_course"

View File

@ -1,4 +1,4 @@
%YAML 1.2 %YAML 1.2
--- ---
settings: settings:
outputDetail: "points_of_interest" # single value "running_time", list of "points_of_interest", complete "driving_course" outputDetail: "points_of_interest" # single value "running_time", list of "points_of_interest", list of "data_points", complete "driving_course"