Compare commits

...

5 Commits

Author SHA1 Message Date
Max Kannenberg 70410e7985 Remove function CharacteristicSections and move code to calc.jl 2022-12-03 21:02:41 +01:00
Max Kannenberg 2f463a4a92 Add docstrings to behavior.jl for documentation 2022-11-07 19:17:02 +01:00
Max Kannenberg da1f641839 Add docstrings to output.jl for documentation 2022-09-09 18:50:22 +02:00
Max Kannenberg 5c5fa14f46 Add docstrings to formulary.jl for documentation 2022-09-05 22:40:22 +02:00
github-actions[bot] 71778ac715
Set version to 1.0.2 2022-09-01 09:01:23 +00:00
6 changed files with 522 additions and 154 deletions

View File

@ -1,7 +1,7 @@
name = "TrainRuns"
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
authors = ["Max Kannenberg", "Martin Scheidt", "contributors"]
version = "1.0.1"
version = "1.0.2"
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"

View File

@ -4,10 +4,29 @@
# __copyright__ = "2020-2022"
# __license__ = "ISC"
## This function calculates the support points of the breakFree section.
# Therefore it gets its first support point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed.
# Info: currently the values of the breakFree section will be calculated like in the accelerating section
"""
addBreakFreeSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
Calculate the support points of the breakFree section and add them to `drivingCourse`.
See also [`addClearingSection!`](@ref), [`addAcceleratingSection!`](@ref), [`addCruisingSection!`](@ref), [`addDiminishingSection!`](@ref), [`addCoastingSection!`](@ref), [`addBrakingSection!`](@ref), [`addHalt!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
# Examples
```julia-repl
julia> addBreakFreeSection(drivingCourse_with_starting_point, stateFlags, CSs, 1, settings_default, train_longdistance)
(Dict[Dict{Symbol, Any}(:label => "", :behavior => "breakFree", :F_T => 300000, :R_wagons => 7309.09433933, :R_path => 0.0, :s => 0, :v => 0.0, :R_train => 9505.53877308, :R_traction => 2196.44443375, :a => 0.6143175668391081, :t => 0.0, :F_R => 9505.53877308), Dict{Symbol, Any}(:label => "", :behavior => "breakFree", :F_T => 300000.0, :R_wagons => 8848.180631278232, :R_path => 0.0, :s => 20, :v => 4.957086107136361, :R_train => 11471.657638238565, :R_traction => 2623.4770069603337, :a => 0.6101597548372565, :t => 8.069256643013498, :F_R => 11471.657638238565)], Dict{Symbol, Bool}(:previousSpeedLimitReached => 0, :speedLimitReached => 0, :brakingStartReached => 0, :resistingForceNegative => 0, :endOfCSReached => 0, :tractionDeficit => 0, :error => 0))
```
"""
function addBreakFreeSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train)
# INFO: currently the values of the breakFree section will be calculated like in the accelerating section
CS = CSs[csId]
# conditions for the break free section
@ -44,7 +63,7 @@ function addBreakFreeSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs
stateFlags[:endOfCSReached] = drivingCourse[end][:s] >= CS[:s_exit]
stateFlags[:brakingStartReached] = drivingCourse[end][:s] +s_braking >= CS[:s_exit]
stateFlags[:tractionDeficit] = drivingCourse[end][:F_T] < drivingCourse[end][:F_R] # or add another flag for equal forces?
stateFlags[:tractionDeficit] = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
stateFlags[:previousSpeedLimitReached] = false
stateFlags[:speedLimitReached] = drivingCourse[end][:v] >= CS[:v_limit]
@ -53,8 +72,25 @@ function addBreakFreeSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs
return (drivingCourse, stateFlags)
end #function addBreakFreeSection!
## This function calculates the support points of the clearing section.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the clearing section.
"""
addClearingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
Calculate the support points of the clearing section and add them to `drivingCourse`.
See also [`addBreakFreeSection!`](@ref), [`addCruisingSection!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
# Examples
See [`addBreakFreeSection!`](@ref).
"""
function addClearingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train)
CS = CSs[csId]
@ -79,8 +115,25 @@ function addClearingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
return (drivingCourse, stateFlags)
end #function addClearingSection
## This function calculates the support points of the accelerating section.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the accelerating section
"""
addAcceleratingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
Calculate the support points of the accelerating section and add them to `drivingCourse`.
See also [`addBreakFreeSection!`](@ref), [`addClearingSection!`](@ref), [`addCruisingSection!`](@ref), [`addDiminishingSection!`](@ref), [`addCoastingSection!`](@ref), [`addBrakingSection!`](@ref), [`addHalt!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
# Examples
See [`addBreakFreeSection!`](@ref).
"""
function addAcceleratingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train)
CS = CSs[csId]
@ -133,10 +186,11 @@ function addAcceleratingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict,
tractionSurplus = drivingCourse[end][:F_T] > drivingCourse[end][:F_R]
end #while
# for testing change the csId to the CS to be analysed
if csId==0
testFlag = true
else
testFlag = false # for testing
testFlag = false
end
# check which limit was reached and adjust the currentStepSize for the next cycle
@ -243,7 +297,7 @@ function addAcceleratingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict,
# set state flags
stateFlags[:endOfCSReached] = endOfCSReached
stateFlags[:brakingStartReached] = brakingStartReached
stateFlags[:tractionDeficit] = !(tractionSurplus || drivingCourse[end][:F_T] == drivingCourse[end][:F_R]) # or add another flag for equal forces?
stateFlags[:tractionDeficit] = !(tractionSurplus || drivingCourse[end][:F_T] == drivingCourse[end][:F_R])
stateFlags[:resistingForceNegative] = drivingCourse[end][:F_R] < 0
stateFlags[:previousSpeedLimitReached] = previousSpeedLimitReached
stateFlags[:speedLimitReached] = speedLimitReached
@ -253,8 +307,26 @@ function addAcceleratingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict,
end #function addAcceleratingSection!
## This function calculates the support points of the cruising section.
# Therefore it gets its first support point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed.
"""
addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, cruisingType, s_cruising)
Calculate the support points of the cruising section and add them to `drivingCourse`.
See also [`addBreakFreeSection!`](@ref), [`addClearingSection!`](@ref), [`addAcceleratingSection!`](@ref), [`addDiminishingSection!`](@ref), [`addCoastingSection!`](@ref), [`addBrakingSection!`](@ref), [`addHalt!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
- `cruisingType::String`: the type of crusing respectively if applicable the reason why the train has to cruise
- `s_cruising::Real`: the planned maximum crusing distance
# Examples
See [`addBreakFreeSection!`](@ref).
"""
function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train, cruisingType::String, s_cruising::Real)
CS = CSs[csId]
@ -262,7 +334,7 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
trainIsBrakingDownhill = cruisingType == "downhillBraking"
# traction effort and resisting forces (in N)
if !trainIsBrakingDownhill # TODO: or just give drivingMode instead of "cruising"/"braking"?
if !trainIsBrakingDownhill
calculateForces!(drivingCourse[end], CSs, csId, "cruising", train, settings.massModel)
else
calculateForces!(drivingCourse[end], CSs, csId, "braking", train, settings.massModel)
@ -271,7 +343,6 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
# conditions for cruising section
#s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
brakingStartReached = drivingCourse[end][:s] + s_braking >= CS[:s_exit] || stateFlags[:brakingStartReached]
speedIsValid = drivingCourse[end][:v] > 0.0 && drivingCourse[end][:v] <= CS[:v_limit]
tractionDeficit = drivingCourse[end][:F_T] < drivingCourse[end][:F_R]
@ -281,9 +352,7 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
if speedIsValid && !brakingStartReached && !tractionDeficit && !targetPositionReached
drivingMode = cruisingType
drivingCourse[end][:behavior] = drivingMode
# TODO: necessary?
targetPosition = min(drivingCourse[end][:s] + s_cruising, CS[:s_exit])
# 07/12 old: s_cruising = min(s_cruising, CS[:s_exit]-drivingCourse[end][:s])
# traction effort and resisting forces (in N)
if !trainIsBrakingDownhill
@ -297,7 +366,6 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
trainInPreviousCS = drivingCourse[end][:s] < CS[:s_entry] + train.length
targetPositionReached = drivingCourse[end][:s] >= targetPosition
resistingForceNegative = drivingCourse[end][:F_R] < 0.0
# TODO: change? to: correctCruisingType = (trainIsClearing || (trainIsBrakingDownhill == drivingCourse[end][:F_R] < 0)) # while clearing tractive or braking force can be used
# use the conditions for the cruising section
while trainInPreviousCS && !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
@ -307,8 +375,6 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
for cycle in 1:settings.approxLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while trainInPreviousCS && !targetPositionReached && !pointOfInterestReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
# the tractive effort is lower than the resisting forces and the train has to use the highest possible effort to try to stay at v_limit OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance?
# tractive effort (in N):
if !trainIsBrakingDownhill
drivingCourse[end][:F_T] = min(drivingCourse[end][:F_T], max(0.0, drivingCourse[end][:F_R]))
@ -316,7 +382,6 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
drivingCourse[end][:F_T] = 0.0
end
# acceleration (in m/s^2):
drivingCourse[end][:a] = 0.0
@ -324,7 +389,7 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
if settings.stepVariable == :distance || settings.stepVariable == :time
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, csId))
else
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, train.length/(10.0^cycle), csId)) # TODO which step size should be used?
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, train.length/(10.0^cycle), csId))
end
drivingCourse[end][:behavior] = drivingMode
@ -357,14 +422,14 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
currentStepSize = settings.stepSize / 10.0^cycle
end
elseif drivingCourse[end][:s] > targetPosition # TODO also the following? drivingCourse[end][:s] > CS[:s_entry] + train.length))
elseif drivingCourse[end][:s] > targetPosition
if settings.stepVariable == :distance
currentStepSize = targetPosition - drivingCourse[end-1][:s]
else
currentStepSize = settings.stepSize / 10.0^cycle
end
elseif drivingCourse[end][:s] == targetPosition # || drivingCourse[end][:s]==CS[:s_exit]
elseif drivingCourse[end][:s] == targetPosition
break
elseif drivingCourse[end][:s] >= CS[:s_entry] + train.length
@ -429,7 +494,7 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
while !targetPositionReached && !tractionDeficit && (trainIsClearing || (trainIsBrakingDownhill == resistingForceNegative)) # while clearing tractive or braking force can be used
nextPointOfInterest = getNextPointOfInterest(CS[:pointsOfInterest], drivingCourse[end][:s])
if nextPointOfInterest[:s] > targetPosition
nextPointOfInterest = (s = targetPosition, label = "") #[targetPosition, ""]
nextPointOfInterest = (s = targetPosition, label = "")
end
# tractive effort (in N):
@ -444,7 +509,6 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
drivingCourse[end][:a] = 0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way
#s_cruisingRemaining=targetPosition-drivingCourse[end][:s]
s_cruisingRemaining = min(nextPointOfInterest[:s] -drivingCourse[end][:s], targetPosition -drivingCourse[end][:s])
# create the next support point
@ -479,7 +543,24 @@ function addCruisingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
end #function addCruisingSection!
## This function calculates the support points for diminishing run when using maximum tractive effort and still getting slower
"""
addDiminishingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
Calculate the support points of the diminishing section (when using maximum tractive effort and still getting slower) and add them to `drivingCourse`.
See also [`addBreakFreeSection!`](@ref), [`addClearingSection!`](@ref), [`addAcceleratingSection!`](@ref), [`addCruisingSection!`](@ref), [`addCoastingSection!`](@ref), [`addBrakingSection!`](@ref), [`addHalt!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
# Examples
See [`addBreakFreeSection!`](@ref).
"""
function addDiminishingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train)
CS = CSs[csId]
@ -633,8 +714,24 @@ function addDiminishingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, C
end #function addDiminishingSection!
## This function calculates the support points of the coasting section.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
"""
addCoastingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
Calculate the support points of the coasting section and add them to `drivingCourse`.
See also [`addBreakFreeSection!`](@ref), [`addClearingSection!`](@ref), [`addAcceleratingSection!`](@ref), [`addCruisingSection!`](@ref), [`addDiminishingSection!`](@ref), [`addBrakingSection!`](@ref), [`addHalt!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
# Examples
See [`addBreakFreeSection!`](@ref).
"""
function addCoastingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train)
CS = CSs[csId]
@ -698,7 +795,7 @@ function addCoastingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
currentStepSize = settings.stepSize / 10.0^cycle
end
elseif drivingCourse[end][:v] < CS[:v_exit] # TODO: if accelereation and coasting functions will be combined this case is only for coasting
elseif drivingCourse[end][:v] < CS[:v_exit]
testFlag && println("in CS",csId," coasting cycle",cycle," case: v=", drivingCourse[end][:v]," < v_exit=", CS[:v_exit]) # for testing
if settings.stepVariable == :velocity
currentStepSize = drivingCourse[end-1][:v] - CS[:v_exit]
@ -727,8 +824,7 @@ function addCoastingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
break
else
# TODO: not needed. just for testing
error("ERROR at coasting until braking section: With the step variable ",settings.stepVariable," the while loop will be left although v<v_limit and s+s_braking<s_exit in CS",csId," with s=" ,drivingCourse[end][:s]," m and v=",drivingCourse[end][:v]," m/s")
end
# delete last support point for recalculating the last step with reduced step size
pop!(drivingCourse)
@ -796,8 +892,24 @@ function addCoastingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs:
end #function addCoastingSection!
## This function calculates the support points of the braking section.
# Therefore it gets its first support point and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
"""
addBrakingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
Calculate the support points of the braking section and add them to `drivingCourse`.
See also [`addBreakFreeSection!`](@ref), [`addClearingSection!`](@ref), [`addAcceleratingSection!`](@ref), [`addCruisingSection!`](@ref), [`addDiminishingSection!`](@ref), [`addCoastingSection!`](@ref), [`addHalt!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
# Examples
See [`addBreakFreeSection!`](@ref).
"""
function addBrakingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train)
CS = CSs[csId]
@ -822,13 +934,14 @@ function addBrakingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::
# acceleration (in m/s^2):
drivingCourse[end][:a] = train.a_braking
# TODO or: drivingCourse[end][:a] = brakingAcceleration(drivingCourse[end][:v], CS[:v_exit], CS[:s_exit]-drivingCourse[end][:s])
# Check if the train stops during this braking step. Therefore check if parts of square roots in moveAStep will be <0.0.
# If it ist the case calculate the exact braking acceleration for the fix end position and velocity.
if settings.stepVariable == :distance && ((drivingCourse[end][:v]/drivingCourse[end][:a])^2+2*currentStepSize/drivingCourse[end][:a])<0.0 || (drivingCourse[end][:v]^2+2*currentStepSize*drivingCourse[end][:a])<0.0
# create empty support point and set it for the values of s_exit and v_exit
push!(drivingCourse, SupportPoint())
drivingCourse[end][:behavior] = drivingMode
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
drivingCourse = recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
else
# create the next support point
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, csId))
@ -842,7 +955,6 @@ function addBrakingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::
end # while
# check which limit was reached and adjust the currentStepSize for the next cycle
# TODO: is there a better way than rounding like in the following?
if cycle < settings.approxLevel+1
if drivingCourse[end][:v] < CS[:v_exit]
if settings.stepVariable == :velocity
@ -862,12 +974,12 @@ function addBrakingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::
break
elseif drivingCourse[end][:v] == CS[:v_exit]
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
drivingCourse = recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
endOfCSReached = true
break
elseif drivingCourse[end][:s] == CS[:s_exit]
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
drivingCourse = recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
targetSpeedReached = true
break
@ -885,15 +997,12 @@ function addBrakingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::
else # if the level of approximation is reached
if drivingCourse[end][:v] < 0.0
# TODO: drivingCourse[end][:v] < CS[:v_exit] should be enough
# reset last point with setting v=v_exit. still possible with v_exit now meaning v_exitMax?
# println("during braking section in CS",csId,": rounding v up from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], 0.0)
# println("during braking section in CS",csId,": rounding v up from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing
drivingCourse = recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], 0.0)
endOfCSReached = true
break
elseif drivingCourse[end][:s] > CS[:s_exit]
# println("during braking section in CS",csId,": rounding s down from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
# recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
# println("during braking section in CS",csId,": rounding s down from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
drivingCourse[end][:s] = CS[:s_exit]
break
elseif drivingCourse[end][:s] > nextPointOfInterest[:s]
@ -903,18 +1012,18 @@ function addBrakingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::
break
elseif drivingCourse[end][:v] < CS[:v_exit]
# reset last point with setting v=v_exit
# println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
# println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
drivingCourse = recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
endOfCSReached = true
break
elseif drivingCourse[end][:v] == CS[:v_exit]
# println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
# println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
drivingCourse = recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
endOfCSReached = true
break
elseif drivingCourse[end][:s] == CS[:s_exit]
# println("during braking section in CS",csId,": rounding v down from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing
recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
# println("during braking section in CS",csId,": rounding v down from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing
drivingCourse = recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
targetSpeedReached = true
break
else
@ -943,10 +1052,25 @@ function addBrakingSection!(drivingCourse::Vector{Dict}, stateFlags::Dict, CSs::
end #function addBrakingSection!
## This function calculates the support point of the halt.
# Therefore it gets its first support point and the characteristic section and returns the characteristic section including the halt if needed.
"""
addHalt!(drivingCourse, stateFlags, CSs, csId, settings, train)
Calculate the support points of the halt section and add them to `drivingCourse`.
See also [`addBreakFreeSection!`](@ref), [`addClearingSection!`](@ref), [`addAcceleratingSection!`](@ref), [`addCruisingSection!`](@ref), [`addDiminishingSection!`](@ref), [`addCoastingSection!`](@ref), [`addBrakingSection!`](@ref).
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `stateFlags::Dict`: the Dictionary containing different states for `drivingCourse`'s values.
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `csId::Integer`: the number of characteristic section in the Vector `CSs`.
- `settings::Settings`: the Settings object containing settings used for calculation.
- `train::Train`: the Train object containing attributes with technical train data.
# Examples
See [`addBreakFreeSection!`](@ref).
"""
function addHalt!(drivingCourse::Vector{Dict}, CSs::Vector{Dict}, csId::Integer, settings::Settings, train::Train)
# CS = CSs[csId] # is not needed here
if drivingCourse[end][:v] == 0.0
drivingMode = "halt"
drivingCourse[end][:behavior] = drivingMode
@ -957,23 +1081,55 @@ function addHalt!(drivingCourse::Vector{Dict}, CSs::Vector{Dict}, csId::Integer,
return drivingCourse
end #function addHalt!
function recalculateLastBrakingPoint!(drivingCourse, s_target, v_target)
"""
recalculateLastBrakingPoint!(drivingCourse, s_target, v_target)
Realculate the last step of the `drivingCourse` depending on new position and velocity.
# Arguments
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `s_target::Real`: the new positon for the last support point in m.
- `v_target::Real`: the new velocity for the last support point in m/s.
# Examples
```julia-repl
julia> recalculateLastBrakingPoint(drivingCourse_with_two_points_near_5000m, 5000.0, 23.333333333333332)
Dict{Symbol, Any}[Dict(:label => "", :behavior => "braking", :F_T => 0.0, :R_wagons => 21655.0, :R_path => 0.0, :s => 4999.999980000006, :v => 23.333333441372545, :R_train => 28640.8, :R_traction => 6985.8, :a => -0.126, :t => 235.16501930395856, :F_R => 28640.8), Dict(:label => "", :behavior => "braking", :F_T => 0.0, :R_wagons => 0.0, :R_path => 0.0, :s => 5000.0, :v => 23.333333333333332, :R_train => 0.0, :R_traction => 0.0, :a => 0.0, :t => 235.16502016110115, :F_R => 0.0)]
```
"""
function recalculateLastBrakingPoint!(drivingCourse::Vector{Dict}, s_target::Real, v_target::Real)
currentPoint = drivingCourse[end]
previousPoint = drivingCourse[end-1]
# set s and v
currentPoint[:s] = s_target # position (in m)
currentPoint[:v] = v_target # velocity (in m/s)
# calculate other values
previousPoint[:a] = brakingAcceleration(previousPoint[:v], currentPoint[:v], currentPoint[:s]-previousPoint[:s])
# # TODO: just for testing
# if previousPoint[:a]<train.a_braking || previousPoint[:a]>=0.0
# println("Warning: a_braking gets to high in CS ",csId, " with a=",previousPoint[:a] ," > ",train.a_braking)
# end
currentPoint[:t] = previousPoint[:t] + Δt_with_Δv(currentPoint[:v]-previousPoint[:v], previousPoint[:a]) # point in time (in s)
# calculate other values
previousPoint[:a] = brakingAcceleration(previousPoint[:v], currentPoint[:v], currentPoint[:s]-previousPoint[:s])
currentPoint[:t] = previousPoint[:t] + Δt_with_Δv(currentPoint[:v]-previousPoint[:v], previousPoint[:a]) # point in time (in s)
return drivingCourse
end #function recalculateLastBrakingPoint
## define the intersection velocities between the characterisitc sections to secure braking behavior
"""
secureBrakingBehavior!(CSs, a_braking, approxLevel)
Calculate the velocities between the characterisitc sections to secure braking behavior.
# Arguments
- `CSs::Vector{Dict}`: the Vector containing dictionaries for all characteristic sections.
- `a_braking::Real`: the constant braking acceleration in m/s^2.
- `approxLevel::Integer`: the last position behind the decimal point that is not rounded.
# Examples
```julia-repl
julia> secureBrakingBehavior!(CSs, -0.375, 3)
Dict[Dict{Symbol, Any}(:s_entry => 0.0, :v_exit => 19.3649, :v_limit => 25.0, :r_path => 0.0, :pointsOfInterest => NamedTuple[(s = 9500.0, label = "")], :s_exit => 9500.0), Dict{Symbol, Any}(:s_entry => 0.0, :v_exit => 0.0, :v_limit => 25.0, :r_path => 1.0, :pointsOfInterest => NamedTuple[(s = 10000.0, label = "")], :s_exit => 10000.0)]
```
"""
function secureBrakingBehavior!(CSs::Vector{Dict}, a_braking::Real, approxLevel::Integer)
# limit the entry and exit velocities of the characteristic sections to secure that the train stops at the moving sections end

View File

@ -322,8 +322,25 @@ function determineCharacteristics(path::Path, train::Train, settings::Settings)
sort!(pointsOfInterest, by = x -> x[:s])
end
characteristicSections = CharacteristicSections(path, train.v_limit, train.length, pointsOfInterest)
characteristicSections = secureBrakingBehavior!(characteristicSections, train.a_braking, settings.approxLevel)
# create the characteristic sections of a moving section 'CSs' dependent on the paths attributes
CSs = Vector{Dict}()
s_csStart = path.sections[1][:s_start] # first position (in m)
return (characteristicSections, pointsOfInterest)
for row in 2:length(path.sections)
previousSection = path.sections[row-1]
currentSection = path.sections[row]
speedLimitIsDifferent = min(previousSection[:v_limit], train.v_limit) != min(currentSection[:v_limit], train.v_limit)
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
if speedLimitIsDifferent || pathResistanceIsDifferent
push!(CSs, CharacteristicSection(s_csStart, previousSection, min(previousSection[:v_limit], train.v_limit), train.length, pointsOfInterest))
s_csStart = currentSection[:s_start]
end #if
end #for
push!(CSs, CharacteristicSection(s_csStart, path.sections[end], min(path.sections[end][:v_limit], train.v_limit), train.length, pointsOfInterest))
# secure that the train is able to brake sufficiently and keeps speed limits
CSs = secureBrakingBehavior!(CSs, train.a_braking, settings.approxLevel)
return (CSs, pointsOfInterest)
end #function determineCharacteristics

View File

@ -613,28 +613,6 @@ function Train(file, type = :YAML)
end #function Train() # outer constructor
## create the moving section's characteristic sections
function CharacteristicSections(path::Path, v_trainLimit::Real, s_trainLength::Real, MS_poi::Vector{NamedTuple})
# create and return the characteristic sections of a moving section dependent on the paths attributes
CSs = Vector{Dict}()
s_csStart = path.sections[1][:s_start] # first position (in m)
#csId = 1
for row in 2:length(path.sections)
previousSection = path.sections[row-1]
currentSection = path.sections[row]
speedLimitIsDifferent = min(previousSection[:v_limit], v_trainLimit) != min(currentSection[:v_limit], v_trainLimit)
pathResistanceIsDifferent = previousSection[:f_Rp] != currentSection[:f_Rp]
if speedLimitIsDifferent || pathResistanceIsDifferent
push!(CSs, CharacteristicSection(s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, MS_poi))
s_csStart = currentSection[:s_start]
#csId = csId+1
end #if
end #for
push!(CSs, CharacteristicSection(s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, MS_poi))
return CSs
end #function CharacteristicSections
## create a characteristic section for a path section.
function CharacteristicSection(s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, MS_poi::Vector{NamedTuple})

View File

@ -27,27 +27,23 @@
## }
#########################
#approxLevel = 6
v00 = 100/3.6 # velocity factor (in m/s)
## calculate forces
## calculate forces:
#TODO: replace the ? ? ?
"""
tractionUnitResistance(v, train)
Calculate the vehicle resistance for the traction unit of the `train` dependend on the velocity `v`.
Calculate the vehicle resistance in N for the traction unit of the `train` dependend on the velocity `v`.
...
# Arguments
- `v::AbstractFloat`: the current velocity in m/s.
- `train::Train`: ? ? ?
...
- `train::Train`: the struct defined in types.jl containing attributes with technical data.
# Examples
```julia-repl
julia> tractionUnitResistance(30.0, ? ? ?)
? ? ?
julia> tractionUnitResistance(15.0, freight_train)
5461.127252
```
"""
function tractionUnitResistance(v::AbstractFloat, train::Train)
@ -58,32 +54,52 @@ function tractionUnitResistance(v::AbstractFloat, train::Train)
m_td = train.m_td # mass on the traction unit's driving axles (in kg)
m_tc = train.m_tc # mass on the traction unit's carrying axles (in kg)
F_R_tractionUnit = f_Rtd0/1000 * m_td * g + f_Rtc0/1000 * m_tc * g + f_Rt2/1000 * (m_td+m_tc) * g * ((v + Δv_air) /v00)^2 # vehicle resistance of the traction unit (in N) # /1000 because of the unit ‰
# TODO: use forceFromCoefficient? F_R_tractionUnit = forceFromCoefficient(f_Rtd0, m_td) + forceFromCoefficient(f_Rtc0, m_tc) + forceFromCoefficient(f_Rt2, m_td+m_tc) * ((v + Δv_air) /v00)^2 # vehicle resistance of the traction unit (in N)
return F_R_tractionUnit
#TODO: same variable name like in the rest of TrainRuns? return R_traction
end #function tractionUnitResistance
"""
TODO
calculate and return the freight wagons' vehicle resistance dependend on the velocity
freightWagonsResistance(v, train)
Calculate the vehicle resistance in N for the freight wagons of the `train` dependend on the velocity `v`.
# Arguments
- `v::AbstractFloat`: the current velocity in m/s.
- `train::Train`: the struct defined in types.jl containing attributes with technical data.
# Examples
```julia-repl
julia> freightWagonsResistance(15.0, freight_train)
20900.732702639998
```
"""
function freightWagonsResistance(v::AbstractFloat, train::Train)
# equation is based on a combination of the equations of Strahl and Sauthoff [Wende:2003, page 153]
# equation is based on the equation of Strahl [Wende:2003, page 153]
f_Rw0 = train.f_Rw0 # coefficient for basic resistance of the set of wagons (consist) (in ‰)
f_Rw2 = train.f_Rw2 # coefficient fo the consistsr air resistance (in ‰)
m_w = train.m_w # mass of the set of wagons (consist) (in kg)
F_R_wagons = m_w *g *(f_Rw0/1000 + f_Rw2/1000 * (v /v00)^2) # vehicle resistance of freight wagons (in N) with Strahl # /1000 because of the unit ‰
# TODO: use forceFromCoefficient? F_R_wagons = forceFromCoefficient(f_Rw0, m_w) + ...
return F_R_wagons
end #function calcWagonsResistance
"""
TODO
calculate and return the passenger wagons' vehicle resistance dependend on the velocity
passengerWagonsResistance(v, train)
Calculate the vehicle resistance in N for the passenger wagons of the `train` dependend on the velocity `v`.
# Arguments
- `v::AbstractFloat`: the current velocity in m/s.
- `train::Train`: the struct defined in types.jl containing attributes with technical data.
# Examples
```julia-repl
julia> passengerWagonsResistance(15.0, longdistance_passenger_train)
14461.2708244928
```
"""
function passengerWagonsResistance(v::AbstractFloat, train::Train)
# equation is based on the equations of Sauthoff [Wende:2003, page 153]
@ -94,129 +110,277 @@ function passengerWagonsResistance(v::AbstractFloat, train::Train)
F_R_wagons = m_w *g *(f_Rw0/1000 + f_Rw1/1000 *v /v00 + f_Rw2/1000 * ((v + Δv_air) /v00)^2) # vehicle resistance of passenger wagons (in N) with Sauthoff # /1000 because of the unit ‰
# TODO: use forceFromCoefficient? F_R_wagons = forceFromCoefficient(f_Rw0, m_w) + ...
return F_R_wagons
end #function calcWagonsResistance
function forceFromCoefficient(f_R::Real, m::Real)
"""
forceFromCoefficient(f, m)
Calculate the force in N with the coefficient `f` in and the vehicle's mass `m` in kg.
# Examples
```julia-repl
julia> forceFromCoefficient(1.5, 68000.0)
1000.2783
```
"""
function forceFromCoefficient(f::Real, m::Real)
# equation is based on [Wende:2003, page 8]
# f_R: specific resistance (in ‰)
# m: vehicle's mass (in kg)
F_R = f_R /1000 *m *g # Resisting Force (in N) # /1000 because of the unit ‰
return F_R
F = f /1000 *m *g # force (in N) # /1000 because of the unit ‰
return F
end #function forceFromCoefficient
## calculate acceleration:
"""
acceleration(F_T, F_R, m_train, ξ_train)
Calculate the acceleration in m/s^2 with train characteristics and forces.
# Arguments
- `F_T::Real`: the tractive effort in N.
- `F_R::Real`: the resisting forces in N.
- `m_train::Real`: the train's mass in kg.
- `ξ_train::Real`: the train's rotation mass factor (without unit).
# Examples
```julia-repl
julia> acceleration(94400.0, 1700.0, 88000.0, 1.08)
0.9753787878787878
```
"""
function acceleration(F_T::Real, F_R::Real, m_train::Real, ξ_train::Real)
# equation is based on [Bruenger:2014, page 72] with a=dv/dt
# F_T: tractive effort (in N)
# F_R: resisting forces (in N)
# m_train: train's mass (in kg)
# ξ_train: train's rotation mass factor (without unit)
a = (F_T - F_R) /m_train /ξ_train # acceleration (in m/s)
a = (F_T - F_R) /m_train /ξ_train # acceleration (in m/s^2)
return a
end #function acceleration
## calculate step sizes:
"""
Δs_with_Δt(Δt, a_prev, v_prev)
Calculate the distance step in m with the time step in s, acceleration in m/s^2 and velocity in m/s.
See also [`Δs_with_Δv`](@ref), [`Δt_with_Δs`](@ref), [`Δt_with_Δv`](@ref), [`Δt_with_constant_v`](@ref), [`Δv_with_Δs`](@ref), [`Δv_with_Δt`](@ref).
# Examples
```julia-repl
julia> Δs_with_Δt(3.0, 0.5, 25.0)
77.25
```
"""
function Δs_with_Δt(Δt::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37]
# Δt: time step (in s)
# a_prev: acceleration from previous support point
# v_prev: velocitiy from previous support point
Δs = Δt * (2*v_prev + Δt*a_prev) /2 # step size (in m)
return Δs
end #function Δs_with_Δt
"""
Δs_with_Δv(Δv, a_prev, v_prev)
Calculate the distance step in m with the velocity step in m/s, acceleration in m/s^2 and velocity in m/s.
See also [`Δs_with_Δt`](@ref), [`Δt_with_Δs`](@ref), [`Δt_with_Δv`](@ref), [`Δt_with_constant_v`](@ref), [`Δv_with_Δs`](@ref), [`Δv_with_Δt`](@ref).
# Examples
```julia-repl
julia> Δs_with_Δv(1.0, 0.5, 25.0)
51.0
```
"""
function Δs_with_Δv(Δv::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37]
# Δv: velocity step (in m/s)
# a_prev: acceleration from previous support point
# v_prev: velocitiy from previous support point
Δs = ((v_prev + Δv)^2 - v_prev^2)/2/a_prev # step size (in m)
Δs = ((v_prev + Δv)^2 - v_prev^2) /2 /a_prev # step size (in m)
return Δs
end #function Δs_with_Δv
"""
Δt_with_Δs(Δs, a_prev, v_prev)
Calculate the time step in s with the distance step in m, acceleration in m/s^2 and velocity in m/s.
See also [`Δs_with_Δt`](@ref), [`Δs_with_Δv`](@ref), [`Δt_with_Δv`](@ref), [`Δt_with_constant_v`](@ref), [`Δv_with_Δs`](@ref), [`Δv_with_Δt`](@ref).
# Examples
```julia-repl
julia> Δt_with_Δs(10.0, 0.5, 25.0)
0.39841267341660824
```
"""
function Δt_with_Δs(Δs::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37]
# Δs: distance step (in m)
# a_prev: acceleration from previous support point
# v_prev: velocitiy from previous support point
Δt = sign(a_prev) *sqrt((v_prev /a_prev)^2 + 2 *Δs /a_prev) - v_prev /a_prev # step size (in m/s)
Δt = sign(a_prev) *sqrt((v_prev /a_prev)^2 + 2 *Δs /a_prev) - v_prev /a_prev # step size (in s)
return Δt
end #function Δt_with_Δs
"""
Δt_with_Δv(Δv, a_prev)
Calculate the time step in s with the velocity step in m/s and the acceleration in m/s^2.
See also [`Δs_with_Δt`](@ref), [`Δs_with_Δv`](@ref), [`Δt_with_Δs`](@ref), [`Δt_with_constant_v`](@ref), [`Δv_with_Δs`](@ref), [`Δv_with_Δt`](@ref).
# Examples
```julia-repl
julia> Δt_with_Δv(1.0, 0.5)
2.0
```
"""
function Δt_with_Δv(Δv::Real, a_prev::Real)
# equation is based on [Wende:2003, page 37]
# Δv: velocity step (in m/s)
# a_prev: acceleration from previous support point
Δt = Δv /a_prev # step size (in s)
return Δt
end #function Δt_with_Δv
"""
Δt_with_constant_v(Δs, v)
Calculate the time step in s with the distance step in m and constant velocity in m/s.
See also [`Δs_with_Δt`](@ref), [`Δs_with_Δv`](@ref), [`Δt_with_Δs`](@ref), [`Δt_with_Δv`](@ref), [`Δv_with_Δs`](@ref), [`Δv_with_Δt`](@ref).
# Examples
```julia-repl
julia> Δt_with_constant_v(10.0, 25.0)
0.4
```
"""
function Δt_with_constant_v(Δs::Real, v::Real)
# equation is based on [Wende:2003, page 37]
# Δs: distance step (in m)
# v: constant velocity (in m/s)
Δt = Δs /v # step size (in s)
return Δt
end #function Δt_with_constant_v
"""
Δv_with_Δs(Δs, a_prev, v_prev)
Calculate the velocity step in m/s with the distance step in m, acceleration in m/s^2 and velocity in m/s.
See also [`Δs_with_Δt`](@ref), [`Δs_with_Δv`](@ref), [`Δt_with_Δs`](@ref), [`Δt_with_Δv`](@ref), [`Δt_with_constant_v`](@ref), [`Δv_with_Δt`](@ref).
# Examples
```julia-repl
julia> Δv_with_Δs(10.0, 0.5, 25.0)
0.19920633670830412
```
"""
function Δv_with_Δs(Δs::Real, a_prev::Real, v_prev::Real)
# equation is based on [Wende:2003, page 37]
# Δs: distance step (in m)
# a_prev: acceleration from previous support point
# v_prev: velocitiy from previous support point
Δv = sqrt(v_prev^2 + 2*Δs*a_prev) - v_prev # step size (in m/s)
return Δv
end #function Δv_with_Δs
"""
Δv_with_Δt(Δt, a_prev, v_prev)
Calculate the velocity step in m/s with the time step in s and acceleration in m/s^2.
See also [`Δs_with_Δt`](@ref), [`Δs_with_Δv`](@ref), [`Δt_with_Δs`](@ref), [`Δt_with_Δv`](@ref), [`Δt_with_constant_v`](@ref), [`Δv_with_Δs`](@ref).
# Examples
```julia-repl
julia> Δv_with_Δt(3.0, 0.5)
1.5
```
"""
function Δv_with_Δt(Δt::Real, a_prev::Real)
# equation is based on [Wende:2003, page 37]
# Δt: time step (in s)
# a_prev: acceleration from previous support point
Δv = Δt * a_prev # step size (in m/s)
return Δv
end #function Δv_with_Δt
## calculate values for braking
"""
brakingDistance(v_start, v_end, a_braking, approxLevel)
Calculate the braking distance in m with velocities in m/s and acceleration in m/s^2.
See also [`brakingAcceleration`](@ref), [`brakingStartVelocity`](@ref).
# Arguments
- `v_start::Real`: the velocity at the start of braking in m/s.
- `v_end::Real`: the target velocity at the end of braking in m/s.
- `a_braking::Real`: the constant braking acceleration in m/s^2.
- `approxLevel::Integer`: the last position behind the decimal point that is not rounded
# Examples
```julia-repl
julia> brakingDistance(25.0, 15.0, -0.4253, 3)
470.2563
```
"""
function brakingDistance(v_start::Real, v_end::Real, a_braking::Real, approxLevel::Integer)
# equation is based on [Wende:2003, page 37]
# v_start: velocity at the start of braking (in m/s)
# v_end: target velocity at the end of braking (in m/s)
# a_braking: constant braking acceleration (in m/s^2)
s_braking = (v_end^2 - v_start^2) /2 /a_braking # braking distance (in m)
# TODO: also possible: Δs_with_Δv(v_end-v_start, a_braking, v_start)
# return max(0.0, ceil(s_braking, digits=approxLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
return max(0.0, ceil(s_braking, digits= approxLevel +1)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
end #function brakingDistance
"""
brakingStartVelocity(v_end, a_braking, s_braking, approxLevel)
Calculate the maximum velocity in m/s where the train can start to brake to reach `v_end`.
See also [`brakingAcceleration`](@ref), [`brakingDistance`](@ref).
# Arguments
- `v_end::Real`: the target velocity at the end of braking in m/s.
- `a_braking::Real`: the constant braking acceleration in m/s^2.
- `s_braking::Real`: the braking distance in m.
- `approxLevel::Integer`: the last position behind the decimal point that is not rounded
# Examples
```julia-repl
julia> brakingStartVelocity(15.0, -0.4253, 500, 3)
25.4656
```
"""
function brakingStartVelocity(v_end::Real, a_braking::Real, s_braking::Real, approxLevel::Integer)
# equation is based on [Wende:2003, page 37]
# v_end: target velocity at the end of braking (in m/s)
# a_braking: constant braking acceleration (in m/s^2)
# s_braking: braking distance (in Ws)
v_start = sqrt(v_end^2 - 2*a_braking *s_braking) # braking start velocity (in m/s)
# return floor(v_start, digits= approxLevel)
return floor(v_start, digits= approxLevel +1)
end #function brakingStartVelocity
"""
brakingAcceleration(v_start, v_end, s_braking)
Calculate the acceleration in m/s^2 to decelerate from `v_start` to `v_end` in m/s on `s_braking` in m.
See also [`brakingDistance`](@ref), [`brakingStartVelocity`](@ref).
# Examples
```julia-repl
julia> brakingAcceleration(25.0, 15.0, 500)
-0.4
```
"""
function brakingAcceleration(v_start::Real, v_end::Real, s_braking::Real)
# equation is based on [Wende:2003, page 37]
# v_start: braking start velocity (in m/s)
# v_end: target velocity at the end of braking (in m/s)
# s_braking: braking distance (in Ws)
a_braking = (v_end^2 - v_start^2) /2 /s_braking # constant braking acceleration (in m/s^2)
return a_braking
end #function brakingAcceleration

View File

@ -4,6 +4,32 @@
# __copyright__ = "2020-2022"
# __license__ = "ISC"
"""
createOutput(settings, drivingCourse, pointsOfInterest)
Create output information depending on `settings`, `drivingCourse` and `pointsOfInterest`.
See also [`createOutput`](@ref).
# Arguments
- `settings::Settings`: the Settings object containing settings for output format and detail.
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `pointsOfInterest::Vector{NamedTuple}`: the Vector containing tuples for the paths' points of interest.
# Examples
```julia-repl
julia> createOutput(settings_poi, drivingCourse_longdistance, pointsOfInterest_pathWithSlope)
5×11 DataFrame
Row label driving_mode s v t a F_T F_R R_path R_traction R_wagons
String String Real Real Real Real Real Real Real Real Real
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 view_point_1 accelerating 850.0 28.707 54.049 0.331 1.93049e5 36602.1 0.0 9088.56 27513.6
2 distant_signal_1 accelerating 1000.0 30.325 59.129 0.294 1.82746e5 43604.7 4344.35 9795.13 29465.2
3 main_signal_1 accelerating 2000.0 37.356 88.468 0.185 1.48352e5 60899.4 8688.69 13259.1 38951.5
4 main_signal_3 braking 9000.0 27.386 258.578 -0.375 0.0 34522.1 0.0 8537.05 25985.0
5 clearing_point_1 braking 9203.37 24.443 266.426 -0.375 0.0 30176.2 0.0 7389.44 22786.8
```
"""
function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfInterest::Vector{NamedTuple})
if settings.outputDetail == :running_time
output::Vector{Dict} = [Dict(:t => drivingCourse[end][:t])]
@ -52,7 +78,34 @@ function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfI
end
function createDataFrame(output_vector::Vector{Dict}, outputDetail, approxLevel::Int)
"""
createDataFrame(output_vector, outputDetail, approxLevel)
Create a DataFrame from `output_vector` with `outputDetail` and `approxLevel`.
See also [`createOutput`](@ref).
# Arguments
- `output_vector::Vector{Dict}`: the Vector containing all data to be outputted.
- `outputDetail::Symbol`: the detail level the DataFrame is created for.
- `approxLevel::Int`: the number of digits for rounding each Number in the DataFrame.
# Examples
```julia-repl
julia> createDataFrame(vector_pointsOfInterest, detail_data_points, approxLevel_default)
5×11 DataFrame
Row label driving_mode s v t a F_T F_R R_path R_traction R_wagons
String String Real Real Real Real Real Real Real Real Real
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 view_point_1 accelerating 850.0 28.707 54.049 0.331 1.93049e5 36602.1 0.0 9088.56 27513.6
2 distant_signal_1 accelerating 1000.0 30.325 59.129 0.294 1.82746e5 43604.7 4344.35 9795.13 29465.2
3 main_signal_1 accelerating 2000.0 37.356 88.468 0.185 1.48352e5 60899.4 8688.69 13259.1 38951.5
4 main_signal_3 braking 9000.0 27.386 258.578 -0.375 0.0 34522.1 0.0 8537.05 25985.0
5 clearing_point_1 braking 9203.37 24.443 266.426 -0.375 0.0 30176.2 0.0 7389.44 22786.8
```
"""
function createDataFrame(output_vector::Vector{Dict}, outputDetail::Symbol, approxLevel::Int)
if outputDetail == :running_time
# create a DataFrame with running time information
dataFrame = DataFrame(t=[round(output_vector[end][:t], digits=approxLevel)])