Skip to content

Commit

Permalink
feat(mapping): configure type distributions for ScenarioVehicle
Browse files Browse the repository at this point in the history
allows defining multiple application types for equal vehicle type names in large sumo scenario

Signed-off-by: Karl Schrab <[email protected]>
  • Loading branch information
kschrab committed Jul 25, 2023
1 parent bcee4f6 commit e40ca0f
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -32,6 +33,7 @@

import org.apache.commons.lang3.ObjectUtils;

import java.util.List;
import javax.annotation.Nonnull;

/**
Expand Down Expand Up @@ -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<CPrototype> 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<String> 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -65,6 +66,7 @@ public class SpawningFramework {
private static final Logger LOG = LoggerFactory.getLogger(SpawningFramework.class);

private final List<CPrototype> prototypeConfigurations = new ArrayList<>();
private final Map<String, List<CPrototype>> typeDistributions = new HashMap<>();
private final Map<String, TrafficLightSpawner> tls = new HashMap<>();
private final List<VehicleFlowGenerator> vehicleFlowGenerators = new ArrayList<>();
private final List<RoadSideUnitSpawner> rsus = new ArrayList<>();
Expand Down Expand Up @@ -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<CPrototype> prototypes : mappingConfiguration.typeDistributions.values()) {
for (List<CPrototype> prototypes : typeDistributions.values()) {
randomizeWeights(rng, prototypes);
}
}
Expand Down Expand Up @@ -426,6 +432,19 @@ CPrototype getPrototypeByName(String name) {
return null;
}

public List<CPrototype> getTypeDistributionByName(String name) {
if (name == null) {
return Lists.newArrayList();
}

final List<CPrototype> types = typeDistributions.get(name);
if (types != null) {
return types;
}

return Lists.newArrayList();
}

/**
* This method handles a time advance called by the {@link MappingAmbassador}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,7 +32,7 @@
* <p/>
* 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
Expand Down Expand Up @@ -147,6 +148,10 @@ public class CPrototype {
*/
public CParameterDeviations deviations;

@Override
public double getWeight() {
return weight;
}

/**
* Creates a copy of this prototype.
Expand Down Expand Up @@ -202,5 +207,4 @@ public String toString() {
+ ", applications: " + (applications != null ? applications : "null")
+ "]";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
112 changes: 65 additions & 47 deletions fed/mosaic-mapping/src/test/resources/mapping_config.json
Original file line number Diff line number Diff line change
@@ -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
}
]
}
}

0 comments on commit e40ca0f

Please sign in to comment.