From 200e560da6de12209263ac2521c27d27ccb70b5c Mon Sep 17 00:00:00 2001 From: Eloi Charpentier Date: Thu, 19 Oct 2023 14:07:25 +0200 Subject: [PATCH 1/4] tests: reproduce allowance search space discontinuity in regression test --- .../search_space_discontinuity_2.json | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/tests/regression_tests_data/search_space_discontinuity_2.json diff --git a/tests/tests/regression_tests_data/search_space_discontinuity_2.json b/tests/tests/regression_tests_data/search_space_discontinuity_2.json new file mode 100644 index 00000000000..819a65fc3cf --- /dev/null +++ b/tests/tests/regression_tests_data/search_space_discontinuity_2.json @@ -0,0 +1,105 @@ +{ + "error_type": "SCHEDULE", + "code": 500, + "error": "{\"type\":\"\",\"context\":{\"trace\":[{\"index\":1}]},\"message\":\"Failed to converge when computing allowances because of a discontinuity in the search space\"}", + "infra_name": "small_infra", + "path_payload": { + "infra": 2, + "name": "foo", + "steps": [ + { + "duration": 0, + "waypoints": [ + { + "track_section": "TD0", + "offset": 19619.352684339327 + } + ] + }, + { + "duration": 0, + "waypoints": [ + { + "track_section": "TD0", + "offset": 10328.66897321028 + } + ] + }, + { + "duration": 0, + "waypoints": [ + { + "track_section": "TC1", + "offset": 942.2893869744591 + } + ] + }, + { + "duration": 1, + "waypoints": [ + { + "track_section": "TA6", + "offset": 7228.631133548441 + } + ] + } + ] + }, + "schedule_payload": { + "timetable": 477, + "path": 6191, + "schedules": [ + { + "train_name": "foo", + "labels": [], + "departure_time": 49769, + "allowances": [ + { + "allowance_type": "standard", + "default_value": { + "value_type": "percentage", + "percentage": 13.909647137885917 + }, + "ranges": [ + { + "begin_position": 0, + "end_position": 16060.88634445774, + "value": { + "value_type": "time", + "seconds": 36.46246472629868 + } + } + ], + "capacity_speed_limit": 6.2294818613912595, + "distribution": "MARECO" + }, + { + "allowance_type": "engineering", + "begin_position": 12524.41472909032, + "end_position": 21770.18710487399, + "value": { + "value_type": "time", + "seconds": 28.070954818841923 + }, + "capacity_speed_limit": 1.7874897194090011, + "distribution": "MARECO" + }, + { + "allowance_type": "engineering", + "begin_position": 12952.70669585063, + "end_position": 19291.81886826793, + "value": { + "value_type": "time", + "seconds": 11.462972603693293 + }, + "capacity_speed_limit": 9.850164632606985, + "distribution": "LINEAR" + } + ], + "initial_speed": 0, + "rolling_stock_id": 449, + "speed_limit_category": "foo" + } + ] + } +} From 09aad64bf1ae245be6218a35d191fd3ddea02fe8 Mon Sep 17 00:00:00 2001 From: Erashin Date: Mon, 13 Nov 2023 17:39:46 +0100 Subject: [PATCH 2/4] core: make coastFromBeginning start at coastFromEnd start speed --- .../part/constraints/EnvelopeConstraint.java | 7 ++++--- .../allowances/mareco_impl/CoastingGenerator.java | 14 ++++++++------ .../envelope_sim/TrainPhysicsIntegratorTest.java | 4 ++-- .../java/fr/sncf/osrd/envelope/EnvelopeShape.java | 3 ++- .../sncf/osrd/sim_infra_adapter/RawInfraAdapter.kt | 1 - 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/constraints/EnvelopeConstraint.java b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/constraints/EnvelopeConstraint.java index 86f1d956340..4441fd6fb82 100644 --- a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/constraints/EnvelopeConstraint.java +++ b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/constraints/EnvelopeConstraint.java @@ -3,6 +3,7 @@ import static fr.sncf.osrd.envelope.EnvelopeCursor.NextStepResult.NEXT_PART; import static fr.sncf.osrd.envelope.EnvelopeCursor.NextStepResult.NEXT_REACHED_END; import static fr.sncf.osrd.envelope.part.constraints.EnvelopePartConstraintType.*; +import static fr.sncf.osrd.envelope_sim.TrainPhysicsIntegrator.areSpeedsEqual; import fr.sncf.osrd.envelope.Envelope; import fr.sncf.osrd.envelope.EnvelopeCursor; @@ -32,9 +33,9 @@ public boolean initCheck(double position, double speed, double direction) { var envelopeSpeed = part.interpolateSpeed(stepIndex, position); cursor = new EnvelopeCursor(envelope, direction < 0, partIndex, stepIndex, position); return switch (type) { - case CEILING -> envelopeSpeed >= speed; - case FLOOR -> envelopeSpeed <= speed; - case EQUAL -> envelopeSpeed == speed; + case CEILING -> envelopeSpeed > speed || areSpeedsEqual(envelopeSpeed, speed); + case FLOOR -> envelopeSpeed < speed || areSpeedsEqual(envelopeSpeed, speed); + case EQUAL -> areSpeedsEqual(envelopeSpeed, speed); }; } diff --git a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java index 332d8ed8e5d..f103642be66 100644 --- a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java +++ b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java @@ -2,6 +2,7 @@ import static fr.sncf.osrd.envelope.part.constraints.EnvelopePartConstraintType.CEILING; import static fr.sncf.osrd.envelope.part.constraints.EnvelopePartConstraintType.FLOOR; +import static fr.sncf.osrd.envelope_sim.TrainPhysicsIntegrator.areSpeedsEqual; import fr.sncf.osrd.envelope.Envelope; import fr.sncf.osrd.envelope.part.ConstrainedEnvelopePartBuilder; @@ -11,15 +12,16 @@ import fr.sncf.osrd.envelope.part.constraints.SpeedConstraint; import fr.sncf.osrd.envelope_sim.*; import fr.sncf.osrd.envelope_sim.overlays.EnvelopeCoasting; -import fr.sncf.osrd.reporting.exceptions.OSRDError; import fr.sncf.osrd.reporting.exceptions.ErrorType; +import fr.sncf.osrd.reporting.exceptions.OSRDError; public final class CoastingGenerator { /** Generate a coasting envelope part which starts at startPos */ public static EnvelopePart coastFromBeginning( Envelope envelope, EnvelopeSimContext context, - double startPos + double startPos, + double startSpeed ) { var partBuilder = new EnvelopePartBuilder(); partBuilder.setAttr(EnvelopeProfile.COASTING); @@ -28,8 +30,7 @@ public static EnvelopePart coastFromBeginning( new SpeedConstraint(0, FLOOR), new EnvelopeConstraint(envelope, CEILING) ); - var speed = envelope.interpolateSpeed(startPos); - EnvelopeCoasting.coast(context, startPos, speed, constrainedBuilder, 1); + EnvelopeCoasting.coast(context, startPos, startSpeed, constrainedBuilder, 1); if (constrainedBuilder.lastIntersection == 0) throw new OSRDError(ErrorType.ImpossibleSimulationError); // We reached a stop while coasting if (partBuilder.isEmpty()) @@ -66,7 +67,7 @@ public static EnvelopePart coastFromEnd( var step = TrainPhysicsIntegrator.step(context, position, speed, Action.COAST, -1); position += step.positionDelta; speed = step.endSpeed; - if (speed < lowSpeedLimit) { + if (!areSpeedsEqual(speed, lowSpeedLimit) && speed < lowSpeedLimit) { speed = lowSpeedLimit; reachedLowLimit = true; } @@ -83,7 +84,8 @@ public static EnvelopePart coastFromEnd( if (!reachedLowLimit && constrainedBuilder.getLastPos() != envelope.getBeginPos()) return backwardPartBuilder.build(); - var resultCoast = coastFromBeginning(envelope, context, constrainedBuilder.getLastPos()); + var resultCoast = coastFromBeginning(envelope, context, constrainedBuilder.getLastPos(), + constrainedBuilder.getLastSpeed()); assert resultCoast == null || resultCoast.getEndPos() <= endPos + context.timeStep * speed; return resultCoast; } diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java index ab9470e43bd..0abfa1b7fdc 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java @@ -112,7 +112,6 @@ public void testAccelerateAndCoast() { for (int i = 0; i < 60; i++) { step = TrainPhysicsIntegrator.step(context, position, speed, Action.COAST, +1); position += step.positionDelta; - var prevSpeed = step.startSpeed; speed = step.endSpeed; } // it should be stopped @@ -130,7 +129,8 @@ public void testEmptyCoastFromBeginning() { EnvelopeDeceleration.decelerate(context, 0, 10, constrainedBuilder, 1); var acceleration = Envelope.make(builder.build()); // starting a coasting phase in a braking phase must result in a null EnvelopePart - var failedCoast = coastFromBeginning(acceleration, context, 0); + var speed = acceleration.interpolateSpeed(0); + var failedCoast = coastFromBeginning(acceleration, context, 0, speed); assertNull(failedCoast); } } diff --git a/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeShape.java b/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeShape.java index 4d110fe42b9..1290b52d8c2 100644 --- a/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeShape.java +++ b/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeShape.java @@ -1,5 +1,6 @@ package fr.sncf.osrd.envelope; +import static fr.sncf.osrd.envelope_sim.TrainPhysicsIntegrator.areSpeedsEqual; import static org.junit.jupiter.api.Assertions.assertEquals; import fr.sncf.osrd.envelope.part.EnvelopePart; @@ -14,7 +15,7 @@ public enum EnvelopeShape { public static EnvelopeShape fromStep(EnvelopePart part, int stepIndex) { var beginSpeed = part.getBeginSpeed(stepIndex); var endSpeed = part.getEndSpeed(stepIndex); - if (beginSpeed == endSpeed) + if (areSpeedsEqual(beginSpeed, endSpeed)) return CONSTANT; else if (beginSpeed < endSpeed) return INCREASING; diff --git a/core/src/main/kotlin/fr/sncf/osrd/sim_infra_adapter/RawInfraAdapter.kt b/core/src/main/kotlin/fr/sncf/osrd/sim_infra_adapter/RawInfraAdapter.kt index 4dce8a9bcf1..7136bac72dc 100644 --- a/core/src/main/kotlin/fr/sncf/osrd/sim_infra_adapter/RawInfraAdapter.kt +++ b/core/src/main/kotlin/fr/sncf/osrd/sim_infra_adapter/RawInfraAdapter.kt @@ -276,7 +276,6 @@ fun adaptRawInfra(infra: SignalingInfra): SimInfraAdapter { signalsPerTrack, builder ) - builder // check if the zone is a release zone if (releaseIndex < oldReleasePoints.size && oldEndDet.detector!! == oldReleasePoints[releaseIndex]) { From 0cda4bd6a09f217c43e46e4dbd38f50212ed83f6 Mon Sep 17 00:00:00 2001 From: Erashin Date: Thu, 16 Nov 2023 14:52:14 +0100 Subject: [PATCH 3/4] tests: reproduce new allowance search space discontinuity test in regression test --- .../search_space_discontinuity_3.json | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/tests/regression_tests_data/search_space_discontinuity_3.json diff --git a/tests/tests/regression_tests_data/search_space_discontinuity_3.json b/tests/tests/regression_tests_data/search_space_discontinuity_3.json new file mode 100644 index 00000000000..3e520d3ef5f --- /dev/null +++ b/tests/tests/regression_tests_data/search_space_discontinuity_3.json @@ -0,0 +1,94 @@ +{ + "error_type": "SCHEDULE", + "code": 500, + "error": "{\"status\":500,\"type\":\"allowance_convergence\",\"context\":{\"trace\":[{\"index\":1}],\"url\":\"http://localhost:8080/standalone_simulation\"},\"message\":\"Failed to converge when computing allowances because of a discontinuity in the search space\"}", + "infra_name": "small_infra", + "path_payload": { + "infra": 5, + "name": "foo", + "steps": [ + { + "duration": 201.26315724275267, + "waypoints": [ + { + "track_section": "TC0", + "offset": 552.2236003214992 + } + ] + }, + { + "duration": 438.6125451117886, + "waypoints": [ + { + "track_section": "TC0", + "offset": 71.51179397666198 + } + ] + }, + { + "duration": 905.27207511261, + "waypoints": [ + { + "track_section": "TA6", + "offset": 982.414023681425 + } + ] + }, + { + "duration": 1, + "waypoints": [ + { + "track_section": "TA0", + "offset": 1375.331921836674 + } + ] + } + ] + }, + "schedule_payload": { + "timetable": 357, + "path": 6918, + "schedules": [ + { + "train_name": "foo", + "labels": [], + "departure_time": 25812, + "allowances": [ + { + "allowance_type": "standard", + "default_value": { + "value_type": "time_per_distance", + "minutes": 6.5231844502540675 + }, + "ranges": [ + { + "begin_position": 0, + "end_position": 7321.423229665372, + "value": { + "value_type": "time", + "seconds": 24.50736878607825 + } + } + ], + "capacity_speed_limit": 4.032742864899781, + "distribution": "MARECO" + }, + { + "allowance_type": "engineering", + "begin_position": 30.507061762109494, + "end_position": 10137.834504522636, + "value": { + "value_type": "time", + "seconds": 36.224369091662 + }, + "capacity_speed_limit": 6.7015598167476504, + "distribution": "MARECO" + } + ], + "initial_speed": 0, + "rolling_stock_id": 449, + "speed_limit_category": "foo" + } + ] + } +} From 0d8bdbc678cf0d6a484bee6636a85a8d801ce0db Mon Sep 17 00:00:00 2001 From: Erashin Date: Thu, 16 Nov 2023 14:56:23 +0100 Subject: [PATCH 4/4] core: add compulsory EnvelopeProfile attribute to EnvelopePart --- .../sncf/osrd/envelope/EnvelopeSpeedCap.java | 9 ++- .../sncf/osrd/envelope/part/EnvelopePart.java | 15 +---- .../AbstractAllowanceWithRanges.java | 7 ++- .../mareco_impl/CoastingGenerator.java | 1 + .../osrd/envelope/ConstraintBuilderTest.java | 9 ++- .../osrd/envelope/EnvelopeBuilderTest.java | 9 ++- .../osrd/envelope/EnvelopeCursorTest.java | 7 +-- .../osrd/envelope/EnvelopeOverlayTest.java | 60 +++++++++++-------- .../osrd/envelope/EnvelopePartSliceTest.java | 21 +++---- .../sncf/osrd/envelope/EnvelopePartTest.java | 19 +++--- .../osrd/envelope/EnvelopeSpeedCapTest.java | 33 +++++----- .../fr/sncf/osrd/envelope/EnvelopeTest.java | 22 +++---- .../TrainPhysicsIntegratorTest.java | 1 + .../sncf/osrd/envelope/EnvelopeTestUtils.java | 24 +++++++- .../osrd/stdcm/graph/STDCMSimulations.java | 2 +- .../osrd/envelope_sim_infra/MRSPTest.java | 20 +++---- .../standalone_sim/StandaloneSimTests.java | 8 +-- .../BlockAvailabilityLegacyAdapterTests.java | 4 +- 18 files changed, 152 insertions(+), 119 deletions(-) diff --git a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/EnvelopeSpeedCap.java b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/EnvelopeSpeedCap.java index 88520f2c265..4c39a4a01dc 100644 --- a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/EnvelopeSpeedCap.java +++ b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/EnvelopeSpeedCap.java @@ -1,22 +1,27 @@ package fr.sncf.osrd.envelope; import fr.sncf.osrd.envelope.part.EnvelopePartBuilder; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import fr.sncf.osrd.envelope_utils.CmpOperator; +import java.util.Collection; +import java.util.HashSet; public class EnvelopeSpeedCap { /** Adds a global speed limit to an envelope */ public static Envelope from( Envelope base, - Iterable attrs, + Collection attrs, double speedLimit ) { var cursor = new EnvelopeCursor(base, false); var builder = OverlayEnvelopeBuilder.forward(base); + var envelopeAttrs = new HashSet<>(attrs); + envelopeAttrs.add(EnvelopeProfile.CONSTANT_SPEED); while (cursor.findSpeed(speedLimit, CmpOperator.STRICTLY_HIGHER)) { var startPos = cursor.getPosition(); var partBuilder = new EnvelopePartBuilder(); - partBuilder.setAttrs(attrs); + partBuilder.setAttrs(envelopeAttrs); partBuilder.initEnvelopePart(startPos, speedLimit, 1); var hasNotReachedEnd = cursor.findSpeed(speedLimit, CmpOperator.STRICTLY_LOWER); diff --git a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/EnvelopePart.java b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/EnvelopePart.java index 3c329c5c1c9..577d7827be8 100644 --- a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/EnvelopePart.java +++ b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope/part/EnvelopePart.java @@ -7,6 +7,7 @@ import fr.sncf.osrd.envelope.EnvelopeAttr; import fr.sncf.osrd.envelope.EnvelopePhysics; import fr.sncf.osrd.envelope.SearchableEnvelope; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import fr.sncf.osrd.envelope_utils.ExcludeFromGeneratedCodeCoverage; import java.util.Arrays; import java.util.Collections; @@ -106,19 +107,6 @@ public static EnvelopePart generateTimes( ); } - /** Creates an envelope part by generating step times from speeds and positions */ - public static EnvelopePart generateTimes( - double[] positions, - double[] speeds - ) { - return new EnvelopePart( - new HashMap<>(), - positions, - speeds, - computeTimes(positions, speeds) - ); - } - // endregion // region ATTRS @@ -165,6 +153,7 @@ public Map, EnvelopeAttr> getAttrs() { * (which should be avoided when possible) */ private void runSanityChecks() { assert attrs != null : "missing attributes"; + assert hasAttr(EnvelopeProfile.class) : "missing EnvelopeProfile attribute"; assert positions.length > 0 : "attempted to create an empty EnvelopePart"; assert positions.length == speeds.length : "there must be the same number of point and speeds"; assert timeDeltas.length == positions.length - 1 : "there must be as many timeDeltas as gaps between points"; diff --git a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/AbstractAllowanceWithRanges.java b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/AbstractAllowanceWithRanges.java index d2fa0db5276..c4d5106b090 100644 --- a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/AbstractAllowanceWithRanges.java +++ b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/AbstractAllowanceWithRanges.java @@ -14,6 +14,7 @@ import fr.sncf.osrd.envelope.part.constraints.EnvelopeConstraint; import fr.sncf.osrd.envelope.part.constraints.EnvelopePartConstraint; import fr.sncf.osrd.envelope.part.constraints.PositionConstraint; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import fr.sncf.osrd.envelope_sim.EnvelopeSimContext; import fr.sncf.osrd.envelope_sim.PhysicsRollingStock; import fr.sncf.osrd.envelope_sim.allowances.utils.AllowanceRange; @@ -157,7 +158,7 @@ private Envelope[] computeAllowanceRegion(Envelope envelopeRegion, EnvelopeSimCo var range = ranges.get(i); var percentage = range.value.getAllowanceRatio( envelopeRegion.getTimeBetween(range.beginPos, range.endPos), - range.beginPos - range.endPos + range.endPos - range.beginPos ); rangePercentages[i] = new RangePercentage(range, percentage); } @@ -401,6 +402,7 @@ private EnvelopePart computeLeftJunction(Envelope envelopeSection, EnvelopeDeceleration.decelerate( context, envelopeSection.getBeginPos(), imposedBeginSpeed, constrainedBuilder, 1 ); + partBuilder.setAttr(EnvelopeProfile.BRAKING); lastIntersection = constrainedBuilder.lastIntersection; } else if (imposedBeginSpeed < envelopeSection.getBeginSpeed()) { constraints.add(new EnvelopeConstraint(envelopeTarget, CEILING)); @@ -412,6 +414,7 @@ private EnvelopePart computeLeftJunction(Envelope envelopeSection, EnvelopeAcceleration.accelerate( context, envelopeSection.getBeginPos(), imposedBeginSpeed, constrainedBuilder, 1 ); + partBuilder.setAttr(EnvelopeProfile.ACCELERATING); lastIntersection = constrainedBuilder.lastIntersection; } if (lastIntersection == 0) { @@ -449,6 +452,7 @@ private EnvelopePart computeRightJunction(Envelope envelopeSection, EnvelopeAcceleration.accelerate( context, envelopeSection.getEndPos(), imposedEndSpeed, constrainedBuilder, -1 ); + partBuilder.setAttr(EnvelopeProfile.ACCELERATING); lastIntersection = constrainedBuilder.lastIntersection; } else if (imposedEndSpeed < envelopeSection.getEndSpeed()) { constraints.add(new EnvelopeConstraint(envelopeTarget, CEILING)); @@ -459,6 +463,7 @@ private EnvelopePart computeRightJunction(Envelope envelopeSection, EnvelopeDeceleration.decelerate( context, envelopeSection.getEndPos(), imposedEndSpeed, constrainedBuilder, -1 ); + partBuilder.setAttr(EnvelopeProfile.BRAKING); lastIntersection = constrainedBuilder.lastIntersection; } if (lastIntersection == 0) { diff --git a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java index f103642be66..230ce082429 100644 --- a/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java +++ b/core/envelope-sim/src/main/java/fr/sncf/osrd/envelope_sim/allowances/mareco_impl/CoastingGenerator.java @@ -52,6 +52,7 @@ public static EnvelopePart coastFromEnd( // coast backwards from the end position until the base curve is met var backwardPartBuilder = new EnvelopePartBuilder(); + backwardPartBuilder.setAttr(EnvelopeProfile.COASTING); var constrainedBuilder = new ConstrainedEnvelopePartBuilder( backwardPartBuilder, new SpeedConstraint(0, FLOOR), diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/ConstraintBuilderTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/ConstraintBuilderTest.java index dc893b0bd4d..bf02b09a527 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/ConstraintBuilderTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/ConstraintBuilderTest.java @@ -5,12 +5,12 @@ import fr.sncf.osrd.envelope.EnvelopeTestUtils.TestAttr; import fr.sncf.osrd.envelope.part.ConstrainedEnvelopePartBuilder; -import fr.sncf.osrd.envelope.part.EnvelopePart; import fr.sncf.osrd.envelope.part.EnvelopePartBuilder; import fr.sncf.osrd.envelope.part.EnvelopePartConsumer; import fr.sncf.osrd.envelope.part.constraints.EnvelopeConstraint; import fr.sncf.osrd.envelope.part.constraints.PositionConstraint; import fr.sncf.osrd.envelope.part.constraints.SpeedConstraint; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import org.junit.jupiter.api.Test; import java.util.List; @@ -27,13 +27,11 @@ public class ConstraintBuilderTest { // 0 1 2 3 4 5 6 7 8 9 10 private ConstrainedEnvelopePartBuilder wrap(EnvelopePartConsumer sink) { - var envelopeFloor = Envelope.make(EnvelopePart.generateTimes( - List.of(), + var envelopeFloor = Envelope.make(EnvelopeTestUtils.generateTimes( new double[] {0, 3, 4, 5, 6, 7, 10}, new double[] {0, 0, 1, 2, 1, 0, 0} )); - var envelopeCeiling = Envelope.make(EnvelopePart.generateTimes( - List.of(), + var envelopeCeiling = Envelope.make(EnvelopeTestUtils.generateTimes( new double[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new double[] {2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2} )); @@ -53,6 +51,7 @@ void testAttrs() { var builder = wrap(partBuilder); builder.setAttrs(List.of(TestAttr.A)); builder.setAttr(TestAttr.B); + builder.setAttr(EnvelopeProfile.ACCELERATING); assertTrue(builder.initEnvelopePart(2, 0, 1)); assertFalse(builder.addStep(5, 1)); var part = partBuilder.build(); diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeBuilderTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeBuilderTest.java index c6725a5e9c3..61e5fe6e917 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeBuilderTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeBuilderTest.java @@ -2,18 +2,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; -import fr.sncf.osrd.envelope.part.EnvelopePart; import org.junit.jupiter.api.Test; public class EnvelopeBuilderTest { @Test public void testEnvelopeBuilder() { var builder = new EnvelopeBuilder(); - builder.addPart(EnvelopePart.generateTimes( + builder.addPart(EnvelopeTestUtils.generateTimes( new double[]{0, 1}, new double[]{10, 20} )); - builder.addPart(EnvelopePart.generateTimes( + builder.addPart(EnvelopeTestUtils.generateTimes( new double[]{1, 2}, new double[]{20, 30} )); @@ -24,11 +23,11 @@ public void testEnvelopeBuilder() { @Test public void testEnvelopeBuilderReversed() { var builder = new EnvelopeBuilder(); - builder.addPart(EnvelopePart.generateTimes( + builder.addPart(EnvelopeTestUtils.generateTimes( new double[]{1, 2}, new double[]{20, 30} )); - builder.addPart(EnvelopePart.generateTimes( + builder.addPart(EnvelopeTestUtils.generateTimes( new double[]{0, 1}, new double[]{10, 20} )); diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeCursorTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeCursorTest.java index 72f1eb6d10b..f581b1d03c1 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeCursorTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeCursorTest.java @@ -2,21 +2,20 @@ import static org.junit.jupiter.api.Assertions.*; -import fr.sncf.osrd.envelope.part.EnvelopePart; import org.junit.jupiter.api.Test; public class EnvelopeCursorTest { public static final Envelope FLAT_ENVELOPE = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{1, 3, 4}, new double[]{4, 4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{4, 6}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{6, 8, 10}, new double[]{4, 4, 4} ) diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeOverlayTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeOverlayTest.java index a23b62cae21..3fee64a1f33 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeOverlayTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeOverlayTest.java @@ -8,6 +8,7 @@ import fr.sncf.osrd.envelope.part.EnvelopePart; import fr.sncf.osrd.envelope.part.EnvelopePartBuilder; import fr.sncf.osrd.envelope.part.constraints.EnvelopeConstraint; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -19,7 +20,7 @@ public class EnvelopeOverlayTest { void noChangeSinglePartOverlay(boolean backwardDir) { // +==============+ // 0 8 - var baseEnvelope = Envelope.make(EnvelopePart.generateTimes( + var baseEnvelope = Envelope.make(EnvelopeTestUtils.generateTimes( new double[]{0, 8}, new double[]{1, 1} )); @@ -36,11 +37,11 @@ void noChangeTwoPartOverlay(boolean backwardDir) { // +==============+==============+ // 0 8 16 var baseEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{0, 8}, new double[]{1, 1} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{8, 16}, new double[]{2, 2} ) @@ -58,7 +59,7 @@ void testConstantSpeedOverlay() { // \ / <= overlay // + // 0 3 4 5 8 - var constSpeedPart = EnvelopePart.generateTimes( + var constSpeedPart = EnvelopeTestUtils.generateTimes( new double[]{0, 8}, new double[]{2, 2} ); @@ -66,6 +67,7 @@ void testConstantSpeedOverlay() { var builder = OverlayEnvelopeBuilder.forward(constSpeedEnvelope); { var partBuilder = new EnvelopePartBuilder(); + partBuilder.setAttr(EnvelopeProfile.COASTING); var overlayBuilder = new ConstrainedEnvelopePartBuilder( partBuilder, new EnvelopeConstraint(constSpeedEnvelope, CEILING)); overlayBuilder.initEnvelopePart(3, constSpeedEnvelope.interpolateSpeed(3), 1); @@ -85,7 +87,7 @@ void testConstantSpeedOverlay() { @Test void testMultipleOverlays() { - var constSpeedPart = EnvelopePart.generateTimes( + var constSpeedPart = EnvelopeTestUtils.generateTimes( new double[]{0, 8}, new double[]{2, 2} ); @@ -94,6 +96,7 @@ void testMultipleOverlays() { { var partBuilder = new EnvelopePartBuilder(); + partBuilder.setAttr(EnvelopeProfile.COASTING); var overlayBuilder = new ConstrainedEnvelopePartBuilder( partBuilder, new EnvelopeConstraint(constSpeedEnvelope, CEILING)); overlayBuilder.initEnvelopePart(0, constSpeedEnvelope.interpolateSpeed(0), 1); @@ -104,6 +107,7 @@ void testMultipleOverlays() { { var partBuilder = new EnvelopePartBuilder(); + partBuilder.setAttr(EnvelopeProfile.COASTING); var overlayBuilder = new ConstrainedEnvelopePartBuilder( partBuilder, new EnvelopeConstraint(constSpeedEnvelope, CEILING)); overlayBuilder.initEnvelopePart(6, constSpeedEnvelope.interpolateSpeed(6), 1); @@ -123,7 +127,7 @@ void testMultipleOverlays() { @ValueSource(booleans = {false, true}) void testSymmetricOverlay(boolean backwardDir) { var constSpeedPart = EnvelopePart.generateTimes( - List.of(TestAttr.B), + List.of(TestAttr.B, EnvelopeProfile.CONSTANT_SPEED), new double[]{0, 3.5, 8}, new double[]{2, 2, 2} ); @@ -134,6 +138,7 @@ void testSymmetricOverlay(boolean backwardDir) { { var partBuilder = new EnvelopePartBuilder(); partBuilder.setAttr(TestAttr.A); + partBuilder.setAttr(EnvelopeProfile.COASTING); var overlayBuilder = new ConstrainedEnvelopePartBuilder( partBuilder, new EnvelopeConstraint(constSpeedEnvelope, CEILING)); overlayBuilder.initEnvelopePart(overlayPoints[0], 2, backwardDir ? -1 : 1); @@ -149,7 +154,7 @@ void testSymmetricOverlay(boolean backwardDir) { var expectedFirst = constSpeedPart.sliceBeginning(constSpeedPart.findLeft(3), 3, Double.NaN); EnvelopeTestUtils.assertEquals(expectedFirst, envelope.get(0)); var expectedMid = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.COASTING), new double[]{3, 4, 5}, new double[]{2, 1, 2} ); @@ -168,19 +173,19 @@ void testBaseCurveSplit(boolean isBackward) { // + // 0 1 3 4 5 6 8 var baseEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{0, 1}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{1, 4}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{4, 6}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{6, 8}, new double[]{4, 4} ) @@ -190,7 +195,8 @@ void testBaseCurveSplit(boolean isBackward) { var cursor = new EnvelopeCursor(baseEnvelope, isBackward); var positions = new double[] { 3, 4, 6 }; var speeds = new double[] { 4, 3, 4 }; - builder.addPart(EnvelopeTestUtils.buildContinuous(cursor, List.of(), positions, speeds, isBackward)); + builder.addPart(EnvelopeTestUtils.buildContinuous(cursor, List.of(EnvelopeProfile.COASTING), positions, speeds, + isBackward)); var envelope = builder.build(); assertEquals(4, envelope.size()); assertTrue(envelope.continuous); @@ -203,27 +209,27 @@ void testDiscontinuityOverlayEnd() { // 4 +===+===+ <= base // 0 1 2 4 5 6 8 10 var baseEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{0, 2}, new double[]{6, 6} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{2, 4}, new double[]{6, 6} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{4, 5}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{5, 6}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{6, 8}, new double[]{6, 6} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{8, 10}, new double[]{6, 6} ) @@ -233,6 +239,7 @@ void testDiscontinuityOverlayEnd() { { var partBuilder = new EnvelopePartBuilder(); + partBuilder.setAttr(EnvelopeProfile.BRAKING); var overlayBuilder = new ConstrainedEnvelopePartBuilder( partBuilder, new EnvelopeConstraint(baseEnvelope, CEILING) @@ -257,19 +264,19 @@ void testLongOverlay(boolean reverse) { // +---+ // 0 1 3 4 5 6 8 var baseEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{0, 1}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{1, 4}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{4, 6}, new double[]{4, 4} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[]{6, 8}, new double[]{4, 4} ) @@ -279,7 +286,8 @@ void testLongOverlay(boolean reverse) { var cursor = new EnvelopeCursor(baseEnvelope, reverse); var positions = new double[] { 3, 4, 5, 6 }; var speeds = new double[] { 4, 3, 3, 4 }; - builder.addPart(EnvelopeTestUtils.buildContinuous(cursor, List.of(), positions, speeds, reverse)); + builder.addPart(EnvelopeTestUtils.buildContinuous(cursor, List.of(EnvelopeProfile.COASTING), positions, speeds, + reverse)); var envelope = builder.build(); assertEquals(4, envelope.size()); assertTrue(envelope.continuous); @@ -287,7 +295,7 @@ void testLongOverlay(boolean reverse) { @Test void testUnlikelyIntersection() { - var inputEnvelope = Envelope.make(EnvelopePart.generateTimes( + var inputEnvelope = Envelope.make(EnvelopeTestUtils.generateTimes( new double[]{0, 3, 4}, new double[]{2, 1, 0} )); @@ -296,6 +304,7 @@ void testUnlikelyIntersection() { { var partBuilder = new EnvelopePartBuilder(); + partBuilder.setAttr(EnvelopeProfile.COASTING); var overlayBuilder = new ConstrainedEnvelopePartBuilder( partBuilder, new EnvelopeConstraint(inputEnvelope, CEILING) @@ -313,7 +322,7 @@ void testUnlikelyIntersection() { @Test void testIncreasingContinuousOverlay() { - var inputEnvelope = Envelope.make(EnvelopePart.generateTimes( + var inputEnvelope = Envelope.make(EnvelopeTestUtils.generateTimes( new double[]{0, 2, 4}, new double[]{1, 1, 3} )); @@ -322,6 +331,7 @@ void testIncreasingContinuousOverlay() { { var partBuilder = new EnvelopePartBuilder(); + partBuilder.setAttr(EnvelopeProfile.ACCELERATING); var overlayBuilder = new ConstrainedEnvelopePartBuilder( partBuilder, new EnvelopeConstraint(inputEnvelope, CEILING) diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartSliceTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartSliceTest.java index 7c3aa443c33..74535a94951 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartSliceTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartSliceTest.java @@ -6,6 +6,7 @@ import fr.sncf.osrd.envelope.EnvelopeTestUtils.TestAttr; import fr.sncf.osrd.envelope.part.EnvelopePart; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import org.junit.jupiter.api.Test; import java.util.List; @@ -14,12 +15,12 @@ public class EnvelopePartSliceTest { @Test void sliceIndex() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {1.5, 3, 5}, new double[] {3, 4, 4} ); var ep2 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {1.5, 3}, new double[] {3, 4} ); @@ -31,7 +32,7 @@ void sliceIndex() { @Test void sliceIndexFull() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {1.5, 3, 5}, new double[] {3, 3, 4} ); @@ -43,7 +44,7 @@ void sliceIndexFull() { @Test void sliceIndexEmpty() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {1.5, 3, 5}, new double[] {3, 3, 4} ); @@ -54,7 +55,7 @@ void sliceIndexEmpty() { @Test void sliceOffsetEmpty() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {1.5, 3, 5}, new double[] {3, 3, 4} ); @@ -65,7 +66,7 @@ void sliceOffsetEmpty() { @Test void sliceOffsetFull() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {1.5, 3, 5}, new double[] {3, 3, 4} ); @@ -76,13 +77,13 @@ void sliceOffsetFull() { @Test void sliceOffsetInterpolate() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.BRAKING), new double[] {0, 3}, new double[] {3.46, 0} ); var slice = ep1.slice(Double.NEGATIVE_INFINITY, 2); var expectedSlice = new EnvelopePart( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.BRAKING), new double[] {0, 2}, new double[] {3.46, 2}, new double[] {0.73} @@ -93,13 +94,13 @@ void sliceOffsetInterpolate() { @Test void sliceWithImposedSpeeds() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {1, 3, 5}, new double[] {3, 3, 4} ); var slice = ep1.sliceWithSpeeds(2, 3, 4, 3.5); var expectedSlice = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(TestAttr.A, EnvelopeProfile.ACCELERATING), new double[] {2, 3, 4}, new double[] {3, 3, 3.5} ); diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartTest.java index f17030342eb..080b0deb6ff 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopePartTest.java @@ -3,7 +3,6 @@ import static fr.sncf.osrd.envelope.EnvelopePhysics.getPartMechanicalEnergyConsumed; import static org.junit.jupiter.api.Assertions.*; -import fr.sncf.osrd.envelope.EnvelopeTestUtils.TestAttr; import fr.sncf.osrd.envelope.part.EnvelopePart; import fr.sncf.osrd.envelope_sim.*; import fr.sncf.osrd.envelope_sim.allowances.utils.AllowanceValue; @@ -15,26 +14,26 @@ class EnvelopePartTest { @Test void toStringTest() { var part = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(EnvelopeProfile.ACCELERATING), new double[]{1.5, 5}, new double[]{3, 4} ); - assertEquals("EnvelopePart { TestAttr=A }", part.toString()); + assertEquals("EnvelopePart { EnvelopeProfile=ACCELERATING }", part.toString()); } @Test void getAttrTest() { var part = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(EnvelopeProfile.ACCELERATING), new double[]{1.5, 5}, new double[]{3, 4} ); - assertEquals(TestAttr.A, part.getAttr(TestAttr.class)); + assertEquals(EnvelopeProfile.ACCELERATING, part.getAttr(EnvelopeProfile.class)); } @Test void interpolateSpeedTest() { - var ep = EnvelopePart.generateTimes( + var ep = EnvelopeTestUtils.generateTimes( new double[]{1.5, 5}, new double[]{3, 4} ); @@ -45,7 +44,7 @@ void interpolateSpeedTest() { @Test void findStep() { - var ep = EnvelopePart.generateTimes( + var ep = EnvelopeTestUtils.generateTimes( new double[]{1.5, 3, 5}, new double[]{3, 4, 4} ); @@ -71,17 +70,17 @@ void findStep() { @Test void testEquals() { var ep1 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(EnvelopeProfile.ACCELERATING), new double[]{1.5, 3, 5}, new double[]{3, 4, 4} ); var ep2 = EnvelopePart.generateTimes( - List.of(TestAttr.A), + List.of(EnvelopeProfile.ACCELERATING), new double[]{1.5, 3, 5}, new double[]{3, 4, 4} ); var ep3 = EnvelopePart.generateTimes( - List.of(TestAttr.B), + List.of(EnvelopeProfile.COASTING), new double[]{1.5, 3, 5}, new double[]{3, 4, 4} ); diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeSpeedCapTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeSpeedCapTest.java index 6264a82b582..aebc71fce08 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeSpeedCapTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeSpeedCapTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import fr.sncf.osrd.envelope.part.EnvelopePart; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import org.junit.jupiter.api.Test; import java.util.List; @@ -11,6 +12,7 @@ public class EnvelopeSpeedCapTest { void testSimpleCap() { var inputEnvelope = Envelope.make( EnvelopePart.generateTimes( + List.of(EnvelopeProfile.COASTING), new double[] {0, 2, 4}, new double[] {0, 2, 0} ) @@ -19,14 +21,17 @@ void testSimpleCap() { var expectedEnvelope = Envelope.make( EnvelopePart.generateTimes( + List.of(EnvelopeProfile.COASTING), new double[] {0, 0.5}, new double[] {0, 1} ), EnvelopePart.generateTimes( + List.of(EnvelopeProfile.CONSTANT_SPEED), new double[] {0.5, 3.5}, new double[] {1, 1} ), EnvelopePart.generateTimes( + List.of(EnvelopeProfile.COASTING), new double[] {3.5, 4}, new double[] {1, 0} ) @@ -43,7 +48,7 @@ void testSimpleCap() { @Test void testFlatCap() { var inputEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 1}, new double[] {2, 2} ) @@ -51,7 +56,7 @@ void testFlatCap() { var cappedEnvelope = EnvelopeSpeedCap.from(inputEnvelope, List.of(), 1); var expectedEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 1}, new double[] {1, 1} ) @@ -62,12 +67,12 @@ void testFlatCap() { @Test void testOpenEndCap() { var envelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 2}, new double[] {0, 2} ), // this part should be completely hidden away - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {2, 4}, new double[] {2, 2} ) @@ -75,11 +80,11 @@ void testOpenEndCap() { var cappedEnvelope = EnvelopeSpeedCap.from(envelope, List.of(), 1); var expectedEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 0.5}, new double[] {0, 1} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0.5, 4}, new double[] {1, 1} ) @@ -90,23 +95,23 @@ void testOpenEndCap() { @Test void testOpenBeginCap() { var envelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 2}, new double[] {2, 2} ), // this part should be completely hidden away - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {2, 4}, new double[] {2, 0} ) ); var cappedEnvelope = EnvelopeSpeedCap.from(envelope, List.of(), 1); var expectedEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 3.5}, new double[] {1, 1} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {3.5, 4}, new double[] {1, 0} ) @@ -117,7 +122,7 @@ void testOpenBeginCap() { @Test void testMultipleCaps() { var envelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 2, 4}, new double[] {2, 0, 2} ) @@ -125,15 +130,15 @@ void testMultipleCaps() { var cappedEnvelope = EnvelopeSpeedCap.from(envelope, List.of(), 1); var expectedEnvelope = Envelope.make( - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {0, 1.5}, new double[] {1, 1} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {1.5, 2, 2.5}, new double[] {1, 0, 1} ), - EnvelopePart.generateTimes( + EnvelopeTestUtils.generateTimes( new double[] {2.5, 4}, new double[] {1, 1} ) diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeTest.java index f6dbd55e11e..12f39ed0ac9 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope/EnvelopeTest.java @@ -9,10 +9,10 @@ public class EnvelopeTest { @Test void testContinuity() { - var partA = EnvelopePart.generateTimes(new double[] {0, 1}, new double[] {1, 1}); - var partB = EnvelopePart.generateTimes(new double[] {2, 3}, new double[] {1, 1}); - var partC = EnvelopePart.generateTimes(new double[] {1, 2}, new double[] {2, 2}); - var partD = EnvelopePart.generateTimes(new double[] {1, 2}, new double[] {1, 1}); + var partA = EnvelopeTestUtils.generateTimes(new double[] {0, 1}, new double[] {1, 1}); + var partB = EnvelopeTestUtils.generateTimes(new double[] {2, 3}, new double[] {1, 1}); + var partC = EnvelopeTestUtils.generateTimes(new double[] {1, 2}, new double[] {2, 2}); + var partD = EnvelopeTestUtils.generateTimes(new double[] {1, 2}, new double[] {1, 1}); assertThrows(RuntimeException.class, () -> Envelope.make(partA, partB)); assertTrue(Envelope.make(partA, partD).continuous); assertFalse(Envelope.make(partA, partC).continuous); @@ -20,7 +20,7 @@ void testContinuity() { @Test void testIterator() { - var a = EnvelopePart.generateTimes(new double[] { 0, 2 }, new double[] { 2, 2 }); + var a = EnvelopeTestUtils.generateTimes(new double[] { 0, 2 }, new double[] { 2, 2 }); var envelope = Envelope.make(a); var res = new ArrayList(); envelope.iterator().forEachRemaining(res::add); @@ -30,8 +30,8 @@ void testIterator() { @Test void testMinMaxSpeed() { - final var partA = EnvelopePart.generateTimes(new double[] { 0, 2 }, new double[] { 1, 2 }); - final var partB = EnvelopePart.generateTimes(new double[] { 2, 4 }, new double[] { 4, 3 }); + final var partA = EnvelopeTestUtils.generateTimes(new double[] { 0, 2 }, new double[] { 1, 2 }); + final var partB = EnvelopeTestUtils.generateTimes(new double[] { 2, 4 }, new double[] { 4, 3 }); final var envelope = Envelope.make(partA, partB); assertEquals(1, partA.getMinSpeed()); @@ -45,8 +45,8 @@ void testMinMaxSpeed() { @Test void testInterpolateSpeed() { - var partA = EnvelopePart.generateTimes(new double[] { 0, 2 }, new double[] { 1, 2 }); - var partB = EnvelopePart.generateTimes(new double[] { 2, 3 }, new double[] { 2, 4 }); + var partA = EnvelopeTestUtils.generateTimes(new double[] { 0, 2 }, new double[] { 1, 2 }); + var partB = EnvelopeTestUtils.generateTimes(new double[] { 2, 3 }, new double[] { 2, 4 }); var envelope = Envelope.make(partA, partB); assertEquals(1, envelope.interpolateSpeed(0)); @@ -56,8 +56,8 @@ void testInterpolateSpeed() { @Test void testInterpolateTime() { - var partA = EnvelopePart.generateTimes(new double[] { 0, 2 }, new double[] { 1, 1 }); - var partB = EnvelopePart.generateTimes(new double[] { 2, 4 }, new double[] { 1, 1 }); + var partA = EnvelopeTestUtils.generateTimes(new double[] { 0, 2 }, new double[] { 1, 1 }); + var partB = EnvelopeTestUtils.generateTimes(new double[] { 2, 4 }, new double[] { 1, 1 }); var envelope = Envelope.make(partA, partB); assertEquals(1, partA.interpolateTotalTime(1)); diff --git a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java index 0abfa1b7fdc..2105e232448 100644 --- a/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java +++ b/core/envelope-sim/src/test/java/fr/sncf/osrd/envelope_sim/TrainPhysicsIntegratorTest.java @@ -127,6 +127,7 @@ public void testEmptyCoastFromBeginning() { new SpeedConstraint(0, EnvelopePartConstraintType.FLOOR) ); EnvelopeDeceleration.decelerate(context, 0, 10, constrainedBuilder, 1); + builder.setAttr(EnvelopeProfile.BRAKING); var acceleration = Envelope.make(builder.build()); // starting a coasting phase in a braking phase must result in a null EnvelopePart var speed = acceleration.interpolateSpeed(0); diff --git a/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeTestUtils.java b/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeTestUtils.java index 1b3ee484d6c..d5c3a64f78f 100644 --- a/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeTestUtils.java +++ b/core/envelope-sim/src/testFixtures/java/fr/sncf/osrd/envelope/EnvelopeTestUtils.java @@ -2,13 +2,16 @@ import static fr.sncf.osrd.envelope.part.constraints.EnvelopePartConstraintType.CEILING; import static fr.sncf.osrd.envelope.part.constraints.EnvelopePartConstraintType.FLOOR; +import static fr.sncf.osrd.envelope_sim.TrainPhysicsIntegrator.areSpeedsEqual; import fr.sncf.osrd.envelope.part.ConstrainedEnvelopePartBuilder; import fr.sncf.osrd.envelope.part.EnvelopePart; import fr.sncf.osrd.envelope.part.EnvelopePartBuilder; import fr.sncf.osrd.envelope.part.constraints.EnvelopeConstraint; import fr.sncf.osrd.envelope.part.constraints.SpeedConstraint; +import fr.sncf.osrd.envelope_sim.EnvelopeProfile; import org.junit.jupiter.api.Assertions; +import java.util.Collections; import java.util.List; public class EnvelopeTestUtils { @@ -89,8 +92,8 @@ static void assertEquals(Envelope expected, Envelope actual) { } /** Creates a flat envelope part */ - public static EnvelopePart makeFlatPart(TestAttr attr, double beginPos, double endPos, double speed) { - return makeFlatPart(List.of(attr), beginPos, endPos, speed); + public static EnvelopePart makeFlatPart(EnvelopeAttr attr, double beginPos, double endPos, double speed) { + return makeFlatPart(List.of(attr, EnvelopeProfile.CONSTANT_SPEED), beginPos, endPos, speed); } /** Creates a flat envelope part */ @@ -102,4 +105,21 @@ public static EnvelopePart makeFlatPart(Iterable attrs, new double[]{speed, speed} ); } + + /** Creates an envelope part by generating step times from speeds and positions */ + public static EnvelopePart generateTimes(double[] positions, double[] speeds) { + //Input a default compulsory EnvelopeProfile attribute. This is not physically correct in some cases. If so, + //use generateTimes with attributes argument. + var envelopeProfile = EnvelopeProfile.BRAKING; + if (areSpeedsEqual(speeds[0], speeds[speeds.length - 1])) { + envelopeProfile = EnvelopeProfile.CONSTANT_SPEED; + } else if (speeds[0] < speeds[speeds.length - 1]) { + envelopeProfile = EnvelopeProfile.ACCELERATING; + } + return EnvelopePart.generateTimes( + Collections.singleton(envelopeProfile), + positions, + speeds + ); + } } diff --git a/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMSimulations.java b/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMSimulations.java index 16936610d75..0ed47af0db7 100644 --- a/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMSimulations.java +++ b/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMSimulations.java @@ -137,7 +137,7 @@ public static Envelope simulateBlock( */ private static Envelope makeSinglePointEnvelope(double speed) { return Envelope.make(new EnvelopePart( - Map.of(), + Map.of(EnvelopeProfile.class, EnvelopeProfile.CONSTANT_SPEED), new double[]{0}, new double[]{speed}, new double[]{} diff --git a/core/src/test/java/fr/sncf/osrd/envelope_sim_infra/MRSPTest.java b/core/src/test/java/fr/sncf/osrd/envelope_sim_infra/MRSPTest.java index e990c8f47b6..5d569be8c02 100644 --- a/core/src/test/java/fr/sncf/osrd/envelope_sim_infra/MRSPTest.java +++ b/core/src/test/java/fr/sncf/osrd/envelope_sim_infra/MRSPTest.java @@ -76,30 +76,30 @@ private Stream testComputeMRSPArgs() { Arguments.of(path, REALISTIC_FAST_TRAIN, false, TRAIN_TAG2, Envelope.make( // No speed section at first => train speed limit - makeFlatPart(List.of(TRAIN_LIMIT, CONSTANT_SPEED), 0, POSITION1, MAX_SPEED), + makeFlatPart(TRAIN_LIMIT, 0, POSITION1, MAX_SPEED), // Speed section with incorrect train tag => speed 1 - makeFlatPart(List.of(SPEED_LIMIT, CONSTANT_SPEED), POSITION1, POSITION2, SPEED1), + makeFlatPart(SPEED_LIMIT, POSITION1, POSITION2, SPEED1), // Speed section with correct train tag => speed 3 - makeFlatPart(List.of(SPEED_LIMIT, CONSTANT_SPEED), POSITION2, POSITION3, SPEED3), + makeFlatPart(SPEED_LIMIT, POSITION2, POSITION3, SPEED3), // No speed section at end => train speed limit - makeFlatPart(List.of(TRAIN_LIMIT, CONSTANT_SPEED), POSITION3, pathLength, MAX_SPEED))), + makeFlatPart(TRAIN_LIMIT, POSITION3, pathLength, MAX_SPEED))), // Multiple speed sections with rolling stock length Arguments.of(path, REALISTIC_FAST_TRAIN, true, null, Envelope.make( // No speed section at first => train speed limit - makeFlatPart(List.of(TRAIN_LIMIT, CONSTANT_SPEED), 0, POSITION1, MAX_SPEED), + makeFlatPart(TRAIN_LIMIT, 0, POSITION1, MAX_SPEED), // Speed section with incorrect train tag: speed 1 - makeFlatPart(List.of(SPEED_LIMIT, CONSTANT_SPEED), POSITION1, - POSITION2 + REALISTIC_FAST_TRAIN.length, SPEED1), + makeFlatPart(SPEED_LIMIT, POSITION1, POSITION2 + REALISTIC_FAST_TRAIN.length, + SPEED1), // Rolling stock length > speedSection2 length => speedSection2 not taken into account // No speed section at end => train speed limit - makeFlatPart(List.of(TRAIN_LIMIT, CONSTANT_SPEED), - POSITION2 + REALISTIC_FAST_TRAIN.length, pathLength, MAX_SPEED))), + makeFlatPart(TRAIN_LIMIT, POSITION2 + REALISTIC_FAST_TRAIN.length, pathLength, + MAX_SPEED))), // No speed sections taken into account: speedSection1 speed2 > train maxSpeed, speedSection2 speed 0m/s Arguments.of(path, REALISTIC_FAST_TRAIN, false, TRAIN_TAG1, - Envelope.make(makeFlatPart(List.of(TRAIN_LIMIT, CONSTANT_SPEED), 0, pathLength, MAX_SPEED)))); + Envelope.make(makeFlatPart(TRAIN_LIMIT, 0, pathLength, MAX_SPEED)))); } } diff --git a/core/src/test/java/fr/sncf/osrd/standalone_sim/StandaloneSimTests.java b/core/src/test/java/fr/sncf/osrd/standalone_sim/StandaloneSimTests.java index 57addf7fb32..7b14ef8926f 100644 --- a/core/src/test/java/fr/sncf/osrd/standalone_sim/StandaloneSimTests.java +++ b/core/src/test/java/fr/sncf/osrd/standalone_sim/StandaloneSimTests.java @@ -3,7 +3,7 @@ import static fr.sncf.osrd.standalone_sim.StandaloneSim.generateAllowanceFromScheduledPoints; import fr.sncf.osrd.envelope.Envelope; -import fr.sncf.osrd.envelope.part.EnvelopePart; +import fr.sncf.osrd.envelope.EnvelopeTestUtils; import fr.sncf.osrd.train.ScheduledPoint; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -13,7 +13,7 @@ public class StandaloneSimTests { @Test public void generateAllowanceFromOneScheduledPoint() { - var envelopeFloor = Envelope.make(EnvelopePart.generateTimes( + var envelopeFloor = Envelope.make(EnvelopeTestUtils.generateTimes( new double[] {0, 1, 2, 3, 4, 5, 6}, new double[] {1, 1, 1, 1, 1, 1, 1} )); @@ -32,7 +32,7 @@ public void generateAllowanceFromOneScheduledPoint() { @Test public void generateAllowanceFromMultipleScheduledPoints() { - var envelopeFloor = Envelope.make(EnvelopePart.generateTimes( + var envelopeFloor = Envelope.make(EnvelopeTestUtils.generateTimes( new double[] {0, 1, 2, 3, 4, 5, 6}, new double[] {1, 1, 1, 1, 1, 1, 1} )); @@ -56,7 +56,7 @@ public void generateAllowanceFromMultipleScheduledPoints() { @Test public void generateAllowanceFromNoScheduledPoints() { - var envelopeFloor = Envelope.make(EnvelopePart.generateTimes( + var envelopeFloor = Envelope.make(EnvelopeTestUtils.generateTimes( new double[] {0, 1, 2, 3, 4, 5, 6}, new double[] {1, 1, 1, 1, 1, 1, 1} )); diff --git a/core/src/test/java/fr/sncf/osrd/stdcm/preprocessing/BlockAvailabilityLegacyAdapterTests.java b/core/src/test/java/fr/sncf/osrd/stdcm/preprocessing/BlockAvailabilityLegacyAdapterTests.java index 0ef987a45cd..cc1eeff30fb 100644 --- a/core/src/test/java/fr/sncf/osrd/stdcm/preprocessing/BlockAvailabilityLegacyAdapterTests.java +++ b/core/src/test/java/fr/sncf/osrd/stdcm/preprocessing/BlockAvailabilityLegacyAdapterTests.java @@ -6,7 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import fr.sncf.osrd.envelope.Envelope; -import fr.sncf.osrd.envelope.part.EnvelopePart; +import fr.sncf.osrd.envelope.EnvelopeTestUtils; import fr.sncf.osrd.envelope_sim.SimpleRollingStock; import fr.sncf.osrd.sim_infra.api.InterlockingInfraKt; import fr.sncf.osrd.standalone_sim.result.ResultTrain; @@ -52,7 +52,7 @@ public void simpleUnavailableRouteTest() { List.of(blocks.get(0)), 0, meters(1), - Envelope.make(EnvelopePart.generateTimes(new double[]{0., 1.}, new double[]{100., 100.})), + Envelope.make(EnvelopeTestUtils.generateTimes(new double[]{0., 1.}, new double[]{100., 100.})), 42 ); var expected = new BlockAvailabilityInterface.Unavailable(42 + 20, 0);