refactored functions, removed characteristics.jl, and unified naming in constructors.jl
parent
370e8cf812
commit
fab1ad017a
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -23,10 +23,18 @@ Categories: Added, Changed, Deprecated, Removed, Fixed, and Security.
|
|||
* renamed Validate.jl into types.jl
|
||||
* renamed TrainRunCalc.jl into calc.jl
|
||||
* moved trainrun function from calc.jl to TrainRun.jl
|
||||
* moved createDataPoint() from behavior.jl to types.jl
|
||||
* moved createBehaviorSection() from behavior.jl to types.jl
|
||||
* moved createMovingSection() from characteristics.jl to types.jl
|
||||
* moved createCharacteristicSection() from characteristics.jl to types.jl
|
||||
* moved createDataPoint() from behavior.jl to constructors.jl
|
||||
* moved createBehaviorSection() from behavior.jl to constructors.jl
|
||||
* moved createMovingSection() from characteristics.jl to constructors.jl
|
||||
* moved createCharacteristicSection() from characteristics.jl to constructors.jl
|
||||
* removed characteristics.jl and moved all functions inside to behavior.jl
|
||||
* moved calculateTractiveEffort() from behavior.jl to calc.jl
|
||||
* moved calculatePathResistance() from behavior.jl to calc.jl
|
||||
* moved calculateForces!() from behavior.jl to calc.jl
|
||||
* moved moveAStep() from behavior.jl to calc.jl
|
||||
* moved getCurrentSpeedLimit() from behavior.jl to calc.jl
|
||||
* moved getNextPointOfInterest() from behavior.jl to calc.jl
|
||||
* moved determineCharacteristics() from behavior.jl to calc.jl
|
||||
* changed title of include files from upper case to lower case
|
||||
* changed seperation of submodules into a single module with file include
|
||||
* updated test files to railtoolkit/schema (2022.05)
|
||||
|
|
|
@ -27,7 +27,6 @@ include("types.jl")
|
|||
include("constructors.jl")
|
||||
include("formulary.jl")
|
||||
include("calc.jl")
|
||||
include("characteristics.jl")
|
||||
include("behavior.jl")
|
||||
include("output.jl")
|
||||
|
||||
|
|
352
src/behavior.jl
352
src/behavior.jl
|
@ -5,188 +5,6 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
"""
|
||||
calculateTractiveEffort(v, tractiveEffortVelocityPairs)
|
||||
|
||||
Calculate the trains tractive effort with the `tractiveEffortVelocityPairs` dependend on the velocity `v`.
|
||||
|
||||
...
|
||||
# Arguments
|
||||
- `v::AbstractFloat`: the current velocity in m/s.
|
||||
- `tractiveEffortVelocityPairs::Array{}`: the trains pairs for velocity in m/s and tractive effort in N as one array containing an array for each pair.
|
||||
...
|
||||
|
||||
# Examples
|
||||
```julia-repl
|
||||
julia> calculateTractiveEffort(20.0, [(0.0, 180000), (20.0, 100000), (40.0, 60000), (60.0, 40000), (80.0, 30000)])
|
||||
100000
|
||||
|
||||
julia> calculateTractiveEffort(30.0, [(0.0, 180000), (20.0, 100000), (40.0, 60000), (60.0, 40000), (80.0, 30000)])
|
||||
80000
|
||||
```
|
||||
"""
|
||||
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs::Array{})
|
||||
for row in 1:length(tractiveEffortVelocityPairs)
|
||||
nextPair = tractiveEffortVelocityPairs[row]
|
||||
if nextPair[1] == v
|
||||
return nextPair[2]
|
||||
elseif nextPair[1] > v
|
||||
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-F_(row-1))/(v_row-v_(row-1))+F_(row-1)
|
||||
previousPair = tractiveEffortVelocityPairs[row-1]
|
||||
F_T_interpolation = (v-previousPair[1]) * (nextPair[2]-previousPair[2]) / (nextPair[1]-previousPair[1]) + previousPair[2]
|
||||
return F_T_interpolation
|
||||
end #if
|
||||
end #for
|
||||
# if v gets higher than the velocities in tractiveEffortVelocityPairs the last tractive effort will be used
|
||||
# TODO: also an extrapolation could be used
|
||||
return tractiveEffortVelocityPairs[end][2]
|
||||
end #function calculateTractiveEffort
|
||||
|
||||
"""
|
||||
calculate and return the path resistance dependend on the trains position and mass model
|
||||
"""
|
||||
function calculatePathResistance(CSs::Vector{Dict}, csId::Integer, s::Real, massModel, train::Train)
|
||||
|
||||
if massModel == :mass_point
|
||||
pathResistance = calcForceFromCoefficient(CSs[csId][:r_path], train.m_train_full)
|
||||
elseif massModel == :homogeneous_strip
|
||||
pathResistance = 0.0
|
||||
s_rear = s - train.length # position of the rear of the train
|
||||
while csId > 0 && s_rear < CSs[csId][:s_exit]
|
||||
pathResistance = pathResistance + (min(s, CSs[csId][:s_exit]) - max(s_rear, CSs[csId][:s_entry])) / train.length * calcForceFromCoefficient(CSs[csId][:r_path], train.m_train_full)
|
||||
csId = csId-1
|
||||
if csId == 0
|
||||
# TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used
|
||||
return pathResistance + (CSs[1][:s_entry] - s_rear) / train.length * calcForceFromCoefficient(CSs[1][:r_path], train.m_train_full)
|
||||
end #if
|
||||
end #while
|
||||
end #if
|
||||
|
||||
return pathResistance
|
||||
end #function calculatePathResistance
|
||||
|
||||
"""
|
||||
calculate and return tractive and resisting forces for a data point
|
||||
"""
|
||||
function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Train, massModel)
|
||||
# calculate resisting forces
|
||||
dataPoint[:R_traction] = calcTractionUnitResistance(dataPoint[:v], train)
|
||||
dataPoint[:R_wagons] = calcWagonsResistance(dataPoint[:v], train)
|
||||
dataPoint[:R_train] = dataPoint[:R_traction] + dataPoint[:R_wagons]
|
||||
dataPoint[:R_path] = calculatePathResistance(CSs, csId, dataPoint[:s], massModel, train)
|
||||
dataPoint[:F_R] = dataPoint[:R_train] + dataPoint[:R_path]
|
||||
|
||||
# calculate tractive effort
|
||||
if bsType == "braking" || bsType == "coasting"
|
||||
dataPoint[:F_T] = 0.0
|
||||
elseif bsType == "cruising"
|
||||
dataPoint[:F_T] = min(max(0.0, dataPoint[:F_R]), calculateTractiveEffort(dataPoint[:v], train.tractiveEffort))
|
||||
else # bsType == "accelerating" || bsType == "diminishing" || 'default'
|
||||
dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train.tractiveEffort)
|
||||
end
|
||||
|
||||
return dataPoint
|
||||
end #function calculateForces!
|
||||
|
||||
|
||||
"""
|
||||
TODO
|
||||
"""
|
||||
function moveAStep(previousPoint::Dict, stepVariable::Symbol, stepSize::Real, csId::Integer)
|
||||
# stepSize is the currentStepSize depending on the accessing function
|
||||
# TODO: csId is only for error messages. Should it be removed?
|
||||
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =#
|
||||
|
||||
# create the next data point
|
||||
newPoint = createDataPoint()
|
||||
newPoint[:i] = previousPoint[:i]+1 # identifier
|
||||
|
||||
# calculate s, t, v, E
|
||||
if stepVariable == :distance # distance step method
|
||||
newPoint[:Δs] = stepSize # step size (in m)
|
||||
if previousPoint[:a] == 0.0
|
||||
if previousPoint[:v] == 0.0
|
||||
error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".")
|
||||
end
|
||||
newPoint[:Δt] = calc_Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = 0.0 # step size (in m/s)
|
||||
else
|
||||
# check if the parts of the following square roots will be <0.0 in the functions calc_Δt_with_Δs and calc_Δv_with_Δs
|
||||
squareRootPartIsNegative = (previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a] < 0.0 || previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a] < 0.0
|
||||
if previousPoint[:a] < 0.0 && squareRootPartIsNegative
|
||||
error("ERROR: The train stops during the accelerating section in CS",csId," because the tractive effort is lower than the resistant forces.",
|
||||
" Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,",
|
||||
" F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.")
|
||||
end
|
||||
newPoint[:Δt] = calc_Δt_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = calc_Δv_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m/s)
|
||||
end
|
||||
|
||||
elseif stepVariable == :time # time step method
|
||||
newPoint[:Δt] = stepSize # step size (in s)
|
||||
newPoint[:Δs] = calc_Δs_with_Δt(newPoint[:Δt], previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
newPoint[:Δv] = calc_Δv_with_Δt(newPoint[:Δt], previousPoint[:a]) # step size (in m/s)
|
||||
|
||||
elseif stepVariable == :velocity # velocity step method
|
||||
if previousPoint[:a] == 0.0
|
||||
if previousPoint[:v] == 0.0
|
||||
error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".")
|
||||
end
|
||||
newPoint[:Δs] = stepSize # step size (in m)
|
||||
# TODO what is the best default step size for constant v? define Δs or Δt?
|
||||
newPoint[:Δt] = calc_Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = 0.0 # step size (in m/s)
|
||||
else
|
||||
newPoint[:Δv] = stepSize * sign(previousPoint[:a]) # step size (in m/s)
|
||||
newPoint[:Δs] = calc_Δs_with_Δv(newPoint[:Δv], previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
newPoint[:Δt] = calc_Δt_with_Δv(newPoint[:Δv], previousPoint[:a]) # step size (in s)
|
||||
end
|
||||
end #if
|
||||
|
||||
newPoint[:s] = previousPoint[:s] + newPoint[:Δs] # position (in m)
|
||||
newPoint[:t] = previousPoint[:t] + newPoint[:Δt] # point in time (in s)
|
||||
newPoint[:v] = previousPoint[:v] + newPoint[:Δv] # velocity (in m/s)
|
||||
newPoint[:ΔW] = calc_ΔW(previousPoint[:F_T], newPoint[:Δs]) # mechanical work in this step (in Ws)
|
||||
newPoint[:W] = previousPoint[:W] + newPoint[:ΔW] # mechanical work (in Ws)
|
||||
newPoint[:ΔE] = calc_ΔE(newPoint[:ΔW]) # energy consumption in this step (in Ws)
|
||||
newPoint[:E] = previousPoint[:E] + newPoint[:ΔE] # energy consumption (in Ws)
|
||||
|
||||
|
||||
return newPoint
|
||||
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)
|
||||
v_limit = CSs[csWithTrainHeadId][:v_limit]
|
||||
s_exit = CSs[csWithTrainHeadId][:s_exit]
|
||||
if csWithTrainHeadId > 1 && s -trainLength < CSs[csWithTrainHeadId][:s_entry]
|
||||
formerCsId = csWithTrainHeadId-1
|
||||
while formerCsId > 0 && s -trainLength < CSs[formerCsId][:s_exit]
|
||||
if CSs[formerCsId][:v_limit] < v_limit # TODO: is the position of the train's rear < movingSection[:s_entry], v_limit of the first CS is used
|
||||
v_limit = CSs[formerCsId][:v_limit]
|
||||
s_exit = CSs[formerCsId][:s_exit]
|
||||
end
|
||||
formerCsId = formerCsId -1
|
||||
end
|
||||
end
|
||||
currentSpeedLimit = Dict(:v => v_limit, :s_end => s_exit + trainLength)
|
||||
return currentSpeedLimit
|
||||
end #function getCurrentSpeedLimit
|
||||
|
||||
"""
|
||||
?
|
||||
"""
|
||||
function getNextPointOfInterest(pointsOfInterest::Vector{Tuple}, s::Real)
|
||||
for s_POI in pointsOfInterest
|
||||
if s_POI[1] > s
|
||||
return s_POI
|
||||
end
|
||||
end
|
||||
error("ERROR in getNextPointOfInterest: There is no POI higher than s=",s," m.")
|
||||
end #function getNextPointOfInterest
|
||||
|
||||
## This function calculates the data points of the breakFree section.
|
||||
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed.
|
||||
# Info: currently the values of the breakFree section will be calculated like in the accelerating section
|
||||
|
@ -196,7 +14,7 @@ function addBreakFreeSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags:
|
|||
trainIsHalting = drivingCourse[end][:v] == 0.0
|
||||
|
||||
if trainIsHalting && !endOfCSReached
|
||||
BS = createBehaviorSection("breakFree", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
BS = BehaviorSection("breakFree", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
|
@ -318,7 +136,7 @@ function addAcceleratingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFla
|
|||
|
||||
# use the conditions for the accelerating section
|
||||
if !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached
|
||||
BS = createBehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
BS = BehaviorSection("accelerating", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length)
|
||||
|
@ -568,7 +386,7 @@ function addCruisingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
|
||||
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])
|
||||
BS = BehaviorSection(cruisingType, drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
# TODO: necessary?
|
||||
s_cruising = min(s_cruising, CS[:s_exit]-BS[:s_entry])
|
||||
|
@ -815,7 +633,7 @@ function addDiminishingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlag
|
|||
|
||||
# use the conditions for the diminishing section
|
||||
if tractionDeficit && !targetSpeedReached && !endOfCSReached
|
||||
BS = createBehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
BS = BehaviorSection("diminishing", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||
|
@ -995,7 +813,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
|||
|
||||
# use the conditions for the coasting section
|
||||
if !targetSpeedReached && !endOfCSReached
|
||||
BS = createBehaviorSection("coasting", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
BS = BehaviorSection("coasting", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
while !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||
|
@ -1152,7 +970,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
|||
|
||||
# use the conditions for the braking section
|
||||
if !targetSpeedReached && !endOfCSReached
|
||||
BS = createBehaviorSection("braking", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
BS = BehaviorSection("braking", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
|
||||
while !targetSpeedReached && !endOfCSReached
|
||||
|
@ -1172,7 +990,7 @@ 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 data point and set it for the values of s_exit and v_exit
|
||||
push!(drivingCourse, createDataPoint())
|
||||
push!(drivingCourse, DataPoint())
|
||||
drivingCourse[end][:i] = drivingCourse[end-1][:i]+1
|
||||
drivingCourse[end][:behavior] = BS[:type]
|
||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
||||
|
@ -1304,7 +1122,7 @@ end #function addBrakingSection!
|
|||
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed.
|
||||
function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Settings, train::Train, CSs::Vector{Dict})
|
||||
if drivingCourse[end][:v] == 0.0
|
||||
BS = createBehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
BS = BehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i])
|
||||
merge!(BS, Dict(:length => 0.0, # total length (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
|
@ -1357,3 +1175,157 @@ function recalculateLastBrakingPoint!(drivingCourse, s_target, v_target)
|
|||
currentPoint[:ΔE] = currentPoint[:ΔW] # energy consumption in this step (in Ws)
|
||||
currentPoint[:E] = previousPoint[:E] + currentPoint[:ΔE] # energy consumption (in Ws)
|
||||
end #function recalculateLastBrakingPoint
|
||||
|
||||
## define the intersection velocities between the characterisitc sections to secure braking behavior
|
||||
function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
|
||||
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
csId = length(CSs)
|
||||
followingCSv_entry = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s
|
||||
while csId >= 1
|
||||
CS = CSs[csId]
|
||||
|
||||
CS[:v_exit] = min(CS[:v_limit], followingCSv_entry)
|
||||
|
||||
v_entryMax = calcBrakingStartVelocity(CS[:v_exit], a_braking, CS[:length])
|
||||
|
||||
CS[:v_entry] = min(CS[:v_limit], v_entryMax)
|
||||
CS[:v_peak] = CS[:v_entry]
|
||||
|
||||
|
||||
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
|
||||
CS[:behaviorSections] = Dict()
|
||||
CS[:E] = 0.0
|
||||
CS[:t] = 0.0
|
||||
|
||||
followingCSv_entry = CS[:v_entry]
|
||||
csId = csId - 1
|
||||
end #while
|
||||
return movingSection
|
||||
end #function secureBrakingBehavior!
|
||||
|
||||
## define the intersection velocities between the characterisitc sections to secure accelerating behavior
|
||||
function secureAcceleratingBehavior!(movingSection::Dict, settings::Settings, train::Train)
|
||||
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
CSs[1][:v_entry] = 0.0 # the entry velocity of the first characteristic section is 0.0 m/s
|
||||
startingPoint = DataPoint()
|
||||
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 data points
|
||||
|
||||
if CS[:v_entry] < CS[:v_peak]
|
||||
# conditions for entering the accelerating phase
|
||||
stateFlags = Dict(:endOfCSReached => false,
|
||||
:brakingStartReached => false,
|
||||
:tractionDeficit => false,
|
||||
:resistingForceNegative => false,
|
||||
:previousSpeedLimitReached => false,
|
||||
:speedLimitReached => false,
|
||||
:error => false,
|
||||
:usedForDefiningCharacteristics => true) # because usedForDefiningCharacteristics == true the braking distance will be ignored during securing the accelerating phase
|
||||
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]
|
||||
|
||||
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
|
||||
CS[:behaviorSections] = Dict()
|
||||
CS[:E] = 0.0
|
||||
CS[:t] = 0.0
|
||||
end #for
|
||||
|
||||
return movingSection
|
||||
end #function secureAcceleratingBehavior!
|
||||
|
||||
|
||||
#=
|
||||
## define the intersection velocities between the characterisitc sections to secure cruising behavior
|
||||
function secureCruisingBehavior!(movingSection::Dict, settings::Settings, train::Train)
|
||||
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
startingPoint = DataPoint()
|
||||
startingPoint[:i] = 1
|
||||
|
||||
previousCSv_exit = CSs[1][:v_entry]
|
||||
|
||||
for CS in CSs
|
||||
# conditions for entering the cruising phase
|
||||
stateFlags = Dict(:endOfCSReached => false,
|
||||
:brakingStartReached => false,
|
||||
:tractionDeficit => false,
|
||||
:resistingForceNegative => false,
|
||||
:previousSpeedLimitReached => false,
|
||||
:speedLimitReached => false,
|
||||
:error => false,
|
||||
:usedForDefiningCharacteristics => true)
|
||||
|
||||
CS[:v_entry] = min(CS[:v_entry], previousCSv_exit)
|
||||
|
||||
startingPoint[:s] = CS[:s_entry]
|
||||
startingPoint[:v] = CS[:v_peak]
|
||||
cruisingCourse::Vector{Dict} = [startingPoint] # List of data points
|
||||
|
||||
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]
|
||||
|
||||
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
|
||||
CS[:behaviorSections] = Dict()
|
||||
CS[:E] = 0.0
|
||||
CS[:t] = 0.0
|
||||
end #for
|
||||
|
||||
return movingSection
|
||||
end #function secureCruisingBehavior!
|
||||
=#
|
||||
|
|
195
src/calc.jl
195
src/calc.jl
|
@ -15,7 +15,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, t
|
|||
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()
|
||||
startingPoint=DataPoint()
|
||||
startingPoint[:i]=1
|
||||
startingPoint[:s]=CSs[1][:s_entry]
|
||||
calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N)
|
||||
|
@ -123,3 +123,196 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, t
|
|||
|
||||
return (movingSection, drivingCourse)
|
||||
end #function calculateMinimumRunningTime
|
||||
|
||||
"""
|
||||
calculateTractiveEffort(v, tractiveEffortVelocityPairs)
|
||||
|
||||
Calculate the trains tractive effort with the `tractiveEffortVelocityPairs` dependend on the velocity `v`.
|
||||
|
||||
...
|
||||
# Arguments
|
||||
- `v::AbstractFloat`: the current velocity in m/s.
|
||||
- `tractiveEffortVelocityPairs::Array{}`: the trains pairs for velocity in m/s and tractive effort in N as one array containing an array for each pair.
|
||||
...
|
||||
|
||||
# Examples
|
||||
```julia-repl
|
||||
julia> calculateTractiveEffort(20.0, [(0.0, 180000), (20.0, 100000), (40.0, 60000), (60.0, 40000), (80.0, 30000)])
|
||||
100000
|
||||
|
||||
julia> calculateTractiveEffort(30.0, [(0.0, 180000), (20.0, 100000), (40.0, 60000), (60.0, 40000), (80.0, 30000)])
|
||||
80000
|
||||
```
|
||||
"""
|
||||
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs::Array{})
|
||||
for row in 1:length(tractiveEffortVelocityPairs)
|
||||
nextPair = tractiveEffortVelocityPairs[row]
|
||||
if nextPair[1] == v
|
||||
return nextPair[2]
|
||||
elseif nextPair[1] > v
|
||||
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-F_(row-1))/(v_row-v_(row-1))+F_(row-1)
|
||||
previousPair = tractiveEffortVelocityPairs[row-1]
|
||||
F_T_interpolation = (v-previousPair[1]) * (nextPair[2]-previousPair[2]) / (nextPair[1]-previousPair[1]) + previousPair[2]
|
||||
return F_T_interpolation
|
||||
end #if
|
||||
end #for
|
||||
# if v gets higher than the velocities in tractiveEffortVelocityPairs the last tractive effort will be used
|
||||
# TODO: also an extrapolation could be used
|
||||
return tractiveEffortVelocityPairs[end][2]
|
||||
end #function calculateTractiveEffort
|
||||
|
||||
"""
|
||||
calculate and return the path resistance dependend on the trains position and mass model
|
||||
"""
|
||||
function calculatePathResistance(CSs::Vector{Dict}, csId::Integer, s::Real, massModel, train::Train)
|
||||
|
||||
if massModel == :mass_point
|
||||
pathResistance = calcForceFromCoefficient(CSs[csId][:r_path], train.m_train_full)
|
||||
elseif massModel == :homogeneous_strip
|
||||
pathResistance = 0.0
|
||||
s_rear = s - train.length # position of the rear of the train
|
||||
while csId > 0 && s_rear < CSs[csId][:s_exit]
|
||||
pathResistance = pathResistance + (min(s, CSs[csId][:s_exit]) - max(s_rear, CSs[csId][:s_entry])) / train.length * calcForceFromCoefficient(CSs[csId][:r_path], train.m_train_full)
|
||||
csId = csId-1
|
||||
if csId == 0
|
||||
# TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used
|
||||
return pathResistance + (CSs[1][:s_entry] - s_rear) / train.length * calcForceFromCoefficient(CSs[1][:r_path], train.m_train_full)
|
||||
end #if
|
||||
end #while
|
||||
end #if
|
||||
|
||||
return pathResistance
|
||||
end #function calculatePathResistance
|
||||
|
||||
"""
|
||||
calculate and return tractive and resisting forces for a data point
|
||||
"""
|
||||
function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Train, massModel)
|
||||
# calculate resisting forces
|
||||
dataPoint[:R_traction] = calcTractionUnitResistance(dataPoint[:v], train)
|
||||
dataPoint[:R_wagons] = calcWagonsResistance(dataPoint[:v], train)
|
||||
dataPoint[:R_train] = dataPoint[:R_traction] + dataPoint[:R_wagons]
|
||||
dataPoint[:R_path] = calculatePathResistance(CSs, csId, dataPoint[:s], massModel, train)
|
||||
dataPoint[:F_R] = dataPoint[:R_train] + dataPoint[:R_path]
|
||||
|
||||
# calculate tractive effort
|
||||
if bsType == "braking" || bsType == "coasting"
|
||||
dataPoint[:F_T] = 0.0
|
||||
elseif bsType == "cruising"
|
||||
dataPoint[:F_T] = min(max(0.0, dataPoint[:F_R]), calculateTractiveEffort(dataPoint[:v], train.tractiveEffort))
|
||||
else # bsType == "accelerating" || bsType == "diminishing" || 'default'
|
||||
dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train.tractiveEffort)
|
||||
end
|
||||
|
||||
return dataPoint
|
||||
end #function calculateForces!
|
||||
|
||||
|
||||
"""
|
||||
TODO
|
||||
"""
|
||||
function moveAStep(previousPoint::Dict, stepVariable::Symbol, stepSize::Real, csId::Integer)
|
||||
# stepSize is the currentStepSize depending on the accessing function
|
||||
# TODO: csId is only for error messages. Should it be removed?
|
||||
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =#
|
||||
|
||||
# create the next data point
|
||||
newPoint = DataPoint()
|
||||
newPoint[:i] = previousPoint[:i]+1 # identifier
|
||||
|
||||
# calculate s, t, v, E
|
||||
if stepVariable == :distance # distance step method
|
||||
newPoint[:Δs] = stepSize # step size (in m)
|
||||
if previousPoint[:a] == 0.0
|
||||
if previousPoint[:v] == 0.0
|
||||
error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".")
|
||||
end
|
||||
newPoint[:Δt] = calc_Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = 0.0 # step size (in m/s)
|
||||
else
|
||||
# check if the parts of the following square roots will be <0.0 in the functions calc_Δt_with_Δs and calc_Δv_with_Δs
|
||||
squareRootPartIsNegative = (previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a] < 0.0 || previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a] < 0.0
|
||||
if previousPoint[:a] < 0.0 && squareRootPartIsNegative
|
||||
error("ERROR: The train stops during the accelerating section in CS",csId," because the tractive effort is lower than the resistant forces.",
|
||||
" Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,",
|
||||
" F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.")
|
||||
end
|
||||
newPoint[:Δt] = calc_Δt_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = calc_Δv_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m/s)
|
||||
end
|
||||
|
||||
elseif stepVariable == :time # time step method
|
||||
newPoint[:Δt] = stepSize # step size (in s)
|
||||
newPoint[:Δs] = calc_Δs_with_Δt(newPoint[:Δt], previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
newPoint[:Δv] = calc_Δv_with_Δt(newPoint[:Δt], previousPoint[:a]) # step size (in m/s)
|
||||
|
||||
elseif stepVariable == :velocity # velocity step method
|
||||
if previousPoint[:a] == 0.0
|
||||
if previousPoint[:v] == 0.0
|
||||
error("ERROR: The train tries to cruise at v=0.0 m/s at s=",previousPoint[:s]," in CS",csId,".")
|
||||
end
|
||||
newPoint[:Δs] = stepSize # step size (in m)
|
||||
# TODO what is the best default step size for constant v? define Δs or Δt?
|
||||
newPoint[:Δt] = calc_Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = 0.0 # step size (in m/s)
|
||||
else
|
||||
newPoint[:Δv] = stepSize * sign(previousPoint[:a]) # step size (in m/s)
|
||||
newPoint[:Δs] = calc_Δs_with_Δv(newPoint[:Δv], previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
newPoint[:Δt] = calc_Δt_with_Δv(newPoint[:Δv], previousPoint[:a]) # step size (in s)
|
||||
end
|
||||
end #if
|
||||
|
||||
newPoint[:s] = previousPoint[:s] + newPoint[:Δs] # position (in m)
|
||||
newPoint[:t] = previousPoint[:t] + newPoint[:Δt] # point in time (in s)
|
||||
newPoint[:v] = previousPoint[:v] + newPoint[:Δv] # velocity (in m/s)
|
||||
newPoint[:ΔW] = calc_ΔW(previousPoint[:F_T], newPoint[:Δs]) # mechanical work in this step (in Ws)
|
||||
newPoint[:W] = previousPoint[:W] + newPoint[:ΔW] # mechanical work (in Ws)
|
||||
newPoint[:ΔE] = calc_ΔE(newPoint[:ΔW]) # energy consumption in this step (in Ws)
|
||||
newPoint[:E] = previousPoint[:E] + newPoint[:ΔE] # energy consumption (in Ws)
|
||||
|
||||
|
||||
return newPoint
|
||||
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)
|
||||
v_limit = CSs[csWithTrainHeadId][:v_limit]
|
||||
s_exit = CSs[csWithTrainHeadId][:s_exit]
|
||||
if csWithTrainHeadId > 1 && s -trainLength < CSs[csWithTrainHeadId][:s_entry]
|
||||
formerCsId = csWithTrainHeadId-1
|
||||
while formerCsId > 0 && s -trainLength < CSs[formerCsId][:s_exit]
|
||||
if CSs[formerCsId][:v_limit] < v_limit # TODO: is the position of the train's rear < movingSection[:s_entry], v_limit of the first CS is used
|
||||
v_limit = CSs[formerCsId][:v_limit]
|
||||
s_exit = CSs[formerCsId][:s_exit]
|
||||
end
|
||||
formerCsId = formerCsId -1
|
||||
end
|
||||
end
|
||||
currentSpeedLimit = Dict(:v => v_limit, :s_end => s_exit + trainLength)
|
||||
return currentSpeedLimit
|
||||
end #function getCurrentSpeedLimit
|
||||
|
||||
"""
|
||||
?
|
||||
"""
|
||||
function getNextPointOfInterest(pointsOfInterest::Vector{Tuple}, s::Real)
|
||||
for s_POI in pointsOfInterest
|
||||
if s_POI[1] > s
|
||||
return s_POI
|
||||
end
|
||||
end
|
||||
error("ERROR in getNextPointOfInterest: There is no POI higher than s=",s," m.")
|
||||
end #function getNextPointOfInterest
|
||||
|
||||
|
||||
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior
|
||||
function determineCharacteristics(path::Path, train::Train, settings::Settings)
|
||||
movingSection = MovingSection(path, train.v_limit, train.length)
|
||||
movingSection = secureBrakingBehavior!(movingSection, train.a_braking)
|
||||
movingSection = secureAcceleratingBehavior!(movingSection, settings, train)
|
||||
#movingSection = secureCruisingBehavior!(movingSection, settings, train)
|
||||
|
||||
return movingSection
|
||||
end #function determineCharacteristics
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
#!/usr/bin/env julia
|
||||
# -*- coding: UTF-8 -*-
|
||||
# __julia-version__ = 1.7.2
|
||||
# __author__ = "Max Kannenberg"
|
||||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior
|
||||
function determineCharacteristics(path::Path, train::Train, settings::Settings)
|
||||
movingSection = createMovingSection(path, train.v_limit, train.length)
|
||||
movingSection = secureBrakingBehavior!(movingSection, train.a_braking)
|
||||
movingSection = secureAcceleratingBehavior!(movingSection, settings, train)
|
||||
#movingSection = secureCruisingBehavior!(movingSection, settings, train)
|
||||
|
||||
return movingSection
|
||||
end #function determineCharacteristics
|
||||
|
||||
## define the intersection velocities between the characterisitc sections to secure braking behavior
|
||||
function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
|
||||
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
csId = length(CSs)
|
||||
followingCSv_entry = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s
|
||||
while csId >= 1
|
||||
CS = CSs[csId]
|
||||
|
||||
CS[:v_exit] = min(CS[:v_limit], followingCSv_entry)
|
||||
|
||||
v_entryMax = calcBrakingStartVelocity(CS[:v_exit], a_braking, CS[:length])
|
||||
|
||||
CS[:v_entry] = min(CS[:v_limit], v_entryMax)
|
||||
CS[:v_peak] = CS[:v_entry]
|
||||
|
||||
|
||||
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
|
||||
CS[:behaviorSections] = Dict()
|
||||
CS[:E] = 0.0
|
||||
CS[:t] = 0.0
|
||||
|
||||
followingCSv_entry = CS[:v_entry]
|
||||
csId = csId - 1
|
||||
end #while
|
||||
return movingSection
|
||||
end #function secureBrakingBehavior!
|
||||
|
||||
## define the intersection velocities between the characterisitc sections to secure accelerating behavior
|
||||
function secureAcceleratingBehavior!(movingSection::Dict, settings::Settings, train::Train)
|
||||
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
CSs[1][:v_entry] = 0.0 # the entry velocity of the first characteristic section is 0.0 m/s
|
||||
startingPoint = createDataPoint()
|
||||
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 data points
|
||||
|
||||
if CS[:v_entry] < CS[:v_peak]
|
||||
# conditions for entering the accelerating phase
|
||||
stateFlags = Dict(:endOfCSReached => false,
|
||||
:brakingStartReached => false,
|
||||
:tractionDeficit => false,
|
||||
:resistingForceNegative => false,
|
||||
:previousSpeedLimitReached => false,
|
||||
:speedLimitReached => false,
|
||||
:error => false,
|
||||
:usedForDefiningCharacteristics => true) # because usedForDefiningCharacteristics == true the braking distance will be ignored during securing the accelerating phase
|
||||
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]
|
||||
|
||||
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
|
||||
CS[:behaviorSections] = Dict()
|
||||
CS[:E] = 0.0
|
||||
CS[:t] = 0.0
|
||||
end #for
|
||||
|
||||
return movingSection
|
||||
end #function secureAcceleratingBehavior!
|
||||
|
||||
|
||||
#=
|
||||
## define the intersection velocities between the characterisitc sections to secure cruising behavior
|
||||
function secureCruisingBehavior!(movingSection::Dict, settings::Settings, train::Train)
|
||||
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak
|
||||
CSs = movingSection[:characteristicSections]
|
||||
|
||||
startingPoint = createDataPoint()
|
||||
startingPoint[:i] = 1
|
||||
|
||||
previousCSv_exit = CSs[1][:v_entry]
|
||||
|
||||
for CS in CSs
|
||||
# conditions for entering the cruising phase
|
||||
stateFlags = Dict(:endOfCSReached => false,
|
||||
:brakingStartReached => false,
|
||||
:tractionDeficit => false,
|
||||
:resistingForceNegative => false,
|
||||
:previousSpeedLimitReached => false,
|
||||
:speedLimitReached => false,
|
||||
:error => false,
|
||||
:usedForDefiningCharacteristics => true)
|
||||
|
||||
CS[:v_entry] = min(CS[:v_entry], previousCSv_exit)
|
||||
|
||||
startingPoint[:s] = CS[:s_entry]
|
||||
startingPoint[:v] = CS[:v_peak]
|
||||
cruisingCourse::Vector{Dict} = [startingPoint] # List of data points
|
||||
|
||||
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]
|
||||
|
||||
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
|
||||
CS[:behaviorSections] = Dict()
|
||||
CS[:E] = 0.0
|
||||
CS[:t] = 0.0
|
||||
end #for
|
||||
|
||||
return movingSection
|
||||
end #function secureCruisingBehavior!
|
||||
=#
|
|
@ -614,7 +614,7 @@ function Train(file, type = :YAML)
|
|||
end #function Train() # outer constructor
|
||||
|
||||
## create a moving section containing characteristic sections
|
||||
function createMovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real)
|
||||
function MovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real)
|
||||
# this function creates and returns a moving section dependent on the paths attributes
|
||||
|
||||
s_entry = path.sections[1][:s_start] # first position (in m)
|
||||
|
@ -631,12 +631,12 @@ function createMovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real
|
|||
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
|
||||
if speedLimitIsDifferent || pathResistanceIsDifferent
|
||||
# 03/09 old: if min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit) || previousSection[:f_Rp] != currentSection[:f_Rp]
|
||||
push!(CSs, createCharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, path))
|
||||
push!(CSs, CharacteristicSection(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, path))
|
||||
s_csStart = currentSection[:s_start]
|
||||
csId = csId+1
|
||||
end #if
|
||||
end #for
|
||||
push!(CSs, createCharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, path))
|
||||
push!(CSs, CharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, path))
|
||||
|
||||
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore
|
||||
:length => pathLength, # total length (in m)
|
||||
|
@ -647,10 +647,10 @@ function createMovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real
|
|||
:characteristicSections => CSs) # list of containing characteristic sections
|
||||
|
||||
return movingSection
|
||||
end #function createMovingSection
|
||||
end #function MovingSection
|
||||
|
||||
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
|
||||
function createCharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, path::Path)
|
||||
function CharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, path::Path)
|
||||
# Create and return a characteristic section dependent on the paths attributes
|
||||
characteristicSection= Dict(:id => id, # identifier
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
|
@ -690,15 +690,33 @@ function createCharacteristicSection(id::Integer, s_entry::Real, section::Dict,
|
|||
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
|
||||
|
||||
return characteristicSection
|
||||
end #function createCharacteristicSection
|
||||
end #function CharacteristicSection
|
||||
|
||||
"""
|
||||
BehaviorSection() TODO!
|
||||
"""
|
||||
function BehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
|
||||
BS= Dict(
|
||||
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "downhillBraking", "diminishing", "coasting", "braking" or "standstill"
|
||||
:length => 0.0, # total length (in m)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => 0.0, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:v_entry => v_entry, # entry speed (in m/s)
|
||||
:v_exit => 0.0, # exit speed (in m/s)
|
||||
:dataPoints => [startingPoint] # list of identifiers of the containing data points starting with the initial point
|
||||
)
|
||||
return BS
|
||||
end #function BehaviorSection
|
||||
|
||||
"""
|
||||
a DataPoint is the smallest element of the driving course. One step of the step approach is between two data points
|
||||
"""
|
||||
function createDataPoint()
|
||||
function DataPoint()
|
||||
dataPoint = Dict(
|
||||
:i => 0, # identifier and counter variable of the driving course
|
||||
:behavior => "", # type of behavior section the data point is part of - see createBehaviorSection()
|
||||
:behavior => "", # type of behavior section the data point is part of - see BehaviorSection()
|
||||
# a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
|
||||
:s => 0.0, # position (in m)
|
||||
:Δs => 0.0, # step size (in m)
|
||||
|
@ -720,22 +738,4 @@ function createDataPoint()
|
|||
:label => "" # a label for importend points
|
||||
)
|
||||
return dataPoint
|
||||
end #function createDataPoint
|
||||
|
||||
"""
|
||||
BehaviorSection() TODO!
|
||||
"""
|
||||
function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
|
||||
BS= Dict(
|
||||
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "downhillBraking", "diminishing", "coasting", "braking" or "standstill"
|
||||
:length => 0.0, # total length (in m)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => 0.0, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:v_entry => v_entry, # entry speed (in m/s)
|
||||
:v_exit => 0.0, # exit speed (in m/s)
|
||||
:dataPoints => [startingPoint] # list of identifiers of the containing data points starting with the initial point
|
||||
)
|
||||
return BS
|
||||
end #function createBehaviorSection
|
||||
end #function DataPoint
|
||||
|
|
Loading…
Reference in New Issue