Skip to content

Commit

Permalink
core: stdcm: handle engineering allowances at low speed
Browse files Browse the repository at this point in the history
Signed-off-by: Eloi Charpentier <[email protected]>
  • Loading branch information
eckter committed Feb 13, 2025
1 parent 9badbe7 commit 397e4db
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,39 @@ void testIncreasingContinuousOverlay() {
assertEquals(2, envelope.size());
assertTrue(envelope.continuous);
}

/** Testing around edge cases with overlays that stop within the first step*/
@Test
void interruptedAtStart() {
// +==============+
// 0 8
var baseEnvelope = Envelope.make(EnvelopeTestUtils.generateTimes(new double[] {0, 8}, new double[] {1, 1}));

// Constraint has been broken immediately after start, part with no step
{
var partBuilder = new EnvelopePartBuilder();
partBuilder.setAttr(EnvelopeProfile.ACCELERATING);
var overlayBuilder =
new ConstrainedEnvelopePartBuilder(partBuilder, new EnvelopeConstraint(baseEnvelope, CEILING));
assertTrue(overlayBuilder.initEnvelopePart(0, 1, 1));
assertTrue(overlayBuilder.addStep(0, 1));
assertFalse(overlayBuilder.addStep(1, 2));
var res = partBuilder.build();
assertEquals(0, res.stepCount());
}

// Constraint has been broken within the first step, part with one (partial) step
{
var partBuilder = new EnvelopePartBuilder();
partBuilder.setAttr(EnvelopeProfile.ACCELERATING);
var overlayBuilder =
new ConstrainedEnvelopePartBuilder(partBuilder, new EnvelopeConstraint(baseEnvelope, CEILING));
assertTrue(overlayBuilder.initEnvelopePart(0, 0.5, 1));
assertTrue(overlayBuilder.addStep(0, 0.5));
assertFalse(overlayBuilder.addStep(1, 5));
var res = partBuilder.build();
assertEquals(1, res.stepCount());
assertTrue(res.getPointPos(1) < 1);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ class EngineeringAllowanceManager(private val graph: STDCMGraph) {
-1.0
)
val builder = OverlayEnvelopeBuilder.backward(maxEffort)
if (speedupPartBuilder.stepCount() > 1) {
val speedupPart = speedupPartBuilder.build()
val speedupPart = speedupPartBuilder.build()
if (speedupPart.stepCount() > 0) {
builder.addPart(speedupPart)
val lastAccelerationPosition = speedupPart.beginPos
if (lastAccelerationPosition > 0.0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,4 +494,79 @@ class EngineeringAllowanceTests {
occupancyTest(res, occupancyGraph)
Assertions.assertEquals(3600.0, res.departureTime, 2 * timeStep)
}

/**
* Reproduces a bug: the engineering allowance area has a very low speed limit, to the point
* where we reach speed=0 within one step.
*/
@Test
fun testSlowdownWithLowLimitSpeed() {
/*
a --> b --> c --> d
space
^
d |######### end
|######### /
c |#########/
| __/
b | __/
| /##################
a |/_##################_> time
*/
val infra = DummyInfra()
val firstBlock = infra.addBlock("a", "b", 1000.meters, 0.5)
val secondBlock = infra.addBlock("b", "c", 10000.meters, 0.5)
val thirdBlock = infra.addBlock("c", "d", 100.meters, 0.5)
val firstBlockEnvelope =
simulateBlock(
infra,
infraExplorerFromBlock(infra, infra, firstBlock),
0.0,
Offset(0.meters),
TestTrains.REALISTIC_FAST_TRAIN,
Comfort.STANDARD,
2.0,
null,
null,
null
)!!
val secondBlockEnvelope =
simulateBlock(
infra,
infraExplorerFromBlock(infra, infra, secondBlock),
firstBlockEnvelope.endSpeed,
Offset(0.meters),
TestTrains.REALISTIC_FAST_TRAIN,
Comfort.STANDARD,
2.0,
null,
null,
null
)!!
val timeThirdBlockFree = firstBlockEnvelope.totalTime + secondBlockEnvelope.totalTime
val occupancyGraph =
ImmutableMultimap.of(
firstBlock,
OccupancySegment(
firstBlockEnvelope.totalTime + 10,
Double.POSITIVE_INFINITY,
0.meters,
1000.meters
),
thirdBlock,
OccupancySegment(0.0, timeThirdBlockFree + 30, 0.meters, 100.meters)
)
val timeStep = 2.0
val res =
STDCMPathfindingBuilder()
.setInfra(infra.fullInfra())
.setStartLocations(setOf(EdgeLocation(firstBlock, Offset(0.meters))))
.setEndLocations(setOf(EdgeLocation(thirdBlock, Offset(1.meters))))
.setUnavailableTimes(occupancyGraph)
.setTimeStep(timeStep)
.run()!!
occupancyTest(res, occupancyGraph, 2 * timeStep)
}
}

0 comments on commit 397e4db

Please sign in to comment.