From e40ca0f73dd6fc7179c928e8c30e718ec0304eb0 Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Tue, 25 Jul 2023 18:37:28 +0200 Subject: [PATCH 1/8] feat(mapping): configure type distributions for ScenarioVehicle allows defining multiple application types for equal vehicle type names in large sumo scenario Signed-off-by: Karl Schrab --- .../mapping/ambassador/MappingAmbassador.java | 79 +++++++----- .../mapping/ambassador/SpawningFramework.java | 25 +++- .../mosaic/fed/mapping/config/CPrototype.java | 8 +- .../ambassador/MappingAmbassadorTest.java | 21 ++++ .../src/test/resources/mapping_config.json | 112 ++++++++++-------- 5 files changed, 161 insertions(+), 84 deletions(-) diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java index 2496509ed..6f8022532 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java @@ -15,6 +15,7 @@ package org.eclipse.mosaic.fed.mapping.ambassador; +import org.eclipse.mosaic.fed.mapping.ambassador.weighting.StochasticSelector; import org.eclipse.mosaic.fed.mapping.config.CMappingAmbassador; import org.eclipse.mosaic.fed.mapping.config.CPrototype; import org.eclipse.mosaic.interactions.mapping.VehicleRegistration; @@ -32,6 +33,7 @@ import org.apache.commons.lang3.ObjectUtils; +import java.util.List; import javax.annotation.Nonnull; /** @@ -121,46 +123,59 @@ private void handleInteraction(ScenarioTrafficLightRegistration interaction) { */ private void handleInteraction(ScenarioVehicleRegistration scenarioVehicle) throws InternalFederateException { if (framework != null) { - final CPrototype prototype = framework.getPrototypeByName(scenarioVehicle.getVehicleType().getName()); - if (prototype == null) { - log.debug( - "There is no such prototype \"{}\" configured. No application will be mapped for vehicle \"{}\".", - scenarioVehicle.getVehicleType().getName(), - scenarioVehicle.getId() - ); - return; - } - if (randomNumberGenerator.nextDouble() >= ObjectUtils.defaultIfNull(prototype.weight, 1.0)) { - log.debug( - "This scenario vehicle \"{}\" of prototype \"{}\" will not be equipped due to a weight condition of {}.", - scenarioVehicle.getId(), - scenarioVehicle.getVehicleType().getName(), - prototype.weight - ); - return; + final List typeDistribution = framework.getTypeDistributionByName(scenarioVehicle.getVehicleType().getName()); + if (!typeDistribution.isEmpty()) { + final CPrototype selected = new StochasticSelector<>(typeDistribution, randomNumberGenerator).nextItem(); + sendVehicleRegistrationForScenarioVehicle(scenarioVehicle, selected.group, selected.applications); + } else { + final CPrototype prototype = framework.getPrototypeByName(scenarioVehicle.getVehicleType().getName()); + if (prototype == null) { + log.debug( + "There is no such prototype \"{}\" configured. No application will be mapped for vehicle \"{}\".", + scenarioVehicle.getVehicleType().getName(), + scenarioVehicle.getId() + ); + return; + } + + if (randomNumberGenerator.nextDouble() >= ObjectUtils.defaultIfNull(prototype.weight, 1.0)) { + log.debug( + "This scenario vehicle \"{}\" of prototype \"{}\" will not be equipped due to a weight condition of {}.", + scenarioVehicle.getId(), + scenarioVehicle.getVehicleType().getName(), + prototype.weight + ); + return; + } + sendVehicleRegistrationForScenarioVehicle(scenarioVehicle, prototype.group, prototype.applications); } - final VehicleRegistration vehicleRegistration = new VehicleRegistration( - scenarioVehicle.getTime(), - scenarioVehicle.getName(), - prototype.group, - prototype.applications, - null, - scenarioVehicle.getVehicleType() - ); - try { - log.info("Mapping Scenario Vehicle. time={}, name={}, type={}, apps={}", - framework.getTime(), scenarioVehicle.getName(), scenarioVehicle.getVehicleType().getName(), prototype.applications); - rti.triggerInteraction(vehicleRegistration); - } catch (Exception e) { - throw new InternalFederateException(e); - } } else { log.warn("No mapping configuration available. Skipping {}", scenarioVehicle.getClass().getSimpleName()); } } + private void sendVehicleRegistrationForScenarioVehicle( + ScenarioVehicleRegistration scenarioVehicle, String group, List applications + ) throws InternalFederateException { + final VehicleRegistration vehicleRegistration = new VehicleRegistration( + scenarioVehicle.getTime(), + scenarioVehicle.getName(), + group, + applications, + null, + scenarioVehicle.getVehicleType() + ); + try { + log.info("Mapping Scenario Vehicle. time={}, name={}, type={}, apps={}", + framework.getTime(), scenarioVehicle.getName(), scenarioVehicle.getVehicleType().getName(), applications); + rti.triggerInteraction(vehicleRegistration); + } catch (Exception e) { + throw new InternalFederateException(e); + } + } + @Override protected void processTimeAdvanceGrant(long time) throws InternalFederateException { try { diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java index 1976e7be6..eff4da93e 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java @@ -46,6 +46,7 @@ import org.eclipse.mosaic.rti.api.InternalFederateException; import org.eclipse.mosaic.rti.api.RtiAmbassador; +import com.google.common.collect.Lists; import org.apache.commons.lang3.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,6 +66,7 @@ public class SpawningFramework { private static final Logger LOG = LoggerFactory.getLogger(SpawningFramework.class); private final List prototypeConfigurations = new ArrayList<>(); + private final Map> typeDistributions = new HashMap<>(); private final Map tls = new HashMap<>(); private final List vehicleFlowGenerators = new ArrayList<>(); private final List rsus = new ArrayList<>(); @@ -172,12 +174,16 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration, } } } + + if (mappingConfiguration.typeDistributions != null) { + SpawningFramework.this.typeDistributions.putAll(mappingConfiguration.typeDistributions); + } + // randomize weights in type-distributions - if (mappingConfiguration.typeDistributions != null - && mappingConfiguration.config != null + if (mappingConfiguration.config != null && mappingConfiguration.config.randomizeWeights ) { - for (List prototypes : mappingConfiguration.typeDistributions.values()) { + for (List prototypes : typeDistributions.values()) { randomizeWeights(rng, prototypes); } } @@ -426,6 +432,19 @@ CPrototype getPrototypeByName(String name) { return null; } + public List getTypeDistributionByName(String name) { + if (name == null) { + return Lists.newArrayList(); + } + + final List types = typeDistributions.get(name); + if (types != null) { + return types; + } + + return Lists.newArrayList(); + } + /** * This method handles a time advance called by the {@link MappingAmbassador}. * diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CPrototype.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CPrototype.java index cd61255cb..6d14da584 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CPrototype.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CPrototype.java @@ -15,6 +15,7 @@ package org.eclipse.mosaic.fed.mapping.config; +import org.eclipse.mosaic.fed.mapping.ambassador.weighting.Weighted; import org.eclipse.mosaic.lib.enums.LaneChangeMode; import org.eclipse.mosaic.lib.enums.SpeedMode; import org.eclipse.mosaic.lib.enums.VehicleClass; @@ -31,7 +32,7 @@ *

* If these values are not defined some default values might be applied depending on prototype type. */ -public class CPrototype { +public class CPrototype implements Weighted { /** * The name of this prototype. This identifier is used to match it against @@ -147,6 +148,10 @@ public class CPrototype { */ public CParameterDeviations deviations; + @Override + public double getWeight() { + return weight; + } /** * Creates a copy of this prototype. @@ -202,5 +207,4 @@ public String toString() { + ", applications: " + (applications != null ? applications : "null") + "]"; } - } diff --git a/fed/mosaic-mapping/src/test/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassadorTest.java b/fed/mosaic-mapping/src/test/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassadorTest.java index f9621585a..2e4061de1 100644 --- a/fed/mosaic-mapping/src/test/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassadorTest.java +++ b/fed/mosaic-mapping/src/test/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassadorTest.java @@ -300,6 +300,27 @@ public void initializeWithMappingFile_scenarioVehicleRegistration() throws Excep Assert.assertNull(lastReceivedInteraction); } + @Test + public void initializeWithMappingFile_scenarioVehicleRegistrationWithTypeDistribution() throws Exception { + final MappingAmbassador ambassador = createMappingAmbassadorWithMappingFile("mapping_config.json"); + ambassador.initialize(0, 100 * TIME.SECOND); + + ambassador.processInteraction(new ScenarioVehicleRegistration(0, "veh_0", new VehicleType("myCarDistribution"))); + assertVehicleRegistration( + "package.appA" + ); + + ambassador.processInteraction(new ScenarioVehicleRegistration(0, "veh_0", new VehicleType("myCarDistribution"))); + assertVehicleRegistration( + "package.appA" + ); + + ambassador.processInteraction(new ScenarioVehicleRegistration(0, "veh_0", new VehicleType("myCarDistribution"))); + assertVehicleRegistration( + "package.appB" + ); + } + @Before public void setup() throws Throwable { when(rtiMock.createRandomNumberGenerator()).thenReturn(new DefaultRandomNumberGenerator(989123)); diff --git a/fed/mosaic-mapping/src/test/resources/mapping_config.json b/fed/mosaic-mapping/src/test/resources/mapping_config.json index 028f2a219..b1866dc44 100644 --- a/fed/mosaic-mapping/src/test/resources/mapping_config.json +++ b/fed/mosaic-mapping/src/test/resources/mapping_config.json @@ -1,49 +1,67 @@ { - "prototypes":[ - { - "name":"PKW", - "accel":2.6, - "decel":4.5, - "length":5.00, - "maxSpeed":70.0, - "minGap":2.5, - "sigma":0.5, - "tau":1 - }, - { - "name":"electricPKW", - "vehicleClass": "ElectricVehicle", - "applications":["org.eclipse.mosaic.app.examples.eventprocessing.sampling.HelloWorldApp", "org.eclipse.mosaic.app.examples.eventprocessing.sampling.IntervalSamplingApp"], - "accel":2.6, - "decel":4.5, - "length":5.00, - "maxSpeed":40.0, - "minGap":2.5, - "sigma":0.5, - "tau":1 - } - ], - "vehicles":[ - { - "startingTime": 5.0, - "targetFlow":1200, - "maxNumberVehicles": 120, - "route":"1", - "types":[ - { - "applications":["org.eclipse.mosaic.app.tutorials.barnim.WeatherWarningApp"], - "name":"PKW", - "weight":0.2 - }, - { - "name":"PKW", - "weight":0.7 - }, - { - "name":"electricPKW", - "weight":0.1 - } - ] - } - ] + "prototypes": [ + { + "name": "PKW", + "accel": 2.6, + "decel": 4.5, + "length": 5.00, + "maxSpeed": 70.0, + "minGap": 2.5, + "sigma": 0.5, + "tau": 1 + }, + { + "name": "electricPKW", + "vehicleClass": "ElectricVehicle", + "applications": [ + "org.eclipse.mosaic.app.examples.eventprocessing.sampling.HelloWorldApp", + "org.eclipse.mosaic.app.examples.eventprocessing.sampling.IntervalSamplingApp" + ], + "accel": 2.6, + "decel": 4.5, + "length": 5.00, + "maxSpeed": 40.0, + "minGap": 2.5, + "sigma": 0.5, + "tau": 1 + } + ], + "vehicles": [ + { + "startingTime": 5.0, + "targetFlow": 1200, + "maxNumberVehicles": 120, + "route": "1", + "types": [ + { + "applications": [ "org.eclipse.mosaic.app.tutorials.barnim.WeatherWarningApp" ], + "name": "PKW", + "weight": 0.2 + }, + { + "name": "PKW", + "weight": 0.7 + }, + { + "name": "electricPKW", + "weight": 0.1 + } + ] + } + ], + "typeDistributions": { + "myCarDistribution": [ + { + "name": "Car", + "group": "CarWithAppA", + "applications": [ "package.appA" ], + "weight": 60 + }, { + "name": "Car", + "group": "CarWithAppB", + "applications": [ "package.appB" ], + "weight": 40 + } + ] + } } From 358110e654e444fbd3d56250c6a3a5dd184ce768 Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Wed, 26 Jul 2023 08:54:04 +0200 Subject: [PATCH 2/8] feat(mapping): use type distributions in LuST scenario Signed-off-by: Karl Schrab --- .../scenarios/LuST/mapping/mapping_config.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json index 87ac75309..fee015614 100644 --- a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json +++ b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json @@ -42,5 +42,19 @@ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ] } - ] + ], + "typeDistributions": { + "bus": [ + { + "applications":[ + "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" + ], + "weight": 0.5 + }, + { + "applications":[], + "weight": 0.5 + } + ] + } } \ No newline at end of file From 45682e41beee5cadc792a67cae18b109b2b26ca7 Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Wed, 26 Jul 2023 08:55:30 +0200 Subject: [PATCH 3/8] clean: reformated LuST mapping Signed-off-by: Karl Schrab --- .../LuST/mapping/mapping_config.json | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json index fee015614..d205abcef 100644 --- a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json +++ b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json @@ -1,58 +1,53 @@ { - "prototypes":[ - { - "name":"passenger1", - "applications":[ + "prototypes": [ + { + "name": "passenger1", + "applications": [ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ] - }, + }, { - "name":"passenger2a", - "applications":[ - + "name": "passenger2a", + "applications": [ ] - }, + }, { - "name":"passenger2b", - "applications":[ - + "name": "passenger2b", + "applications": [ ] - }, + }, { - "name":"passenger3", - "applications":[ - + "name": "passenger3", + "applications": [ ] - }, + }, { - "name":"passenger4", - "applications":[ - + "name": "passenger4", + "applications": [ ] - }, + }, { - "name":"passenger5", - "applications":[ - + "name": "passenger5", + "applications": [ ] - }, + }, { - "name":"bus", - "applications":[ + "name": "bus", + "applications": [ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ] - } - ], + } + ], "typeDistributions": { "bus": [ { - "applications":[ + "applications": [ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ], "weight": 0.5 }, { - "applications":[], + "applications": [ ], "weight": 0.5 } ] From cd09d16661acbb2f9830aa0abba264e482a0d920 Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Wed, 26 Jul 2023 08:56:16 +0200 Subject: [PATCH 4/8] clean: removed old bus type from LuST mapping Signed-off-by: Karl Schrab --- .../resources/scenarios/LuST/mapping/mapping_config.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json index d205abcef..4e008c146 100644 --- a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json +++ b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json @@ -30,12 +30,6 @@ "name": "passenger5", "applications": [ ] - }, - { - "name": "bus", - "applications": [ - "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" - ] } ], "typeDistributions": { From 77432e37b0f430f71035f05ad8b899f077c22b9b Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Wed, 26 Jul 2023 09:07:28 +0200 Subject: [PATCH 5/8] clean(mapping): minor cleanup of SpawningFramework Signed-off-by: Karl Schrab --- .../mapping/ambassador/SpawningFramework.java | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java index eff4da93e..9d71842a6 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java @@ -175,74 +175,22 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration, } } + // Store type-distributions if (mappingConfiguration.typeDistributions != null) { - SpawningFramework.this.typeDistributions.putAll(mappingConfiguration.typeDistributions); + typeDistributions.putAll(mappingConfiguration.typeDistributions); } // randomize weights in type-distributions - if (mappingConfiguration.config != null - && mappingConfiguration.config.randomizeWeights - ) { + if (mappingConfiguration.config != null && mappingConfiguration.config.randomizeWeights) { for (List prototypes : typeDistributions.values()) { randomizeWeights(rng, prototypes); } } // Vehicle Spawners - boolean flowNoise = mappingConfiguration.config != null && mappingConfiguration.config.randomizeFlows; boolean spawnersExist = false; if (mappingConfiguration.vehicles != null) { - // A remainder after one scaling is always less than 1. - // If after some scalings remainderSum became more than 1, - // we add one to maxNumberVehicles of the current vehicle spawner and subtract one from remainderSum, - // getting back to less than 1 value. - double remainderSum = 0; - double scaleTraffic = mappingConfiguration.config != null ? mappingConfiguration.config.scaleTraffic : 1d; - for (CVehicle vehicleConfiguration : mappingConfiguration.vehicles) { - - //The "continue" still can be called if the spawner exists but the value of - // maxNumberVehicles was explicitly set to 0 in the mapping - //(convenient for testing of different mapping variations) - if (vehicleConfiguration == null - || (vehicleConfiguration.maxNumberVehicles != null - && vehicleConfiguration.maxNumberVehicles == 0)) { - continue; - } - if (vehicleConfiguration.maxNumberVehicles == null) { - vehicleConfiguration.maxNumberVehicles = Integer.MAX_VALUE; - } - spawnersExist = true; - - if ((Math.abs(scaleTraffic - 1.0) > 0.0001d)) { - if (vehicleConfiguration.maxNumberVehicles != Integer.MAX_VALUE) { - double numberOfVehiclesScaled = vehicleConfiguration.maxNumberVehicles * scaleTraffic; - remainderSum += (numberOfVehiclesScaled) - (int) numberOfVehiclesScaled; - - vehicleConfiguration.maxNumberVehicles = (int) (Math.floor(numberOfVehiclesScaled) + Math.floor(remainderSum)); - remainderSum -= Math.floor(remainderSum); - } - vehicleConfiguration.targetFlow = Math.round(vehicleConfiguration.targetFlow * scaleTraffic); - } - - if (mappingConfiguration.typeDistributions != null) { - vehicleConfiguration.types = replaceWithTypesFromPredefinedDistribution( - vehicleConfiguration, - mappingConfiguration.typeDistributions, - rng - ); - } - - if (config != null && config.adjustStartingTimes && config.start != null) { - vehicleConfiguration.startingTime = vehicleConfiguration.startingTime - config.start; - if (vehicleConfiguration.maxTime != null) { - vehicleConfiguration.maxTime = vehicleConfiguration.maxTime - config.start; - } - } - - if (vehicleConfiguration.startingTime >= 0) { - vehicleFlowGenerators.add(new VehicleFlowGenerator(vehicleConfiguration, rng, flowNoise)); - } - } + spawnersExist = generateVehicleFlows(mappingConfiguration.vehicles, mappingConfiguration.config, rng); } if (mappingConfiguration.vehicles == null || !spawnersExist) { @@ -259,6 +207,7 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration, } } + boolean flowNoise = mappingConfiguration.config != null && mappingConfiguration.config.randomizeFlows; for (OriginDestinationVehicleFlowGenerator mapper : matrices) { mapper.generateVehicleStreams(this, rng, flowNoise); } @@ -320,9 +269,60 @@ private void randomizeWeights(RandomNumberGenerator rng, List types) } } + private boolean generateVehicleFlows(List vehicles, CMappingConfiguration config, RandomNumberGenerator rng) { + // A remainder after one scaling is always less than 1. + // If after some scalings remainderSum became more than 1, + // we add one to maxNumberVehicles of the current vehicle spawner and subtract one from remainderSum, + // getting back to less than 1 value. + boolean spawnersExist = false; + double remainderSum = 0; + double scaleTraffic = config != null ? config.scaleTraffic : 1d; + for (CVehicle vehicleConfiguration : vehicles) { + + //The "continue" still can be called if the spawner exists but the value of + // maxNumberVehicles was explicitly set to 0 in the mapping + //(convenient for testing of different mapping variations) + if (vehicleConfiguration == null + || (vehicleConfiguration.maxNumberVehicles != null + && vehicleConfiguration.maxNumberVehicles == 0)) { + continue; + } + if (vehicleConfiguration.maxNumberVehicles == null) { + vehicleConfiguration.maxNumberVehicles = Integer.MAX_VALUE; + } + spawnersExist = true; + + if ((Math.abs(scaleTraffic - 1.0) > 0.0001d)) { + if (vehicleConfiguration.maxNumberVehicles != Integer.MAX_VALUE) { + double numberOfVehiclesScaled = vehicleConfiguration.maxNumberVehicles * scaleTraffic; + remainderSum += (numberOfVehiclesScaled) - (int) numberOfVehiclesScaled; + + vehicleConfiguration.maxNumberVehicles = (int) (Math.floor(numberOfVehiclesScaled) + Math.floor(remainderSum)); + remainderSum -= Math.floor(remainderSum); + } + vehicleConfiguration.targetFlow = Math.round(vehicleConfiguration.targetFlow * scaleTraffic); + } + + vehicleConfiguration.types = replaceWithTypesFromPredefinedDistribution( + vehicleConfiguration, rng + ); + + if (config != null && config.adjustStartingTimes && config.start != null) { + vehicleConfiguration.startingTime = vehicleConfiguration.startingTime - config.start; + if (vehicleConfiguration.maxTime != null) { + vehicleConfiguration.maxTime = vehicleConfiguration.maxTime - config.start; + } + } + + if (vehicleConfiguration.startingTime >= 0) { + vehicleFlowGenerators.add(new VehicleFlowGenerator(vehicleConfiguration, rng, config != null && config.randomizeFlows)); + } + } + return spawnersExist; + } + - private List replaceWithTypesFromPredefinedDistribution( - CVehicle spawner, Map> typeDistributions, RandomNumberGenerator rng) { + private List replaceWithTypesFromPredefinedDistribution(CVehicle spawner, RandomNumberGenerator rng) { // return distribution given by typeDistribution if (spawner.typeDistribution != null) { return new ArrayList<>(typeDistributions.get(spawner.typeDistribution)); From 12e95163ef80d893f34dab75607420780572b100 Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Fri, 28 Jul 2023 17:22:05 +0200 Subject: [PATCH 6/8] clean(mapping): avoid instantiation of selectors using map cache Signed-off-by: Karl Schrab --- .../mapping/ambassador/MappingAmbassador.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java index 6f8022532..af11305d9 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java @@ -33,7 +33,9 @@ import org.apache.commons.lang3.ObjectUtils; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.annotation.Nonnull; /** @@ -56,7 +58,8 @@ public class MappingAmbassador extends AbstractFederateAmbassador { /** * Read the CMappingAmbassador from the configuration. */ - private CMappingAmbassador mappingAmbassadorConfiguration; + private final CMappingAmbassador mappingAmbassadorConfiguration; + /** * Pointer to save the {@link ScenarioTrafficLightRegistration} when it arrives too early. @@ -65,6 +68,11 @@ public class MappingAmbassador extends AbstractFederateAmbassador { private RandomNumberGenerator randomNumberGenerator; + /** + * Cache stochastic selectors to avoid unnecessary instantiations. + */ + private final Map> typeDistributionSelectors = new HashMap<>(); + /** * Constructor for the {@link MappingAmbassador}. * @@ -126,7 +134,12 @@ private void handleInteraction(ScenarioVehicleRegistration scenarioVehicle) thro final List typeDistribution = framework.getTypeDistributionByName(scenarioVehicle.getVehicleType().getName()); if (!typeDistribution.isEmpty()) { - final CPrototype selected = new StochasticSelector<>(typeDistribution, randomNumberGenerator).nextItem(); + StochasticSelector selector = typeDistributionSelectors.get(scenarioVehicle.getVehicleType().getName()); + if (selector == null) { + selector = new StochasticSelector<>(typeDistribution, randomNumberGenerator); + typeDistributionSelectors.put(scenarioVehicle.getVehicleType().getName(), selector); + } + final CPrototype selected = selector.nextItem(); sendVehicleRegistrationForScenarioVehicle(scenarioVehicle, selected.group, selected.applications); } else { final CPrototype prototype = framework.getPrototypeByName(scenarioVehicle.getVehicleType().getName()); @@ -197,6 +210,7 @@ public void initialize(long startTime, long endTime) throws InternalFederateExce // enriched with functionality) framework = new SpawningFramework(mappingAmbassadorConfiguration, scenarioTrafficLightRegistration, rti, randomNumberGenerator); + typeDistributionSelectors.clear(); // Send out the VehicleTypesInitialization, publishing information // about the different vehicle types in the simulation rti.triggerInteraction(framework.generateVehicleTypesInitialization()); From 12213b1f21d113b235935f679c639a0066da198d Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Mon, 31 Jul 2023 11:01:25 +0200 Subject: [PATCH 7/8] feat(mapping): reuse predefined prototype, added integration test for Sievekingplatz Signed-off-by: Karl Schrab --- .../mapping/mapping_config.json | 15 ++++- .../mapping/ambassador/MappingAmbassador.java | 9 ++- .../mosaic/test/ReleaseSievekingplatzIT.java | 57 +++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 test/mosaic-integration-tests/src/test/java/org/eclipse/mosaic/test/ReleaseSievekingplatzIT.java diff --git a/bundle/src/assembly/resources/scenarios/Sievekingplatz/mapping/mapping_config.json b/bundle/src/assembly/resources/scenarios/Sievekingplatz/mapping/mapping_config.json index 5e26817bb..77057ce2a 100644 --- a/bundle/src/assembly/resources/scenarios/Sievekingplatz/mapping/mapping_config.json +++ b/bundle/src/assembly/resources/scenarios/Sievekingplatz/mapping/mapping_config.json @@ -5,6 +5,7 @@ }, { "name": "Bike", + "weight": 0.8, "applications": [ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ] }, { @@ -13,10 +14,22 @@ }, { "name": "Bus", - "weight": 0.4, "applications": [ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ] } ], + "typeDistributions": { + "Bus": [ + { + "name": "Bus", + "weight": 0.4 + }, + { + "name": "Bus", + "weight": 0.6, + "applications": [ ] + } + ] + }, "vehicles": [ { "startingTime": "10.0 s", diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java index af11305d9..98f2d62a7 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/MappingAmbassador.java @@ -99,7 +99,7 @@ public MappingAmbassador(AmbassadorParameter ambassadorParameter) { @Override protected void processInteraction(Interaction interaction) throws InternalFederateException { try { - log.info("processInteraction(): " + interaction.getClass().getCanonicalName()); + log.debug("processInteraction(): " + interaction.getTypeId()); if (interaction.getTypeId().equals(ScenarioTrafficLightRegistration.TYPE_ID)) { handleInteraction((ScenarioTrafficLightRegistration) interaction); } else if (interaction.getTypeId().equals(ScenarioVehicleRegistration.TYPE_ID)) { @@ -140,7 +140,12 @@ private void handleInteraction(ScenarioVehicleRegistration scenarioVehicle) thro typeDistributionSelectors.put(scenarioVehicle.getVehicleType().getName(), selector); } final CPrototype selected = selector.nextItem(); - sendVehicleRegistrationForScenarioVehicle(scenarioVehicle, selected.group, selected.applications); + final CPrototype predefined = framework.getPrototypeByName(selected.name); + sendVehicleRegistrationForScenarioVehicle(scenarioVehicle, + // use group/application list from predefined type, if not defined in type distribution + selected.group == null && predefined != null ? predefined.group : selected.group, + selected.applications == null && predefined != null ? predefined.applications : selected.applications + ); } else { final CPrototype prototype = framework.getPrototypeByName(scenarioVehicle.getVehicleType().getName()); if (prototype == null) { diff --git a/test/mosaic-integration-tests/src/test/java/org/eclipse/mosaic/test/ReleaseSievekingplatzIT.java b/test/mosaic-integration-tests/src/test/java/org/eclipse/mosaic/test/ReleaseSievekingplatzIT.java new file mode 100644 index 000000000..f0ca70e95 --- /dev/null +++ b/test/mosaic-integration-tests/src/test/java/org/eclipse/mosaic/test/ReleaseSievekingplatzIT.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 Fraunhofer FOKUS and others. All rights reserved. + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contact: mosaic@fokus.fraunhofer.de + */ + +package org.eclipse.mosaic.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.eclipse.mosaic.starter.MosaicSimulation; +import org.eclipse.mosaic.test.junit.LogAssert; +import org.eclipse.mosaic.test.junit.MosaicSimulationRule; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +public class ReleaseSievekingplatzIT { + + @ClassRule + public static MosaicSimulationRule simulationRule = new MosaicSimulationRule(); + + private static MosaicSimulation.SimulationResult simulationResult; + + @BeforeClass + public static void runSimulation() { + simulationResult = simulationRule.executeReleaseScenario("Sievekingplatz"); + } + + @Test + public void executionSuccessful() { + assertNull(simulationResult.exception); + assertTrue(simulationResult.success); + } + + @Test + public void deployAppForOnlyOneOfTwoBusses() throws Exception { + assertEquals(2, LogAssert.count(simulationRule, "Mapping.log", + ".*Mapping Scenario Vehicle.* type=Bus.*" + )); + assertEquals(1, LogAssert.count(simulationRule, "Mapping.log", + ".*Mapping Scenario Vehicle.* type=Bus.*, apps=\\[org.*" + )); + } +} From d728d45faa29ffbd575903f2a3241b33509de6f7 Mon Sep 17 00:00:00 2001 From: Karl Schrab Date: Mon, 31 Jul 2023 11:25:45 +0200 Subject: [PATCH 8/8] fix: fixed invalid mapping_config of LuST scenario Signed-off-by: Karl Schrab --- .../resources/scenarios/LuST/mapping/mapping_config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json index 4e008c146..0afd9204c 100644 --- a/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json +++ b/bundle/src/assembly/resources/scenarios/LuST/mapping/mapping_config.json @@ -35,12 +35,14 @@ "typeDistributions": { "bus": [ { + "name": "bus", "applications": [ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ], "weight": 0.5 }, { + "name": "bus", "applications": [ ], "weight": 0.5 }