2022-04-28 17:29:24 +02:00
#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __author__ = "Max Kannenberg"
# __copyright__ = "2020-2022"
# __license__ = "ISC"
2022-06-22 11:11:44 +02:00
## 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.
2022-04-28 17:29:24 +02:00
# Info: currently the values of the breakFree section will be calculated like in the accelerating section
2022-08-17 22:26:46 +02:00
function addBreakFreeSection! ( drivingCourse :: Vector { Dict } , stateFlags :: Dict , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train )
CS = CSs [ csId ]
2022-04-28 17:29:24 +02:00
# conditions for the break free section
endOfCSReached = drivingCourse [ end ] [ :s ] >= CS [ :s_exit ] || stateFlags [ :endOfCSReached ]
trainIsHalting = drivingCourse [ end ] [ :v ] == 0.0
if trainIsHalting && ! endOfCSReached
2022-07-13 00:15:57 +02:00
drivingMode = " breakFree "
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-08-18 13:44:57 +02:00
startingPoint = length ( drivingCourse )
2022-04-28 17:29:24 +02:00
# traction effort and resisting forces (in N)
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " accelerating " , train , settings . massModel ) # currently the tractive effort is calculated like in the accelerating section
2022-04-28 17:29:24 +02:00
# calculate the breakFree section with calculating the accelerating section and just using the first step and removing the rest
2022-08-17 22:26:46 +02:00
try ( drivingCourse , stateFlags ) = addAcceleratingSection! ( drivingCourse , stateFlags , CSs , csId , settings , train )
2022-04-28 17:29:24 +02:00
catch ( acceleratingError )
println ( " This error happened during the break free phase that is using the accelerating function: " )
rethrow ( acceleratingError )
end
2022-06-22 11:11:44 +02:00
# delete every supportPoint except the first two
2022-08-18 13:44:57 +02:00
while length ( drivingCourse ) > startingPoint + 1
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
end
# change the accelerating data to break free
2022-07-13 00:15:57 +02:00
drivingCourse [ end - 1 ] [ :behavior ] = drivingMode
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
end # else: return the characteristic section without a breakFree section
# determine state flags
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
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 [ :resistingForceNegative ] = drivingCourse [ end ] [ :F_R ] < 0
stateFlags [ :previousSpeedLimitReached ] = false
stateFlags [ :speedLimitReached ] = drivingCourse [ end ] [ :v ] >= CS [ :v_limit ]
2022-08-17 12:18:27 +02:00
stateFlags [ :error ] = drivingCourse [ end ] [ :v ] > CS [ :v_limit ] || drivingCourse [ end ] [ :s ] > CS [ :s_exit ]
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
return ( drivingCourse , stateFlags )
2022-04-28 17:29:24 +02:00
end #function addBreakFreeSection!
2022-06-22 11:11:44 +02:00
## This function calculates the support points of the clearing section.
2022-04-28 17:29:24 +02:00
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the clearing section.
2022-08-17 22:26:46 +02:00
function addClearingSection! ( drivingCourse :: Vector { Dict } , stateFlags :: Dict , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train )
CS = CSs [ csId ]
2022-04-28 17:29:24 +02:00
if stateFlags [ :previousSpeedLimitReached ]
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
2022-08-17 12:18:27 +02:00
s_clearing = min ( CS [ :s_exit ] - drivingCourse [ end ] [ :s ] - s_braking , lowestSpeedLimit [ :s_end ] - drivingCourse [ end ] [ :s ] )
2022-04-28 17:29:24 +02:00
if s_clearing > 0.0
2022-08-17 22:26:46 +02:00
( drivingCourse , stateFlags ) = addCruisingSection! ( drivingCourse , stateFlags , CSs , csId , settings , train , " clearing " , s_clearing )
calculateForces! ( drivingCourse [ end ] , CSs , csId , " accelerating " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
else
2022-08-17 22:26:46 +02:00
error ( " ERROR: clearing <=0.0 although it has to be >0.0 in CS " , csId )
2022-04-28 17:29:24 +02:00
end
#stateFlags[:previousSpeedLimitReached] = false
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-08-17 12:18:27 +02:00
stateFlags [ :previousSpeedLimitReached ] = lowestSpeedLimit [ :v ] != CS [ :v_limit ] && drivingCourse [ end ] [ :v ] >= lowestSpeedLimit [ :v ]
2022-04-28 17:29:24 +02:00
else
stateFlags [ :error ] = true
end
2022-08-17 22:26:46 +02:00
return ( drivingCourse , stateFlags )
2022-04-28 17:29:24 +02:00
end #function addClearingSection
2022-06-22 11:11:44 +02:00
## This function calculates the support points of the accelerating section.
2022-04-28 17:29:24 +02:00
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the accelerating section
2022-08-17 22:26:46 +02:00
function addAcceleratingSection! ( drivingCourse :: Vector { Dict } , stateFlags :: Dict , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train )
CS = CSs [ csId ]
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " accelerating " , train , settings . massModel )
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
# conditions for the accelerating section
endOfCSReached = drivingCourse [ end ] [ :s ] >= CS [ :s_exit ] || stateFlags [ :endOfCSReached ]
tractionSurplus = drivingCourse [ end ] [ :F_T ] > drivingCourse [ end ] [ :F_R ]
brakingStartReached = drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ] || stateFlags [ :brakingStartReached ]
previousSpeedLimitReached = stateFlags [ :previousSpeedLimitReached ]
2022-08-16 23:23:02 +02:00
speedLimitReached = drivingCourse [ end ] [ :v ] >= CS [ :v_limit ] || stateFlags [ :speedLimitReached ]
2022-04-28 17:29:24 +02:00
# use the conditions for the accelerating section
2022-08-16 23:23:02 +02:00
if ! speedLimitReached && ! endOfCSReached && tractionSurplus && ! brakingStartReached
2022-07-13 00:15:57 +02:00
drivingMode = " accelerating "
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-08-17 12:18:27 +02:00
previousSpeedLimitReached = lowestSpeedLimit [ :v ] != CS [ :v_limit ] && drivingCourse [ end ] [ :v ] >= lowestSpeedLimit [ :v ]
2022-08-16 23:23:02 +02:00
while ! speedLimitReached && ! endOfCSReached && tractionSurplus && ! brakingStartReached && ! previousSpeedLimitReached
2022-04-28 17:29:24 +02:00
currentStepSize = settings . stepSize # initialize the step size that can be reduced near intersections
nextPointOfInterest = getNextPointOfInterest ( CS [ :pointsOfInterest ] , drivingCourse [ end ] [ :s ] )
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
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
2022-08-16 23:23:02 +02:00
while ! speedLimitReached && ! brakingStartReached && ! pointOfInterestReached && tractionSurplus && ! previousSpeedLimitReached
2022-08-17 12:18:27 +02:00
if drivingCourse [ end ] [ :s ] >= lowestSpeedLimit [ :s_end ]
2022-08-16 23:23:02 +02:00
# could be asked after creating an support point. This way here prevents even a minimal exceedance of speed limit. On the other hand the train cruises possibly a little to long
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-04-28 17:29:24 +02:00
end
# acceleration (in m/s^2):
2022-06-05 15:41:28 +02:00
drivingCourse [ end ] [ :a ] = acceleration ( drivingCourse [ end ] [ :F_T ] , drivingCourse [ end ] [ :F_R ] , train . m_train_full , train . ξ_train )
2022-04-28 17:29:24 +02:00
2022-06-22 11:11:44 +02:00
# create the next support point
2022-08-17 22:26:46 +02:00
push! ( drivingCourse , moveAStep ( drivingCourse [ end ] , settings . stepVariable , currentStepSize , csId ) )
2022-07-13 00:15:57 +02:00
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , drivingMode , train , settings . massModel )
2022-04-28 17:29:24 +02:00
# conditions for the next while cycle
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
brakingStartReached = drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ]
2022-08-16 23:23:02 +02:00
speedLimitReached = drivingCourse [ end ] [ :v ] >= CS [ :v_limit ]
2022-08-17 12:18:27 +02:00
previousSpeedLimitReached = lowestSpeedLimit [ :v ] < CS [ :v_limit ] && ( drivingCourse [ end ] [ :v ] > lowestSpeedLimit [ :v ] || ( drivingCourse [ end ] [ :v ] == lowestSpeedLimit [ :v ] && drivingCourse [ end ] [ :s ] < lowestSpeedLimit [ :s_end ] ) )
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ] # POIs include s_exit as well
2022-04-28 17:29:24 +02:00
tractionSurplus = drivingCourse [ end ] [ :F_T ] > drivingCourse [ end ] [ :F_R ]
end #while
2022-08-17 22:26:46 +02:00
if csId == 0
2022-04-28 17:29:24 +02:00
testFlag = true
else
testFlag = false # for testing
end
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < settings . approxLevel + 1
if drivingCourse [ end ] [ :F_T ] <= drivingCourse [ end ] [ :F_R ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: F_T= " , drivingCourse [ end ] [ :F_T ] , " <= F_R= " , drivingCourse [ end ] [ :F_R ] ) # for testing
2022-04-28 17:29:24 +02:00
currentStepSize = settings . stepSize / 10.0 ^ cycle
elseif s_braking > 0.0 && drivingCourse [ end ] [ :s ] + s_braking > CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " ,+ " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " > s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
currentStepSize = settings . stepSize / 10.0 ^ cycle
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: s= " , drivingCourse [ end ] [ :s ] , " > nextPOI= " , nextPointOfInterest [ 1 ] ) # for testing
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :distance
2022-05-04 16:34:17 +02:00
currentStepSize = nextPointOfInterest [ 1 ] - drivingCourse [ end - 1 ] [ :s ]
2022-04-28 17:29:24 +02:00
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
2022-08-17 12:18:27 +02:00
elseif drivingCourse [ end ] [ :v ] > lowestSpeedLimit [ :v ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " > v_lowestLimit= " , lowestSpeedLimit [ :v ] ) # for testing
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :velocity
2022-08-17 12:18:27 +02:00
currentStepSize = lowestSpeedLimit [ :v ] - drivingCourse [ end - 1 ] [ :v ]
2022-04-28 17:29:24 +02:00
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
elseif drivingCourse [ end ] [ :s ] + s_braking == CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " ,+ " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " == s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
if s_braking == 0.0
endOfCSReached = true
end
break
2022-08-17 12:18:27 +02:00
elseif drivingCourse [ end ] [ :v ] == lowestSpeedLimit [ :v ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " == v_lowestLimit= " , lowestSpeedLimit [ :v ] ) # for testing
2022-04-28 17:29:24 +02:00
break
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: s= " , drivingCourse [ end ] [ :s ] , " == nextPOI= " , nextPointOfInterest [ 1 ] ) # for testing
2022-05-04 16:34:17 +02:00
if nextPointOfInterest [ 1 ] == CS [ :s_exit ]
2022-04-28 17:29:24 +02:00
endOfCSReached = true
end
break
else
2022-08-17 12:18:27 +02:00
println ( " v= " , drivingCourse [ end ] [ :v ] , " v_limit= " , CS [ :v_limit ] , " v_lowestLimit= " , lowestSpeedLimit [ :v ] )
2022-05-04 16:34:17 +02:00
println ( " s= " , drivingCourse [ end ] [ :s ] , " s_exit= " , CS [ :s_exit ] , " s+s_braking= " , drivingCourse [ end ] [ :s ] + s_braking , " nextPOI= " , nextPointOfInterest [ 1 ] )
2022-04-28 17:29:24 +02:00
println ( " F_T= " , drivingCourse [ end ] [ :F_T ] , " F_R= " , drivingCourse [ end ] [ :F_R ] )
2022-08-17 22:26:46 +02:00
error ( " ERROR at accelerating section: With the step variable " , settings . stepVariable , " the while loop will be left although v<v_limit and s<s_exit in CS " , csId , " with s= " , drivingCourse [ end ] [ :s ] , " m and v= " , drivingCourse [ end ] [ :v ] , " m/s " )
2022-04-28 17:29:24 +02:00
end
2022-06-22 11:11:44 +02:00
# delete last support point for recalculating the last step with reduced step size
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next for cycle
brakingStartReached = false
previousSpeedLimitReached = false
speedLimitReached = false
endOfCSReached = false
pointOfInterestReached = false
tractionSurplus = true
else # if the level of approximation is reached
2022-08-17 12:18:27 +02:00
if drivingCourse [ end ] [ :v ] > lowestSpeedLimit [ :v ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " > v_lowestLimit= " , lowestSpeedLimit [ :v ] , " with v_limit= " , CS [ :v_limit ] ) # for testing
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next section
brakingStartReached = false
elseif drivingCourse [ end ] [ :s ] + s_braking > CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " ,+ " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " > s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
if s_braking > 0.0
pop! ( drivingCourse )
else
drivingCourse [ end ] [ :s ] = CS [ :s_exit ] # round s down to CS[:s_exit]
end
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: s= " , drivingCourse [ end ] [ :s ] , " > nextPointOfInterest[1]= " , nextPointOfInterest [ 1 ] ) # for testing
2022-05-04 16:34:17 +02:00
drivingCourse [ end ] [ :s ] = nextPointOfInterest [ 1 ] # round s down to nextPointOfInterest
2022-04-28 17:29:24 +02:00
elseif drivingCourse [ end ] [ :F_T ] <= drivingCourse [ end ] [ :F_R ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: F_T= " , drivingCourse [ end ] [ :F_T ] , " <= F_R= " , drivingCourse [ end ] [ :F_R ] ) # for testing
2022-04-28 17:29:24 +02:00
else
if drivingCourse [ end ] [ :s ] + s_braking == CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " else case and there: s +s_braking= " , drivingCourse [ end ] [ :s ] , " ,+ " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " > s_exit= " , CS [ :s_exit ] ) # for testing
2022-08-17 12:18:27 +02:00
elseif drivingCourse [ end ] [ :v ] == lowestSpeedLimit [ :v ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " accelerating cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " == v_lowestLimit= " , lowestSpeedLimit [ :v ] ) # for testing
2022-04-28 17:29:24 +02:00
end
end
# TODO is it possible to put this into to the if-fork?
if drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
endOfCSReached = true
end
end
end #for
if drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
endOfCSReached = true
end
2022-05-31 13:06:40 +02:00
if drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :label ] = nextPointOfInterest [ 2 ]
end
2022-04-28 17:29:24 +02:00
end #while
end
# 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 [ :resistingForceNegative ] = drivingCourse [ end ] [ :F_R ] < 0
stateFlags [ :previousSpeedLimitReached ] = previousSpeedLimitReached
2022-08-16 23:23:02 +02:00
stateFlags [ :speedLimitReached ] = speedLimitReached
stateFlags [ :error ] = ! ( endOfCSReached || brakingStartReached || stateFlags [ :tractionDeficit ] || previousSpeedLimitReached || speedLimitReached )
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
return ( drivingCourse , stateFlags )
2022-04-28 17:29:24 +02:00
end #function addAcceleratingSection!
2022-06-22 11:11:44 +02:00
## 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.
2022-08-17 22:26:46 +02:00
function addCruisingSection! ( drivingCourse :: Vector { Dict } , stateFlags :: Dict , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train , cruisingType :: String , s_cruising :: Real )
CS = CSs [ csId ]
2022-04-28 17:29:24 +02:00
trainIsClearing = cruisingType == " clearing "
trainIsBrakingDownhill = cruisingType == " downhillBraking "
# traction effort and resisting forces (in N)
2022-07-13 00:15:57 +02:00
if ! trainIsBrakingDownhill # TODO: or just give drivingMode instead of "cruising"/"braking"?
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " cruising " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
else
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " braking " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
end
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
# conditions for cruising section
2022-06-05 15:41:28 +02:00
#s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
2022-04-28 17:29:24 +02:00
brakingStartReached = drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ] || stateFlags [ :brakingStartReached ]
2022-08-16 23:23:02 +02:00
speedIsValid = drivingCourse [ end ] [ :v ] > 0.0 && drivingCourse [ end ] [ :v ] <= CS [ :v_limit ]
2022-04-28 17:29:24 +02:00
tractionDeficit = drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
targetPositionReached = s_cruising == 0.0
resistingForceNegative = drivingCourse [ end ] [ :F_R ] < 0
if speedIsValid && ! brakingStartReached && ! tractionDeficit && ! targetPositionReached
2022-07-13 00:15:57 +02:00
drivingMode = cruisingType
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
# TODO: necessary?
2022-07-13 00:15:57 +02:00
targetPosition = min ( drivingCourse [ end ] [ :s ] + s_cruising , CS [ :s_exit ] )
# 07/12 old: s_cruising = min(s_cruising, CS[:s_exit]-drivingCourse[end][:s])
2022-04-28 17:29:24 +02:00
# traction effort and resisting forces (in N)
if ! trainIsBrakingDownhill
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " cruising " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
else
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " braking " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
end
2022-08-17 22:26:46 +02:00
if settings . massModel == :homogeneous_strip && csId > 1
2022-04-28 17:29:24 +02:00
# conditions for cruising section
2022-05-12 16:32:15 +02:00
trainInPreviousCS = drivingCourse [ end ] [ :s ] < CS [ :s_entry ] + train . length
2022-07-13 00:15:57 +02:00
targetPositionReached = drivingCourse [ end ] [ :s ] >= targetPosition
2022-04-28 17:29:24 +02:00
resistingForceNegative = drivingCourse [ end ] [ :F_R ] < 0.0
2022-08-16 23:23:02 +02:00
# TODO: change? to: correctCruisingType = (trainIsClearing || (trainIsBrakingDownhill == drivingCourse[end][:F_R] < 0)) # while clearing tractive or braking force can be used
2022-04-28 17:29:24 +02:00
# use the conditions for the cruising section
while trainInPreviousCS && ! targetPositionReached && ! tractionDeficit && ( trainIsClearing || ( trainIsBrakingDownhill == resistingForceNegative ) ) # while clearing tractive or braking force can be used
currentStepSize = settings . stepSize
2022-05-31 13:06:40 +02:00
nextPointOfInterest = getNextPointOfInterest ( CS [ :pointsOfInterest ] , drivingCourse [ end ] [ :s ] )
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
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
2022-08-16 23:23:02 +02:00
# 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
2022-04-28 17:29:24 +02:00
#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 ] ) )
else
drivingCourse [ end ] [ :F_T ] = 0.0
end
# acceleration (in m/s^2):
drivingCourse [ end ] [ :a ] = 0.0
2022-06-22 11:11:44 +02:00
# create the next support point
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :distance || settings . stepVariable == time
2022-08-17 22:26:46 +02:00
push! ( drivingCourse , moveAStep ( drivingCourse [ end ] , settings . stepVariable , currentStepSize , csId ) )
2022-04-28 17:29:24 +02:00
else
2022-08-17 22:26:46 +02:00
push! ( drivingCourse , moveAStep ( drivingCourse [ end ] , settings . stepVariable , train . length / ( 10.0 ^ cycle ) , csId ) ) # TODO which step size should be used?
2022-04-28 17:29:24 +02:00
end
2022-07-13 00:15:57 +02:00
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
# traction effort and resisting forces (in N)
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " default " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
# conditions for the next while cycle
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ] # POIs include s_exit as well
2022-04-28 17:29:24 +02:00
tractionDeficit = drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
2022-07-13 00:15:57 +02:00
targetPositionReached = drivingCourse [ end ] [ :s ] >= targetPosition
2022-05-12 16:32:15 +02:00
trainInPreviousCS = drivingCourse [ end ] [ :s ] < CS [ :s_entry ] + train . length
2022-04-28 17:29:24 +02:00
resistingForceNegative = drivingCourse [ end ] [ :F_R ] < 0.0
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < settings . approxLevel + 1
if drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
currentStepSize = settings . stepSize / 10.0 ^ cycle
elseif ! trainIsBrakingDownhill && resistingForceNegative
currentStepSize = settings . stepSize / 10.0 ^ cycle
elseif trainIsBrakingDownhill && ! resistingForceNegative
currentStepSize = settings . stepSize / 10.0 ^ cycle
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :distance
2022-05-04 16:34:17 +02:00
currentStepSize = nextPointOfInterest [ 1 ] - drivingCourse [ end - 1 ] [ :s ]
2022-04-28 17:29:24 +02:00
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
2022-08-17 22:26:46 +02:00
elseif drivingCourse [ end ] [ :s ] > targetPosition # TODO also the following? drivingCourse[end][:s] > CS[:s_entry] + train.length))
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :distance
2022-07-13 00:15:57 +02:00
currentStepSize = targetPosition - drivingCourse [ end - 1 ] [ :s ]
2022-04-28 17:29:24 +02:00
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
2022-07-13 00:15:57 +02:00
elseif drivingCourse [ end ] [ :s ] == targetPosition # || drivingCourse[end][:s]==CS[:s_exit]
2022-04-28 17:29:24 +02:00
break
2022-05-12 16:32:15 +02:00
elseif drivingCourse [ end ] [ :s ] >= CS [ :s_entry ] + train . length
2022-04-28 17:29:24 +02:00
break
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
break
elseif ! trainInPreviousCS
break
else
2022-08-17 22:26:46 +02:00
error ( " ERROR at cruising section: With the step variable " , settings . stepVariable , " the while loop will be left although the if cases don't apply in CS " , csId , " with s= " , drivingCourse [ end ] [ :s ] , " m and v= " , drivingCourse [ end ] [ :v ] , " m/s " )
2022-04-28 17:29:24 +02:00
end
2022-06-22 11:11:44 +02:00
# delete last support point for recalculating the last step with reduced step size
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next for cycle
pointOfInterestReached = false
tractionDeficit = false
targetPositionReached = false
trainInPreviousCS = true
resistingForceNegative = drivingCourse [ end ] [ :F_R ] < 0.0
else # if the level of approximation is reached
2022-05-04 16:34:17 +02:00
if drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :s ] = nextPointOfInterest [ 1 ] # round s down to nextPointOfInterest
2022-07-13 00:15:57 +02:00
elseif drivingCourse [ end ] [ :s ] > targetPosition
if drivingMode != " clearing "
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
end
2022-07-13 00:15:57 +02:00
elseif drivingCourse [ end ] [ :s ] == targetPosition
2022-04-28 17:29:24 +02:00
break
elseif drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
break
elseif ! trainIsBrakingDownhill && resistingForceNegative
break
elseif trainIsBrakingDownhill && ! resistingForceNegative
break
elseif ! trainInPreviousCS
break
else
end
end
end #for
2022-05-31 13:06:40 +02:00
if drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :label ] = nextPointOfInterest [ 2 ]
end
2022-04-28 17:29:24 +02:00
end #while
end #if
# conditions for the next while cycle
2022-07-13 00:15:57 +02:00
targetPositionReached = drivingCourse [ end ] [ :s ] >= targetPosition
2022-04-28 17:29:24 +02:00
tractionDeficit = drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
resistingForceNegative = drivingCourse [ end ] [ :F_R ] < 0.0
while ! targetPositionReached && ! tractionDeficit && ( trainIsClearing || ( trainIsBrakingDownhill == resistingForceNegative ) ) # while clearing tractive or braking force can be used
2022-05-31 13:06:40 +02:00
nextPointOfInterest = getNextPointOfInterest ( CS [ :pointsOfInterest ] , drivingCourse [ end ] [ :s ] )
2022-07-13 00:15:57 +02:00
if nextPointOfInterest [ 1 ] > targetPosition
nextPointOfInterest = [ targetPosition , " " ]
2022-05-31 13:06:40 +02:00
end
2022-04-28 17:29:24 +02:00
# tractive effort (in N):
if ! trainIsBrakingDownhill
drivingCourse [ end ] [ :F_T ] = min ( drivingCourse [ end ] [ :F_T ] , max ( 0.0 , drivingCourse [ end ] [ :F_R ] ) )
else
drivingCourse [ end ] [ :F_T ] = 0.0
end
drivingCourse [ end ] [ :a ] = 0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way
2022-07-13 00:15:57 +02:00
#s_cruisingRemaining=targetPosition-drivingCourse[end][:s]
s_cruisingRemaining = min ( nextPointOfInterest [ 1 ] - drivingCourse [ end ] [ :s ] , targetPosition - drivingCourse [ end ] [ :s ] )
2022-04-28 17:29:24 +02:00
2022-06-22 11:11:44 +02:00
# create the next support point
2022-08-17 22:26:46 +02:00
push! ( drivingCourse , moveAStep ( drivingCourse [ end ] , :distance , s_cruisingRemaining , csId ) )
2022-07-13 00:15:57 +02:00
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-05-31 13:06:40 +02:00
if drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :label ] = nextPointOfInterest [ 2 ]
end
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " default " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
# conditions for the next while cycle
2022-07-13 00:15:57 +02:00
targetPositionReached = drivingCourse [ end ] [ :s ] >= targetPosition
2022-04-28 17:29:24 +02:00
tractionDeficit = drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
resistingForceNegative = drivingCourse [ end ] [ :F_R ] < 0
end #while
end # else: return the characteristic section without a cruising section
# set state flags
stateFlags [ :endOfCSReached ] = drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
stateFlags [ :brakingStartReached ] = brakingStartReached || drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ]
stateFlags [ :tractionDeficit ] = tractionDeficit
stateFlags [ :resistingForceNegative ] = drivingCourse [ end ] [ :F_R ] < 0.0
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-08-17 12:18:27 +02:00
stateFlags [ :previousSpeedLimitReached ] = lowestSpeedLimit [ :v ] != CS [ :v_limit ] && drivingCourse [ end ] [ :v ] >= lowestSpeedLimit [ :v ]
2022-04-28 17:29:24 +02:00
stateFlags [ :error ] = ! ( targetPositionReached || tractionDeficit || ! ( cruisingType == " clearing " || ( ( cruisingType == " downhillBraking " ) == resistingForceNegative ) ) )
2022-08-17 22:26:46 +02:00
return ( drivingCourse , stateFlags )
2022-04-28 17:29:24 +02:00
end #function addCruisingSection!
2022-06-22 11:11:44 +02:00
## This function calculates the support points for diminishing run when using maximum tractive effort and still getting slower
2022-08-17 22:26:46 +02:00
function addDiminishingSection! ( drivingCourse :: Vector { Dict } , stateFlags :: Dict , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train )
CS = CSs [ csId ]
calculateForces! ( drivingCourse [ end ] , CSs , csId , " diminishing " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
# conditions for diminishing section
targetSpeedReached = drivingCourse [ end ] [ :v ] <= 0.0
endOfCSReached = drivingCourse [ end ] [ :s ] >= CS [ :s_exit ] || stateFlags [ :endOfCSReached ]
tractionDeficit = drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ] #|| stateFlags[:tractionDeficit]
2022-06-05 15:41:28 +02:00
#s_braking = brakingDistance(drivingCourse[end][:v], CS[:v_exit], train.a_braking, settings.approxLevel)
2022-04-28 17:29:24 +02:00
brakingStartReached = drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ] || stateFlags [ :brakingStartReached ]
# use the conditions for the diminishing section
if tractionDeficit && ! targetSpeedReached && ! endOfCSReached
2022-07-13 00:15:57 +02:00
drivingMode = " diminishing "
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
while tractionDeficit && ! targetSpeedReached && ! endOfCSReached && ! brakingStartReached
2022-08-17 12:18:27 +02:00
currentStepSize = settings . stepSize # initialize the step size that can be reduced near intersections
2022-05-31 13:06:40 +02:00
nextPointOfInterest = getNextPointOfInterest ( CS [ :pointsOfInterest ] , drivingCourse [ end ] [ :s ] )
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
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 tractionDeficit && ! brakingStartReached && ! pointOfInterestReached && ! targetSpeedReached
2022-05-04 16:34:17 +02:00
# 03/09 old: while drivingCourse[end][:F_T] < drivingCourse[end][:F_R] && !brakingStartReached && drivingCourse[end][:s] < nextPointOfInterest[1] && drivingCourse[end][:v]>0.0 # as long as s_i + s_braking < s_end
2022-04-28 17:29:24 +02:00
# acceleration (in m/s^2):
2022-06-05 15:41:28 +02:00
drivingCourse [ end ] [ :a ] = acceleration ( drivingCourse [ end ] [ :F_T ] , drivingCourse [ end ] [ :F_R ] , train . m_train_full , train . ξ_train )
2022-04-28 17:29:24 +02:00
2022-06-22 11:11:44 +02:00
# create the next support point
2022-08-17 22:26:46 +02:00
push! ( drivingCourse , moveAStep ( drivingCourse [ end ] , settings . stepVariable , currentStepSize , csId ) )
2022-07-13 00:15:57 +02:00
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , drivingMode , train , settings . massModel )
2022-04-28 17:29:24 +02:00
# conditions for the next while cycle
2022-08-17 12:58:53 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
brakingStartReached = drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ]
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
targetSpeedReached = drivingCourse [ end ] [ :v ] <= 0.0
tractionDeficit = drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
endOfCSReached = drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
end #while
2022-08-17 22:26:46 +02:00
if csId == 0
2022-04-28 17:29:24 +02:00
testFlag = true
else
testFlag = false # for testing
end
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < settings . approxLevel + 1
if drivingCourse [ end ] [ :v ] < 0.0
2022-05-30 17:47:36 +02:00
# if settings.stepVariable == :velocity
# currentStepSize = drivingCourse[end-1][:v]
# else
2022-04-28 17:29:24 +02:00
currentStepSize = settings . stepSize / 10.0 ^ cycle
2022-05-30 17:47:36 +02:00
# end
2022-04-28 17:29:24 +02:00
elseif drivingCourse [ end ] [ :F_T ] > drivingCourse [ end ] [ :F_R ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: F_T= " , drivingCourse [ end ] [ :F_T ] , " > F_R= " , drivingCourse [ end ] [ :F_R ] ) # for testing
2022-04-28 17:29:24 +02:00
currentStepSize = settings . stepSize / 10.0 ^ cycle
elseif s_braking > 0.0 && drivingCourse [ end ] [ :s ] + s_braking > CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " + " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " > s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
currentStepSize = settings . stepSize / 10.0 ^ cycle
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: s= " , drivingCourse [ end ] [ :s ] , " > nextPOI= " , nextPointOfInterest [ 1 ] ) # for testing
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :distance
2022-05-04 16:34:17 +02:00
currentStepSize = nextPointOfInterest [ 1 ] - drivingCourse [ end - 1 ] [ :s ]
2022-04-28 17:29:24 +02:00
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
elseif drivingCourse [ end ] [ :s ] + s_braking == CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " + " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " == s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
break
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: s= " , drivingCourse [ end ] [ :s ] , " == nextPOI= " , nextPointOfInterest [ 1 ] ) # for testing
2022-04-28 17:29:24 +02:00
break
elseif drivingCourse [ end ] [ :F_T ] == drivingCourse [ end ] [ :F_R ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: F_T= " , drivingCourse [ end ] [ :F_T ] , " == F_R= " , drivingCourse [ end ] [ :F_R ] ) # for testing
2022-04-28 17:29:24 +02:00
break
elseif drivingCourse [ end ] [ :v ] == 0.0
2022-08-17 22:26:46 +02:00
error ( " ERROR: The train stops during diminishing run in CS " , csId , " at position s= " , drivingCourse [ end ] [ :s ] , " m because the maximum tractive effort is lower than the resistant forces. " ,
2022-04-28 17:29:24 +02:00
" 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_wagons= " , drivingCourse [ end - 1 ] [ :R_wagons ] , " N R_path= " , drivingCourse [ end - 1 ] [ :R_path ] , " N. " )
else
2022-08-17 22:26:46 +02:00
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 " , csId , " with s= " , drivingCourse [ end ] [ :s ] , " m and v= " , drivingCourse [ end ] [ :v ] , " m/s " )
2022-04-28 17:29:24 +02:00
end
2022-06-22 11:11:44 +02:00
# delete last support point for recalculating the last step with reduced step size
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next for cycle
brakingStartReached = false
pointOfInterestReached = false
targetSpeedReached = false
tractionDeficit = true
endOfCSReached = false
else # if the level of approximation is reached
if drivingCourse [ end ] [ :v ] <= 0.0
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " <= 0.0 " ) # for testing
error ( " ERROR: The train stops during diminishing run in CS " , csId , " because the maximum tractive effort is lower than the resistant forces. " ,
2022-04-28 17:29:24 +02:00
" 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_wagons= " , drivingCourse [ end - 1 ] [ :R_wagons ] , " N R_path= " , drivingCourse [ end - 1 ] [ :R_path ] , " N. " )
elseif s_braking > 0.0 && drivingCourse [ end ] [ :s ] + s_braking > CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " + " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " > s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
pointOfInterestReached = false
targetSpeedReached = false
tractionDeficit = true
endOfCSReached = false
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: s= " , drivingCourse [ end ] [ :s ] , " > nextPointOfInterest[1]= " , nextPointOfInterest [ 1 ] ) # for testing
2022-05-04 16:34:17 +02:00
drivingCourse [ end ] [ :s ] = nextPointOfInterest [ 1 ] # round s down to nextPointOfInterest
2022-04-28 17:29:24 +02:00
elseif drivingCourse [ end ] [ :F_T ] >= drivingCourse [ end ] [ :F_R ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: F_T= " , drivingCourse [ end ] [ :F_T ] , " >= F_R= " , drivingCourse [ end ] [ :F_R ] ) # for testing
2022-04-28 17:29:24 +02:00
break
else
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " diminishing cycle " , cycle , " case: else with v= " , drivingCourse [ end ] [ :v ] , " > 0.0 and F_T= " , drivingCourse [ end ] [ :F_T ] , " <= F_R= " , drivingCourse [ end ] [ :F_R ] ) # for testing
2022-04-28 17:29:24 +02:00
#println(" and s +s_braking=", drivingCourse[end][:s],"+",s_braking," = ",drivingCourse[end][:s] +s_braking," <= s_exit=",CS[:s_exit]) # for testing
2022-05-04 16:34:17 +02:00
#println(" and s=", drivingCourse[end][:s]," <= nextPointOfInterest[1]=",nextPointOfInterest[1]) # for testing
2022-04-28 17:29:24 +02:00
# if drivingCourse[end][:s] + s_braking == CS[:s_exit]
# brakingStartReached = true
# end
end #if
# # TODO is it possible to put this into to the if-fork?
# if drivingCourse[end][:s] == CS[:s_exit]
# endOfCSReached = true
# end
end #if
end #for
2022-05-31 13:06:40 +02:00
if drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :label ] = nextPointOfInterest [ 2 ]
end
2022-04-28 17:29:24 +02:00
end #while
end
# set state flags
stateFlags [ :endOfCSReached ] = endOfCSReached
stateFlags [ :brakingStartReached ] = brakingStartReached
stateFlags [ :tractionDeficit ] = tractionDeficit
stateFlags [ :resistingForceNegative ] = drivingCourse [ end ] [ :F_R ] < 0
2022-08-16 23:23:02 +02:00
stateFlags [ :speedLimitReached ] = drivingCourse [ end ] [ :v ] >= CS [ :v_limit ]
2022-04-28 17:29:24 +02:00
stateFlags [ :error ] = ! ( endOfCSReached || brakingStartReached || ! tractionDeficit )
2022-08-17 22:26:46 +02:00
return ( drivingCourse , stateFlags )
2022-04-28 17:29:24 +02:00
end #function addDiminishingSection!
2022-06-22 11:11:44 +02:00
## This function calculates the support points of the coasting section.
2022-04-28 17:29:24 +02:00
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
2022-08-17 22:26:46 +02:00
function addCoastingSection! ( drivingCourse :: Vector { Dict } , stateFlags :: Dict , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train )
CS = CSs [ csId ]
2022-04-28 17:29:24 +02:00
# conditions for coasting section
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-08-17 12:18:27 +02:00
previousSpeedLimitReached = lowestSpeedLimit [ :v ] != CS [ :v_limit ] && drivingCourse [ end ] [ :v ] > lowestSpeedLimit [ :v ]
2022-08-16 23:23:02 +02:00
speedLimitReached = drivingCourse [ end ] [ :v ] > CS [ :v_limit ]
targetSpeedReached = drivingCourse [ end ] [ :v ] <= CS [ :v_exit ] || previousSpeedLimitReached || speedLimitReached
2022-04-28 17:29:24 +02:00
endOfCSReached = drivingCourse [ end ] [ :s ] >= CS [ :s_exit ] || stateFlags [ :endOfCSReached ]
2022-06-05 15:41:28 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
brakingStartReached = drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ] || stateFlags [ :brakingStartReached ]
# use the conditions for the coasting section
if ! targetSpeedReached && ! endOfCSReached
2022-07-13 00:15:57 +02:00
drivingMode = " coasting "
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
while ! targetSpeedReached && ! endOfCSReached && ! brakingStartReached
2022-08-17 12:18:27 +02:00
currentStepSize = settings . stepSize # initialize the step size that can be reduced near intersections
2022-05-04 16:34:17 +02:00
nextPointOfInterest [ 1 ] = getNextPointOfInterest ( CS [ :pointsOfInterest ] , drivingCourse [ end ] [ :s ] )
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
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 ! targetSpeedReached && ! brakingStartReached && ! pointOfInterestReached
2022-08-17 12:18:27 +02:00
if drivingCourse [ end ] [ :s ] >= lowestSpeedLimit [ :s_end ]
2022-08-16 23:23:02 +02:00
# could be asked after creating an support point. This way here prevents even a minimal exceedance of speed limit.
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-08-16 23:23:02 +02:00
end
2022-04-28 17:29:24 +02:00
# traction effort and resisting forces (in N):
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , drivingMode , train , settings . massModel )
2022-04-28 17:29:24 +02:00
# acceleration (in m/s^2):
2022-06-05 15:41:28 +02:00
drivingCourse [ end ] [ :a ] = acceleration ( drivingCourse [ end ] [ :F_T ] , drivingCourse [ end ] [ :F_R ] , train . m_train_full , train . ξ_train )
2022-04-28 17:29:24 +02:00
2022-06-22 11:11:44 +02:00
# create the next support point
2022-08-17 22:26:46 +02:00
push! ( drivingCourse , moveAStep ( drivingCourse [ end ] , settings . stepVariable , currentStepSize , csId ) )
2022-07-13 00:15:57 +02:00
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
# conditions for the next while cycle
2022-06-05 15:41:28 +02:00
s_braking = brakingDistance ( drivingCourse [ end ] [ :v ] , CS [ :v_exit ] , train . a_braking , settings . approxLevel )
2022-04-28 17:29:24 +02:00
brakingStartReached = drivingCourse [ end ] [ :s ] + s_braking >= CS [ :s_exit ]
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-08-17 12:18:27 +02:00
targetSpeedReached = drivingCourse [ end ] [ :v ] <= CS [ :v_exit ] || drivingCourse [ end ] [ :v ] > CS [ :v_limit ] || lowestSpeedLimit [ :v ] < CS [ :v_limit ] && ( drivingCourse [ end ] [ :v ] > lowestSpeedLimit [ :v ] || ( drivingCourse [ end ] [ :v ] == lowestSpeedLimit [ :v ] && drivingCourse [ end ] [ :s ] < lowestSpeedLimit [ :s_end ] ) )
2022-04-28 17:29:24 +02:00
end # while
testFlag = false
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < settings . approxLevel + 1
if drivingCourse [ end ] [ :s ] + s_braking > CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " coasting cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " + " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " > s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
currentStepSize = settings . stepSize / 10.0 ^ cycle
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " coasting cycle " , cycle , " case: s= " , drivingCourse [ end ] [ :s ] , " > nextPointOfInterest[1]= " , nextPointOfInterest [ 1 ] ) # for testing
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :distance
2022-05-04 16:34:17 +02:00
currentStepSize = nextPointOfInterest [ 1 ] - drivingCourse [ end - 1 ] [ :s ]
2022-04-28 17:29:24 +02:00
else
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
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " coasting cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " < v_exit= " , CS [ :v_exit ] ) # for testing
2022-05-30 17:47:36 +02:00
if settings . stepVariable == :velocity
2022-08-16 23:23:02 +02:00
currentStepSize = drivingCourse [ end - 1 ] [ :v ] - CS [ :v_exit ]
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
2022-08-17 12:18:27 +02:00
elseif drivingCourse [ end ] [ :v ] > lowestSpeedLimit [ :v ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " coasting cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " > v_lowestLimit= " , lowestSpeedLimit [ :v ] ) # for testing
2022-08-16 23:23:02 +02:00
if settings . stepVariable == :velocity
2022-08-17 12:18:27 +02:00
currentStepSize = lowestSpeedLimit [ :v ] - drivingCourse [ end - 1 ] [ :v ]
2022-04-28 17:29:24 +02:00
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
2022-08-16 23:23:02 +02:00
2022-04-28 17:29:24 +02:00
elseif drivingCourse [ end ] [ :s ] + s_braking == CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " coasting cycle " , cycle , " case: s +s_braking= " , drivingCourse [ end ] [ :s ] , " + " , s_braking , " = " , drivingCourse [ end ] [ :s ] + s_braking , " == s_exit= " , CS [ :s_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
break
elseif drivingCourse [ end ] [ :v ] == CS [ :v_exit ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " coasting cycle " , cycle , " case: v= " , drivingCourse [ end ] [ :v ] , " == v_exit= " , CS [ :v_exit ] ) # for testing
2022-04-28 17:29:24 +02:00
break
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
2022-08-17 22:26:46 +02:00
testFlag && println ( " in CS " , csId , " coasting cycle " , cycle , " case: s = " , drivingCourse [ end ] [ :s ] , " > nextPointOfInterest[1]= " , nextPointOfInterest [ 1 ] ) # for testing
2022-04-28 17:29:24 +02:00
break
else
# TODO: not needed. just for testing
2022-08-17 22:26:46 +02:00
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 " )
2022-04-28 17:29:24 +02:00
end
2022-06-22 11:11:44 +02:00
# delete last support point for recalculating the last step with reduced step size
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next for cycle
brakingStartReached = false
pointOfInterestReached = false
targetSpeedReached = false
else # if the level of approximation is reached
if drivingCourse [ end ] [ :v ] <= 0.0
2022-08-17 22:26:46 +02:00
println ( " INFO: The train stops during the coasting section in CS " , csId , " " ,
2022-04-28 17:29:24 +02:00
" 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_wagons= " , drivingCourse [ end - 1 ] [ :R_wagons ] , " N R_path= " , drivingCourse [ end - 1 ] [ :R_path ] , " N and s_braking= " , s_braking , " m. " )
elseif drivingCourse [ end ] [ :s ] + s_braking > CS [ :s_exit ]
2022-06-22 11:11:44 +02:00
# delete last support point because it went to far
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next for cycle
# brakingStartReached = true
pointOfInterestReached = false
targetSpeedReached = false
2022-08-17 12:18:27 +02:00
elseif drivingCourse [ end ] [ :v ] > lowestSpeedLimit [ :v ] # if the train gets to fast it has to brake to hold the velocity limit
2022-06-22 11:11:44 +02:00
# delete last support point because it went to far
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next for cycle
brakingStartReached = false
pointOfInterestReached = false
2022-08-17 12:18:27 +02:00
if lowestSpeedLimit [ :v ] != CS [ :v_limit ]
2022-08-16 23:23:02 +02:00
previousSpeedLimitReached = true
else
speedLimitReached = true
end
2022-04-28 17:29:24 +02:00
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :s ] = nextPointOfInterest [ 1 ] # round s down to nextPointOfInterest
2022-04-28 17:29:24 +02:00
else
# do nothing for example for drivingCourse[end][:s] + s_braking == CS[:s_exit]
end
end
end #for
2022-05-31 13:06:40 +02:00
if drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :label ] = nextPointOfInterest [ 2 ]
end
2022-04-28 17:29:24 +02:00
end #while
end
# set state flags
stateFlags [ :endOfCSReached ] = endOfCSReached
stateFlags [ :brakingStartReached ] = brakingStartReached
stateFlags [ :tractionDeficit ] = drivingCourse [ end ] [ :F_T ] < drivingCourse [ end ] [ :F_R ]
stateFlags [ :resistingForceNegative ] = drivingCourse [ end ] [ :F_R ] < 0
2022-08-16 23:23:02 +02:00
stateFlags [ :previousSpeedLimitReached ] = previousSpeedLimitReached
stateFlags [ :speedLimitReached ] = speedLimitReached
stateFlags [ :error ] = ! ( endOfCSReached || brakingStartReached || stateFlags [ :tractionDeficit ] || previousSpeedLimitReached || speedLimitReached )
2022-04-28 17:29:24 +02:00
2022-08-17 22:26:46 +02:00
return ( drivingCourse , stateFlags )
2022-04-28 17:29:24 +02:00
end #function addCoastingSection!
2022-06-22 11:11:44 +02:00
## 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.
2022-08-17 22:26:46 +02:00
function addBrakingSection! ( drivingCourse :: Vector { Dict } , stateFlags :: Dict , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train )
CS = CSs [ csId ]
2022-04-28 17:29:24 +02:00
# conditions for braking section
targetSpeedReached = drivingCourse [ end ] [ :v ] <= CS [ :v_exit ]
endOfCSReached = drivingCourse [ end ] [ :s ] >= CS [ :s_exit ] || stateFlags [ :endOfCSReached ]
# use the conditions for the braking section
if ! targetSpeedReached && ! endOfCSReached
2022-07-13 00:15:57 +02:00
drivingMode = " braking "
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
while ! targetSpeedReached && ! endOfCSReached
currentStepSize = settings . stepSize # initialize the step size that can be reduced near intersections
nextPointOfInterest = getNextPointOfInterest ( CS [ :pointsOfInterest ] , drivingCourse [ end ] [ :s ] )
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
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 ! targetSpeedReached && ! endOfCSReached && ! pointOfInterestReached
2022-05-04 16:34:17 +02:00
# 03/09 old: while drivingCourse[end][:v] > CS[:v_exit] && !targetSpeedReached && drivingCourse[end][:s] < CS[:s_exit] && drivingCourse[end][:s] < nextPointOfInterest[1]
2022-04-28 17:29:24 +02:00
# traction effort and resisting forces (in N):
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , drivingMode , train , settings . massModel )
2022-04-28 17:29:24 +02:00
# acceleration (in m/s^2):
2022-05-12 16:32:15 +02:00
drivingCourse [ end ] [ :a ] = train . a_braking
2022-06-05 15:41:28 +02:00
# TODO or: drivingCourse[end][:a] = brakingAcceleration(drivingCourse[end][:v], CS[:v_exit], CS[:s_exit]-drivingCourse[end][:s])
2022-04-28 17:29:24 +02:00
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
2022-06-22 11:11:44 +02:00
# create empty support point and set it for the values of s_exit and v_exit
push! ( drivingCourse , SupportPoint ( ) )
2022-07-13 00:15:57 +02:00
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
recalculateLastBrakingPoint! ( drivingCourse , CS [ :s_exit ] , CS [ :v_exit ] )
else
2022-06-22 11:11:44 +02:00
# create the next support point
2022-08-17 22:26:46 +02:00
push! ( drivingCourse , moveAStep ( drivingCourse [ end ] , settings . stepVariable , currentStepSize , csId ) )
2022-07-13 00:15:57 +02:00
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
end
# conditions for the next while cycle
2022-05-04 16:34:17 +02:00
pointOfInterestReached = drivingCourse [ end ] [ :s ] >= nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
endOfCSReached = drivingCourse [ end ] [ :s ] >= CS [ :s_exit ]
targetSpeedReached = drivingCourse [ end ] [ :v ] <= CS [ :v_exit ]
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 ]
2022-05-04 16:34:17 +02:00
if settings . stepVariable == :velocity
2022-04-28 17:29:24 +02:00
currentStepSize = drivingCourse [ end - 1 ] [ :v ] - CS [ :v_exit ]
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
2022-08-17 22:26:46 +02:00
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
if settings . stepVariable == :distance
2022-05-04 16:34:17 +02:00
currentStepSize = nextPointOfInterest [ 1 ] - drivingCourse [ end - 1 ] [ :s ]
2022-04-28 17:29:24 +02:00
else
currentStepSize = settings . stepSize / 10.0 ^ cycle
end
2022-08-17 22:26:46 +02:00
2022-04-28 17:29:24 +02:00
elseif drivingCourse [ end ] [ :v ] == CS [ :v_exit ] && drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
break
2022-08-17 22:26:46 +02:00
2022-04-28 17:29:24 +02:00
elseif drivingCourse [ end ] [ :v ] == CS [ :v_exit ]
recalculateLastBrakingPoint! ( drivingCourse , CS [ :s_exit ] , CS [ :v_exit ] )
endOfCSReached = true
break
2022-08-17 22:26:46 +02:00
2022-04-28 17:29:24 +02:00
elseif drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
recalculateLastBrakingPoint! ( drivingCourse , CS [ :s_exit ] , CS [ :v_exit ] )
targetSpeedReached = true
break
2022-08-17 22:26:46 +02:00
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
2022-04-28 17:29:24 +02:00
break
end
2022-06-22 11:11:44 +02:00
# delete last support point for recalculating the last step with reduced step size
2022-04-28 17:29:24 +02:00
pop! ( drivingCourse )
# conditions for the next for cycle
pointOfInterestReached = false
endOfCSReached = false
targetSpeedReached = false
else # if the level of approximation is reached
if drivingCourse [ end ] [ :v ] < 0.0
# TODO: drivingCourse[end][:v] < CS[:v_exit] should be enough
2022-08-17 22:26:46 +02:00
# 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
2022-04-28 17:29:24 +02:00
recalculateLastBrakingPoint! ( drivingCourse , CS [ :s_exit ] , 0.0 )
endOfCSReached = true
break
elseif drivingCourse [ end ] [ :s ] > CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
# println("during braking section in CS",csId,": rounding s down from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
2022-04-28 17:29:24 +02:00
# recalculateLastBrakingPoint!(drivingCourse, CS[:s_exit], CS[:v_exit])
drivingCourse [ end ] [ :s ] = CS [ :s_exit ]
break
2022-05-04 16:34:17 +02:00
elseif drivingCourse [ end ] [ :s ] > nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :s ] = nextPointOfInterest [ 1 ] # round s down to nextPointOfInterest
2022-04-28 17:29:24 +02:00
break
elseif drivingCourse [ end ] [ :v ] == CS [ :v_exit ] && drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
break
elseif drivingCourse [ end ] [ :v ] < CS [ :v_exit ]
# reset last point with setting v=v_exit
2022-08-17 22:26:46 +02:00
# println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
2022-04-28 17:29:24 +02:00
recalculateLastBrakingPoint! ( drivingCourse , CS [ :s_exit ] , CS [ :v_exit ] )
endOfCSReached = true
break
elseif drivingCourse [ end ] [ :v ] == CS [ :v_exit ]
2022-08-17 22:26:46 +02:00
# println("during braking section in CS",csId,": rounding s up from ", drivingCourse[end][:s] ," to ", CS[:s_exit]) # for testing
2022-04-28 17:29:24 +02:00
recalculateLastBrakingPoint! ( drivingCourse , CS [ :s_exit ] , CS [ :v_exit ] )
endOfCSReached = true
break
elseif drivingCourse [ end ] [ :s ] == CS [ :s_exit ]
2022-08-17 22:26:46 +02:00
# println("during braking section in CS",csId,": rounding v down from ", drivingCourse[end][:v] ," to ", CS[:v_exit]) # for testing
2022-04-28 17:29:24 +02:00
recalculateLastBrakingPoint! ( drivingCourse , CS [ :s_exit ] , CS [ :v_exit ] )
targetSpeedReached = true
break
else
2022-05-04 16:34:17 +02:00
# do nothing for example for drivingCourse[end][:s]==nextPointOfInterest[1]
2022-04-28 17:29:24 +02:00
end
end
end #for
2022-05-31 13:06:40 +02:00
if drivingCourse [ end ] [ :s ] == nextPointOfInterest [ 1 ]
drivingCourse [ end ] [ :label ] = nextPointOfInterest [ 2 ]
end
2022-04-28 17:29:24 +02:00
end #while
end # else: return the characteristic section without a braking section
# set state flags
2022-08-17 22:26:46 +02:00
lowestSpeedLimit = getLowestSpeedLimit ( CSs , csId , drivingCourse [ end ] [ :s ] , train . length )
2022-08-17 12:18:27 +02:00
stateFlags [ :previousSpeedLimitReached ] = lowestSpeedLimit [ :v ] != CS [ :v_limit ] && drivingCourse [ end ] [ :v ] >= lowestSpeedLimit [ :v ]
2022-04-28 17:29:24 +02:00
stateFlags [ :speedLimitReached ] = drivingCourse [ end ] [ :v ] >= CS [ :v_exit ]
stateFlags [ :endOfCSReached ] = endOfCSReached
stateFlags [ :error ] = ! ( endOfCSReached )
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , " default " , train , settings . massModel )
2022-04-28 17:29:24 +02:00
stateFlags [ :resistingForceNegative ] = drivingCourse [ end ] [ :F_R ] < 0
2022-08-17 22:26:46 +02:00
return ( drivingCourse , stateFlags )
2022-04-28 17:29:24 +02:00
end #function addBrakingSection!
2022-06-22 11:11:44 +02:00
## 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.
2022-08-17 22:26:46 +02:00
function addHalt! ( drivingCourse :: Vector { Dict } , CSs :: Vector { Dict } , csId :: Integer , settings :: Settings , train :: Train )
# CS = CSs[csId] # is not needed here
2022-04-28 17:29:24 +02:00
if drivingCourse [ end ] [ :v ] == 0.0
2022-07-13 00:15:57 +02:00
drivingMode = " halt "
drivingCourse [ end ] [ :behavior ] = drivingMode
2022-04-28 17:29:24 +02:00
# traction effort and resisting forces (in N)
2022-08-17 22:26:46 +02:00
calculateForces! ( drivingCourse [ end ] , CSs , csId , drivingMode , train , settings . massModel )
2022-05-24 16:15:08 +02:00
end # else: return the characteristic section without a halt section section
2022-08-17 22:26:46 +02:00
return drivingCourse
2022-05-24 16:15:08 +02:00
end #function addHalt!
2022-04-28 17:29:24 +02:00
function recalculateLastBrakingPoint! ( drivingCourse , s_target , v_target )
currentPoint = drivingCourse [ end ]
previousPoint = drivingCourse [ end - 1 ]
2022-08-17 12:18:27 +02:00
# set s and v
currentPoint [ :s ] = s_target # position (in m)
currentPoint [ :v ] = v_target # velocity (in m/s)
2022-04-28 17:29:24 +02:00
# calculate other values
2022-06-30 18:42:35 +02:00
previousPoint [ :a ] = brakingAcceleration ( previousPoint [ :v ] , currentPoint [ :v ] , currentPoint [ :s ] - previousPoint [ :s ] )
2022-04-28 17:29:24 +02:00
# # TODO: just for testing
2022-05-12 16:32:15 +02:00
# if previousPoint[:a]<train.a_braking || previousPoint[:a]>=0.0
2022-08-17 22:26:46 +02:00
# println("Warning: a_braking gets to high in CS ",csId, " with a=",previousPoint[:a] ," > ",train.a_braking)
2022-04-28 17:29:24 +02:00
# end
2022-06-30 18:42:35 +02:00
currentPoint [ :t ] = previousPoint [ :t ] + Δt_with_Δv ( currentPoint [ :v ] - previousPoint [ :v ] , previousPoint [ :a ] ) # point in time (in s)
2022-04-28 17:29:24 +02:00
end #function recalculateLastBrakingPoint
2022-06-03 17:24:16 +02:00
## define the intersection velocities between the characterisitc sections to secure braking behavior
2022-07-12 16:59:45 +02:00
function secureBrakingBehavior! ( CSs :: Vector { Dict } , a_braking :: Real , approxLevel :: Integer )
2022-08-17 15:22:10 +02:00
# limit the entry and exit velocities of the characteristic sections to secure that the train stops at the moving sections end
2022-06-03 17:24:16 +02:00
csId = length ( CSs )
2022-08-17 15:22:10 +02:00
v_entryFollowing = 0.0 # the exit velocity of the last characteristic section is 0.0 m/s
2022-06-03 17:24:16 +02:00
while csId >= 1
2022-08-17 15:22:10 +02:00
# calculate the maximum possible entry velocity to define the previous section's maximum allowed exit velocity
2022-06-03 17:24:16 +02:00
CS = CSs [ csId ]
2022-08-17 15:22:10 +02:00
CS [ :v_exit ] = min ( CS [ :v_limit ] , v_entryFollowing )
2022-06-03 17:24:16 +02:00
2022-08-17 15:22:10 +02:00
v_entry = brakingStartVelocity ( CS [ :v_exit ] , a_braking , CS [ :s_exit ] - CS [ :s_entry ] , approxLevel )
2022-06-03 17:24:16 +02:00
2022-08-17 15:22:10 +02:00
v_entryFollowing = min ( CS [ :v_limit ] , v_entry )
2022-06-03 17:24:16 +02:00
csId = csId - 1
end #while
2022-07-12 16:59:45 +02:00
return CSs
2022-06-03 17:24:16 +02:00
end #function secureBrakingBehavior!