Add function addStandstill! for creating the BehaviorSection standstill

pull/1/head v0.6.2
Max Kannenberg 2021-12-17 21:14:58 +01:00
parent 4b6700612d
commit fd0476ad1f
6 changed files with 142 additions and 112 deletions

View File

@ -1,7 +1,7 @@
name = "TrainRun"
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
authors = ["Max Kannenberg"]
version = "0.6.1"
version = "0.6.2"
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"

View File

@ -31,6 +31,16 @@ train_run = calculateDrivingDynamics(train, running_path, settings)
# History
## Version 0.6.2
Add function addStandstill! for creating the BehaviorSection standstill
- Add function addStandstill! to MovinPhases.jl
- Use function addStandstill! in OperationModes.jl
- Rename the BehaviorSection standStill to standstill
- Fix: Rename addStartingPhase! to addBreakFreePhase!
## Version 0.6.1
Add an attribute to DataPoint to record the corresponding driving behavior

View File

@ -1,7 +1,7 @@
module MovingPhases
using ..types
export addAccelerationPhase!, addAccelerationPhaseUntilBraking!, addCruisingPhase!, addCoastingPhaseUntilBraking!, addBrakingPhase!, addBrakingPhaseStepwise!, calculateForces!
export addAccelerationPhase!, addAccelerationPhaseUntilBraking!, addCruisingPhase!, addCoastingPhaseUntilBraking!, addBrakingPhase!, addBrakingPhaseStepwise!, addStandstill!, calculateForces!
# addBrakingPhaseStepwise! is not used in the current version of the tool
v00=100/3.6 # velocity constant (in m/s)
@ -260,7 +260,7 @@ end # function considerFormerSpeedLimits!
## This function calculates the data points of the breakFree phase.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed.
# Info: currently the values of the breakFree phase will be calculated like in the acceleration phase
function addStartingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
function addBreakFreePhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
if drivingCourse[end].v==0.0 && drivingCourse[end].s<CS.s_exit
breakFreeSection=BehaviorSection()
breakFreeSection.type="breakFree" # type of behavior section
@ -326,14 +326,14 @@ function addStartingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
merge!(CS.behaviorSections, Dict(:breakFree => breakFreeSection))
end # else: return the characteristic section without a breakFree section
return (CS, drivingCourse)
end #function addStartingPhase!
end #function addBreakFreePhase!
## This function calculates the data points of the acceleration phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section
function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
if drivingCourse[end].v==0.0
(CS, drivingCourse)=addStartingPhase!(CS, drivingCourse, settings, train, CSs)
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
@ -469,7 +469,7 @@ end #function addAccelerationPhase!
## This function calculates the data points of the acceleration phase.
function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
if drivingCourse[end].v==0.0
(CS, drivingCourse)=addStartingPhase!(CS, drivingCourse, settings, train, CSs)
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")
@ -736,6 +736,103 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
end #function addCruisingPhase!
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower
function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing")
if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<CS.s_exit
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s<CS.s_exit
diminishingSection=BehaviorSection()
diminishingSection.type="diminishing" # type of behavior section
diminishingSection.s_entry=drivingCourse[end].s # first position (in m)
diminishingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(diminishingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = diminishingSection.type
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
# 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# 11/21: old, only for cruising:
#if drivingCourse[end].a==0.0
# error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path)
#end
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id))
drivingCourse[end].behavior = diminishingSection.type
push!(diminishingSection.dataPoints, drivingCourse[end].i)
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end].v<=0.0
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s + s_braking > CS.s_exit
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s + s_braking==CS.s_exit
# 11/21 old without s_braking: elseif drivingCourse[end].s==CS.s_exit
break
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle
else
error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# push!(diminishingSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].s + s_braking > CS.s_exit
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
break
else
end
end
end #for
if length(diminishingSection.dataPoints) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start
# calculate the accumulated diminishing section information
diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
diminishingSection.s_exit=drivingCourse[end].s # last position (in m)
diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m)
diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+diminishingSection.t # total running time (in s)
CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection))
end
end
return (CS, drivingCourse)
end #function addDiminishingPhase!
## This function calculates the data points of the coasting phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
@ -855,7 +952,6 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
end #function addCoastingPhaseUntilBraking!
## This function calculates the data points of the braking phase. (standard braking phase with only two data points)
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat)
@ -914,7 +1010,6 @@ function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataP
end #function addBrakingPhase!
## This function calculates the data points of the braking phase. # 09/07 new braking phase with more than two data points
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat)
@ -995,100 +1090,31 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect
end #function addBrakingPhaseStepwise!
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower
function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing")
## This function calculates the data point of the standstill.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed.
function addStandstill!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<CS.s_exit
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s<CS.s_exit
diminishingSection=BehaviorSection()
diminishingSection.type="diminishing" # type of behavior section
diminishingSection.s_entry=drivingCourse[end].s # first position (in m)
diminishingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(diminishingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = diminishingSection.type
if drivingCourse[end].v == 0.0
standstillSection=BehaviorSection()
standstillSection.type="standstill" # type of behavior section
standstillSection.s_entry=drivingCourse[end].s # first position (in m)
standstillSection.s_exit=drivingCourse[end].s # last position (in m)
standstillSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
standstillSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
standstillSection.length=0.0 # total length (in m)
standstillSection.t=0.0 # total running time (in s)
standstillSection.E=0.0 # total energy consumption (in Ws)
push!(standstillSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the first of its data points
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
# 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
drivingCourse[end].behavior = standstillSection.type
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# 11/21: old, only for cruising:
#if drivingCourse[end].a==0.0
# error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path)
#end
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id))
drivingCourse[end].behavior = diminishingSection.type
push!(diminishingSection.dataPoints, drivingCourse[end].i)
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end].v<=0.0
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s + s_braking > CS.s_exit
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s + s_braking==CS.s_exit
# 11/21 old without s_braking: elseif drivingCourse[end].s==CS.s_exit
break
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle
else
error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# push!(diminishingSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].s + s_braking > CS.s_exit
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
break
else
end
end
end #for
if length(diminishingSection.dataPoints) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start
# calculate the accumulated diminishing section information
diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
diminishingSection.s_exit=drivingCourse[end].s # last position (in m)
diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m)
diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+diminishingSection.t # total running time (in s)
CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection))
end
end
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, standstillSection.type)
merge!(CS.behaviorSections, Dict(:standstill => standstillSection))
end # else: return the characteristic section without a standstillSection section
return (CS, drivingCourse)
end #function addDiminishingPhase!
end #function addStandstill!
end #module MovingPhases

