From 2983b2c2e1dfac9d01de48c5b814e159de962195 Mon Sep 17 00:00:00 2001 From: Max Kannenberg <95709892+MaxKannenberg@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:10:21 +0200 Subject: [PATCH] Fix mass model "homogeneous strip" for distance and time step methods --- .../settings_distanceStep_homStrip.yaml | 12 ++ data/settings/settings_timeStep_homStrip.yaml | 12 ++ src/Behavior.jl | 130 ++++++++++++++---- src/Characteristics.jl | 48 +++++-- src/EnergySaving.jl | 1 + src/TrainRunCalc.jl | 29 ++-- 6 files changed, 183 insertions(+), 49 deletions(-) create mode 100644 data/settings/settings_distanceStep_homStrip.yaml create mode 100644 data/settings/settings_timeStep_homStrip.yaml diff --git a/data/settings/settings_distanceStep_homStrip.yaml b/data/settings/settings_distanceStep_homStrip.yaml new file mode 100644 index 0000000..3ce88a1 --- /dev/null +++ b/data/settings/settings_distanceStep_homStrip.yaml @@ -0,0 +1,12 @@ +%YAML 1.2 +--- +settings: +# settings for the simulation + massModel: "homogeneous strip" # model type of train mass "mass point" or "homogeneous strip" + stepVariable: "s in m" # step variable of the step method "s in m", "t in s" or "v in m/s" + stepSize: 10 # step size (unit depends on stepVariable s in m, t in s and v in m/s) + operationModeMinimumRunningTime: true # operation mode "minimum running time" + operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption" + typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV" + detailOfOutput: "driving course" # should the output be "minimal", "points of interest" or "driving course"? + csvDirectory: "~/Desktop/TrainRun" diff --git a/data/settings/settings_timeStep_homStrip.yaml b/data/settings/settings_timeStep_homStrip.yaml new file mode 100644 index 0000000..9a07241 --- /dev/null +++ b/data/settings/settings_timeStep_homStrip.yaml @@ -0,0 +1,12 @@ +%YAML 1.2 +--- +settings: +# settings for the simulation + massModel: "homogeneous strip" # model type of train mass "mass point" or "homogeneous strip" + stepVariable: "t in s" # step variable of the step method "s in m", "t in s" or "v in m/s" + stepSize: 3.0 # step size (unit depends on stepVariable s in m, t in s and v in m/s) + operationModeMinimumRunningTime: true # operation mode "minimum running time" + operationModeMinimumEnergyConsumption: false # operation mode "minimum energy consumption" + typeOfOutput: "julia dictionary" # output as "julia dictionary" or as "CSV" + detailOfOutput: "driving course" # should the output be "minimal", "points of interest" or "driving course"? + csvDirectory: "~/Desktop/TrainRun" diff --git a/src/Behavior.jl b/src/Behavior.jl index 30e3936..91b7f90 100644 --- a/src/Behavior.jl +++ b/src/Behavior.jl @@ -15,7 +15,7 @@ export addBreakFreeSection!, addClearingSection!, addAcceleratingSection!, addCr calculateForces!, createDataPoint, # export functions from DrivingDynamics -calcBrakingDistance, calcBrakingStartVelocity +calcBrakingDistance, calcBrakingStartVelocity, calc_Δs_with_Δt approximationLevel = 6 # value for approximation to intersections TODO further explanation (e.g. approximationLevel = 3 -> with stepSize 10 m the approximation will be calculated accurate on 10 mm ; 1s -> 1 ms; 1 km/h -> 3.6 mm/s) @@ -552,46 +552,75 @@ end #function addAcceleratingSection! ## This function calculates the data points of the cruising section. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed. function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String) + trainIsClearing = cruisingType == "clearing" + trainIsBrakingDownhill = cruisingType == "downhillBraking" + # traction effort and resisting forces (in N) - calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) + if !trainIsBrakingDownhill # TODO: or just give BS[:type] instead of "cruising"/"braking"? + calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) + else + calculateForces!(drivingCourse[end], CSs, CS[:id], "braking", train, settings[:massModel]) + end + + if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics] + ignoreBraking = true + s_braking = 0.0 + else + ignoreBraking = false + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + end # conditions for cruising section - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + #s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] || stateFlags[:brakingStartReached] speedIsValid = drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] targetPositionReached = s_cruising == 0.0 + resistingForceNegative = drivingCourse[end][:F_R] < 0 +#println(" vor if speedIsValid=",speedIsValid ," brakingStartReached=", brakingStartReached," tractionDeficit=", tractionDeficit," targetPositionReached=", targetPositionReached) if speedIsValid && !brakingStartReached && !tractionDeficit && !targetPositionReached # 03/04 old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && !brakingStartReached && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] BS = createBehaviorSection(cruisingType, drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) drivingCourse[end][:behavior] = BS[:type] - trainIsClearing = BS[:type] == "clearing" - trainIsBrakingDownhill = BS[:type] == "downhillBraking" - # TODO: necessary? s_cruising = min(s_cruising, CS[:s_exit]-BS[:s_entry]) # traction effort and resisting forces (in N) - calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) # TODO: or give BS[:type] instead of "cruising"? +#03/25 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 if settings[:massModel]=="homogeneous strip" && CS[:id] > 1 # conditions for cruising section trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train[:length] targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising resistingForceNegative = drivingCourse[end][:F_R] < 0.0 +# 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 # 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 for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while trainInPreviousCS && targetPositionReached && !pointOfInterestReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used + while trainInPreviousCS && !targetPositionReached && !pointOfInterestReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used # 03/09 old: while drivingCourse[end][:s] < CS[:s_entry] + train[:length] && drivingCourse[end][:s] < BS[:s_entry] +s_cruising && drivingCourse[end][:s] < nextPointOfInterest && drivingCourse[end][:F_T]>=drivingCourse[end][:F_R] # the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS #TODO: maybe just consider former CS with different path resistance? + # 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 + drivingCourse[end][:F_T] = 0.0 + end + # acceleration (in m/s^2): drivingCourse[end][:a] = 0.0 @@ -606,7 +635,13 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: push!(BS[:dataPoints], drivingCourse[end][:i]) # traction effort and resisting forces (in N) - calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) + 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 # conditions for the next while cycle pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest # POIs include s_exit as well @@ -621,7 +656,10 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end][:F_R] < 0.0 + elseif !trainIsBrakingDownhill && resistingForceNegative + currentStepSize = settings[:stepSize] / 10.0^cycle + + elseif trainIsBrakingDownhill && !resistingForceNegative currentStepSize = settings[:stepSize] / 10.0^cycle elseif drivingCourse[end][:s] > nextPointOfInterest @@ -647,7 +685,10 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: elseif drivingCourse[end][:s] == nextPointOfInterest break - else # TODO copied from addAcceleratingSection -> probably not needed here !? + 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") end @@ -660,6 +701,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: tractionDeficit = false targetPositionReached = false trainInPreviousCS = true + resistingForceNegative = drivingCourse[end][:F_R] < 0.0 else # if the level of approximation is reached if drivingCourse[end][:s] > nextPointOfInterest @@ -674,8 +716,13 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: break elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R] break - elseif drivingCourse[end][:F_R] < 0.0 + elseif !trainIsBrakingDownhill && resistingForceNegative break + elseif trainIsBrakingDownhill && !resistingForceNegative + break + elseif !trainInPreviousCS + break + else end @@ -692,6 +739,17 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: while !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used # 03/09 old: while drivingCourse[end][:s] < BS[:s_entry]+s_cruising && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R] nextPointOfInterest = min(BS[:s_entry]+s_cruising, getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])) + + # 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 + drivingCourse[end][:F_T] = 0.0 + end + + + drivingCourse[end][:a] = 0.0 # acceleration (in m/s^2) # calculate the remaining cruising way @@ -703,7 +761,13 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: drivingCourse[end][:behavior] = BS[:type] push!(BS[:dataPoints], drivingCourse[end][:i]) - calculateForces!(drivingCourse[end], CSs, CS[:id], "cruising", train, settings[:massModel]) + 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 # conditions for the next while cycle targetPositionReached = drivingCourse[end][:s] >= BS[:s_entry] +s_cruising @@ -712,8 +776,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: end #while # TODO: realize this better inside the upper loops? - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] + # calculate the accumulated cruising section information merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) @@ -730,7 +793,9 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: # set state flags stateFlags[:endOfCSReached] = drivingCourse[end][:s] == CS[:s_exit] - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + if !ignoreBraking + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + end stateFlags[:brakingStartReached] = brakingStartReached || drivingCourse[end][:s] + s_braking >= CS[:s_exit] stateFlags[:tractionDeficit] = tractionDeficit stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0.0 @@ -746,11 +811,19 @@ end #function addCruisingSection! function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::Dict, settings::Dict, train::Dict, CSs::Vector{Dict}) calculateForces!(drivingCourse[end], CSs, CS[:id], "diminishing", train, settings[:massModel]) + if haskey(stateFlags, :usedForDefiningCharacteristics) && stateFlags[:usedForDefiningCharacteristics] + ignoreBraking = true + s_braking = 0.0 + else + ignoreBraking = false + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + end + # conditions for diminishing section targetSpeedReached = drivingCourse[end][:v] <= 0.0 endOfCSReached = drivingCourse[end][:s] >= CS[:s_exit] || stateFlags[:endOfCSReached] tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] #|| stateFlags[:tractionDeficit] - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + #s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] || stateFlags[:brakingStartReached] # use the conditions for the diminishing section @@ -777,11 +850,14 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag calculateForces!(drivingCourse[end], CSs, CS[:id], BS[:type], train, settings[:massModel]) # conditions for the next while cycle - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + if !ignoreBraking + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + end brakingStartReached = drivingCourse[end][:s] +s_braking >= CS[:s_exit] pointOfInterestReached = drivingCourse[end][:s] >= nextPointOfInterest targetSpeedReached = drivingCourse[end][:v] <= 0.0 tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] + endOfCSReached = drivingCourse[end][:s] == CS[:s_exit] end #while if CS[:id]==0 @@ -843,6 +919,7 @@ 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 @@ -860,6 +937,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag pointOfInterestReached = false targetSpeedReached = false tractionDeficit = true + endOfCSReached = false elseif drivingCourse[end][:s] > nextPointOfInterest testFlag && println("in CS",CS[:id]," diminishing cycle",cycle," case: s=", drivingCourse[end][:s]," > nextPointOfInterest=",nextPointOfInterest) # for testing @@ -880,10 +958,10 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag # end end #if - # TODO is it possible to put this into to the if-fork? - if drivingCourse[end][:s] == CS[:s_exit] - endOfCSReached = true - end + # # 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 end #while @@ -908,7 +986,7 @@ 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_exit] + stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_peak] stateFlags[:error] = !(endOfCSReached || brakingStartReached || !tractionDeficit) return (CS, drivingCourse, stateFlags) @@ -1028,7 +1106,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: pop!(BS[:dataPoints]) # conditions for the next for cycle - brakingStartReached = false + # brakingStartReached = true pointOfInterestReached = false targetSpeedReached = false @@ -1040,7 +1118,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:: # conditions for the next for cycle brakingStartReached = false pointOfInterestReached = false - targetSpeedReached = true + # targetSpeedReached = true elseif drivingCourse[end][:s] > nextPointOfInterest drivingCourse[end][:s] = nextPointOfInterest # round s down to nextPointOfInterest diff --git a/src/Characteristics.jl b/src/Characteristics.jl index 9ab339c..023e79f 100644 --- a/src/Characteristics.jl +++ b/src/Characteristics.jl @@ -17,7 +17,7 @@ function determineCharacteristics(path::Dict, train::Dict, settings::Dict) movingSection = createMovingSection(path, train[:v_limit]) movingSection = secureBrakingBehavior!(movingSection, train[:a_braking]) movingSection = secureAcceleratingBehavior!(movingSection, settings, train) - movingSection = secureCruisingBehavior!(movingSection, settings, train) + #movingSection = secureCruisingBehavior!(movingSection, settings, train) return movingSection end #function determineCharacteristics @@ -149,17 +149,28 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train: :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] && !stateFlags[:tractionDeficit] - if !stateFlags[:previousSpeedLimitReached] + 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) + 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] = 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 @@ -171,14 +182,13 @@ function secureAcceleratingBehavior!(movingSection::Dict, settings::Dict, train: CS[:behaviorSections] = Dict() CS[:E] = 0.0 CS[:t] = 0.0 - end #for return movingSection end #function secureAcceleratingBehavior! - +#= ## define the intersection velocities between the characterisitc sections to secure cruising behavior function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dict) # limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak @@ -198,7 +208,7 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic :previousSpeedLimitReached => false, :speedLimitReached => false, :error => false, - :usedForDefiningCharacteristics => true) # currently only used during the definition of the accelerating characteristics + :usedForDefiningCharacteristics => true) CS[:v_entry] = min(CS[:v_entry], previousCSv_exit) @@ -206,7 +216,23 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic startingPoint[:v] = CS[:v_peak] cruisingCourse::Vector{Dict} = [startingPoint] # List of data points - (CS, cruisingCourse, stateFlags) = addCruisingSection!(CS, cruisingCourse, stateFlags, CS[:length], settings, train, CSs, "cruising") # this function changes the cruisingCourse + while !stateFlags[:endOfCSReached] #&& s_cruising > 0.0 + if !stateFlags[:tractionDeficit] + s_cruising = CS[:s_exit] - cruisingCourse[end][:s] + if !stateFlags[:resistingForceNegative]# cruisingCourse[end][:F_R] >= 0 + (CS, cruisingCourse, stateFlags) = addCruisingSection!(CS, cruisingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising") # this function changes the cruisingCourse + else + (CS, cruisingCourse, stateFlags) = addCruisingSection!(CS, cruisingCourse, stateFlags, s_cruising, settings, train, CSs, "downhillBraking") + end + else + if settings[:massModel] == "mass point" || cruisingCourse[end][:s] > CS[:s_entry] + train[:length] + break + else + (CS, cruisingCourse, stateFlags) = addDiminishingSection!(CS, cruisingCourse, stateFlags, settings, train, CSs) # this function is needed in case the resisitng forces are higher than the maximum possible tractive effort + end + end + end + CS[:v_exit] = min(CS[:v_exit], cruisingCourse[end][:v]) previousCSv_exit = CS[:v_exit] @@ -219,5 +245,5 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic return movingSection end #function secureCruisingBehavior! - +=# end #module Characteristics diff --git a/src/EnergySaving.jl b/src/EnergySaving.jl index f5900ad..9d696ab 100644 --- a/src/EnergySaving.jl +++ b/src/EnergySaving.jl @@ -13,6 +13,7 @@ # TODO from 2022/01/19: Are here calculations that should be transferred to DrivingDynamics.jl? # TODO from 2022/01/22: use always copyCharacteristicSection and don't do it manually like "csModified=Dict(:id => csOriginal[:id], ..." three times # TODO from 2022/03/18: stateFlags need to be added to functions that add behavior sections +# TODO from 2022/03/21: consider previous speed limits during the coasting section in case F_R < 0.0 and the train is getting faster module EnergySaving diff --git a/src/TrainRunCalc.jl b/src/TrainRunCalc.jl index f1c744f..9c5e9d3 100644 --- a/src/TrainRunCalc.jl +++ b/src/TrainRunCalc.jl @@ -72,8 +72,8 @@ end # function calculateDrivingDynamics function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict) CSs::Vector{Dict} = movingSection[:characteristicSections] - if settings[:massModel] == "homogeneous strip" - println("WARNING: ! ! ! TrainRun.jl doesn't work reliably for the mass model homogeneous strip. This mass model should not be used ! ! !") + if settings[:massModel] == "homogeneous strip" && settings[:stepVariable] == "v in m/s" + println("WARNING: ! ! ! TrainRun.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 startingPoint=createDataPoint() @@ -115,20 +115,25 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train elseif stateFlags[:previousSpeedLimitReached] (CS, drivingCourse, stateFlags) = addClearingSection!(CS, drivingCourse, stateFlags, settings, train, CSs) - elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached] # v < v_limit + 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_R] < 0 && stateFlags[:speedLimitReached] # v < v_limit - if settings[:massModel] == "mass point" - s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) - s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking - elseif settings[:massModel] == "homogeneous strip" - # TODO: Add downhillBraking for homogeneous strip - error("Add downhillBraking for homogeneous strip !") - # cruise until F_R >= 0.0 + elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached] + # cruise only one step + if settings[:stepVariable] =="s in m" + s_cruising = settings[:stepSize] + elseif settings[:stepVariable] =="t in s" + s_cruising = calc_Δs_with_Δt(settings[:stepSize], drivingCourse[end][:a], drivingCourse[end][:v]) + elseif settings[:stepVariable] =="v in m/s" + 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") - if s_cruising > 0.0 # TODO: define a minimum cruising length? + elseif drivingCourse[end][:F_R] < 0 && stateFlags[:speedLimitReached] + s_braking = calcBrakingDistance(drivingCourse[end][:v], CS[:v_exit], train[:a_braking]) + s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking + + if s_cruising > 0.0 (CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "downhillBraking") else stateFlags[:brakingStartReached] = true