From 1dc6f8345a007bea26fc3565a7c69873331ac2a7 Mon Sep 17 00:00:00 2001 From: Max Kannenberg <95709892+MaxKannenberg@users.noreply.github.com> Date: Fri, 4 Mar 2022 02:20:33 +0100 Subject: [PATCH] Refactor the call for adding breakFree and diminshing sections --- src/Behavior.jl | 376 ++++++++++++++++------------------------- src/Characteristics.jl | 1 + src/DrivingDynamics.jl | 6 +- src/TrainRunCalc.jl | 159 +++++------------ 4 files changed, 195 insertions(+), 347 deletions(-) diff --git a/src/Behavior.jl b/src/Behavior.jl index 1dde12f..e097223 100644 --- a/src/Behavior.jl +++ b/src/Behavior.jl @@ -10,7 +10,7 @@ module Behavior include("./DrivingDynamics.jl") using .DrivingDynamics -export addAcceleratingSection!, addCruisingSection!, addCoastingSection!, addBrakingSection!, addStandstill!, +export addBreakFreeSection!, addAcceleratingSection!, addCruisingSection!, addDiminishingSection!, addCoastingSection!, addBrakingSection!, addStandstill!, # addBrakingSectionInOneStep! is not used in the current version of the tool calculateForces!, createDataPoint, @@ -92,13 +92,14 @@ function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bs dataPoint[:F_R] = dataPoint[:R_train] + dataPoint[:R_path] # calculate tractive effort - if bsType == "accelerating" || bsType == "diminishing" - dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train[:tractiveEffortVelocityPairs]) + if bsType == "braking" || bsType == "coasting" + dataPoint[:F_T] = 0.0 elseif bsType == "cruising" dataPoint[:F_T] = min(max(0.0, dataPoint[:F_R]), calculateTractiveEffort(dataPoint[:v], train[:tractiveEffortVelocityPairs])) - else - dataPoint[:F_T] = 0.0 + else # bsType == "accelerating" || bsType == "diminishing" || 'default' + dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train[:tractiveEffortVelocityPairs]) end + return dataPoint end #function calculateForces! @@ -168,74 +169,6 @@ function moveAStep(previousPoint::Dict, stepVariable::String, stepSize::Real, cs end #function moveAStep -""" -# if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept -""" -#= -function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer, currentPoint::Dict, trainLength::Real) - formerSpeedLimits=[] - if csWithTrainHeadId > 1 && currentPoint[:s] - trainLength < CSs[csWithTrainHeadId][:s_entry] - formerCsId=csWithTrainHeadId-1 - while formerCsId > 0 && currentPoint[:s] - trainLength < CSs[formerCsId][:s_exit] - if CSs[formerCsId][:v_limit] < CSs[csWithTrainHeadId][:v_limit] # TODO: is the position of train's rear < movingSection[:s_entry], v_limit of the first CS is used - push!(formerSpeedLimits, [CSs[formerCsId][:s_exit], CSs[formerCsId][:v_limit]]) - for i in 1:length(formerSpeedLimits)-1 - if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2] - pop!(formerSpeedLimits) - break - end - end - end - formerCsId=formerCsId-1 - end - end - return formerSpeedLimits -end # function detectFormerSpeedLimits - -function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, acceleratingSection::Dict) - # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, acceleratingSection::Dict) - # would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, acceleratingSection::Dict) - if length(formerSpeedLimits) > 0 - # if a former speed limit has been exceeded the accelerating steps of this CS will be removed and a clearing section will be inserted before accelerating - if drivingCourse[end][:v] > formerSpeedLimits[end][2] - while drivingCourse[end][:s] > get(CS[:behaviorSections], :clearing, acceleratingSection)[:s_entry] - pop!(drivingCourse) - end - - if haskey(CS[:behaviorSections], :clearing) - CS[:t] = CS[:t]-CS[:behaviorSections][:clearing][:t] # reducing the total running time (in s) - CS[:E] = CS[:E]-CS[:behaviorSections][:clearing][:E] # reducing the total energy consumption (in Ws) - delete!(CS[:behaviorSections], :clearing) - end - - # create a (new and longer) clearing section - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end][:s]-train[:length])) - - if s_clearing > 0.0 - (CS, drivingCourse) = addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") - else - error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id]) - end - - # 09/22: if drivingCourse[end][:s] < CS[:s_exit] - if drivingCourse[end][:s] < CS[:s_exit] - s_braking - # reset the acceleratingSection - acceleratingSection = createBehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) - else - return (CS, drivingCourse, formerSpeedLimits, acceleratingSection, true) - end - end - - # remove former speed limits of characteristic sections the train has left during the last step from the list - while length(formerSpeedLimits) > 0 && drivingCourse[end][:s] - train[:length] >= formerSpeedLimits[end][1] - pop!(formerSpeedLimits) - end - end - return (CS, drivingCourse, formerSpeedLimits, acceleratingSection, false) -end # function considerFormerSpeedLimits! -=# - function considerFormerSpeedLimit!(CS::Dict, drivingCourse::Vector{Dict}, acceleratingSection::Dict, settings::Dict, train::Dict, CSs::Vector{Dict}, currentSpeedLimit::Dict) # if a former speed limit has been exceeded the accelerating steps of this CS will be removed and a clearing section will be inserted before accelerating if drivingCourse[end][:v] > currentSpeedLimit[:v] @@ -254,7 +187,7 @@ function considerFormerSpeedLimit!(CS::Dict, drivingCourse::Vector{Dict}, accele s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, currentSpeedLimit[:s_end] - drivingCourse[end][:s]) if s_clearing > 0.0 - (CS, drivingCourse) = addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") + (CS, drivingCourse, brakingStartReached) = addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") else error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id]) end @@ -272,6 +205,9 @@ function considerFormerSpeedLimit!(CS::Dict, drivingCourse::Vector{Dict}, accele return (CS, drivingCourse, acceleratingSection) end # function considerFormerSpeedLimit! +""" +# if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept +""" function getCurrentSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::Real, trainLength::Real) v_limit = CSs[csWithTrainHeadId][:v_limit] s_exit = CSs[csWithTrainHeadId][:s_exit] @@ -301,66 +237,35 @@ end #function getNextPointOfInterest ## This function calculates the data points of the breakFree section. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed. # Info: currently the values of the breakFree section will be calculated like in the accelerating section -function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) - if settings[:stepVariable] == "v in m/s" - println("WARNING: ! ! ! TrainRun.jl doesn't work reliably for the step variable v. Therefore v should not be used ! ! !") - end +function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, ignoreBraking::Bool) if drivingCourse[end][:v]==0.0 && drivingCourse[end][:s] drivingCourse[BS[:dataPoints][1]][:i] +1 + pop!(drivingCourse) + end - # check if a point of interest was missed - if drivingCourse[end][:s] > nextPointOfInterest - if settings[:stepVariable] == "s in m" - currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s] - else - currentStepSize = settings[:stepSize] / 10.0^cycle - end + # change the accelerating data to break free + drivingCourse[end-1][:behavior] = BS[:type] + drivingCourse[end][:behavior] = BS[:type] + push!(BS[:dataPoints], drivingCourse[end][:i]) - if calculationCycle <= approximationLevel - calculationCycle = calculationCycle +1 - # delete last data point for recalculating the last step with reduced step size - pop!(drivingCourse) - pop!(BS[:dataPoints]) - else - drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest - drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s] - brokenFree = true - break#free - end - - elseif drivingCourse[end][:v] > CS[:v_peak] - if settings[:stepVariable] == "v in m/s" - currentStepSize = CS[:v_peak]-drivingCourse[end-1][:v] - else - currentStepSize = settings[:stepSize] / 10.0^cycle - end - - else #if drivingCourse[end][:s] == nextPointOfInterest || drivingCourse[end][:v] == CS[:v_peak] - brokenFree = true - break#free - end #if - end #while + # remove the accelerating section from the CS + CS[:t] = CS[:t] - get(CS[:behaviorSections], :accelerating, Dict(:t=>0.0))[:t] # total running time (in s) + CS[:E] = CS[:E] - get(CS[:behaviorSections], :accelerating, Dict(:E=>0.0))[:E] # total energy consumption (in Ws) + delete!(CS[:behaviorSections], :accelerating) # calculate the accumulated breakFree section information merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) @@ -386,33 +291,30 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings CS = CSs[csId] drivingCourse = movingSection[:drivingCourse]=# - if drivingCourse[end][:v] == 0.0 - (CS, drivingCourse) = addBreakFreeSection!(CS, drivingCourse, settings, train, CSs) - end #if - calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel]) - if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] - (CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs) - calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings[:massModel]) - end if ignoreBraking s_braking = 0.0 + else + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) end -# # if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept -# formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length]) - - # conditions for accelerating section + # conditions for the accelerating section targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak] trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit] tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R] + if ignoreBraking + s_braking = 0.0 + else + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + end + brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] + # use the conditions for the accelerating section if !targetSpeedReached && !trainAtEnd && tractionSurplus BS = createBehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingCourse[end][:behavior] = BS[:type] - brakingStartReached = false while !targetSpeedReached && !trainAtEnd && tractionSurplus && !brakingStartReached currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) @@ -423,7 +325,8 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) end - while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && drivingCourse[end][:s] +s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit + while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit + # 03/02 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:v] <= currentSpeedLimit[:v] && drivingCourse[end][:s] +s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit # 02/23 old: while drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s] +s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T] > drivingCourse[end][:F_R] # as long as s_i + s_braking < s_CSexit if drivingCourse[end][:s] >= currentSpeedLimit[:s_end] # could be asked after creating an data point. This way here prevents even a minimal exceedance of speed limit will be noticed. On the other hand the train cruises possibly a little to long @@ -439,37 +342,31 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings drivingCourse[end][:behavior] = BS[:type] push!(BS[:dataPoints], drivingCourse[end][:i]) - # if length(formerSpeedLimits) > 0 # If the rear of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal - # (CS, drivingCourse, formerSpeedLimits, BS, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, BS) - # if endOfCsReached - # return (CS, drivingCourse) - # end - # # TODO: do the following that was done here in addAcceleratingSection_without_Braking! ? currentStepSize = settings[:stepSize] # initialize the step size that can be reduced near intersections - # end - calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel]) if !ignoreBraking s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] end end #while + if CS[:id]==0 + testFlag = true + else + testFlag = false # for testing + end + # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 - if drivingCourse[end][:v] <= 0.0 - #println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," <= 0.0") # for testing - currentStepSize = settings[:stepSize] / 10.0^cycle - # TODO 01/21 should not be needed anymore with diminishing. - - elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] - #println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing + if drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing currentStepSize = settings[:stepSize] / 10.0^cycle elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit] - #println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing currentStepSize = settings[:stepSize] / 10.0^cycle elseif drivingCourse[end][:s] > nextPointOfInterest - #println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing if settings[:stepVariable] == "s in m" currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s] else @@ -477,7 +374,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings end elseif drivingCourse[end][:v] > CS[:v_peak] - #println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing if settings[:stepVariable] == "v in m/s" currentStepSize = CS[:v_peak]-drivingCourse[end-1][:v] else @@ -485,34 +382,26 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings end elseif drivingCourse[end][:v] > currentSpeedLimit[:v] - #if drivingCourse[end][:s] < currentSpeedLimit[:s_end] - #if drivingCourse[end][:s] - train[:length] < currentSpeedLimit[:s_end] - #println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing (CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit) - #end break # TODO: think about alternative: handle the the position where the rear of the train leaves a CS similar to a POI. Then it will be calculated exactly and even a minimal exceedance of speed limit will be noticed elseif drivingCourse[end][:s] +s_braking == CS[:s_exit] - #println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing brakingStartReached = true if s_braking == 0.0 trainAtEnd = true end break - elseif drivingCourse[end][:s] == CS[:s_exit] - #println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == s_exit=",CS[:s_exit]) # for testing - trainAtEnd = true - break - elseif drivingCourse[end][:v] == CS[:v_peak] - #println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_peak=",CS[:v_peak]) # for testing + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_peak=",CS[:v_peak]) # for testing targetSpeedReached = true break elseif drivingCourse[end][:s] == nextPointOfInterest - #println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing break else @@ -525,23 +414,20 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings # delete last data point for recalculating the last step with reduced step size pop!(drivingCourse) pop!(BS[:dataPoints]) + brakingStartReached = false else # if the level of approximation is reached - if drivingCourse[end][:v] <= 0.0 - # 01/21 should not be needed anymore with diminishing. - # push!(BS[:dataPoints], drivingCourse[end][:i]) - error("ERROR: The train stops during the accelerating section in CS",CS[:id]," between the positions ",drivingCourse[end-1][:s]," m and ",drivingCourse[end][:s]," m because the tractive effort is lower than the resistant forces.", - " Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2", - " F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.") - - elseif drivingCourse[end][:v] > CS[:v_peak] + if drivingCourse[end][:v] > CS[:v_peak] + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing targetSpeedReached = true pop!(drivingCourse) pop!(BS[:dataPoints]) + brakingStartReached = false elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing + brakingStartReached = true if s_braking > 0.0 - brakingStartReached = true pop!(drivingCourse) pop!(BS[:dataPoints]) else @@ -550,22 +436,24 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings end elseif drivingCourse[end][:s] > nextPointOfInterest + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:s]," > nextPointOfInterest",nextPointOfInterest) # for testing drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s] elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing tractionSurplus = false - (CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs) - calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel]) elseif drivingCourse[end][:v] > currentSpeedLimit[:v] - #if drivingCourse[end][:s] - train[:length] < currentSpeedLimit[:s_end] - (CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit) - # end + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing + (CS, drivingCourse, BS) = considerFormerSpeedLimit!(CS, drivingCourse, BS, settings, train, CSs, currentSpeedLimit) # TODO: think about alternative: handle the the position where the rear of the train leaves a CS similar to a POI. Then it will be calculated exactly and the train start accelerating immediately and not only at the next data point. else - + if drivingCourse[end][:s] + s_braking == CS[:s_exit] + testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," else case and there: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing + brakingStartReached = true + end end # TODO is it possible to put this into to the if-fork? @@ -592,11 +480,11 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings CS[:t] = CS[:t] + BS[:t] # total running time (in s) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws) - merge!(CS[:behaviorSections], Dict(:accelerating => BS)) + mergeBehaviorSection!(CS[:behaviorSections], BS) end end - return (CS, drivingCourse) + return (CS, drivingCourse, brakingStartReached) end #function addAcceleratingSection! @@ -606,18 +494,11 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising:: # traction effort and resisting forces (in N) calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) - if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] - (CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs) - # 01/08 old with DataPoint as struct: old drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel])) - calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking # may not work with EnergySaving when decreasing the length of cruising and adding coasting - # s_cruising = max(0.0, CS[:s_exit] - drivingCourse[end][:s] - s_braking) # may not work with EnergySaving when decreasing the length of cruising and adding coasting - # 02/25 old:s_cruising = max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(:length=>0.0))[:length]) - - end - if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]= drivingCourse[end][:F_R] + if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && !brakingStartReached && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] + # old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]= drivingCourse[end][:F_R] BS = createBehaviorSection(cruisingType, drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingCourse[end][:behavior] = BS[:type] @@ -712,10 +593,6 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising:: break elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R] tractionSurplus = false - (CS, drivingCourse) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs) - calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) - - # s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(length=>0.0))[:length]) else @@ -733,10 +610,9 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising:: # calculate the remaining cruising way #s_cruisingRemaining=BS[:s_entry] + s_cruising-drivingCourse[end][:s] - s_cruisingRemaining = nextPointOfInterest - drivingCourse[end][:s] + s_cruisingRemaining = min(nextPointOfInterest -drivingCourse[end][:s], BS[:s_entry] +s_cruising -drivingCourse[end][:s]) # create the next data point -# 02/18 old push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], "s in m", s_cruisingRemaining, CS[:id])) drivingCourse[end][:behavior] = BS[:type] push!(BS[:dataPoints], drivingCourse[end][:i]) @@ -744,6 +620,10 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising:: calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) end #while + # TODO: realize this better inside the upper loops? + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] + # calculate the accumulated cruising section information merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) :s_exit => drivingCourse[end][:s], # last position (in m) @@ -754,10 +634,10 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising:: CS[:t] = CS[:t] + BS[:t] # total running time (in s) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws) - merge!(CS[:behaviorSections], Dict(Symbol(BS[:type]) => BS)) + mergeBehaviorSection!(CS[:behaviorSections], BS) end # else: return the characteristic section without a cruising section - return (CS, drivingCourse) + return (CS, drivingCourse, brakingStartReached) end #function addCruisingSection! @@ -769,11 +649,13 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit] tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R] + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] + # use the conditions for the diminishing section if !tractionSurplus && !targetSpeedReached && !trainAtEnd BS = createBehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingCourse[end][:behavior] = BS[:type] - brakingStartReached = false while !tractionSurplus && !targetSpeedReached && !trainAtEnd && !brakingStartReached currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections @@ -781,7 +663,9 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - while drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:s] + s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end + #while drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] && drivingCourse[end][:s] + s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end + #while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && drivingCourse[end][:s] + s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end + while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end # acceleration (in m/s^2): drivingCourse[end][:a] = calcAcceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train[:m_train], train[:ξ_train]) @@ -791,9 +675,16 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: push!(BS[:dataPoints], drivingCourse[end][:i]) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel]) end #while + if CS[:id]==0 + testFlag = true + else + testFlag = false # for testing + end + # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 if drivingCourse[end][:v] < 0.0 @@ -803,15 +694,15 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: currentStepSize = settings[:stepSize] / 10.0^cycle end elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] - #println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," > F_R=",drivingCourse[end][:F_R]) # for testing + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," > F_R=",drivingCourse[end][:F_R]) # for testing currentStepSize = settings[:stepSize] / 10.0^cycle elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit] - #println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing currentStepSize = settings[:stepSize] / 10.0^cycle elseif drivingCourse[end][:s] > nextPointOfInterest - #println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest) # for testing if settings[:stepVariable] == "s in m" currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s] else @@ -819,12 +710,17 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: end elseif drivingCourse[end][:s] + s_braking == CS[:s_exit] - #println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing brakingStartReached = true break elseif drivingCourse[end][:s] == nextPointOfInterest - #println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest) # for testing + break + + elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," == F_R=",drivingCourse[end][:F_R]) # for testing + tractionSurplus = true break elseif drivingCourse[end][:v] == 0.0 @@ -839,9 +735,11 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: # delete last data point for recalculating the last step with reduced step size pop!(drivingCourse) pop!(BS[:dataPoints]) + brakingStartReached = false else # if the level of approximation is reached if drivingCourse[end][:v] <= 0.0 + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: v=", drivingCourse[end][:v]," <= 0.0") # for testing targetSpeedReached = true # push!(BS[:dataPoints], drivingCourse[end][:i]) error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.", @@ -849,20 +747,29 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: " F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.") elseif s_braking > 0.0 && drivingCourse[end][:s] + s_braking > CS[:s_exit] + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing brakingStartReached = true pop!(drivingCourse) pop!(BS[:dataPoints]) elseif drivingCourse[end][:s] > nextPointOfInterest + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s] - elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] + elseif drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," >= F_R=", drivingCourse[end][:F_R]) # for testing tractionSurplus = true break else + testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: else with v=", drivingCourse[end][:v]," > 0.0 and F_T=", drivingCourse[end][:F_T]," <= F_R=", drivingCourse[end][:F_R]) # for testing + #println(" and s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing + #println(" and s=", drivingCourse[end][:s]," <= nextPointOfInterest=",nextPointOfInterest) # for testing + if drivingCourse[end][:s] + s_braking == CS[:s_exit] + brakingStartReached = true + end end #if # TODO is it possible to put this into to the if-fork? @@ -884,11 +791,11 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings: CS[:t] = CS[:t] + BS[:t] # total running time (in s) CS[:E] = CS[:E] + BS[:E] # total energy consumption (in Ws) - merge!(CS[:behaviorSections], Dict(:diminishing=>BS)) + mergeBehaviorSection!(CS[:behaviorSections], BS) end end - return (CS, drivingCourse) + return (CS, drivingCourse, brakingStartReached) end #function addDiminishingSection! @@ -902,11 +809,13 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit] + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] + # use the conditions for the coasting section if !targetSpeedReached && !trainAtEnd BS = createBehaviorSection("coasting", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingCourse[end][:behavior] = BS[:type] - brakingStartReached = false while !targetSpeedReached && !trainAtEnd && !brakingStartReached currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections @@ -914,7 +823,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && drivingCourse[end][:s] + s_braking < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest # as long as s_i + s_braking < s_end + while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:v] <= CS[:v_peak] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest # as long as s_i + s_braking < s_end # traction effort and resisting forces (in N): calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel]) @@ -927,6 +836,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di push!(BS[:dataPoints], drivingCourse[end][:i]) s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] end # while # check which limit was reached and adjust the currentStepSize for the next cycle @@ -971,6 +881,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di # delete last data point for recalculating the last step with reduced step size pop!(drivingCourse) pop!(BS[:dataPoints]) + brakingStartReached = false else # if the level of approximation is reached if drivingCourse[end][:v] <= 0.0 @@ -1004,7 +915,9 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest drivingCourse[end][:Δs] = drivingCourse[end][:s] - drivingCourse[end-1][:s] else - + if drivingCourse[end][:s] + s_braking == CS[:s_exit] + brakingStartReached = true + end end end end #for @@ -1023,14 +936,13 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Di merge!(CS[:behaviorSections], Dict(:coasting=>BS)) end - return (CS, drivingCourse) + return (CS, drivingCourse, brakingStartReached) end #function addCoastingSection! -## This function calculates the data points of the braking section. # 09/07 new braking section with more than two data points +## This function calculates the data points of the braking section. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed. function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) - #function addBrakingSectionStepwise!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) # conditions for braking section targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] trainAtEnd = drivingCourse[end][:s] >= CS[:s_exit] @@ -1054,16 +966,12 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dic # TODO or: drivingCourse[end][:a] = calcBrakingAcceleration(drivingCourse[end][:v], CS[:v_exit], CS[:s_exit]-drivingCourse[end][:s]) if settings[:stepVariable] == "s in m" && ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0 - # targetSpeedReached = true - # create empty data point and set it for the values of s_exit and v_exit push!(drivingCourse, createDataPoint()) drivingCourse[end][:i] = drivingCourse[end-1][:i]+1 drivingCourse[end][:behavior] = BS[:type] push!(BS[:dataPoints], drivingCourse[end][:i]) recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) - # break - # end else # create the next data point push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) @@ -1082,12 +990,6 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dic else currentStepSize = settings[:stepSize] / 10.0^cycle end - #=elseif drivingCourse[end][:s] > CS[:s_exit] - if settings[:stepVariable] == "s in m" - currentStepSize = CS[:s_exit] - drivingCourse[end-1][:s] - else - currentStepSize = settings[:stepSize] / 10.0^cycle - end=# elseif drivingCourse[end][:s] > nextPointOfInterest if settings[:stepVariable] == "s in m" currentStepSize = nextPointOfInterest - drivingCourse[end-1][:s] @@ -1210,6 +1112,20 @@ function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, t return (CS, drivingCourse) end #function addStandstill! +function mergeBehaviorSection!(BSs::Dict, BS::Dict) + if !haskey(BSs, Symbol(BS[:type])) + merge!(BSs, Dict(Symbol(BS[:type]) => BS)) + else + number = "2" + while haskey(BSs, Symbol(BS[:type]*number)) + number = string(parse(Int, number)+1) + end + merge!(BSs, Dict(Symbol(BS[:type]*number) => BS)) + println("INFO: The ",number,". ",BS[:type]," section has been created. ! ! ! ! ! ! ! ! !") + end + return BSs +end #function mergeBehaviorSection! + function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer) BS= Dict(#:type => behavior, # type of behavior section: breakFree, clearing, accelerating, cruising, diminishing, coasting, braking or standstill :type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "standstill" diff --git a/src/Characteristics.jl b/src/Characteristics.jl index b79a1b3..123f57d 100644 --- a/src/Characteristics.jl +++ b/src/Characteristics.jl @@ -137,6 +137,7 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train: acceleratingCourse::Vector{Dict} = [startingPoint] # List of data points if CS[:v_entry] < CS[:v_peak] + (CS, acceleratingCourse) = addBreakFreeSection!(CS, acceleratingCourse, settings, train, CSs, true) (CS, acceleratingCourse) = addAcceleratingSection!(CS, acceleratingCourse, settings, train, CSs, true) # this function changes the acceleratingCourse CS[:v_peak] = max(CS[:v_entry], acceleratingCourse[end][:v]) CS[:v_exit] = min(CS[:v_exit], CS[:v_peak], acceleratingCourse[end][:v]) diff --git a/src/DrivingDynamics.jl b/src/DrivingDynamics.jl index 5946e0e..54da2c4 100644 --- a/src/DrivingDynamics.jl +++ b/src/DrivingDynamics.jl @@ -228,7 +228,8 @@ function calcBrakingDistance(v_start::Real, v_end::Real, a_braking::Real) # a_braking: constant braking acceleration (in m/s^2) s_braking = (v_end^2 - v_start^2) /2 /a_braking # braking distance (in m) # TODO: also possible: calc_Δs_with_Δv(v_end-v_start, a_braking, v_start) - return max(0.0, ceil(s_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors +# return max(0.0, ceil(s_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors + return max(0.0, ceil(s_braking, digits=approximationLevel +1)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors end #function calcBrakingDistance function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real) @@ -238,7 +239,8 @@ function calcBrakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real) # a_braking: constant braking acceleration (in m/s^2) # s_braking: braking distance (in Ws) v_start = sqrt(v_end^2 - 2*a_braking *s_braking) # braking start velocity (in m/s) - return floor(v_start, digits=approximationLevel) +# return floor(v_start, digits=approximationLevel) + return floor(v_start, digits=approximationLevel +1) end #function calcBrakingStartVelocity function calcBrakingAcceleration(v_start::Real, v_end::Real, s_braking::Real) diff --git a/src/TrainRunCalc.jl b/src/TrainRunCalc.jl index d9d3ef3..9b23e0a 100644 --- a/src/TrainRunCalc.jl +++ b/src/TrainRunCalc.jl @@ -26,10 +26,6 @@ export calculateDrivingDynamics approximationLevel = 6 # value for approximation to intersections and precisely calculated digits # TODO: define it here and give it to each function? (Behavior, ...) - - # INFO for diminishing and cruising: if v decreases to a value where F_T-F_R is positive the train could accelerate to a value of v where F_T-F_R is negative and so forth and so on. In Behavior.jl it is realized not oscillating with accelerating and diminishing but just with cruising instead of accelerating und therefore keeping the velocity value where F_T-F_R>0. - - # Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`. """ @@ -76,9 +72,14 @@ end # function calculateDrivingDynamics function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict) CSs::Vector{Dict} = movingSection[:characteristicSections] + if settings[:massModel] == "homogeneous strip" + println("WARNING: ! ! ! TrainRun.jl doesn't work reliably for the mass model homogeneous strip. This mass model should not be used ! ! !") + end + startingPoint=createDataPoint() startingPoint[:i]=1 startingPoint[:s]=CSs[1][:s_entry] + calculateForces!(startingPoint, CSs, 1, "default", train, settings[:massModel]) # traction effort and resisting forces (in N) drivingCourse::Vector{Dict} = [startingPoint] # List of data points for csId in 1:length(CSs) @@ -92,21 +93,48 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_entry=",CS[:v_entry]) end - if drivingCourse[end][:v] < CS[:v_peak] - (CS, drivingCourse) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false) - end #if - - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking + if drivingCourse[end][:v] == 0.0 + (CS, drivingCourse) = addBreakFreeSection!(CS, drivingCourse, settings, train, CSs, false) + end #if - if s_cruising > 0.0 # TODO: define a minimum cruising length? - (CS, drivingCourse) = addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") - end + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + brakingStartReached = drivingCourse[end][:s] + s_braking == CS[:s_exit] + testFlag = false # for testing - if drivingCourse[end][:v] > CS[:v_exit] - (CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs) - end #if + while !brakingStartReached && drivingCourse[end][:s] +s_braking < CS[:s_exit] + calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings[:massModel]) # traction effort and resisting forces (in N) + + if drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] + if drivingCourse[end][:v] < CS[:v_peak] - 1/10^approximationLevel * settings[:stepSize] # TODO: check if multiplying with stepSize is necessary + (CS, drivingCourse, brakingStartReached) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false) + #s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + # testFlag && println("in CS",CS[:id]," after accelerating s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing + else + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking + + if s_cruising > 0.0 # TODO: define a minimum cruising length? + + (CS, drivingCourse, brakingStartReached) = addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + testFlag && println("in CS",CS[:id]," after cruising s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing + + # TODO: add downhillBraking as a special cruising Section: + # (CS, drivingCourse, brakingStartReached) = addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "downhillBraking") + + end + end #if + else + (CS, drivingCourse, brakingStartReached) = addDiminishingSection!(CS, drivingCourse, settings, train, CSs) + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + # testFlag && println("in CS",CS[:id]," after diminishing s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing + end + end + + if drivingCourse[end][:v] > CS[:v_exit] + (CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs) + end #if # for testing: @@ -127,102 +155,3 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train end #function calculateMinimumRunningTime end # module TrainRunCalc - - - #= -# calculate a train run focussing on using the minimum possible running time -function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict) - CSs::Vector{Dict} = movingSection[:characteristicSections] - - startingPoint=createDataPoint() - startingPoint[:i]=1 - startingPoint[:s]=CSs[1][:s_entry] - drivingCourse::Vector{Dict} = [startingPoint] # List of data points - - for csId in 1:length(CSs) - CS = CSs[csId] - BSs = CS[:behaviorSections] - - # for testing: - if drivingCourse[end][:s] != CS[:s_entry] - println("ERROR: In CS", csId," the train run starts at s=",drivingCourse[end][:s]," and not s_entry=",CS[:s_entry]) - end - if drivingCourse[end][:v] > CS[:v_entry] - println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_entry=",CS[:v_entry]) - end - - # check if the CS has a cruising section - s_breakFree = get(BSs, :breakFree, Dict(:length=>0.0))[:length] - s_clearing = get(BSs, :clearing, Dict(:length=>0.0))[:length] - s_accelerating = get(BSs, :accelerating, Dict(:length=>0.0))[:length] - s_braking = calcBrakingDistance(CS[:v_peak], CS[:v_exit], train[:a_braking]) - # old: s_braking = max(0.0, ceil((CS[:v_exit]^2-CS[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors - - # calculate the cruising sections length - s_cruising = max(0.0, CS[:length] - s_breakFree - s_clearing - s_accelerating - s_braking) - - # reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit - CS[:behaviorSections] = Dict() - CS[:E] = 0.0 - CS[:t] = 0.0 - -# TODO 02/09: could there be a better structure for processing the different moving phases? (this if fork was added on 2022/09/02) - if s_clearing > 0.0 && s_breakFree + s_accelerating == 0.0 - (CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") - end - - if s_cruising == CS[:length] - (CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") - elseif s_cruising > 0.0 || s_braking == 0.0 - - if drivingCourse[end][:v] < CS[:v_peak] - (CS, drivingCourse) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false) # TODO or better ignoreBraking = true? - end #if - - if CS[:s_exit]-drivingCourse[end][:s]-max(0.0, (CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors - println("ERROR: After accelerating in CS ",csId," the braking distance is too short!") - println(" before accelerating in CS",csId, " with s=",drivingCourse[end][:s]," s_braking=",((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking])," s_exit=",CS[:s_exit]) - println(" and v=",drivingCourse[end][:v]," v_peak=",CS[:v_peak]," v_exit=",CS[:v_exit]) - end - - s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors - s_cruising=CS[:s_exit]-drivingCourse[end][:s]-s_braking - - if s_cruising > 0.0 - (CS, drivingCourse)=addCruisingSection!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") - end - else - if CS[:v_entry] < CS[:v_peak] || s_accelerating > 0.0 # or instead of " || s_accelerating > 0.0" use "v_entry <= v_peak" or "v_i <= v_peak" - # 09/09 old (not sufficient for steep gradients): if CS[:v_entry] < CS[:v_peak] - # old 02/22 (CS, drivingCourse)=addAcceleratingSectionUntilBraking!(CS, drivingCourse, settings, train, CSs) - (CS, drivingCourse) = addAcceleratingSection!(CS, drivingCourse, settings, train, CSs, false) - end #if - end #if - - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - - if drivingCourse[end][:v] > CS[:v_exit] - #(CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings[:massModel], train, CSs) - (CS, drivingCourse)=addBrakingSection!(CS, drivingCourse, settings, train, CSs) - end #if - - # for testing: - if drivingCourse[end][:s] != CS[:s_exit] - println("ERROR: In CS", csId," the train run ends at s=",drivingCourse[end][:s]," and not s_exit=",CS[:s_exit]) - end - if drivingCourse[end][:v] > CS[:v_exit] - println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_exit=",CS[:v_exit]) - end - - end #for - - (CSs[end], drivingCourse) = addStandstill!(CSs[end], drivingCourse, settings, train, CSs) - - movingSection[:t] = drivingCourse[end][:t] # total running time (in s) - movingSection[:E] = drivingCourse[end][:E] # total energy consumption (in Ws) - - return (movingSection, drivingCourse) -end #function calculateMinimumRunningTime - -end # module TrainRunCalc - =#