Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mapping): configure type distributions for ScenarioVehicle #333

Merged
merged 8 commits into from
Jul 31, 2023
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
{
"prototypes":[
{
"name":"passenger1",
"applications":[
"org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp"
]
},
"prototypes": [
{
"name":"passenger2a",
"applications":[

"name": "passenger1",
"applications": [
"org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp"
]
},
},
{
"name":"passenger2b",
"applications":[

"name": "passenger2a",
"applications": [
]
},
},
{
"name":"passenger3",
"applications":[

"name": "passenger2b",
"applications": [
]
},
},
{
"name":"passenger4",
"applications":[

"name": "passenger3",
"applications": [
]
},
},
{
"name":"passenger5",
"applications":[

"name": "passenger4",
"applications": [
]
},
},
{
"name":"bus",
"applications":[
"org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp"
"name": "passenger5",
"applications": [
]
}
]
}
],
"typeDistributions": {
"bus": [
{
"name": "bus",
"applications": [
"org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp"
],
"weight": 0.5
},
{
"name": "bus",
"applications": [ ],
"weight": 0.5
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
},
{
"name": "Bike",
"weight": 0.8,
"applications": [ "org.eclipse.mosaic.app.tutorial.eventprocessing.sampling.HelloWorldApp" ]
},
{
Expand All @@ -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",
Expand Down
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,9 @@

import org.apache.commons.lang3.ObjectUtils;

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

/**
Expand All @@ -54,7 +58,8 @@ public class MappingAmbassador extends AbstractFederateAmbassador {
/**
* Read the <code>CMappingAmbassador</code> from the configuration.
*/
private CMappingAmbassador mappingAmbassadorConfiguration;
private final CMappingAmbassador mappingAmbassadorConfiguration;


/**
* Pointer to save the {@link ScenarioTrafficLightRegistration} when it arrives too early.
Expand All @@ -63,6 +68,11 @@ public class MappingAmbassador extends AbstractFederateAmbassador {

private RandomNumberGenerator randomNumberGenerator;

/**
* Cache stochastic selectors to avoid unnecessary instantiations.
*/
private final Map<String, StochasticSelector<CPrototype>> typeDistributionSelectors = new HashMap<>();

/**
* Constructor for the {@link MappingAmbassador}.
*
Expand All @@ -89,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)) {
Expand Down Expand Up @@ -121,46 +131,69 @@ 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
final List<CPrototype> typeDistribution = framework.getTypeDistributionByName(scenarioVehicle.getVehicleType().getName());
if (!typeDistribution.isEmpty()) {
StochasticSelector<CPrototype> 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();
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
);
return;
} else {
final CPrototype prototype = framework.getPrototypeByName(scenarioVehicle.getVehicleType().getName());
if (prototype == null) {
schwepmo marked this conversation as resolved.
Show resolved Hide resolved
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 All @@ -182,6 +215,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());
Expand Down
Loading
Loading