diff --git a/CHANGELOG.md b/CHANGELOG.md index dbe662d..c25f502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,22 @@ Categories: Added, Changed, Deprecated, Removed, Fixed, and Security. ## [Unreleased] +### Added +* output alternative with starting points of the driving modes + +### Changed +* renamed data points into 'support points' +* reduced number of decimal places of output data +* replace v_peak by the existing v_limit +* changed type of a point of interest from Tuple to NamedTuple + +### Removed +* dictionary MovingSection +* redundant keys from the dictionary CharacteristicSection +* dictionary BehaviorSection +* redundant keys from the dictionary SupportPoint +* function secureAcceleratingBehavior() + ## Version [1.0.1] 2022-06-05 @@ -208,4 +224,4 @@ Proof of concept and master thesis submission. [0.4]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.3...v0.4 [0.3]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.2...v0.3 [0.2]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.1...v0.2 -[0.1]: https://github.com/railtoolkit/TrainRuns.jl/releases/tag/v0.1 \ No newline at end of file +[0.1]: https://github.com/railtoolkit/TrainRuns.jl/releases/tag/v0.1 diff --git a/src/TrainRuns.jl b/src/TrainRuns.jl index 5cf5801..98882bb 100644 --- a/src/TrainRuns.jl +++ b/src/TrainRuns.jl @@ -50,7 +50,7 @@ function trainrun(train::Train, path::Path, settings=Settings()::Settings) # TODO settings.outputDetail == :verbose && println("The characteristics haven been determined.") # calculate the train run with the minimum running time - (characteristicSections, drivingCourse) = calculateMinimumRunningTime!(characteristicSections, settings, train) + drivingCourse = calculateMinimumRunningTime(characteristicSections, settings, train) # TODO settings.outputDetail == :verbose && println("The driving course for the shortest running time has been calculated.") # accumulate data and create an output dictionary diff --git a/src/behavior.jl b/src/behavior.jl index 4649260..34d11e6 100644 --- a/src/behavior.jl +++ b/src/behavior.jl @@ -7,7 +7,9 @@ ## This function calculates the support points of the breakFree section. # 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 -function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict}) +function addBreakFreeSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train) + CS = CSs[csId] + # conditions for the break free section endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached] trainIsHalting = drivingCourse[end][:v] == 0.0 @@ -15,20 +17,20 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags: if trainIsHalting && !endOfCSReached drivingMode = "breakFree" drivingCourse[end][:behavior] = drivingMode - startingPoint = drivingCourse[end][:i] + startingPoint = length(drivingCourse) # 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, csId, "accelerating", train, settings.massModel) # currently the tractive effort is calculated like in the accelerating section # calculate the breakFree section with calculating the accelerating section and just using the first step and removing the rest - try (CS, drivingCourse, stateFlags) = addAcceleratingSection!(CS, drivingCourse, stateFlags, settings, train, CSs) + try (drivingCourse, stateFlags) = addAcceleratingSection!(drivingCourse, stateFlags, CSs, csId, settings, train) catch(acceleratingError) println("This error happened during the break free phase that is using the accelerating function:") rethrow(acceleratingError) end # delete every supportPoint except the first two - while drivingCourse[end][:i] > startingPoint +1 + while length(drivingCourse) > startingPoint +1 pop!(drivingCourse) end @@ -38,131 +40,100 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags: end # else: return the characteristic section without a breakFree section # determine state flags + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics] - s_braking = 0.0 - else - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end - - # reset state flags stateFlags[:endOfCSReached] = drivingCourse[end][:s] >= CS[:s_exit] stateFlags[:brakingStartReached] = drivingCourse[end][:s] +s_braking >= CS[:s_exit] stateFlags[:tractionDeficit] = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] # or add another flag for equal forces? stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0 stateFlags[:previousSpeedLimitReached] = false stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_limit] - stateFlags[:error] = !(stateFlags[:endOfCSReached] || stateFlags[:brakingStartReached] || stateFlags[:tractionDeficit] || stateFlags[:previousSpeedLimitReached] || stateFlags[:speedLimitReached]) + stateFlags[:error] = drivingCourse[end][:v] > CS[:v_limit] || drivingCourse[end][:s] > CS[:s_exit] - return (CS, drivingCourse, stateFlags) + return (drivingCourse, stateFlags) end #function addBreakFreeSection! ## 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. -function addClearingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict}) +function addClearingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train) + CS = CSs[csId] + if stateFlags[:previousSpeedLimitReached] - currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length) + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics] - ignoreBraking = true - s_braking = 0.0 - else - ignoreBraking = false - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end - - s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, currentSpeedLimit[:s_end] - drivingCourse[end][:s]) + s_clearing = min(CS[:s_exit]-drivingCourse[end][:s]-s_braking, lowestSpeedLimit[:s_end] - drivingCourse[end][:s]) if s_clearing > 0.0 - (CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_clearing, settings, train, CSs, "clearing") - calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel) - # stateFlags[:brakingStartReached] = brakingStartReached - # stateFlags[:endOfCSReached] = stateFlags[:endOfCSReached] || drivingCourse[end][:s] == CS[:s_exit] + (drivingCourse, stateFlags) = addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, "clearing", s_clearing) + calculateForces!(drivingCourse[end], CSs, csId, "accelerating", train, settings.massModel) else - error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id]) + error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",csId) end #stateFlags[:previousSpeedLimitReached] = false - currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length) - stateFlags[:previousSpeedLimitReached] = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v] + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) + stateFlags[:previousSpeedLimitReached] = lowestSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= lowestSpeedLimit[:v] else stateFlags[:error] = true end - return (CS, drivingCourse, stateFlags) + return (drivingCourse, stateFlags) end #function addClearingSection ## 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 -function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Settings, train::Train, CSs::Vector{Dict}) - #= TODO: instead of CS just give csId? - -> CS = CSs[csId] =# +function addAcceleratingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train) + CS = CSs[csId] - calculateForces!(drivingCourse[end], CSs, CS[:id], "accelerating", train, settings.massModel) - - if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics] - ignoreBraking = true - s_braking = 0.0 - else - ignoreBraking = false - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end + calculateForces!(drivingCourse[end], CSs, csId, "accelerating", train, settings.massModel) + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) # conditions for the accelerating section - targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak] || stateFlags[:speedLimitReached] endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached] tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R] brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] || stateFlags[:brakingStartReached] previousSpeedLimitReached = stateFlags[:previousSpeedLimitReached] + speedLimitReached = drivingCourse[end][:v] >= CS[:v_limit] || stateFlags[:speedLimitReached] # use the conditions for the accelerating section - if !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached + if !speedLimitReached && !endOfCSReached && tractionSurplus && !brakingStartReached drivingMode = "accelerating" drivingCourse[end][:behavior] = drivingMode - currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length) - previousSpeedLimitReached = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v] - speedLimitReached = drivingCourse[end][:v] >= CS[:v_limit] - #speedLimitReached = drivingCourse[end][:v] > currentSpeedLimit[:v] - #targetSpeedReached = speedLimitReached - while !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached && !previousSpeedLimitReached + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) + previousSpeedLimitReached = lowestSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= lowestSpeedLimit[:v] + + while !speedLimitReached && !endOfCSReached && tractionSurplus && !brakingStartReached && !previousSpeedLimitReached currentStepSize = settings.stepSize # initialize the step size that can be reduced near intersections nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] 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 - if !ignoreBraking - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end - - 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 - if drivingCourse[end][:s] >= currentSpeedLimit[:s_end] - # 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) + while !speedLimitReached && !brakingStartReached && !pointOfInterestReached && tractionSurplus && !previousSpeedLimitReached + if drivingCourse[end][:s] >= lowestSpeedLimit[:s_end] + # could be asked after creating an support point. This way here prevents even a minimal exceedance of speed limit. On the other hand the train cruises possibly a little to long + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) end # acceleration (in m/s^2): drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train) # create the next support point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) + push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, csId)) drivingCourse[end][:behavior] = drivingMode - calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, drivingMode, train, settings.massModel) # conditions for the next while cycle - if !ignoreBraking - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) + brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] - speedLimitReached = drivingCourse[end][:v] > CS[:v_limit] - previousSpeedLimitReached = currentSpeedLimit[:v] < CS[:v_limit] && (drivingCourse[end][:v] > currentSpeedLimit[:v] || (drivingCourse[end][:v] == currentSpeedLimit[:v] && drivingCourse[end][:s] < currentSpeedLimit[:s_end])) - targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak] - #targetSpeedReached = speedLimitReached - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] # POIs include s_exit as well + speedLimitReached = drivingCourse[end][:v] >= CS[:v_limit] + previousSpeedLimitReached = lowestSpeedLimit[:v] < CS[:v_limit] && (drivingCourse[end][:v] > lowestSpeedLimit[:v] || (drivingCourse[end][:v] == lowestSpeedLimit[:v] && drivingCourse[end][:s] < lowestSpeedLimit[:s_end])) + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] # POIs include s_exit as well tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R] end #while - if CS[:id]==0 + if csId==0 testFlag = true else testFlag = false # for testing @@ -171,66 +142,47 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < settings.approxLevel+1 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 + testFlag && println("in CS",csId," 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] - 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",csId," 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[1] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest[1]) # for testing + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] + testFlag && println("in CS",csId," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest[:s]) # for testing if settings.stepVariable == :distance - currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s] + currentStepSize = nextPointOfInterest[:s] - drivingCourse[end-1][:s] else currentStepSize = settings.stepSize / 10.0^cycle end - elseif drivingCourse[end][:v] > CS[:v_peak] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=",CS[:v_peak]) # for testing - if settings.stepVariable == :speed - currentStepSize = CS[:v_peak]-drivingCourse[end-1][:v] - else - currentStepSize = settings.stepSize / 10.0^cycle - end - - elseif drivingCourse[end][:v] > currentSpeedLimit[:v] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing + elseif drivingCourse[end][:v] > lowestSpeedLimit[:v] + testFlag && println("in CS",csId," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_lowestLimit=", lowestSpeedLimit[:v]) # for testing if settings.stepVariable == :velocity - currentStepSize = currentSpeedLimit[:v]-drivingCourse[end-1][:v] - + currentStepSize = lowestSpeedLimit[:v] - drivingCourse[end-1][:v] else currentStepSize = settings.stepSize / 10.0^cycle end elseif drivingCourse[end][:s] + s_braking == CS[:s_exit] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing - if s_braking == 0.0 - endOfCSReached = true - end + testFlag && println("in CS",csId," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing break - elseif drivingCourse[end][:v] == CS[:v_peak] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_peak=",CS[:v_peak]) # for testing + elseif drivingCourse[end][:v] == lowestSpeedLimit[:v] + testFlag && println("in CS",csId," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_lowestLimit=", lowestSpeedLimit[:v]) # for testing break - elseif drivingCourse[end][:v] == currentSpeedLimit[:v] && drivingCourse[end][:s] < currentSpeedLimit[:s_end] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_limitCurrent=",currentSpeedLimit[:v]) # for testing - break - - elseif drivingCourse[end][:s] == nextPointOfInterest[1] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest[1]) # for testing - if nextPointOfInterest[1] == CS[:s_exit] - endOfCSReached = true - end + elseif drivingCourse[end][:s] == nextPointOfInterest[:s] + testFlag && println("in CS",csId," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest[:s]) # for testing break else - println("v=",drivingCourse[end][:v]," v_peak= ", CS[:v_peak] , " v_cLimit=", currentSpeedLimit[:v]) - println("s=" ,drivingCourse[end][:s]," s_exit=", CS[:s_exit], " s+s_braking=", drivingCourse[end][:s] +s_braking," nextPOI=",nextPointOfInterest[1]) + println("v=",drivingCourse[end][:v]," v_limit= ", CS[:v_limit] , " v_lowestLimit=", lowestSpeedLimit[:v]) + println("s=" ,drivingCourse[end][:s]," s_exit=", CS[:s_exit], " s+s_braking=", drivingCourse[end][:s] +s_braking," nextPOI=",nextPointOfInterest[:s]) println("F_T=",drivingCourse[end][:F_T] ," F_R=", drivingCourse[end][:F_R]) - error("ERROR at accelerating section: With the step variable ",settings.stepVariable," the while loop will be left although 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 + if drivingCourse[end][:v] > lowestSpeedLimit[:v] + testFlag && println("in CS",csId," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_lowestLimit=", lowestSpeedLimit[:v], "with v_limit=",CS[:v_limit]) # for testing pop!(drivingCourse) # conditions for the next section brakingStartReached = false elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing + testFlag && println("in CS",csId," 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 pop!(drivingCourse) @@ -261,41 +211,30 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla drivingCourse[end][:s] = CS[:s_exit] # round s down to CS[:s_exit] end - 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 - drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] + testFlag && println("in CS",csId," accelerating cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[:s]=",nextPointOfInterest[:s]) # for testing + drivingCourse[end][:s] = nextPointOfInterest[:s] # round s down to nextPointOfInterest 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 - - elseif drivingCourse[end][:v] > currentSpeedLimit[:v] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," > v_limitCurrent=",currentSpeedLimit[:v]) # for testing - previousSpeedLimitReached = true - - pop!(drivingCourse) + testFlag && println("in CS",csId," accelerating cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," <= F_R=",drivingCourse[end][:F_R]) # for testing else if drivingCourse[end][:s] + s_braking == CS[:s_exit] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," else case and there: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing - elseif drivingCourse[end][:v] == currentSpeedLimit[:v] - testFlag && println("in CS",CS[:id]," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_limitCurrent=",currentSpeedLimit[:v]) # for testing + testFlag && println("in CS",csId," accelerating cycle",cycle," else case and there: s +s_braking=", drivingCourse[end][:s],",+",s_braking," = ",drivingCourse[end][:s] +s_braking," > s_exit=",CS[:s_exit]) # for testing + + elseif drivingCourse[end][:v] == lowestSpeedLimit[:v] + testFlag && println("in CS",csId," accelerating cycle",cycle," case: v=", drivingCourse[end][:v]," == v_lowestLimit=", lowestSpeedLimit[:v]) # for testing end end - - # TODO is it possible to put this into to the if-fork? - if drivingCourse[end][:s] == CS[:s_exit] - endOfCSReached = true - end - end end #for if drivingCourse[end][:s] == CS[:s_exit] endOfCSReached = true end - if drivingCourse[end][:s] == nextPointOfInterest[1] - drivingCourse[end][:label] = nextPointOfInterest[2] + if drivingCourse[end][:s] == nextPointOfInterest[:s] + drivingCourse[end][:label] = nextPointOfInterest[:label] end end #while @@ -307,44 +246,39 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla stateFlags[:tractionDeficit] = !(tractionSurplus || drivingCourse[end][:F_T] == drivingCourse[end][:F_R]) # or add another flag for equal forces? stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0 stateFlags[:previousSpeedLimitReached] = previousSpeedLimitReached - stateFlags[:speedLimitReached] = targetSpeedReached - stateFlags[:error] = !(endOfCSReached || brakingStartReached || stateFlags[:tractionDeficit] || previousSpeedLimitReached || targetSpeedReached) + stateFlags[:speedLimitReached] = speedLimitReached + stateFlags[:error] = !(endOfCSReached || brakingStartReached || stateFlags[:tractionDeficit] || previousSpeedLimitReached || speedLimitReached) - return (CS, drivingCourse, stateFlags) + return (drivingCourse, stateFlags) end #function addAcceleratingSection! ## This function calculates the support points of the cruising section. # 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!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train, cruisingType::String, s_cruising::Real) + CS = CSs[csId] + trainIsClearing = cruisingType == "clearing" trainIsBrakingDownhill = cruisingType == "downhillBraking" # traction effort and resisting forces (in N) 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, csId, "cruising", train, settings.massModel) else - calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, "braking", train, settings.massModel) end - if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics] - ignoreBraking = true - s_braking = 0.0 - else - ignoreBraking = false - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) # conditions for cruising section #s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] || stateFlags[:brakingStartReached] - speedIsValid = drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] + speedIsValid = drivingCourse[end][:v] > 0.0 && drivingCourse[end][:v] <= CS[:v_limit] tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] targetPositionReached = s_cruising == 0.0 resistingForceNegative = drivingCourse[end][:F_R] < 0 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] drivingMode = cruisingType drivingCourse[end][:behavior] = drivingMode # TODO: necessary? @@ -353,28 +287,27 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: # traction effort and resisting forces (in N) if !trainIsBrakingDownhill - calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, "cruising", train, settings.massModel) else - calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, "braking", train, settings.massModel) end - if settings.massModel == :homogeneous_strip && CS[:id] > 1 + if settings.massModel == :homogeneous_strip && csId > 1 # conditions for cruising section trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train.length targetPositionReached = drivingCourse[end][:s] >= targetPosition resistingForceNegative = drivingCourse[end][:F_R] < 0.0 -# 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 -#&& targetSpeedReached + # TODO: change? to: correctCruisingType = (trainIsClearing || (trainIsBrakingDownhill == drivingCourse[end][:F_R] < 0)) # while clearing tractive or braking force can be used + # use the conditions for the cruising section while trainInPreviousCS && !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used currentStepSize = settings.stepSize nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] 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 - # 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 resisting forces and the train has to use the highest possible effort to try to stay at v_limit 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? # tractive effort (in N): if !trainIsBrakingDownhill @@ -388,24 +321,18 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: drivingCourse[end][:a] = 0.0 # create the next support point - if settings.stepVariable == :distance || settings.stepVariable == time - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) + if settings.stepVariable == :distance || settings.stepVariable == :time + push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, csId)) 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], settings.stepVariable, train.length/(10.0^cycle), csId)) # TODO which step size should be used? end drivingCourse[end][:behavior] = drivingMode # traction effort and resisting forces (in N) - calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) -# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) - #if !trainIsBrakingDownhill - # calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) - #else - # calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel) - #end + calculateForces!(drivingCourse[end], CSs, csId, "default", train, settings.massModel) # conditions for the next while cycle - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] # POIs include s_exit as well + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] # POIs include s_exit as well tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] targetPositionReached = drivingCourse[end][:s] >= targetPosition trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train.length @@ -423,14 +350,14 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: elseif trainIsBrakingDownhill && !resistingForceNegative currentStepSize = settings.stepSize / 10.0^cycle - elseif drivingCourse[end][:s] > nextPointOfInterest[1] + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] if settings.stepVariable == :distance - currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s] + currentStepSize = nextPointOfInterest[:s] - drivingCourse[end-1][:s] else currentStepSize = settings.stepSize / 10.0^cycle end - elseif drivingCourse[end][:s] > targetPosition # 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] > CS[:s_entry] + train.length)) if settings.stepVariable == :distance currentStepSize = targetPosition - drivingCourse[end-1][:s] else @@ -443,14 +370,14 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: elseif drivingCourse[end][:s] >= CS[:s_entry] + train.length break - elseif drivingCourse[end][:s] == nextPointOfInterest[1] + elseif drivingCourse[end][:s] == nextPointOfInterest[:s] break elseif !trainInPreviousCS break else - 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",csId," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s") end # delete last support point for recalculating the last step with reduced step size @@ -464,8 +391,8 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: resistingForceNegative = drivingCourse[end][:F_R] < 0.0 else # if the level of approximation is reached - if drivingCourse[end][:s] > nextPointOfInterest[1] - drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest + if drivingCourse[end][:s] > nextPointOfInterest[:s] + drivingCourse[end][:s] = nextPointOfInterest[:s] # round s down to nextPointOfInterest elseif drivingCourse[end][:s] > targetPosition if drivingMode != "clearing" pop!(drivingCourse) @@ -487,8 +414,8 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: end end #for - if drivingCourse[end][:s] == nextPointOfInterest[1] - drivingCourse[end][:label] = nextPointOfInterest[2] + if drivingCourse[end][:s] == nextPointOfInterest[:s] + drivingCourse[end][:label] = nextPointOfInterest[:label] end end #while @@ -500,14 +427,12 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: resistingForceNegative = drivingCourse[end][:F_R] < 0.0 while !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used - # 03/09 old: while drivingCourse[end][:s] < targetPosition && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) - if nextPointOfInterest[1] > targetPosition - nextPointOfInterest = [targetPosition, ""] + if nextPointOfInterest[:s] > targetPosition + nextPointOfInterest = (s = targetPosition, label = "") #[targetPosition, ""] end # tractive effort (in N): -#03/25 drivingCourse[end][:F_T] = min(drivingCourse[end][:F_T], max(0.0, drivingCourse[end][:F_R])) if !trainIsBrakingDownhill drivingCourse[end][:F_T] = min(drivingCourse[end][:F_T], max(0.0, drivingCourse[end][:F_R])) else @@ -520,22 +445,17 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: # calculate the remaining cruising way #s_cruisingRemaining=targetPosition-drivingCourse[end][:s] - s_cruisingRemaining = min(nextPointOfInterest[1] -drivingCourse[end][:s], targetPosition -drivingCourse[end][:s]) + s_cruisingRemaining = min(nextPointOfInterest[:s] -drivingCourse[end][:s], targetPosition -drivingCourse[end][:s]) # create the next support point - push!(drivingCourse, moveAStep(drivingCourse[end], :distance, s_cruisingRemaining, CS[:id])) + push!(drivingCourse, moveAStep(drivingCourse[end], :distance, s_cruisingRemaining, csId)) drivingCourse[end][:behavior] = drivingMode - if drivingCourse[end][:s] == nextPointOfInterest[1] - drivingCourse[end][:label] = nextPointOfInterest[2] + if drivingCourse[end][:s] == nextPointOfInterest[:s] + drivingCourse[end][:label] = nextPointOfInterest[:label] end - calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) -# calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) - #if !trainIsBrakingDownhill - # calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings.massModel) - #else - # calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings.massModel) - #end + calculateForces!(drivingCourse[end], CSs, csId, "default", train, settings.massModel) + # conditions for the next while cycle targetPositionReached = drivingCourse[end][:s] >= targetPosition @@ -547,31 +467,25 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: # set state flags stateFlags[:endOfCSReached] = drivingCourse[end][:s] == CS[:s_exit] - if !ignoreBraking - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) stateFlags[:brakingStartReached] = brakingStartReached || drivingCourse[end][:s] + s_braking >= CS[:s_exit] stateFlags[:tractionDeficit] = tractionDeficit stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0.0 - currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length) - stateFlags[:previousSpeedLimitReached] = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v] + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) + stateFlags[:previousSpeedLimitReached] = lowestSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= lowestSpeedLimit[:v] stateFlags[:error] = !(targetPositionReached || tractionDeficit || !(cruisingType == "clearing" || ((cruisingType == "downhillBraking") == resistingForceNegative))) - return (CS, drivingCourse, stateFlags) + return (drivingCourse, stateFlags) end #function addCruisingSection! ## 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}) - calculateForces!(drivingCourse[end], CSs, CS[:id], "diminishing", train, settings.massModel) +function addDiminishingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train) + CS = CSs[csId] - if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics] - ignoreBraking = true - s_braking = 0.0 - else - ignoreBraking = false - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end + calculateForces!(drivingCourse[end], CSs, csId, "diminishing", train, settings.massModel) + + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) # conditions for diminishing section targetSpeedReached = drivingCourse[end][:v] <= 0.0 @@ -586,34 +500,31 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag drivingCourse[end][:behavior] = drivingMode 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 nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] 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 tractionDeficit && !brakingStartReached && !pointOfInterestReached && !targetSpeedReached - # 03/09 old: while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1] && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end # acceleration (in m/s^2): drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train) # create the next support point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) + push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, csId)) drivingCourse[end][:behavior] = drivingMode - calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, drivingMode, train, settings.massModel) # conditions for the next while cycle - if !ignoreBraking - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - end + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) + brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] targetSpeedReached = drivingCourse[end][:v] <= 0.0 tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] - endOfCSReached = drivingCourse[end][:s] == CS[:s_exit] end #while - if CS[:id]==0 + if csId==0 testFlag = true else testFlag = false # for testing @@ -628,40 +539,40 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag currentStepSize = settings.stepSize / 10.0^cycle # end 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",csId," 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] - 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",csId," 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[1] - testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest[1]) # for testing + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] + testFlag && println("in CS",csId," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPOI=",nextPointOfInterest[:s]) # for testing if settings.stepVariable == :distance - currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s] + currentStepSize = nextPointOfInterest[:s] - drivingCourse[end-1][:s] else currentStepSize = settings.stepSize / 10.0^cycle end elseif 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",csId," diminishing cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing break - elseif drivingCourse[end][:s] == nextPointOfInterest[1] - testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest[1]) # for testing + elseif drivingCourse[end][:s] == nextPointOfInterest[:s] + testFlag && println("in CS",csId," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," == nextPOI=",nextPointOfInterest[:s]) # 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 + testFlag && println("in CS",csId," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," == F_R=",drivingCourse[end][:F_R]) # for testing break elseif drivingCourse[end][:v] == 0.0 - error("ERROR: The train stops during diminishing run in CS",CS[:id]," at position s=",drivingCourse[end][:s]," m because the maximum tractive effort is lower than the resistant forces.", + error("ERROR: The train stops during diminishing run in CS",csId," at position s=",drivingCourse[end][:s]," m 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", " 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.") else - error("ERROR during diminishing run: With the step variable ",settings.stepVariable," the while loop will be left although s+s_braking0.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_braking0.0 in CS",csId," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s") end # delete last support point for recalculating the last step with reduced step size pop!(drivingCourse) @@ -671,51 +582,41 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag pointOfInterestReached = false targetSpeedReached = false tractionDeficit = true - endOfCSReached = 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 - error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.", + testFlag && println("in CS",csId," diminishing cycle",cycle," case: v=", drivingCourse[end][:v]," <= 0.0") # for testing + error("ERROR: The train stops during diminishing run in CS",csId," 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", " 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 + testFlag && println("in CS",csId," 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) pointOfInterestReached = false targetSpeedReached = false tractionDeficit = true - endOfCSReached = false - 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 - drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] + testFlag && println("in CS",csId," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[:s]=",nextPointOfInterest[:s]) # for testing + drivingCourse[end][:s] = nextPointOfInterest[:s] # round s down to nextPointOfInterest 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",csId," diminishing cycle",cycle," case: F_T=", drivingCourse[end][:F_T]," >= F_R=", drivingCourse[end][:F_R]) # for testing 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 + testFlag && println("in CS",csId," 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[1]=",nextPointOfInterest[1]) # for testing - - # if drivingCourse[end][:s] + s_braking == CS[:s_exit] - # brakingStartReached = true - # end + #println(" and s=", drivingCourse[end][:s]," <= nextPointOfInterest[:s]=",nextPointOfInterest[:s]) # for testing end #if - - # # TODO is it possible to put this into to the if-fork? - # if drivingCourse[end][:s] == CS[:s_exit] - # endOfCSReached = true - # end end #if end #for - if drivingCourse[end][:s] == nextPointOfInterest[1] - drivingCourse[end][:label] = nextPointOfInterest[2] + endOfCSReached = drivingCourse[end][:s] == CS[:s_exit] + if drivingCourse[end][:s] == nextPointOfInterest[:s] + drivingCourse[end][:label] = nextPointOfInterest[:label] end end #while end @@ -725,21 +626,23 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag stateFlags[:brakingStartReached] = brakingStartReached stateFlags[:tractionDeficit] = tractionDeficit stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0 - stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_peak] + stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_limit] stateFlags[:error] = !(endOfCSReached || brakingStartReached || !tractionDeficit) - return (CS, drivingCourse, stateFlags) + return (drivingCourse, stateFlags) end #function addDiminishingSection! ## 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 -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 - # with getCurrentSpeedLimit +function addCoastingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train) + CS = CSs[csId] # conditions for coasting section - targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) + previousSpeedLimitReached = lowestSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] > lowestSpeedLimit[:v] + speedLimitReached = drivingCourse[end][:v] > CS[:v_limit] + targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] || previousSpeedLimitReached || speedLimitReached endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached] s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) @@ -751,28 +654,32 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: drivingCourse[end][:behavior] = drivingMode while !targetSpeedReached && !endOfCSReached && !brakingStartReached - currentStepSize=settings.stepSize # initialize the step size that can be reduced near intersections - nextPointOfInterest[1] = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] + currentStepSize = settings.stepSize # initialize the step size that can be reduced near intersections + nextPointOfInterest[:s] = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] 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 !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] + if drivingCourse[end][:s] >= lowestSpeedLimit[:s_end] + # could be asked after creating an support point. This way here prevents even a minimal exceedance of speed limit. + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) + end + # traction effort and resisting forces (in N): - calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, drivingMode, train, settings.massModel) # acceleration (in m/s^2): drivingCourse[end][:a] = acceleration(drivingCourse[end][:F_T], drivingCourse[end][:F_R], train.m_train_full, train.ξ_train) # create the next support point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) + push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, csId)) drivingCourse[end][:behavior] = drivingMode # conditions for the next while cycle s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] - targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] || drivingCourse[end][:v] > CS[:v_peak] + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] + targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] || drivingCourse[end][:v] > CS[:v_limit] || lowestSpeedLimit[:v] < CS[:v_limit] && (drivingCourse[end][:v] > lowestSpeedLimit[:v] || (drivingCourse[end][:v] == lowestSpeedLimit[:v] && drivingCourse[end][:s] < lowestSpeedLimit[:s_end])) end # while testFlag = false @@ -780,47 +687,48 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < settings.approxLevel+1 if drivingCourse[end][:s] + s_braking > CS[:s_exit] - testFlag && println("in CS",CS[:id]," coasting 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",csId," coasting 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[1] - testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing - + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] + testFlag && println("in CS",csId," coasting cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest[:s]=",nextPointOfInterest[:s]) # for testing if settings.stepVariable == :distance - currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s] + currentStepSize = nextPointOfInterest[:s] - drivingCourse[end-1][:s] else currentStepSize = settings.stepSize / 10.0^cycle end elseif drivingCourse[end][:v] < CS[:v_exit] # TODO: if accelereation and coasting functions will be combined this case is only for coasting - testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," < v_exit=", CS[:v_exit]) # for testing - if settings.stepVariable == :velocity - currentStepSize = drivingCourse[end-1][:v] - CS[:v_exit] - else - currentStepSize = settings.stepSize / 10.0^cycle - end - elseif drivingCourse[end][:v] > CS[:v_peak] - testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," > v_peak=", CS[:v_peak]) # for testing + testFlag && println("in CS",csId," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," < v_exit=", CS[:v_exit]) # for testing if settings.stepVariable == :velocity - currentStepSize = CS[:v_peak] - drivingCourse[end-1][:v] + currentStepSize = drivingCourse[end-1][:v] - CS[:v_exit] else currentStepSize = settings.stepSize / 10.0^cycle end + + elseif drivingCourse[end][:v] > lowestSpeedLimit[:v] + testFlag && println("in CS",csId," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," > v_lowestLimit=", lowestSpeedLimit[:v]) # for testing + if settings.stepVariable == :velocity + currentStepSize = lowestSpeedLimit[:v] - drivingCourse[end-1][:v] + else + currentStepSize = settings.stepSize / 10.0^cycle + end + elseif drivingCourse[end][:s] + s_braking == CS[:s_exit] - testFlag && println("in CS",CS[:id]," coasting 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",csId," coasting cycle",cycle," case: s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," == s_exit=",CS[:s_exit]) # for testing break elseif drivingCourse[end][:v] == CS[:v_exit] - testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," == v_exit=", CS[:v_exit]) # for testing + testFlag && println("in CS",csId," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," == v_exit=", CS[:v_exit]) # for testing break - elseif drivingCourse[end][:s] == nextPointOfInterest[1] - testFlag && println("in CS",CS[:id]," coasting cycle",cycle," case: s =", drivingCourse[end][:s]," > nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing + elseif drivingCourse[end][:s] == nextPointOfInterest[:s] + testFlag && println("in CS",csId," coasting cycle",cycle," case: s =", drivingCourse[end][:s]," > nextPointOfInterest[:s]=",nextPointOfInterest[:s]) # for testing break else # 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 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] > lowestSpeedLimit[:v] # if the train gets to fast it has to brake to hold the velocity limit # delete last support point because it went to far pop!(drivingCourse) # conditions for the next for cycle brakingStartReached = false pointOfInterestReached = false - # targetSpeedReached = true + if lowestSpeedLimit[:v] != CS[:v_limit] + previousSpeedLimitReached = true + else + speedLimitReached = true + end - elseif drivingCourse[end][:s] > nextPointOfInterest[1] - drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] + drivingCourse[end][:s] = nextPointOfInterest[:s] # round s down to nextPointOfInterest else # do nothing for example for drivingCourse[end][:s] + s_braking == CS[:s_exit] end end end #for - if drivingCourse[end][:s] == nextPointOfInterest[1] - drivingCourse[end][:label] = nextPointOfInterest[2] + endOfCSReached = drivingCourse[end][:s] == CS[:s_exit] + if drivingCourse[end][:s] == nextPointOfInterest[:s] + drivingCourse[end][:label] = nextPointOfInterest[:label] end end #while - - stateFlags[:speedLimitReached] = false end # set state flags @@ -877,15 +788,19 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: stateFlags[:brakingStartReached] = brakingStartReached stateFlags[:tractionDeficit] = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0 - stateFlags[:error] = !(endOfCSReached || brakingStartReached || stateFlags[:tractionDeficit] || previousSpeedLimitReached || targetSpeedReached) + stateFlags[:previousSpeedLimitReached] = previousSpeedLimitReached + stateFlags[:speedLimitReached] = speedLimitReached + stateFlags[:error] = !(endOfCSReached || brakingStartReached || stateFlags[:tractionDeficit] || previousSpeedLimitReached || speedLimitReached) - return (CS, drivingCourse, stateFlags) + return (drivingCourse, stateFlags) end #function addCoastingSection! ## This function calculates the support points of the braking section. # 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!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train) + CS = CSs[csId] + # conditions for braking section targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached] @@ -898,13 +813,12 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D while !targetSpeedReached && !endOfCSReached currentStepSize = settings.stepSize # initialize the step size that can be reduced near intersections nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s]) - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] 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 !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] # traction effort and resisting forces (in N): - calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, drivingMode, train, settings.massModel) # acceleration (in m/s^2): drivingCourse[end][:a] = train.a_braking @@ -913,18 +827,16 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D 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 support point and set it for the values of s_exit and v_exit push!(drivingCourse, SupportPoint()) - drivingCourse[end][:i] = drivingCourse[end-1][:i]+1 drivingCourse[end][:behavior] = drivingMode recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) else # create the next support point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, CS[:id])) + push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, csId)) drivingCourse[end][:behavior] = drivingMode end - #println(drivingCourse[end][:i],". s=",drivingCourse[end][:s]," s_exit=", CS[:s_exit]," v_exit=", CS[:v_exit]," v=",drivingCourse[end][:v]) # conditions for the next while cycle - pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[1] + pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest[:s] endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] targetSpeedReached = drivingCourse[end][:v] <= CS[:v_exit] end # while @@ -938,26 +850,28 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D else currentStepSize = settings.stepSize / 10.0^cycle end - elseif drivingCourse[end][:s] > nextPointOfInterest[1] + + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] if settings.stepVariable == :distance - currentStepSize = nextPointOfInterest[1] - drivingCourse[end-1][:s] + currentStepSize = nextPointOfInterest[:s] - drivingCourse[end-1][:s] else currentStepSize = settings.stepSize / 10.0^cycle end + elseif drivingCourse[end][:v] == CS[:v_exit] && drivingCourse[end][:s] == CS[:s_exit] break + elseif drivingCourse[end][:v] == CS[:v_exit] recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) endOfCSReached = true - # println(" with a=", drivingCourse[end-1][:a]) # for testing break + elseif drivingCourse[end][:s] == CS[:s_exit] - # println("during braking section in CS",CS[:id],": rounding v down from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) targetSpeedReached = true - # println(" with a=", drivingCourse[end-1][:a]) # for testing break - elseif drivingCourse[end][:s] == nextPointOfInterest[1] + + elseif drivingCourse[end][:s] == nextPointOfInterest[:s] break end @@ -972,169 +886,110 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D else # if the level of approximation is reached if drivingCourse[end][:v] < 0.0 # TODO: drivingCourse[end][:v] < CS[:v_exit] should be enough - # reset last point with setting v=v_exit - # println("during braking section in CS",CS[:id],": rounding v up from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing + # reset last point with setting v=v_exit. still possible with v_exit now meaning v_exitMax? + # println("during braking section in CS",csId,": rounding v up from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], 0.0) endOfCSReached = true break elseif drivingCourse[end][:s] > CS[:s_exit] - # println("during braking section in CS",CS[:id],": rounding s down from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing + # println("during braking section in CS",csId,": rounding s down from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing # recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) drivingCourse[end][:s] = CS[:s_exit] break - elseif drivingCourse[end][:s] > nextPointOfInterest[1] - drivingCourse[end][:s] = nextPointOfInterest[1] # round s down to nextPointOfInterest + elseif drivingCourse[end][:s] > nextPointOfInterest[:s] + drivingCourse[end][:s] = nextPointOfInterest[:s] # round s down to nextPointOfInterest break elseif drivingCourse[end][:v] == CS[:v_exit] && drivingCourse[end][:s] == CS[:s_exit] break elseif drivingCourse[end][:v] < CS[:v_exit] # reset last point with setting v=v_exit - # println("during braking section in CS",CS[:id],": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing + # println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) endOfCSReached = true break elseif drivingCourse[end][:v] == CS[:v_exit] - # println("during braking section in CS",CS[:id],": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing + # println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) endOfCSReached = true break elseif drivingCourse[end][:s] == CS[:s_exit] - # println("during braking section in CS",CS[:id],": rounding v down from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing + # println("during braking section in CS",csId,": rounding v down from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit]) targetSpeedReached = true break else - # do nothing for example for drivingCourse[end][:s]==nextPointOfInterest[1] + # do nothing for example for drivingCourse[end][:s]==nextPointOfInterest[:s] end end end #for - if drivingCourse[end][:s] == nextPointOfInterest[1] - drivingCourse[end][:label] = nextPointOfInterest[2] + if drivingCourse[end][:s] == nextPointOfInterest[:s] + drivingCourse[end][:label] = nextPointOfInterest[:label] end end #while end # else: return the characteristic section without a braking section # set state flags - currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length) - stateFlags[:previousSpeedLimitReached] = currentSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= currentSpeedLimit[:v] + lowestSpeedLimit = getLowestSpeedLimit(CSs, csId, drivingCourse[end][:s], train.length) + stateFlags[:previousSpeedLimitReached] = lowestSpeedLimit[:v] != CS[:v_limit] && drivingCourse[end][:v] >= lowestSpeedLimit[:v] stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_exit] stateFlags[:endOfCSReached] = endOfCSReached stateFlags[:error] = !(endOfCSReached) - calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, "default", train, settings.massModel) stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0 - return (CS, drivingCourse, stateFlags) + return (drivingCourse, stateFlags) end #function addBrakingSection! ## This function calculates the support point of the halt. # 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!(drivingCourse::Vector{Dict}, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train) + # CS = CSs[csId] # is not needed here if drivingCourse[end][:v] == 0.0 drivingMode = "halt" drivingCourse[end][:behavior] = drivingMode # traction effort and resisting forces (in N) - calculateForces!(drivingCourse[end], CSs, CS[:id], drivingMode, train, settings.massModel) + calculateForces!(drivingCourse[end], CSs, csId, drivingMode, train, settings.massModel) end # else: return the characteristic section without a halt section section - return (CS, drivingCourse) + return drivingCourse end #function addHalt! function recalculateLastBrakingPoint!(drivingCourse, s_target, v_target) currentPoint = drivingCourse[end] previousPoint = drivingCourse[end-1] - # set s and v - currentPoint[:s] = s_target # position (in m) - currentPoint[:v] = v_target # velocity (in m/s) + # set s and v + currentPoint[:s] = s_target # position (in m) + currentPoint[:v] = v_target # velocity (in m/s) # calculate other values previousPoint[:a] = brakingAcceleration(previousPoint[:v], currentPoint[:v], currentPoint[:s]-previousPoint[:s]) # # TODO: just for testing # if 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 ",csId, " with a=",previousPoint[:a] ," > ",train.a_braking) # end currentPoint[:t] = previousPoint[:t] + Δt_with_Δv(currentPoint[:v]-previousPoint[:v], previousPoint[:a]) # point in time (in s) end #function recalculateLastBrakingPoint ## define the intersection velocities between the characterisitc sections to secure braking behavior function secureBrakingBehavior!(CSs::Vector{Dict}, a_braking::Real, approxLevel::Integer) - # limit 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 velocities of the characteristic sections to secure that the train stops at the moving sections end csId = length(CSs) - followingCSv_entry = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s + v_entryFollowing = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s while csId >= 1 + # calculate the maximum possible entry velocity to define the previous section's maximum allowed exit velocity CS = CSs[csId] - CS[:v_exit] = min(CS[:v_limit], followingCSv_entry) + CS[:v_exit] = min(CS[:v_limit], v_entryFollowing) - v_entryMax = brakingStartVelocity(CS[:v_exit], a_braking, CS[:length], approxLevel) + v_entry = brakingStartVelocity(CS[:v_exit], a_braking, CS[:s_exit]-CS[:s_entry], approxLevel) - CS[:v_entry] = min(CS[:v_limit], v_entryMax) - CS[:v_peak] = CS[:v_entry] + v_entryFollowing = min(CS[:v_limit], v_entry) - followingCSv_entry = CS[:v_entry] csId = csId - 1 end #while return CSs end #function secureBrakingBehavior! - -## define the intersection velocities between the characterisitc sections to secure accelerating behavior -function secureAcceleratingBehavior!(CSs::Vector{Dict}, settings::Settings, train::Train) - # limit the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises afterwards - - CSs[1][:v_entry] = 0.0 # the entry velocity of the first characteristic section is 0.0 m/s - startingPoint = SupportPoint() - startingPoint[:i] = 1 - - previousCSv_exit = CSs[1][:v_entry] - for CS in CSs - CS[:v_entry] = min(CS[:v_entry], previousCSv_exit) - startingPoint[:s] = CS[:s_entry] - startingPoint[:v] = CS[:v_entry] - calculateForces!(startingPoint, CSs, CS[:id], "accelerating", train, settings.massModel) # traction effort and resisting forces (in N) - acceleratingCourse::Vector{Dict} = [startingPoint] # List of support points - - if CS[:v_entry] < CS[:v_peak] - # conditions for entering the accelerating phase - stateFlags = Dict(:endOfCSReached => false, - :brakingStartReached => false, - :tractionDeficit => false, - :resistingForceNegative => false, - :previousSpeedLimitReached => false, - :speedLimitReached => false, - :error => false, - :usedForDefiningCharacteristics => true) # because usedForDefiningCharacteristics == true the braking distance will be ignored during securing the accelerating phase - v_peak = CS[:v_entry] - (CS, acceleratingCourse, stateFlags) = addBreakFreeSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) - while !stateFlags[:speedLimitReached] && !stateFlags[:endOfCSReached] - if !stateFlags[:tractionDeficit] - if !stateFlags[:previousSpeedLimitReached] - (CS, acceleratingCourse, stateFlags) = addAcceleratingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function changes the acceleratingCourse - - elseif stateFlags[:previousSpeedLimitReached] - (CS, acceleratingCourse, stateFlags) = addClearingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function is needed in case the train is not allowed to accelerate because of a previous speed limit - end - else - if settings.massModel == :mass_point || acceleratingCourse[end][:s] > CS[:s_entry] + train.length - break - else - (CS, acceleratingCourse, stateFlags) = addDiminishingSection!(CS, acceleratingCourse, stateFlags, settings, train, CSs) # this function is needed in case the resisitng forces are higher than the maximum possible tractive effort - end - end - v_peak = max(v_peak, acceleratingCourse[end][:v]) - end - - # CS[:v_peak] = max(CS[:v_entry], acceleratingCourse[end][:v]) - CS[:v_peak] = v_peak - CS[:v_exit] = min(CS[:v_exit], CS[:v_peak], acceleratingCourse[end][:v]) - else #CS[:v_entry] == CS[:v_peak] - # v_exit stays the same - end #if - - previousCSv_exit = CS[:v_exit] - end #for - - return CSs -end #function secureAcceleratingBehavior! diff --git a/src/calc.jl b/src/calc.jl index c97d744..b07ae21 100644 --- a/src/calc.jl +++ b/src/calc.jl @@ -7,109 +7,99 @@ # 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 -function calculateMinimumRunningTime!(CSs::Vector{Dict}, settings::Settings, train::Train) - - 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 ! ! !") - end # TODO - +function calculateMinimumRunningTime(CSs::Vector{Dict}, settings::Settings, train::Train) startingPoint = SupportPoint() - 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 support points for csId in 1:length(CSs) CS = CSs[csId] - # for testing: # TODO - 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 - # 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) - calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) # tractive effort and resisting forces (in N) + calculateForces!(drivingCourse[end], CSs, csId, "default", train, settings.massModel) # tractive effort and resisting forces (in N) previousSpeedLimitReached = false stateFlags = Dict(:endOfCSReached => drivingCourse[end][:s] > CS[:s_exit], :brakingStartReached => drivingCourse[end][:s] + s_braking == CS[:s_exit], :tractionDeficit => drivingCourse[end][:F_T] < drivingCourse[end][:F_R], # or add another flag for equal forces? :resistingForceNegative => drivingCourse[end][:F_R] < 0.0, - :previousSpeedLimitReached => false, #speedLimitReached, # check already at this position? + :previousSpeedLimitReached => false, :speedLimitReached => drivingCourse[end][:v] > CS[:v_limit], :error => false) - # determine the behavior sections for this characteristic section. It has to be at least one of those BS: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "halt") - while !stateFlags[:endOfCSReached] # s < s_exit - if !stateFlags[:brakingStartReached] # s+s_braking < s_exit - if !stateFlags[:tractionDeficit] - if drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && drivingCourse[end][:v] == 0.0 - (CS, drivingCourse, stateFlags) = addBreakFreeSection!(CS, drivingCourse, stateFlags, settings, train, CSs) - - elseif stateFlags[:previousSpeedLimitReached] - (CS, drivingCourse, stateFlags) = addClearingSection!(CS, drivingCourse, stateFlags, settings, train, CSs) - - elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached] - (CS, drivingCourse, stateFlags) = addAcceleratingSection!(CS, drivingCourse, stateFlags, settings, train, CSs) - - elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached] - # cruise only one step - if settings.stepVariable == :distance - s_cruising = settings.stepSize - elseif settings.stepVariable == time - s_cruising = Δs_with_Δt(settings.stepSize, drivingCourse[end][:a], drivingCourse[end][:v]) - elseif settings.stepVariable == velocity - s_cruising = train.length/(10.0) # TODO which step size should be used? - end - (CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising") - - elseif drivingCourse[end][:F_R] < 0 && stateFlags[:speedLimitReached] - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking - - if s_cruising > 0.0 - (CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "downhillBraking") - else - stateFlags[:brakingStartReached] = true - end - - elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] || stateFlags[:speedLimitReached] - s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) - s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking - - if s_cruising > 1/10^(settings.approxLevel) # TODO: define another minimum cruising length? - (CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising") - else - stateFlags[:brakingStartReached] = true - end - else - error() - end - elseif stateFlags[:tractionDeficit] - (CS, drivingCourse, stateFlags) = addDiminishingSection!(CS, drivingCourse, stateFlags, settings, train, CSs) - - else - error() + # determine the behavior sections for this characteristic section. It has to be at least one of those BS: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "halt") + while !stateFlags[:endOfCSReached] # s < s_exit + if stateFlags[:error] + error("ERROR in calc in CS",csId,": BS=",drivingCourse[end][:behavior]," s=",drivingCourse[end][:s]," s_braking=",s_braking," v_limit=",CS[:v_limit]," v=",drivingCourse[end][:v]," v_exit=",CS[:v_exit]," with the flags: endOfCS: ",stateFlags[:endOfCSReached]," brakingStart: ",stateFlags[:brakingStartReached]," F_T drivingCourse[end][:F_R] && drivingCourse[end][:v] == 0.0 + (drivingCourse, stateFlags) = addBreakFreeSection!(drivingCourse, stateFlags, CSs, csId, settings, train) - # set state flag - stateFlags[:endOfCSReached] = true + elseif stateFlags[:previousSpeedLimitReached] + (drivingCourse, stateFlags) = addClearingSection!(drivingCourse, stateFlags, CSs, csId, settings, train) + + elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached] + (drivingCourse, stateFlags) = addAcceleratingSection!(drivingCourse, stateFlags, CSs, csId, settings, train) + + elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached] + # cruise only one step + if settings.stepVariable == :distance + s_cruising = settings.stepSize + elseif settings.stepVariable == time + s_cruising = Δs_with_Δt(settings.stepSize, drivingCourse[end][:a], drivingCourse[end][:v]) + elseif settings.stepVariable == velocity + s_cruising = train.length/(10.0) # TODO which step size should be used? + end + (drivingCourse, stateFlags) = addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, "cruising", s_cruising) + + elseif drivingCourse[end][:F_R] < 0 && stateFlags[:speedLimitReached] + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) + s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking + + if s_cruising > 0.0 + (drivingCourse, stateFlags) = addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, "downhillBraking", s_cruising) + else + stateFlags[:brakingStartReached] = true + end + + elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] || stateFlags[:speedLimitReached] + s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel) + s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking + + if s_cruising > 1/10^(settings.approxLevel) # TODO: define another minimum cruising length? + (drivingCourse, stateFlags) = addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, "cruising", s_cruising) + else + stateFlags[:brakingStartReached] = true + end + else + error() + end + elseif stateFlags[:tractionDeficit] + (drivingCourse, stateFlags) = addDiminishingSection!(drivingCourse, stateFlags, CSs, csId, settings, train) + + else + error() + end + else#if !stateFlags[:endOfCSReached] # s < s_exit + (drivingCourse, stateFlags) = addBrakingSection!(drivingCourse, stateFlags, CSs, csId, settings, train) + #else + # error() + end + + if CS[:s_exit] - drivingCourse[end][:s] < 1/10^(settings.approxLevel) + drivingCourse[end][:s] = CS[:s_exit] # round s up to CS[:s_exit] + + # set state flag + stateFlags[:endOfCSReached] = true + end end - end - #if s == s_exit - # halt - #end + #if s == s_exit + # halt + #end # for testing: # TODO @@ -121,9 +111,9 @@ function calculateMinimumRunningTime!(CSs::Vector{Dict}, settings::Settings, tra end end #for - (CSs[end], drivingCourse) = addHalt!(CSs[end], drivingCourse, settings, train, CSs) + drivingCourse = addHalt!(drivingCourse, CSs, length(CSs), settings, train) - return (CSs, drivingCourse) + return drivingCourse end #function calculateMinimumRunningTime @@ -232,7 +222,6 @@ function moveAStep(previousPoint::Dict, stepVariable::Symbol, stepSize::Real, cs # create the next support point newPoint = SupportPoint() - newPoint[:i] = previousPoint[:i]+1 # identifier # calculate s, t, v, E if stepVariable == :distance # distance step method @@ -287,7 +276,7 @@ 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 getCurrentSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::Real, trainLength::Real) +function getLowestSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::Real, trainLength::Real) v_limit = CSs[csWithTrainHeadId][:v_limit] s_exit = CSs[csWithTrainHeadId][:s_exit] if csWithTrainHeadId > 1 && s -trainLength < CSs[csWithTrainHeadId][:s_entry] @@ -300,17 +289,17 @@ function getCurrentSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s:: formerCsId = formerCsId -1 end end - currentSpeedLimit = Dict(:v => v_limit, :s_end => s_exit + trainLength) - return currentSpeedLimit -end #function getCurrentSpeedLimit + lowestSpeedLimit = Dict(:v => v_limit, :s_end => s_exit + trainLength) + return lowestSpeedLimit +end #function getLowestSpeedLimit """ TODO """ -function getNextPointOfInterest(pointsOfInterest::Vector{Tuple}, s::Real) +function getNextPointOfInterest(pointsOfInterest::Vector{NamedTuple}, s::Real) for POI in pointsOfInterest - if POI[1] > s + if POI[:s] > s return POI end end @@ -321,22 +310,20 @@ end #function getNextPointOfInterest ## 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) # determine the positions of the points of interest depending on the interesting part of the train (front/rear) and the train's length - ##TODO: use a tuple with naming - pointsOfInterest = Tuple[] + pointsOfInterest = NamedTuple[] 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]) ) + push!(pointsOfInterest, (s = s_poi, label = POI[:label]) ) end - sort!(pointsOfInterest, by = x -> x[1]) + sort!(pointsOfInterest, by = x -> x[:s]) end 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 diff --git a/src/constructors.jl b/src/constructors.jl index 7d93711..3216467 100644 --- a/src/constructors.jl +++ b/src/constructors.jl @@ -614,59 +614,52 @@ function Train(file, type = :YAML) end #function Train() # outer constructor ## create the moving section's characteristic sections -function CharacteristicSections(path::Path, v_trainLimit::Real, s_trainLength::Real, MS_poi::Vector{Tuple}) +function CharacteristicSections(path::Path, v_trainLimit::Real, s_trainLength::Real, MS_poi::Vector{NamedTuple}) # create and return the characteristic sections of a moving section dependent on the paths attributes - CSs=Vector{Dict}() + CSs = Vector{Dict}() s_csStart = path.sections[1][:s_start] # first position (in m) - csId = 1 + #csId = 1 for row in 2:length(path.sections) previousSection = path.sections[row-1] currentSection = path.sections[row] speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp] if speedLimitIsDifferent || pathResistanceIsDifferent - push!(CSs, CharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, MS_poi)) + push!(CSs, CharacteristicSection(s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, MS_poi)) s_csStart = currentSection[:s_start] - csId = csId+1 + #csId = csId+1 end #if end #for - push!(CSs, CharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, MS_poi)) + push!(CSs, CharacteristicSection(s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, MS_poi)) return CSs end #function CharacteristicSections -## 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}) +## create a characteristic section for a path section. +function CharacteristicSection(s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, MS_poi::Vector{NamedTuple}) # Create and return a characteristic section dependent on the paths attributes - characteristicSection::Dict{Symbol, Any} = Dict(:id => id, # identifier - :s_entry => s_entry, # first position (in m) + characteristicSection::Dict{Symbol, Any} = Dict(:s_entry => s_entry, # first position (in m) :s_exit => section[:s_end], # last position (in m) - :length => section[:s_end] -s_entry, # total length (in m) :r_path => section[:f_Rp], # path resistance (in ‰) :v_limit => v_limit, # speed limit (in m/s) - # initializing :v_entry, :v_peak and :v_exit with :v_limit - :v_peak => v_limit, # maximum reachable speed (in m/s) - :v_entry => v_limit, # maximum entry speed (in m/s) - :v_exit => v_limit) # maximum exit speed (in m/s) + :v_exit => v_limit) # maximum exit speed (in m/s) initialized with v_limit - # list of positions of every point of interest (POI) in this charateristic section for which support points should be calculated + # get the list of positions of every point of interest (POI) in this charateristic section for which support points should be calculated from the list of the whole moving section's POI s_exit = characteristicSection[:s_exit] - - ##TODO: use a tuple with naming - pointsOfInterest = Tuple[] + CS_poi = NamedTuple[] if !isempty(MS_poi) for POI in MS_poi - s_poi = POI[1] + s_poi = POI[:s] if s_entry < s_poi && s_poi <= s_exit - push!(pointsOfInterest, (POI)) + push!(CS_poi, POI) end end end - if isempty(pointsOfInterest) || pointsOfInterest[end][1] < s_exit - push!(pointsOfInterest, (s_exit,"")) # s_exit has to be the last POI so that there will always be a POI to campare the current position with + if isempty(CS_poi) || CS_poi[end][:s] < s_exit + push!(CS_poi, (s = s_exit, label = "")) # s_exit has to be the last POI so that there will always be a POI to campare the current position with end - merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest)) + merge!(characteristicSection, Dict(:pointsOfInterest => CS_poi)) return characteristicSection end #function CharacteristicSection @@ -676,9 +669,8 @@ a SupportPoint is the smallest element of the driving course. One step of the st """ function SupportPoint() supportPoint = Dict( - :i => 0, # identifier and counter variable of the driving course :behavior => "", # type of behavior section the support point is part of - see BehaviorSection() - # 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 + # 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) :t => 0.0, # point in time (in s) :v => 0.0, # velocity (in m/s) diff --git a/src/output.jl b/src/output.jl index a77688a..e77e350 100644 --- a/src/output.jl +++ b/src/output.jl @@ -4,7 +4,7 @@ # __copyright__ = "2020-2022" # __license__ = "ISC" -function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfInterest::Vector{Tuple}) +function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfInterest::Vector{NamedTuple}) if settings.outputDetail == :running_time output::Vector{Dict} = [Dict(:t => drivingCourse[end][:t])] @@ -19,7 +19,7 @@ function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfI supportPoint = 1 for POI in 1:length(pointsOfInterest) while supportPoint <= length(drivingCourse) - if pointsOfInterest[POI][1] == drivingCourse[supportPoint][:s] + if pointsOfInterest[POI][:s] == drivingCourse[supportPoint][:s] push!(output, drivingCourse[supportPoint]) break end