View File

@ -91,11 +91,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end =#
end #for
# calculate the last data points resisting forces
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "braking")
if drivingCourse[end].v == 0.0
drivingCourse[end].behavior = "standStill"
end
(CSs[end], drivingCourse)=addStandstill!(CSs[end], drivingCourse, settings, train, CSs)
movingSection[:t] = drivingCourse[end].t # total running time (in s)
movingSection[:E] = drivingCourse[end].E # total energy consumption (in Ws)
@ -184,7 +180,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end].Δt
lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standStill,
lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standstill,
get(CSsOrig[csIdMax].behaviorSections, :braking,
get(CSsOrig[csIdMax].behaviorSections, :cruisingAfterCoasting,
get(CSsOrig[csIdMax].behaviorSections, :coasting,
@ -237,7 +233,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
# update all the data point references in the behaviour sections of the following characteristic sections and the other modified characteristic sections
if difference!= 0
# update the data point references in the behaviour sections of the following characteristic sections
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for csId in csIdMax+1:length(CSsOrig)
for bs in 1: length(allBs)
if haskey(CSsOrig[csId].behaviorSections, allBs[bs])
@ -277,9 +273,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end #if doCombinationOfMethods
end # while
if drivingCourseOriginal[end].v == 0.0
drivingCourseOriginal[end].behavior = "standStill"
end
(CSsOrig[end], drivingCourseOriginal) = addStandstill!(CSsOrig[end], drivingCourseOriginal, settings, train, CSsOrig)
println("t_recoveryAvailable=",movingSectionOriginal[:t_recoveryAvailable])
return (movingSectionOriginal, drivingCourseOriginal)
@ -344,7 +338,7 @@ function findBestModification(energySavingModifications::Vector{EnergySavingModi
end #function findBestModification
function updateEnergySavingModifications(energySavingModifications::Vector{EnergySavingModification}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
difference = endOfModificationId-lastIdOfSelectedCsOriginal
for modNr in csIdMax+1:length(energySavingModifications)
if energySavingModifications[modNr].ratio>0

View File

@ -258,7 +258,7 @@ function printSectionInformation(movingSection::Dict)
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t])
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for csId in 1:length(CSs)
println("CS ",csId," mit length=", CSs[csId].length," mit t=", CSs[csId].t)
for bs in 1: length(allBs)

View File

@ -6,7 +6,7 @@ export DataPoint, BehaviorSection, CharacteristicSection, EnergySavingModificati
## a data point is the smallest element of the driving course. One step of the step approach is between two data points
mutable struct DataPoint
i::Integer # identifier and counter variable of the dricing course
behavior::String # type of BehaviorSection the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standStill")
behavior::String # type of BehaviorSection the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standstill")
# a data point which is the last point of one BehaviorSection and the first point of the next BehaviorSection will be attached to the latter
s::AbstractFloat # position (in m)
Δs::AbstractFloat # step size (in m)
@ -35,7 +35,7 @@ DataPoint(original::DataPoint)=DataPoint(original.i, original.behavior, original
## different sections the whole path can be devided in the following
## smallest section of the path is the behavior section. It relates to the containing data points via their identifier.
mutable struct BehaviorSection
type::String # type of behavior section: "breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standStill"
type::String # type of behavior section: "breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standstill"
length::AbstractFloat # total length (in m)
s_entry::AbstractFloat # first position (in m)
s_exit::AbstractFloat # last position (in m)
@ -72,7 +72,7 @@ end # mutable struct CharacteristicSection
CharacteristicSection()=CharacteristicSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Dict{Symbol, BehaviorSection}())
function CharacteristicSection(original::CharacteristicSection)
copy=CharacteristicSection(original.id, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_limit, original.v_target, original.v_entry, original.v_exit, original.f_Rp, Dict{Symbol, BehaviorSection}())
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for bs in 1: length(allBs)
if haskey(original.behaviorSections, allBs[bs])
merge!(copy.behaviorSections, Dict(allBs[bs] => BehaviorSection(original.behaviorSections[allBs[bs]])))