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: introducing SensorModule to provide access to environmental events #418

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class EmergencyBrakeApp extends ConfigurableApplication<CEmergencyBrakeAp
@Override
public void onStartup() {
getOs().getAdHocModule().enable();
getOs().getSensorModule().getEnvironmentSensor().enable();
}

/**
Expand All @@ -67,7 +68,8 @@ public void onStartup() {
@Override
public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull VehicleData updatedVehicleData) {

boolean obstacleDetected = getOs().getStateOfEnvironmentSensor(SensorType.OBSTACLE) > 0;
boolean obstacleDetected = getOs().getSensorModule().getEnvironmentSensor().getSensorData()
.strengthOf(SensorType.OBSTACLE) > 0;

// Initiate emergency brake if obstacle is detected
if (obstacleDetected && !emergencyBrake) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.eclipse.mosaic.fed.application.app.api.os.VehicleOperatingSystem;
import org.eclipse.mosaic.interactions.communication.V2xMessageTransmission;
import org.eclipse.mosaic.lib.enums.AdHocChannel;
import org.eclipse.mosaic.lib.enums.SensorType;
import org.eclipse.mosaic.lib.objects.vehicle.VehicleData;
import org.eclipse.mosaic.lib.util.scheduling.Event;

Expand Down Expand Up @@ -57,11 +56,6 @@ public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull
final List<? extends Application> applications = getOs().getApplications();
final IntraVehicleMsg message = new IntraVehicleMsg(getOs().getId(), getRandom().nextInt(0, MAX_ID));

// Example usage for how to detect sensor readings
if (getOs().getStateOfEnvironmentSensor(SensorType.OBSTACLE) > 0) {
getLog().infoSimTime(this, "Reading sensor");
}

for (Application application : applications) {
final Event event = new Event(getOs().getSimulationTime() + 10, application, message);
this.getOs().getEventManager().addEvent(event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@
package org.eclipse.mosaic.app.tutorial;

import org.eclipse.mosaic.fed.application.app.AbstractApplication;
import org.eclipse.mosaic.fed.application.app.api.VehicleApplication;
import org.eclipse.mosaic.fed.application.app.api.os.VehicleOperatingSystem;
import org.eclipse.mosaic.fed.application.app.api.sensor.EnvironmentSensorData;
import org.eclipse.mosaic.lib.enums.SensorType;
import org.eclipse.mosaic.lib.objects.vehicle.VehicleData;
import org.eclipse.mosaic.lib.util.scheduling.Event;
import org.eclipse.mosaic.rti.TIME;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
* This application shall induce vehicles to slow down in hazardous environments.
* In onVehicleUpdated() the application requests new data from a vehicle's
Expand All @@ -35,22 +31,19 @@
* within a specified time frame. After the respective vehicle has left the dangerous
* zone, its speed will no longer be reduced.
*/
public class SlowDownApp extends AbstractApplication<VehicleOperatingSystem> implements VehicleApplication {
public class SlowDownApp extends AbstractApplication<VehicleOperatingSystem> {

private final static float SPEED = 25 / 3.6f;

private boolean hazardousArea = false;

/**
* This method is used to request new data from the sensors and in that case
* react on the retrieved data.
* It is called at each simulation step when the vehicle info has been updated for
* the vehicle that has this application equipped.
*/
@Override
public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull VehicleData updatedVehicleData) {
public void onStartup() {
getOs().getSensorModule().getEnvironmentSensor().enable();
getOs().getSensorModule().getEnvironmentSensor().reactOnSensorDataUpdate(this::onEnvironmentSensorUpdate);
}

// Enumeration of possible environment sensor types that are available in a vehicle
private void onEnvironmentSensorUpdate(EnvironmentSensorData environmentSensorData) {
SensorType[] types = SensorType.values();

// Initialize sensor strength
Expand All @@ -63,7 +56,7 @@ public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull
*/
for (SensorType currentType : types) {
// The strength of a detected sensor
strength = getOs().getStateOfEnvironmentSensor(currentType);
strength = environmentSensorData.strengthOf(currentType);

if (strength > 0) {
break;
Expand All @@ -81,19 +74,13 @@ public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull
getOs().resetSpeed();
hazardousArea = false;
}

}

@Override
public void processEvent(Event event) throws Exception {

}

@Override
public void onStartup() {

}

@Override
public void onShutdown() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,13 @@ private Denm constructDenm() {
final GeoCircle geoCircle = new GeoCircle(HAZARD_LOCATION, 3000.0D);
final MessageRouting routing = getOs().getCellModule().createMessageRouting().geoBroadcastBasedOnUnicast(geoCircle);

final int strength = getOs().getStateOfEnvironmentSensor(SENSOR_TYPE);

return new Denm(routing,
new DenmContent(
getOs().getSimulationTime(),
null,
HAZARD_ROAD,
SENSOR_TYPE,
strength,
0,
SPEED,
0.0f,
HAZARD_LOCATION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public void onStartup() {
getLog().infoSimTime(this, "Activated AdHoc Module");
}

getOs().getSensorModule().getEnvironmentSensor().enable();

getOs().requestVehicleParametersUpdate()
.changeColor(Color.RED)
.apply();
Expand Down Expand Up @@ -137,28 +139,19 @@ public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull
* This method is used to request new data from the sensors and, in case of new data, react on it.
*/
private void detectSensors() {
// Enumeration of possible environment sensor types that are available in a vehicle
SensorType[] types = SensorType.values();

// Initialize sensor type
SensorType type = null;
// Initialize sensor strength
int strength = 0;

/*
* The current strength of each environment sensor is examined here.
* If one is higher than zero, we reason that we are in a hazardous area with the
* given hazard.
*/
for (SensorType currentType : types) {
for (SensorType currentType : SensorType.values()) {

// The strength of a detected sensor
strength = getOs().getStateOfEnvironmentSensor(currentType);
int strength = getOs().getSensorModule().getEnvironmentSensor().getSensorData().strengthOf(currentType);

if (strength > 0) {
type = currentType;
// Method which is called to react on new or changed environment events
reactOnEnvironmentData(type, strength);
reactOnEnvironmentData(currentType, strength);
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.AdHocModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage;
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.NavigationModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.sensor.DefaultSensorModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.sensor.EnvironmentSensor;
import org.eclipse.mosaic.fed.application.ambassador.util.UnitLogger;
import org.eclipse.mosaic.fed.application.app.api.os.VehicleOperatingSystem;
import org.eclipse.mosaic.fed.application.app.api.sensor.EnvironmentSensorData;
import org.eclipse.mosaic.lib.enums.SensorType;
import org.eclipse.mosaic.lib.objects.addressing.AdHocMessageRoutingBuilder;
import org.eclipse.mosaic.lib.objects.addressing.SourceAddressContainer;
Expand Down Expand Up @@ -66,6 +69,9 @@ public class WeatherWarningAppTest {
@Mock
private AdHocModule adHocModuleMock;

@Mock
private DefaultSensorModule sensorModuleMock;

@Before
public void setup() {
when(operatingSystem.getAdHocModule()).thenReturn(adHocModuleMock);
Expand All @@ -74,6 +80,11 @@ public void setup() {
mock(VehicleParameters.VehicleParametersChangeRequest.class);
when(operatingSystem.requestVehicleParametersUpdate()).thenReturn(vehicleParametersChangeRequestMock);
when(vehicleParametersChangeRequestMock.changeColor(any())).thenReturn(vehicleParametersChangeRequestMock);

// everytime a mock returns a mock a unicorn dies. I count 3 dead unicorns.
when(operatingSystem.getSensorModule()).thenReturn(sensorModuleMock);
when(sensorModuleMock.getEnvironmentSensor()).thenReturn(mock(EnvironmentSensor.class));
when(sensorModuleMock.getEnvironmentSensor().getSensorData()).thenReturn(mock(EnvironmentSensorData.class));
}

@Test
Expand Down Expand Up @@ -116,7 +127,7 @@ public void test_SwitchRouteIfDenmWasReceived() {
}

private void setSensor(SensorType sensorType, int value) {
when(operatingSystem.getStateOfEnvironmentSensor(same(sensorType))).thenReturn(value);
when(operatingSystem.getSensorModule().getEnvironmentSensor().getSensorData().strengthOf(same(sensorType))).thenReturn(value);
}

private void setupMessageRouting() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage;
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.CentralNavigationComponent;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.CentralPerceptionComponent;
import org.eclipse.mosaic.fed.application.ambassador.simulation.sensor.DefaultSensorModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.sensor.EnvironmentSensor;
import org.eclipse.mosaic.fed.application.ambassador.util.EventNicenessPriorityRegister;
import org.eclipse.mosaic.fed.application.app.api.MosaicApplication;
import org.eclipse.mosaic.fed.application.app.api.TrafficSignAwareApplication;
import org.eclipse.mosaic.fed.application.app.api.os.OperatingSystem;
import org.eclipse.mosaic.fed.application.app.api.os.modules.Sensible;
import org.eclipse.mosaic.fed.application.config.CApplicationAmbassador;
import org.eclipse.mosaic.interactions.application.ApplicationInteraction;
import org.eclipse.mosaic.interactions.application.SumoTraciResponse;
Expand Down Expand Up @@ -510,11 +512,11 @@ private void process(final V2xFullMessageReception v2xFullMessageReception) {

/**
* This function does not directly fire an event, but puts it in a environmentEvents-map (see {@link AbstractSimulationUnit}).
* Use {@link OperatingSystem#getStateOfEnvironmentSensor} to determine the state of a Sensor. Keep in mind, that
* Use {@link DefaultSensorModule#getEnvironmentSensor()} to to determine the state of a Sensor. Keep in mind, that
* the map only stores the latest {@link EnvironmentEvent} of a specific type and overwrites old values.
* <p>Events will not directly be removed from the map, but since events are mapped to their type, there
* can't be more members than there are SensorType's. Nonetheless, the map can be cleared using
* {@link AbstractSimulationUnit#cleanPastEnvironmentEvents()}, which is also invoked by {@link SimulationKernel#garbageCollection()}.
* can't be more members than there are SensorType's. Nonetheless, the map is cleared using
* {@link EnvironmentSensor#cleanPastEnvironmentEvents()}, which is invoked by {@link SimulationKernel#garbageCollection()}.
* </p>
*
* @param environmentSensorUpdates the Interaction of type EnvironmentSensorUpdates to be processed
Expand All @@ -523,7 +525,7 @@ private void process(final EnvironmentSensorUpdates environmentSensorUpdates) {
// store the sensor data immediately, the sensor event hold their intermittent time
final AbstractSimulationUnit simulationUnit = UnitSimulator.UnitSimulator.getUnitFromId(environmentSensorUpdates.getUnitId());
// we don't simulate vehicles without an application
if (simulationUnit == null) {
if (!(simulationUnit instanceof Sensible)) {
return;
}
for (EnvironmentEvent event : environmentSensorUpdates.getEvents()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.eclipse.mosaic.fed.application.ambassador.simulation.AbstractSimulationUnit;
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.CentralNavigationComponent;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.CentralPerceptionComponent;
import org.eclipse.mosaic.fed.application.ambassador.simulation.sensor.EnvironmentSensor;
import org.eclipse.mosaic.fed.application.app.api.os.modules.Sensible;
import org.eclipse.mosaic.fed.application.config.CApplicationAmbassador;
import org.eclipse.mosaic.interactions.communication.V2xMessageRemoval;
import org.eclipse.mosaic.lib.math.RandomNumberGenerator;
Expand Down Expand Up @@ -277,7 +279,7 @@ public Map<String, VehicleRoute> getRoutes() {
/**
* Registers a new route to the simulation kernel.
*
* @param id the id of the route
* @param id the id of the route
* @param route the {@link VehicleRoute} to register
*/
public void registerRoute(String id, VehicleRoute route) {
Expand Down Expand Up @@ -348,7 +350,10 @@ void garbageCollection() {
}
// clean past environment events
for (AbstractSimulationUnit simulationUnit : UnitSimulator.UnitSimulator.getAllUnits().values()) {
simulationUnit.cleanPastEnvironmentEvents();
if (simulationUnit instanceof Sensible sensible &&
sensible.getSensorModule().getEnvironmentSensor() instanceof EnvironmentSensor environmentSensor) {
environmentSensor.cleanPastEnvironmentEvents();
}
}

// is the garbage collection enabled?
Expand Down
Loading
Loading