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 Validate.jl into types.jl
|
||||||
* renamed TrainRunCalc.jl into calc.jl
|
* renamed TrainRunCalc.jl into calc.jl
|
||||||
* moved trainrun function from calc.jl to TrainRun.jl
|
* moved trainrun function from calc.jl to TrainRun.jl
|
||||||
* moved createDataPoint() from behavior.jl to types.jl
|
* moved createDataPoint() from behavior.jl to constructors.jl
|
||||||
* moved createBehaviorSection() from behavior.jl to types.jl
|
* moved createBehaviorSection() from behavior.jl to constructors.jl
|
||||||
* moved createMovingSection() from characteristics.jl to types.jl
|
* moved createMovingSection() from characteristics.jl to constructors.jl
|
||||||
* moved createCharacteristicSection() from characteristics.jl to types.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 title of include files from upper case to lower case
|
||||||
* changed seperation of submodules into a single module with file include
|
* changed seperation of submodules into a single module with file include
|
||||||
* updated test files to railtoolkit/schema (2022.05)
|
* updated test files to railtoolkit/schema (2022.05)
|
||||||
|
|
|
@ -27,7 +27,6 @@ include("types.jl")
|
||||||
include("constructors.jl")
|
include("constructors.jl")
|
||||||
include("formulary.jl")
|
include("formulary.jl")
|
||||||
include("calc.jl")
|
include("calc.jl")
|
||||||
include("characteristics.jl")
|
|
||||||
include("behavior.jl")
|
include("behavior.jl")
|
||||||
include("output.jl")
|
include("output.jl")
|
||||||
|
|
||||||
|
|
352
src/behavior.jl
352
src/behavior.jl
|
@ -5,188 +5,6 @@
|
||||||
# __copyright__ = "2020-2022"
|
# __copyright__ = "2020-2022"
|
||||||
# __license__ = "ISC"
|
# __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.
|
## 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.
|
# 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
|
# 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
|
trainIsHalting = drivingCourse[end][:v] == 0.0
|
||||||
|
|
||||||
if trainIsHalting && !endOfCSReached
|
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]
|
drivingCourse[end][:behavior] = BS[:type]
|
||||||
|
|
||||||
# traction effort and resisting forces (in N)
|
# 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
|
# use the conditions for the accelerating section
|
||||||
if !targetSpeedReached && !endOfCSReached && tractionSurplus && !brakingStartReached
|
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]
|
drivingCourse[end][:behavior] = BS[:type]
|
||||||
|
|
||||||
currentSpeedLimit = getCurrentSpeedLimit(CSs, CS[:id], drivingCourse[end][:s], train.length)
|
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
|
if speedIsValid && !brakingStartReached && !tractionDeficit && !targetPositionReached
|
||||||
# 03/04 old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && !brakingStartReached && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
|
# 03/04 old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && !brakingStartReached && drivingCourse[end][:F_T] >= drivingCourse[end][:F_R]
|
||||||
BS = 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]
|
drivingCourse[end][:behavior] = BS[:type]
|
||||||
# TODO: necessary?
|
# TODO: necessary?
|
||||||
s_cruising = min(s_cruising, CS[:s_exit]-BS[:s_entry])
|
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
|
# use the conditions for the diminishing section
|
||||||
if tractionDeficit && !targetSpeedReached && !endOfCSReached
|
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]
|
drivingCourse[end][:behavior] = BS[:type]
|
||||||
|
|
||||||
while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
while tractionDeficit && !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||||
|
@ -995,7 +813,7 @@ function addCoastingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::
|
||||||
|
|
||||||
# use the conditions for the coasting section
|
# use the conditions for the coasting section
|
||||||
if !targetSpeedReached && !endOfCSReached
|
if !targetSpeedReached && !endOfCSReached
|
||||||
BS = 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]
|
drivingCourse[end][:behavior] = BS[:type]
|
||||||
|
|
||||||
while !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
while !targetSpeedReached && !endOfCSReached && !brakingStartReached
|
||||||
|
@ -1152,7 +970,7 @@ function addBrakingSection!(CS::Dict, drivingCourse::Vector{Dict}, stateFlags::D
|
||||||
|
|
||||||
# use the conditions for the braking section
|
# use the conditions for the braking section
|
||||||
if !targetSpeedReached && !endOfCSReached
|
if !targetSpeedReached && !endOfCSReached
|
||||||
BS = 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]
|
drivingCourse[end][:behavior] = BS[:type]
|
||||||
|
|
||||||
while !targetSpeedReached && !endOfCSReached
|
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
|
if settings.stepVariable == :distance && ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0
|
||||||
# create empty data point and set it for the values of s_exit and v_exit
|
# create empty 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][:i] = drivingCourse[end-1][:i]+1
|
||||||
drivingCourse[end][:behavior] = BS[:type]
|
drivingCourse[end][:behavior] = BS[:type]
|
||||||
push!(BS[:dataPoints], drivingCourse[end][:i])
|
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.
|
# 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})
|
function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Settings, train::Train, CSs::Vector{Dict})
|
||||||
if drivingCourse[end][:v] == 0.0
|
if drivingCourse[end][:v] == 0.0
|
||||||
BS = 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)
|
merge!(BS, Dict(:length => 0.0, # total length (in m)
|
||||||
:t => 0.0, # total running time (in s)
|
:t => 0.0, # total running time (in s)
|
||||||
:E => 0.0, # total energy consumption (in Ws)
|
: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] = currentPoint[:ΔW] # energy consumption in this step (in Ws)
|
||||||
currentPoint[:E] = previousPoint[:E] + currentPoint[:ΔE] # energy consumption (in Ws)
|
currentPoint[:E] = previousPoint[:E] + currentPoint[:ΔE] # energy consumption (in Ws)
|
||||||
end #function recalculateLastBrakingPoint
|
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 ! ! !")
|
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
|
end
|
||||||
|
|
||||||
startingPoint=createDataPoint()
|
startingPoint=DataPoint()
|
||||||
startingPoint[:i]=1
|
startingPoint[:i]=1
|
||||||
startingPoint[:s]=CSs[1][:s_entry]
|
startingPoint[:s]=CSs[1][:s_entry]
|
||||||
calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N)
|
calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N)
|
||||||
|
@ -123,3 +123,196 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, t
|
||||||
|
|
||||||
return (movingSection, drivingCourse)
|
return (movingSection, drivingCourse)
|
||||||
end #function calculateMinimumRunningTime
|
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
|
end #function Train() # outer constructor
|
||||||
|
|
||||||
## create a moving section containing characteristic sections
|
## 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
|
# this function creates and returns a moving section dependent on the paths attributes
|
||||||
|
|
||||||
s_entry = path.sections[1][:s_start] # first position (in m)
|
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]
|
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
|
||||||
if speedLimitIsDifferent || pathResistanceIsDifferent
|
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]
|
# 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]
|
s_csStart = currentSection[:s_start]
|
||||||
csId = csId+1
|
csId = csId+1
|
||||||
end #if
|
end #if
|
||||||
end #for
|
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
|
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)
|
: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
|
:characteristicSections => CSs) # list of containing characteristic sections
|
||||||
|
|
||||||
return movingSection
|
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.
|
## 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
|
# Create and return a characteristic section dependent on the paths attributes
|
||||||
characteristicSection= Dict(:id => id, # identifier
|
characteristicSection= Dict(:id => id, # identifier
|
||||||
:s_entry => s_entry, # first position (in m)
|
: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))
|
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
|
||||||
|
|
||||||
return characteristicSection
|
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
|
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(
|
dataPoint = Dict(
|
||||||
:i => 0, # identifier and counter variable of the driving course
|
:i => 0, # identifier and counter variable of the driving course
|
||||||
:behavior => "", # type of behavior section the data point is part of - see 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
|
# 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, # position (in m)
|
||||||
:Δs => 0.0, # step size (in m)
|
:Δs => 0.0, # step size (in m)
|
||||||
|
@ -720,22 +738,4 @@ function createDataPoint()
|
||||||
:label => "" # a label for importend points
|
:label => "" # a label for importend points
|
||||||
)
|
)
|
||||||
return dataPoint
|
return dataPoint
|
||||||
end #function createDataPoint
|
end #function DataPoint
|
||||||
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
|
|
Loading…
Reference in New Issue