Compare commits
26 Commits
86aab025f2
...
25278d63de
Author | SHA1 | Date |
---|---|---|
Martin Scheidt | 25278d63de | |
Martin Scheidt | 31befe815d | |
Max Kannenberg | 8b3d16517b | |
Max Kannenberg | 804f797b08 | |
Max Kannenberg | a7fe8db1c2 | |
Max Kannenberg | bc02e96a6c | |
Max Kannenberg | 8c286b0d2b | |
Max Kannenberg | 94839a28c0 | |
Max Kannenberg | 4a047f4cf2 | |
Max Kannenberg | 4d44674d21 | |
Max Kannenberg | 548d46b6c4 | |
Max Kannenberg | b421fbec5a | |
Max Kannenberg | 6af0912359 | |
Max Kannenberg | f11e64b8b8 | |
Max Kannenberg | c4d8b2c79c | |
Max Kannenberg | 3626f46df9 | |
Max Kannenberg | 395b7eb11c | |
Max Kannenberg | 442a342e84 | |
Martin Scheidt | b8578ae49c | |
Max Kannenberg | cbd4e7f97f | |
Max Kannenberg | 5e33e62a79 | |
Max Kannenberg | acf8cd0c3b | |
Max Kannenberg | 99a07094fc | |
Max Kannenberg | b7e0f21ffb | |
Max Kannenberg | a3a68e5553 | |
Max Kannenberg | 892b84251a |
|
@ -1,8 +1,7 @@
|
|||
name: "continuous integration test"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
branches: [ main, development ]
|
||||
paths-ignore:
|
||||
- 'CHANGELOG.md'
|
||||
- 'CITATION.cff'
|
||||
|
@ -16,6 +15,7 @@ on:
|
|||
- '.github/workflows/TagBot.yml'
|
||||
- '.github/zenodo/*'
|
||||
pull_request:
|
||||
branches: [ main, development ]
|
||||
paths-ignore:
|
||||
- 'CHANGELOG.md'
|
||||
- 'CITATION.cff'
|
||||
|
|
|
@ -4,7 +4,7 @@ on:
|
|||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Version to register or component to bump
|
||||
description: "Version to register or component to bump (without leading 'v' e.g. '1.0.1')"
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
|
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -10,6 +10,25 @@ Categories: Added, Changed, Deprecated, Removed, Fixed, and Security.
|
|||
## [Unreleased]
|
||||
|
||||
|
||||
## Version [1.0.2] 2022-09-01
|
||||
|
||||
### Added
|
||||
* output alternative with starting points of the driving modes
|
||||
|
||||
### Changed
|
||||
* renamed data points into 'support points'
|
||||
* reduced number of decimal places of output data
|
||||
* replace v_peak by the existing v_limit
|
||||
* changed type of a point of interest from Tuple to NamedTuple
|
||||
|
||||
### Removed
|
||||
* dictionary MovingSection
|
||||
* redundant keys from the dictionary CharacteristicSection
|
||||
* dictionary BehaviorSection
|
||||
* redundant keys from the dictionary SupportPoint
|
||||
* function secureAcceleratingBehavior()
|
||||
|
||||
|
||||
## Version [1.0.1] 2022-06-05
|
||||
|
||||
* automated Julia package registration
|
||||
|
@ -192,7 +211,8 @@ Modules and variables were renamed.
|
|||
Proof of concept and master thesis submission.
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/railtoolkit/TrainRuns.jl/compare/v1.0.1...main
|
||||
[Unreleased]: https://github.com/railtoolkit/TrainRuns.jl/compare/v1.0.2...main
|
||||
[1.0.2]: https://github.com/railtoolkit/TrainRuns.jl/compare/v1.0.1...v1.0.2
|
||||
[1.0.1]: https://github.com/railtoolkit/TrainRuns.jl/compare/v1.0.0...v1.0.1
|
||||
[1.0.0]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.8...v1.0.0
|
||||
[0.8]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.7...v0.8
|
||||
|
@ -208,4 +228,4 @@ Proof of concept and master thesis submission.
|
|||
[0.4]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.3...v0.4
|
||||
[0.3]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.2...v0.3
|
||||
[0.2]: https://github.com/railtoolkit/TrainRuns.jl/compare/v0.1...v0.2
|
||||
[0.1]: https://github.com/railtoolkit/TrainRuns.jl/releases/tag/v0.1
|
||||
[0.1]: https://github.com/railtoolkit/TrainRuns.jl/releases/tag/v0.1
|
||||
|
|
|
@ -46,15 +46,15 @@ xxx.xx # in seconds
|
|||
"""
|
||||
function trainrun(train::Train, path::Path, settings=Settings()::Settings)
|
||||
# prepare the input data
|
||||
movingSection = determineCharacteristics(path, train, settings)
|
||||
# settings.outputDetail == :verbose && println("The moving section has been prepared.")
|
||||
(characteristicSections, pointsOfInterest) = determineCharacteristics(path, train, settings)
|
||||
# TODO settings.outputDetail == :verbose && println("The characteristics haven been determined.")
|
||||
|
||||
# calculate the train run for oparation mode "minimum running time"
|
||||
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
|
||||
# settings.outputDetail == :verbose && println("The driving course for the shortest running time has been calculated.")
|
||||
# calculate the train run with the minimum running time
|
||||
drivingCourse = calculateMinimumRunningTime(characteristicSections, settings, train)
|
||||
# TODO settings.outputDetail == :verbose && println("The driving course for the shortest running time has been calculated.")
|
||||
|
||||
# accumulate data and create an output dictionary
|
||||
output = createOutput(settings, drivingCourse, movingSection[:pointsOfInterest])
|
||||
output = createOutput(settings, drivingCourse, pointsOfInterest)
|
||||
|
||||
return output
|
||||
end # function trainrun
|
||||
|
|
924
src/behavior.jl
924
src/behavior.jl
File diff suppressed because it is too large
Load Diff
270
src/calc.jl
270
src/calc.jl
|
@ -7,106 +7,102 @@
|
|||
# Calculate the running time of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
|
||||
|
||||
# calculate a train run focussing on using the minimum possible running time
|
||||
function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, train::Train)
|
||||
CSs::Vector{Dict} = movingSection[:characteristicSections]
|
||||
|
||||
if settings.massModel == :homogeneous_strip && settings.stepVariable == speed
|
||||
println("WARNING: ! ! ! TrainRuns.jl doesn't work reliably for the mass model homogeneous strip with step size v in m/s. The calculation time can be extremely high when calcutlating paths with steep gradients ! ! !")
|
||||
end
|
||||
|
||||
startingPoint=DataPoint()
|
||||
startingPoint[:i]=1
|
||||
startingPoint[:s]=CSs[1][:s_entry]
|
||||
function calculateMinimumRunningTime(CSs::Vector{Dict}, settings::Settings, train::Train)
|
||||
startingPoint = SupportPoint()
|
||||
startingPoint[:s] = CSs[1][:s_entry]
|
||||
calculateForces!(startingPoint, CSs, 1, "default", train, settings.massModel) # traction effort and resisting forces (in N)
|
||||
drivingCourse::Vector{Dict} = [startingPoint] # List of data points
|
||||
drivingCourse::Vector{Dict} = [startingPoint] # List of support points
|
||||
|
||||
for csId in 1:length(CSs)
|
||||
CS = CSs[csId]
|
||||
# for testing
|
||||
if drivingCourse[end][:s] != CS[:s_entry]
|
||||
println("ERROR: In CS", csId," the train run starts at s=",drivingCourse[end][:s]," and not s_entry=",CS[:s_entry])
|
||||
end
|
||||
if drivingCourse[end][:v] > CS[:v_entry]
|
||||
println("ERROR: In CS", csId," the train run ends with v=",drivingCourse[end][:v]," and not with v_entry=",CS[:v_entry])
|
||||
end
|
||||
|
||||
# determine the different flags for switching between the states for creatinge moving phases
|
||||
# determine the different flags for switching between the states for creating moving phases
|
||||
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
|
||||
calculateForces!(drivingCourse[end], CSs, CS[:id], "default", train, settings.massModel) # tractive effort and resisting forces (in N)
|
||||
calculateForces!(drivingCourse[end], CSs, csId, "default", train, settings.massModel) # tractive effort and resisting forces (in N)
|
||||
|
||||
previousSpeedLimitReached = false
|
||||
stateFlags = Dict(:endOfCSReached => drivingCourse[end][:s] > CS[:s_exit],
|
||||
:brakingStartReached => drivingCourse[end][:s] + s_braking == CS[:s_exit],
|
||||
:tractionDeficit => drivingCourse[end][:F_T] < drivingCourse[end][:F_R], # or add another flag for equal forces?
|
||||
:resistingForceNegative => drivingCourse[end][:F_R] < 0.0,
|
||||
:previousSpeedLimitReached => false, #speedLimitReached, # check already at this position?
|
||||
:previousSpeedLimitReached => false,
|
||||
:speedLimitReached => drivingCourse[end][:v] > CS[:v_limit],
|
||||
:error => false)
|
||||
|
||||
# determine the behavior sections for this characteristic section. It has to be at least one of those BS: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "halt")
|
||||
while !stateFlags[:endOfCSReached] # s < s_exit
|
||||
if !stateFlags[:brakingStartReached] # s+s_braking < s_exit
|
||||
if !stateFlags[:tractionDeficit]
|
||||
if drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && drivingCourse[end][:v] == 0.0
|
||||
(CS, drivingCourse, stateFlags) = addBreakFreeSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
|
||||
|
||||
elseif stateFlags[:previousSpeedLimitReached]
|
||||
(CS, drivingCourse, stateFlags) = addClearingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
|
||||
|
||||
elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached]
|
||||
(CS, drivingCourse, stateFlags) = addAcceleratingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
|
||||
|
||||
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached]
|
||||
# cruise only one step
|
||||
if settings.stepVariable == :distance
|
||||
s_cruising = settings.stepSize
|
||||
elseif settings.stepVariable == time
|
||||
s_cruising = Δs_with_Δt(settings.stepSize, drivingCourse[end][:a], drivingCourse[end][:v])
|
||||
elseif settings.stepVariable == velocity
|
||||
s_cruising = train.length/(10.0) # TODO which step size should be used?
|
||||
end
|
||||
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising")
|
||||
|
||||
elseif drivingCourse[end][:F_R] < 0 && stateFlags[:speedLimitReached]
|
||||
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
|
||||
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
|
||||
|
||||
if s_cruising > 0.0
|
||||
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "downhillBraking")
|
||||
else
|
||||
stateFlags[:brakingStartReached] = true
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] || stateFlags[:speedLimitReached]
|
||||
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
|
||||
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
|
||||
|
||||
if s_cruising > 0.0 # TODO: define a minimum cruising length?
|
||||
(CS, drivingCourse, stateFlags) = addCruisingSection!(CS, drivingCourse, stateFlags, s_cruising, settings, train, CSs, "cruising")
|
||||
else
|
||||
stateFlags[:brakingStartReached] = true
|
||||
end
|
||||
else
|
||||
error()
|
||||
end
|
||||
elseif stateFlags[:tractionDeficit]
|
||||
(CS, drivingCourse, stateFlags) = addDiminishingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
|
||||
|
||||
else
|
||||
error()
|
||||
# determine the behavior sections for this characteristic section. It has to be at least one of those BS: "breakFree", "clearing", "accelerating", "cruising", "diminishing", "coasting", "braking" or "halt")
|
||||
while !stateFlags[:endOfCSReached] # s < s_exit
|
||||
if stateFlags[:error]
|
||||
error("ERROR in calc in CS",csId,": BS=",drivingCourse[end][:behavior]," s=",drivingCourse[end][:s]," s_braking=",s_braking," v_limit=",CS[:v_limit]," v=",drivingCourse[end][:v]," v_exit=",CS[:v_exit]," with the flags: endOfCS: ",stateFlags[:endOfCSReached]," brakingStart: ",stateFlags[:brakingStartReached]," F_T<F_R: ",stateFlags[:tractionDeficit]," F_R<0: ",stateFlags[:resistingForceNegative]," v_previousLimit: ",stateFlags[:previousSpeedLimitReached]," v_limit: ",stateFlags[:speedLimitReached]," error: ",stateFlags[:error])
|
||||
end
|
||||
|
||||
if !stateFlags[:brakingStartReached] # s+s_braking < s_exit
|
||||
if !stateFlags[:tractionDeficit]
|
||||
if drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && drivingCourse[end][:v] == 0.0
|
||||
(drivingCourse, stateFlags) = addBreakFreeSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
|
||||
|
||||
elseif stateFlags[:previousSpeedLimitReached]
|
||||
(drivingCourse, stateFlags) = addClearingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
|
||||
|
||||
elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached]
|
||||
(drivingCourse, stateFlags) = addAcceleratingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
|
||||
|
||||
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] && !stateFlags[:speedLimitReached]
|
||||
# cruise only one step
|
||||
if settings.stepVariable == :distance
|
||||
s_cruising = settings.stepSize
|
||||
elseif settings.stepVariable == time
|
||||
s_cruising = Δs_with_Δt(settings.stepSize, drivingCourse[end][:a], drivingCourse[end][:v])
|
||||
elseif settings.stepVariable == velocity
|
||||
s_cruising = train.length/(10.0) # TODO which step size should be used?
|
||||
end
|
||||
(drivingCourse, stateFlags) = addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, "cruising", s_cruising)
|
||||
|
||||
elseif drivingCourse[end][:F_R] < 0 && stateFlags[:speedLimitReached]
|
||||
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
|
||||
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
|
||||
|
||||
if s_cruising > 0.0
|
||||
(drivingCourse, stateFlags) = addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, "downhillBraking", s_cruising)
|
||||
else
|
||||
stateFlags[:brakingStartReached] = true
|
||||
end
|
||||
|
||||
elseif drivingCourse[end][:F_T] == drivingCourse[end][:F_R] || stateFlags[:speedLimitReached]
|
||||
s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
|
||||
s_cruising = CS[:s_exit] - drivingCourse[end][:s] - s_braking
|
||||
|
||||
if s_cruising > 1/10^(settings.approxLevel) # TODO: define another minimum cruising length?
|
||||
(drivingCourse, stateFlags) = addCruisingSection!(drivingCourse, stateFlags, CSs, csId, settings, train, "cruising", s_cruising)
|
||||
else
|
||||
stateFlags[:brakingStartReached] = true
|
||||
end
|
||||
else
|
||||
error()
|
||||
end
|
||||
elseif stateFlags[:tractionDeficit]
|
||||
(drivingCourse, stateFlags) = addDiminishingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
|
||||
|
||||
else
|
||||
error()
|
||||
end
|
||||
else#if !stateFlags[:endOfCSReached] # s < s_exit
|
||||
(drivingCourse, stateFlags) = addBrakingSection!(drivingCourse, stateFlags, CSs, csId, settings, train)
|
||||
#else
|
||||
# error()
|
||||
end
|
||||
|
||||
if CS[:s_exit] - drivingCourse[end][:s] < 1/10^(settings.approxLevel)
|
||||
drivingCourse[end][:s] = CS[:s_exit] # round s up to CS[:s_exit]
|
||||
|
||||
# set state flag
|
||||
stateFlags[:endOfCSReached] = true
|
||||
end
|
||||
else#if !stateFlags[:endOfCSReached] # s < s_exit
|
||||
(CS, drivingCourse, stateFlags) = addBrakingSection!(CS, drivingCourse, stateFlags, settings, train, CSs)
|
||||
#else
|
||||
# error()
|
||||
end
|
||||
end
|
||||
#if s == s_exit
|
||||
# halt
|
||||
#end
|
||||
#if s == s_exit
|
||||
# halt
|
||||
#end
|
||||
|
||||
|
||||
# for testing:
|
||||
# for testing: # TODO
|
||||
if drivingCourse[end][:s] != CS[:s_exit]
|
||||
println("ERROR: In CS", csId," the train run ends at s=",drivingCourse[end][:s]," and not s_exit=",CS[:s_exit])
|
||||
end
|
||||
|
@ -115,11 +111,9 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Settings, t
|
|||
end
|
||||
end #for
|
||||
|
||||
(CSs[end], drivingCourse) = addHalt!(CSs[end], drivingCourse, settings, train, CSs)
|
||||
drivingCourse = addHalt!(drivingCourse, CSs, length(CSs), settings, train)
|
||||
|
||||
movingSection[:t] = drivingCourse[end][:t] # total running time (in s)
|
||||
|
||||
return (movingSection, drivingCourse)
|
||||
return drivingCourse
|
||||
end #function calculateMinimumRunningTime
|
||||
|
||||
|
||||
|
@ -180,7 +174,7 @@ function calculatePathResistance(CSs::Vector{Dict}, csId::Integer, s::Real, mass
|
|||
pathResistance = pathResistance + (min(s, CSs[csId][:s_exit]) - max(s_rear, CSs[csId][:s_entry])) / train.length * forceFromCoefficient(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
|
||||
# TODO: currently for values < s_trainrun_start the values of s_trainrun_start will be used
|
||||
return pathResistance + (CSs[1][:s_entry] - s_rear) / train.length * forceFromCoefficient(CSs[1][:r_path], train.m_train_full)
|
||||
end #if
|
||||
end #while
|
||||
|
@ -191,30 +185,30 @@ end #function calculatePathResistance
|
|||
|
||||
|
||||
"""
|
||||
calculate and return tractive and resisting forces for a data point
|
||||
calculate and return tractive and resisting forces for a support point
|
||||
"""
|
||||
function calculateForces!(dataPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Train, massModel)
|
||||
function calculateForces!(supportPoint::Dict, CSs::Vector{Dict}, csId::Integer, bsType::String, train::Train, massModel)
|
||||
# calculate resisting forces
|
||||
dataPoint[:R_traction] = tractionUnitResistance(dataPoint[:v], train)
|
||||
supportPoint[:R_traction] = tractionUnitResistance(supportPoint[:v], train)
|
||||
if train.transportType == :freight
|
||||
dataPoint[:R_wagons] = freightWagonsResistance(dataPoint[:v], train)
|
||||
supportPoint[:R_wagons] = freightWagonsResistance(supportPoint[:v], train)
|
||||
elseif train.transportType == :passenger
|
||||
dataPoint[:R_wagons] = passengerWagonsResistance(dataPoint[:v], train)
|
||||
supportPoint[:R_wagons] = passengerWagonsResistance(supportPoint[:v], train)
|
||||
end
|
||||
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]
|
||||
supportPoint[:R_train] = supportPoint[:R_traction] + supportPoint[:R_wagons]
|
||||
supportPoint[:R_path] = calculatePathResistance(CSs, csId, supportPoint[:s], massModel, train)
|
||||
supportPoint[:F_R] = supportPoint[:R_train] + supportPoint[:R_path]
|
||||
|
||||
# calculate tractive effort
|
||||
if bsType == "braking" || bsType == "coasting" || bsType == "halt"
|
||||
dataPoint[:F_T] = 0.0
|
||||
supportPoint[:F_T] = 0.0
|
||||
elseif bsType == "cruising"
|
||||
dataPoint[:F_T] = min(max(0.0, dataPoint[:F_R]), calculateTractiveEffort(dataPoint[:v], train.tractiveEffort))
|
||||
supportPoint[:F_T] = min(max(0.0, supportPoint[:F_R]), calculateTractiveEffort(supportPoint[:v], train.tractiveEffort))
|
||||
else # bsType == "accelerating" || bsType == "diminishing" || 'default'
|
||||
dataPoint[:F_T] = calculateTractiveEffort(dataPoint[:v], train.tractiveEffort)
|
||||
supportPoint[:F_T] = calculateTractiveEffort(supportPoint[:v], train.tractiveEffort)
|
||||
end
|
||||
|
||||
return dataPoint
|
||||
return supportPoint
|
||||
end #function calculateForces!
|
||||
|
||||
|
||||
|
@ -226,55 +220,54 @@ function moveAStep(previousPoint::Dict, stepVariable::Symbol, stepSize::Real, cs
|
|||
# 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
|
||||
# create the next support point
|
||||
newPoint = SupportPoint()
|
||||
|
||||
# calculate s, t, v, E
|
||||
if stepVariable == :distance # distance step method
|
||||
newPoint[:Δs] = stepSize # step size (in m)
|
||||
Δ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] = Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = 0.0 # step size (in m/s)
|
||||
Δt = Δt_with_constant_v(Δs, previousPoint[:v]) # step size (in s)
|
||||
Δ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 Δt_with_Δs and Δ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
|
||||
squareRootPartIsNegative = (previousPoint[:v]/previousPoint[:a])^2+2*Δs/previousPoint[:a] < 0.0 || previousPoint[:v]^2+2*Δ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] = Δt_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = Δv_with_Δs(newPoint[:Δs], previousPoint[:a], previousPoint[:v]) # step size (in m/s)
|
||||
Δt = Δt_with_Δs(Δs, previousPoint[:a], previousPoint[:v]) # step size (in s)
|
||||
Δv = Δv_with_Δs(Δ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] = Δs_with_Δt(newPoint[:Δt], previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
newPoint[:Δv] = Δv_with_Δt(newPoint[:Δt], previousPoint[:a]) # step size (in m/s)
|
||||
Δt = stepSize # step size (in s)
|
||||
Δs = Δs_with_Δt(Δt, previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
Δv = Δv_with_Δt(Δ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)
|
||||
Δs = stepSize # step size (in m)
|
||||
# TODO what is the best default step size for constant v? define Δs or Δt?
|
||||
newPoint[:Δt] = Δt_with_constant_v(newPoint[:Δs], previousPoint[:v]) # step size (in s)
|
||||
newPoint[:Δv] = 0.0 # step size (in m/s)
|
||||
Δt = Δt_with_constant_v(Δs, previousPoint[:v]) # step size (in s)
|
||||
Δv = 0.0 # step size (in m/s)
|
||||
else
|
||||
newPoint[:Δv] = stepSize * sign(previousPoint[:a]) # step size (in m/s)
|
||||
newPoint[:Δs] = Δs_with_Δv(newPoint[:Δv], previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
newPoint[:Δt] = Δt_with_Δv(newPoint[:Δv], previousPoint[:a]) # step size (in s)
|
||||
Δv = stepSize * sign(previousPoint[:a]) # step size (in m/s)
|
||||
Δs = Δs_with_Δv(Δv, previousPoint[:a], previousPoint[:v]) # step size (in m)
|
||||
Δt = Δt_with_Δv(Δ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[:s] = previousPoint[:s] + Δs # position (in m)
|
||||
newPoint[:t] = previousPoint[:t] + Δt # point in time (in s)
|
||||
newPoint[:v] = previousPoint[:v] + Δv # velocity (in m/s)
|
||||
|
||||
return newPoint
|
||||
end #function moveAStep
|
||||
|
@ -283,30 +276,30 @@ end #function moveAStep
|
|||
"""
|
||||
# if the rear of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
|
||||
"""
|
||||
function getCurrentSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::Real, trainLength::Real)
|
||||
function getLowestSpeedLimit(CSs::Vector{Dict}, csWithTrainHeadId::Integer, s::Real, trainLength::Real)
|
||||
v_limit = CSs[csWithTrainHeadId][:v_limit]
|
||||
s_exit = CSs[csWithTrainHeadId][:s_exit]
|
||||
if csWithTrainHeadId > 1 && s -trainLength < CSs[csWithTrainHeadId][:s_entry]
|
||||
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
|
||||
if CSs[formerCsId][:v_limit] < v_limit # TODO: is the position of the train's rear < s_trainrun_start, 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
|
||||
lowestSpeedLimit = Dict(:v => v_limit, :s_end => s_exit + trainLength)
|
||||
return lowestSpeedLimit
|
||||
end #function getLowestSpeedLimit
|
||||
|
||||
|
||||
"""
|
||||
TODO
|
||||
"""
|
||||
function getNextPointOfInterest(pointsOfInterest::Vector{Tuple}, s::Real)
|
||||
function getNextPointOfInterest(pointsOfInterest::Vector{NamedTuple}, s::Real)
|
||||
for POI in pointsOfInterest
|
||||
if POI[1] > s
|
||||
if POI[:s] > s
|
||||
return POI
|
||||
end
|
||||
end
|
||||
|
@ -314,12 +307,23 @@ function getNextPointOfInterest(pointsOfInterest::Vector{Tuple}, s::Real)
|
|||
end #function getNextPointOfInterest
|
||||
|
||||
|
||||
## create a moving section and its containing characteristic sections with secured braking, accelerating and cruising behavior
|
||||
## create vectors with the moving section's points of interest and with the characteristic sections with secured braking and accelerating behavior
|
||||
function determineCharacteristics(path::Path, train::Train, settings::Settings)
|
||||
movingSection = MovingSection(path, train.v_limit, train.length)
|
||||
movingSection = secureBrakingBehavior!(movingSection, train.a_braking, settings.approxLevel)
|
||||
movingSection = secureAcceleratingBehavior!(movingSection, settings, train)
|
||||
#movingSection = secureCruisingBehavior!(movingSection, settings, train)
|
||||
# determine the positions of the points of interest depending on the interesting part of the train (front/rear) and the train's length
|
||||
pointsOfInterest = NamedTuple[]
|
||||
if !isempty(path.poi)
|
||||
for POI in path.poi
|
||||
s_poi = POI[:station]
|
||||
if POI[:measure] == "rear"
|
||||
s_poi += train.length
|
||||
end
|
||||
push!(pointsOfInterest, (s = s_poi, label = POI[:label]) )
|
||||
end
|
||||
sort!(pointsOfInterest, by = x -> x[:s])
|
||||
end
|
||||
|
||||
return movingSection
|
||||
characteristicSections = CharacteristicSections(path, train.v_limit, train.length, pointsOfInterest)
|
||||
characteristicSections = secureBrakingBehavior!(characteristicSections, train.a_braking, settings.approxLevel)
|
||||
|
||||
return (characteristicSections, pointsOfInterest)
|
||||
end #function determineCharacteristics
|
||||
|
|
|
@ -51,7 +51,7 @@ function Settings(
|
|||
"outputDetail": {
|
||||
"description": "Selecting the detail of the result",
|
||||
"type": "string",
|
||||
"enum": [ "running_time", "points_of_interest", "driving_course" ]
|
||||
"enum": [ "running_time", "points_of_interest", "data_points", "driving_course" ]
|
||||
},
|
||||
"outputFormat": {
|
||||
"description": "Output format",
|
||||
|
@ -254,9 +254,9 @@ function Path(file, type = :YAML)
|
|||
if POI_PRESENT
|
||||
sort!(tmp_points, by = x -> x[1])
|
||||
for elem in tmp_points
|
||||
station = elem[1] # first point of the section (in m)
|
||||
label = elem[2] # paths speed limt (in m/s)
|
||||
measure = elem[3] # specific path resistance of the section (in ‰)
|
||||
station = elem[1] # station in m
|
||||
label = elem[2] # name
|
||||
measure = elem[3] # front or rear
|
||||
|
||||
point = Dict(:station => station,
|
||||
:label => label,
|
||||
|
@ -613,128 +613,68 @@ function Train(file, type = :YAML)
|
|||
|
||||
end #function Train() # outer constructor
|
||||
|
||||
## create a moving section containing characteristic sections
|
||||
function MovingSection(path::Path, v_trainLimit::Real, s_trainLength::Real)
|
||||
# this function creates and returns a moving section dependent on the paths attributes
|
||||
## 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
|
||||
|
||||
s_entry = path.sections[1][:s_start] # first position (in m)
|
||||
s_exit = path.sections[end][:s_end] # last position (in m)
|
||||
pathLength = s_exit - s_entry # total length (in m)
|
||||
|
||||
##TODO: use a tuple with naming
|
||||
pointsOfInterest = Tuple[]
|
||||
if !isempty(path.poi)
|
||||
for POI in path.poi
|
||||
s_poi = POI[:station]
|
||||
if POI[:measure] == "rear"
|
||||
s_poi += s_trainLength
|
||||
end
|
||||
push!(pointsOfInterest, (s_poi, POI[:label]) )
|
||||
end
|
||||
sort!(pointsOfInterest, by = x -> x[1])
|
||||
end
|
||||
|
||||
CSs=Vector{Dict}()
|
||||
s_csStart=s_entry
|
||||
csId=1
|
||||
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(csId, s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, pointsOfInterest))
|
||||
push!(CSs, CharacteristicSection(s_csStart, previousSection, min(previousSection[:v_limit], v_trainLimit), s_trainLength, MS_poi))
|
||||
s_csStart = currentSection[:s_start]
|
||||
csId = csId+1
|
||||
#csId = csId+1
|
||||
end #if
|
||||
end #for
|
||||
push!(CSs, CharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, pointsOfInterest))
|
||||
push!(CSs, CharacteristicSection(s_csStart, path.sections[end], min(path.sections[end][:v_limit], v_trainLimit), s_trainLength, MS_poi))
|
||||
|
||||
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)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => s_exit, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:characteristicSections => CSs, # list of containing characteristic sections
|
||||
:pointsOfInterest => pointsOfInterest) # list of containing points of interest
|
||||
return CSs
|
||||
end #function CharacteristicSections
|
||||
|
||||
return movingSection
|
||||
end #function MovingSection
|
||||
|
||||
## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
|
||||
function CharacteristicSection(id::Integer, s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, MS_poi::Vector{Tuple})
|
||||
## create a characteristic section for a path section.
|
||||
function CharacteristicSection(s_entry::Real, section::Dict, v_limit::Real, s_trainLength::Real, MS_poi::Vector{NamedTuple})
|
||||
# Create and return a characteristic section dependent on the paths attributes
|
||||
characteristicSection= Dict(:id => id, # identifier
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => section[:s_end], # last position (in m)
|
||||
:length => section[:s_end] -s_entry, # total length (in m)
|
||||
:r_path => section[:f_Rp], # path resistance (in ‰)
|
||||
:behaviorSections => Dict(), # list of containing behavior sections
|
||||
:t => 0.0, # total running time (in s)
|
||||
:v_limit => v_limit, # speed limit (in m/s)
|
||||
# initializing :v_entry, :v_peak and :v_exit with :v_limit
|
||||
:v_peak => v_limit, # maximum reachable speed (in m/s)
|
||||
:v_entry => v_limit, # maximum entry speed (in m/s)
|
||||
:v_exit => v_limit) # maximum exit speed (in m/s)
|
||||
characteristicSection::Dict{Symbol, Any} = Dict(:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => section[:s_end], # last position (in m)
|
||||
:r_path => section[:f_Rp], # path resistance (in ‰)
|
||||
:v_limit => v_limit, # speed limit (in m/s)
|
||||
:v_exit => v_limit) # maximum exit speed (in m/s) initialized with v_limit
|
||||
|
||||
# list of positions of every point of interest (POI) in this charateristic section for which data points should be calculated
|
||||
# get the list of positions of every point of interest (POI) in this charateristic section for which support points should be calculated from the list of the whole moving section's POI
|
||||
s_exit = characteristicSection[:s_exit]
|
||||
|
||||
##TODO: use a tuple with naming
|
||||
pointsOfInterest = Tuple[]
|
||||
CS_poi = NamedTuple[]
|
||||
if !isempty(MS_poi)
|
||||
for POI in MS_poi
|
||||
s_poi = POI[1]
|
||||
s_poi = POI[:s]
|
||||
if s_entry < s_poi && s_poi <= s_exit
|
||||
push!(pointsOfInterest, (POI))
|
||||
push!(CS_poi, POI)
|
||||
end
|
||||
end
|
||||
end
|
||||
if isempty(pointsOfInterest) || pointsOfInterest[end][1] < s_exit
|
||||
push!(pointsOfInterest, (s_exit,"")) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
|
||||
if isempty(CS_poi) || CS_poi[end][:s] < s_exit
|
||||
push!(CS_poi, (s = s_exit, label = "")) # s_exit has to be the last POI so that there will always be a POI to campare the current position with
|
||||
end
|
||||
merge!(characteristicSection, Dict(:pointsOfInterest => pointsOfInterest))
|
||||
merge!(characteristicSection, Dict(:pointsOfInterest => CS_poi))
|
||||
|
||||
return characteristicSection
|
||||
end #function CharacteristicSection
|
||||
|
||||
"""
|
||||
BehaviorSection() TODO!
|
||||
a SupportPoint is the smallest element of the driving course. One step of the step approach is between two support points
|
||||
"""
|
||||
function BehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
|
||||
BS= Dict(
|
||||
:type => type, # type of behavior section: "breakFree", "clearing", "accelerating", "cruising", "downhillBraking", "diminishing", "coasting", "braking" or "standstill"
|
||||
:length => 0.0, # total length (in m)
|
||||
:s_entry => s_entry, # first position (in m)
|
||||
:s_exit => 0.0, # last position (in m)
|
||||
:t => 0.0, # total running time (in s)
|
||||
:E => 0.0, # total energy consumption (in Ws)
|
||||
:v_entry => v_entry, # entry speed (in m/s)
|
||||
:v_exit => 0.0, # exit speed (in m/s)
|
||||
:dataPoints => [startingPoint] # list of identifiers of the containing data points starting with the initial point
|
||||
)
|
||||
return BS
|
||||
end #function BehaviorSection
|
||||
|
||||
"""
|
||||
a DataPoint is the smallest element of the driving course. One step of the step approach is between two data points
|
||||
"""
|
||||
function DataPoint()
|
||||
dataPoint = Dict(
|
||||
:i => 0, # identifier and counter variable of the driving course
|
||||
:behavior => "", # type of behavior section the data point is part of - see 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
|
||||
function SupportPoint()
|
||||
supportPoint = Dict(
|
||||
:behavior => "", # type of behavior section the support point is part of - see BehaviorSection()
|
||||
# a support point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
|
||||
:s => 0.0, # position (in m)
|
||||
:Δs => 0.0, # step size (in m)
|
||||
:t => 0.0, # point in time (in s)
|
||||
:Δt => 0.0, # step size (in s)
|
||||
:v => 0.0, # velocity (in m/s)
|
||||
:Δv => 0.0, # step size (in m/s)
|
||||
:a => 0.0, # acceleration (in m/s^2)
|
||||
:W => 0.0, # mechanical work (in Ws)
|
||||
:ΔW => 0.0, # mechanical work in this step (in Ws)
|
||||
:E => 0.0, # energy consumption (in Ws)
|
||||
:ΔE => 0.0, # energy consumption in this step (in Ws)
|
||||
:F_T => 0.0, # tractive effort (in N)
|
||||
:F_R => 0.0, # resisting force (in N)
|
||||
:R_path => 0.0, # path resistance (in N)
|
||||
|
@ -743,5 +683,5 @@ function DataPoint()
|
|||
:R_wagons => 0.0, # set of wagons resistance (in N)
|
||||
:label => "" # a label for important points
|
||||
)
|
||||
return dataPoint
|
||||
end #function DataPoint
|
||||
return supportPoint
|
||||
end #function SupportPoint
|
||||
|
|
|
@ -124,8 +124,8 @@ 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 data point
|
||||
# v_prev: velocitiy from previous data point
|
||||
# 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
|
||||
|
@ -134,8 +134,8 @@ 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 data point
|
||||
# v_prev: velocitiy from previous data point
|
||||
# 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)
|
||||
return Δs
|
||||
end #function Δs_with_Δv
|
||||
|
@ -144,8 +144,8 @@ 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 data point
|
||||
# v_prev: velocitiy from previous data point
|
||||
# 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)
|
||||
return Δt
|
||||
|
@ -155,7 +155,7 @@ 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 data point
|
||||
# a_prev: acceleration from previous support point
|
||||
Δt = Δv /a_prev # step size (in s)
|
||||
return Δt
|
||||
end #function Δt_with_Δv
|
||||
|
@ -173,8 +173,8 @@ 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 data point
|
||||
# v_prev: velocitiy from previous data point
|
||||
# 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
|
||||
|
@ -183,7 +183,7 @@ 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 data point
|
||||
# a_prev: acceleration from previous support point
|
||||
Δv = Δt * a_prev # step size (in m/s)
|
||||
return Δv
|
||||
end #function Δv_with_Δt
|
||||
|
|
|
@ -4,41 +4,59 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfInterest::Vector{Tuple})
|
||||
function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfInterest::Vector{NamedTuple})
|
||||
if settings.outputDetail == :running_time
|
||||
output::Vector{Dict} = [Dict(:t => drivingCourse[end][:t])]
|
||||
|
||||
elseif settings.outputDetail == :points_of_interest && !isempty(pointsOfInterest)
|
||||
# get only the driving course's data points with POI labels
|
||||
elseif settings.outputDetail == :points_of_interest
|
||||
# get only the driving course's support points with POI labels
|
||||
# if there is no point with POI label return the information of departure and arrival (first and last points)
|
||||
output = Dict[]
|
||||
dataPoint = 1
|
||||
for POI in 1:length(pointsOfInterest)
|
||||
while dataPoint <= length(drivingCourse)
|
||||
if pointsOfInterest[POI][1] == drivingCourse[dataPoint][:s]
|
||||
push!(output, drivingCourse[dataPoint])
|
||||
break
|
||||
if isempty(pointsOfInterest)
|
||||
push!(output, drivingCourse[1])
|
||||
push!(output, drivingCourse[end])
|
||||
else
|
||||
supportPoint = 1
|
||||
for POI in 1:length(pointsOfInterest)
|
||||
while supportPoint <= length(drivingCourse)
|
||||
if pointsOfInterest[POI][:s] == drivingCourse[supportPoint][:s]
|
||||
push!(output, drivingCourse[supportPoint])
|
||||
break
|
||||
end
|
||||
supportPoint += 1
|
||||
end
|
||||
dataPoint += 1
|
||||
end
|
||||
end
|
||||
|
||||
else #if settings.outputDetail == :driving_course || (settings.outputDetail == :points_of_interest && !isempty(path.poi))
|
||||
elseif settings.outputDetail == :data_points
|
||||
# get the driving course's support points where a new behavior section starts and the driving mode changes
|
||||
output = Dict[]
|
||||
# the first support point is the first data point
|
||||
push!(output, drivingCourse[1])
|
||||
|
||||
for supportPoint in 2:length(drivingCourse)
|
||||
if drivingCourse[supportPoint-1][:behavior] != drivingCourse[supportPoint][:behavior]
|
||||
push!(output, drivingCourse[supportPoint])
|
||||
end
|
||||
end
|
||||
|
||||
elseif settings.outputDetail == :driving_course
|
||||
output = drivingCourse
|
||||
end
|
||||
|
||||
if settings.outputFormat == :dataframe
|
||||
return createDataFrame(output, settings.outputDetail)
|
||||
return createDataFrame(output, settings.outputDetail, settings.approxLevel)
|
||||
elseif settings.outputFormat == :vector
|
||||
return output
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function createDataFrame(output_vector::Vector{Dict}, outputDetail)
|
||||
function createDataFrame(output_vector::Vector{Dict}, outputDetail, approxLevel::Int)
|
||||
if outputDetail == :running_time
|
||||
# create a DataFrame with running time information
|
||||
dataFrame = DataFrame(t=[output_vector[end][:t]])
|
||||
else # :points_of_interest or :driving_course
|
||||
dataFrame = DataFrame(t=[round(output_vector[end][:t], digits=approxLevel)])
|
||||
else # :points_of_interest, :data_points or :driving_course
|
||||
columnSymbols = [:label, :behavior, :s, :v, :t, :a, :F_T, :F_R, :R_path, :R_traction, :R_wagons]
|
||||
|
||||
allColumns = []
|
||||
|
@ -54,6 +72,7 @@ function createDataFrame(output_vector::Vector{Dict}, outputDetail)
|
|||
for point in output_vector
|
||||
push!(currentRealColumn, point[columnSymbols[column]])
|
||||
end
|
||||
currentRealColumn = round.(currentRealColumn, digits=approxLevel)
|
||||
push!(allColumns, currentRealColumn)
|
||||
end
|
||||
end # for
|
||||
|
@ -63,4 +82,4 @@ function createDataFrame(output_vector::Vector{Dict}, outputDetail)
|
|||
end
|
||||
|
||||
return dataFrame
|
||||
end #createDataFrameForDrivingCourse
|
||||
end #createDataFrame
|
||||
|
|
|
@ -10,7 +10,7 @@ struct Settings
|
|||
stepVariable::Symbol # variable of the linear multistep method: ":distance", ":time" or ":velocity".
|
||||
stepSize::Real # step size, unit depends on stepVariable - :distance in meter, time in seconds and velocity in meter/second.
|
||||
approxLevel::Int # value for approximation; used when rounding or iterating.
|
||||
outputDetail::Symbol # single Float() ":running_time", Vector() of ":points_of_interest",
|
||||
outputDetail::Symbol # single Float() ":running_time", Vector() of ":points_of_interest", Vector() of ":data_points"
|
||||
# or complete Vector() ":driving_course"
|
||||
outputFormat::Symbol # output as ":dataframe" or as ":vector".
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputDetail: "driving_course" # single value "running_time", list of "points_of_interest", complete "driving_course"
|
||||
outputDetail: "driving_course" # single value "running_time", list of "points_of_interest", list of "data_points", complete "driving_course"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputDetail: "points_of_interest" # single value "running_time", list of "points_of_interest", complete "driving_course"
|
||||
outputDetail: "points_of_interest" # single value "running_time", list of "points_of_interest", list of "data_points", complete "driving_course"
|
||||
|
|
Loading…
Reference in New Issue