Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into 899-sensor-module
Browse files Browse the repository at this point in the history
# Conflicts:
#	app/tutorials/traffic-light-communication/src/main/java/org/eclipse/mosaic/app/tutorial/EventSendingApp.java
#	app/tutorials/weather-warning/src/main/java/org/eclipse/mosaic/app/tutorial/WeatherServerApp.java
#	app/tutorials/weather-warning/src/main/java/org/eclipse/mosaic/app/tutorial/WeatherWarningApp.java
#	fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/AbstractSimulationUnit.java
  • Loading branch information
kschrab committed Oct 2, 2024
2 parents 6d6a37a + 9d9d593 commit c55829d
Show file tree
Hide file tree
Showing 36 changed files with 922 additions and 792 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Additional simulators and assessment features are provided by [Fraunhofer FOKUS]
* The coupling to [OMNeT++](https://omnetpp.org) is implemented in a very similar manner. The corresponding federate implementation can be found [in our MOSAIC Addons repository](https://github.com/mosaic-addons/omnetpp-federate).
We currently support OMNeT++ version `5.5` in combination with the INET framework in version `4.1`.
* We created the [Berlin SUMO Traffic (BeST) scenario](https://github.com/mosaic-addons/best-scenario) which provides 2.2 million vehicle trips in 24h for Berlin, Germany. The scenario is fully compatible with the latest release of MOSAIC.
* In our research, we currently use Eclipse MOSAIC and the BeST scenario to evaluate traffic state estimation algorithms. For that, we provide [application models and tools for Traffic State Estimation](https://github.com/mosaic-addons/traffic-state-estimation) compatible with MOSAIC.

## Contact

Expand All @@ -65,6 +66,9 @@ For further questions we are available via mosaic@fokus.fraunhofer.de

## Prerequisites

> [!IMPORTANT]
> **In contrast to previous versions, Eclipse MOSAIC now requires at least Java 17 SDK.**
For a successful build you need the following software to be installed:

* **Maven 3.1.x** or higher.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,18 @@
package org.eclipse.mosaic.app.tutorial;

import org.eclipse.mosaic.app.tutorial.message.IntraVehicleMsg;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.AdHocModuleConfiguration;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.CamBuilder;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedAcknowledgement;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage;
import org.eclipse.mosaic.fed.application.app.AbstractApplication;
import org.eclipse.mosaic.fed.application.app.api.Application;
import org.eclipse.mosaic.fed.application.app.api.CommunicationApplication;
import org.eclipse.mosaic.fed.application.app.api.VehicleApplication;
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.objects.vehicle.VehicleData;
import org.eclipse.mosaic.lib.util.scheduling.Event;

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

public class EventSendingApp extends AbstractApplication<VehicleOperatingSystem> implements VehicleApplication, CommunicationApplication {
public class EventSendingApp extends AbstractApplication<VehicleOperatingSystem> implements VehicleApplication {
/**
* Used for choosing a RAND id for the message that is sent intra-vehicle.
*/
Expand All @@ -43,12 +36,6 @@ public class EventSendingApp extends AbstractApplication<VehicleOperatingSystem>
@Override
public void onStartup() {
getLog().infoSimTime(this, "Initialize application");
getOs().getAdHocModule().enable(new AdHocModuleConfiguration()
.addRadio()
.channel(AdHocChannel.CCH)
.power(50)
.create());
getLog().infoSimTime(this, "Activated AdHoc Module");
}

@Override
Expand All @@ -62,31 +49,13 @@ public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull
}
}

@Override
public void onMessageReceived(ReceivedV2xMessage receivedV2xMessage) {
getLog().infoSimTime(this, "Received V2X Message from {}", receivedV2xMessage.getMessage().getRouting().getSource().getSourceName());
}

@Override
public void processEvent(Event event) throws Exception {
getLog().infoSimTime(this, "Received event: {}", getOs().getSimulationTimeMs(), event.getResourceClassSimpleName());
getLog().infoSimTime(this, "Received event: {}", event.getResourceClassSimpleName());
}

@Override
public void onShutdown() {
getLog().infoSimTime(this, "Shutdown application");
}

@Override
public void onAcknowledgementReceived(ReceivedAcknowledgement acknowledgedMessage) {
}

@Override
public void onCamBuilding(CamBuilder camBuilder) {
}

@Override
public void onMessageTransmitted(V2xMessageTransmission v2xMessageTransmission) {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2024 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.app.tutorial;

import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.AdHocModuleConfiguration;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.CamBuilder;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedAcknowledgement;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage;
import org.eclipse.mosaic.fed.application.app.AbstractApplication;
import org.eclipse.mosaic.fed.application.app.api.CommunicationApplication;
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.util.scheduling.Event;

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

public class MessageReceivingApp extends AbstractApplication<VehicleOperatingSystem> implements CommunicationApplication {

@Override
public void onStartup() {
getLog().infoSimTime(this, "Initialize application");
getOs().getAdHocModule().enable(new AdHocModuleConfiguration()
.addRadio()
.channel(AdHocChannel.CCH)
.power(50)
.create());
getLog().infoSimTime(this, "Activated AdHoc Module");
}

@Override
public void onShutdown() {
getLog().infoSimTime(this, "Shutdown application");
}

@Override
public void processEvent(Event event) throws Exception {
getLog().infoSimTime(this, "Received event: {}", event.getResourceClassSimpleName());
}

@Override
public void onMessageReceived(ReceivedV2xMessage receivedV2xMessage) {
getLog().infoSimTime(this, "Received V2X Message from {}", receivedV2xMessage.getMessage().getRouting().getSource().getSourceName());
}

@Override
public void onAcknowledgementReceived(ReceivedAcknowledgement acknowledgedMessage) {
}

@Override
public void onCamBuilding(CamBuilder camBuilder) {
}

@Override
public void onMessageTransmitted(V2xMessageTransmission v2xMessageTransmission) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@

package org.eclipse.mosaic.app.tutorial;

import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.CamBuilder;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedAcknowledgement;
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage;
import org.eclipse.mosaic.fed.application.app.AbstractApplication;
import org.eclipse.mosaic.fed.application.app.api.CommunicationApplication;
import org.eclipse.mosaic.fed.application.app.api.os.ServerOperatingSystem;
import org.eclipse.mosaic.interactions.communication.V2xMessageTransmission;
import org.eclipse.mosaic.lib.enums.SensorType;
import org.eclipse.mosaic.lib.geo.GeoCircle;
import org.eclipse.mosaic.lib.geo.GeoPoint;
import org.eclipse.mosaic.lib.objects.v2x.MessageRouting;
import org.eclipse.mosaic.lib.objects.v2x.V2xMessage;
import org.eclipse.mosaic.lib.objects.v2x.etsi.Denm;
import org.eclipse.mosaic.lib.objects.v2x.etsi.DenmContent;
import org.eclipse.mosaic.lib.util.scheduling.Event;
Expand All @@ -31,25 +37,18 @@
* about certain hazards on the road. The hazard is hard-coded for tutorial purposes,
* in more realistic scenarios the location would've been updated dynamically.
*/
public class WeatherServerApp extends AbstractApplication<ServerOperatingSystem> {
public class WeatherServerApp extends AbstractApplication<ServerOperatingSystem> implements CommunicationApplication {

/**
* Send hazard location at this interval, in seconds.
* Send warning at this interval, in seconds.
*/
private final static long INTERVAL = 2 * TIME.SECOND;

/**
* Location of the hazard which causes the route change.
*/
private final static GeoPoint HAZARD_LOCATION = GeoPoint.latLon(52.633047, 13.565314);

/**
* Road ID where hazard is located.
* Save the last received DEN message for relaying.
*/
private final static String HAZARD_ROAD = "311964536_1313885442_2879911873";

private final static SensorType SENSOR_TYPE = SensorType.ICE;
private final static float SPEED = 25 / 3.6f;
private Denm lastReceivedMessage = null;


/**
Expand Down Expand Up @@ -87,10 +86,14 @@ public void processEvent(Event event) throws Exception {
* and thus the DENM is sent periodically at this interval.
*/
private void sample() {
final Denm denm = constructDenm(); // Construct exemplary DENM

getOs().getCellModule().sendV2xMessage(denm);
getLog().infoSimTime(this, "Sent DENM");
if (lastReceivedMessage == null) {
getLog().infoSimTime(this, "No warning present.");
} else {
final Denm denm = constructDenm();
getLog().debugSimTime(this, "{}", denm);
getOs().getCellModule().sendV2xMessage(denm);
getLog().infoSimTime(this, "Relayed last DENM");
}
// Line up new event for periodic sending
getOs().getEventManager().addEvent(
getOs().getSimulationTime() + INTERVAL, this
Expand All @@ -106,32 +109,65 @@ private void sample() {
* @return The constructed DENM
*/
private Denm constructDenm() {
final GeoCircle geoCircle = new GeoCircle(HAZARD_LOCATION, 3000.0D);
final GeoCircle geoCircle = new GeoCircle(lastReceivedMessage.getEventLocation(), 3000.0D);
final MessageRouting routing = getOs().getCellModule().createMessageRouting().geoBroadcastBasedOnUnicast(geoCircle);

return new Denm(routing,
new DenmContent(
getOs().getSimulationTime(),
null,
HAZARD_ROAD,
SENSOR_TYPE,
0,
SPEED,
0.0f,
HAZARD_LOCATION,
null,
null
lastReceivedMessage.getTime(),
lastReceivedMessage.getSenderPosition(),
lastReceivedMessage.getEventRoadId(),
lastReceivedMessage.getWarningType(),
lastReceivedMessage.getEventStrength(),
lastReceivedMessage.getCausedSpeed(),
lastReceivedMessage.getSenderDeceleration(),
lastReceivedMessage.getEventLocation(),
lastReceivedMessage.getEventArea(),
lastReceivedMessage.getExtendedContainer()
),
200
);
}

@Override
public void onMessageReceived(ReceivedV2xMessage receivedV2xMessage) {
final V2xMessage msg = receivedV2xMessage.getMessage();
getLog().infoSimTime(this, "Received {} from {}.",
msg.getSimpleClassName(),
msg.getRouting().getSource().getSourceName()
);
// Only DEN Messages are handled
if (!(msg instanceof Denm)) {
getLog().infoSimTime(this, "Ignoring message of type: {}", msg.getSimpleClassName());
return;
}
lastReceivedMessage = (Denm) msg;
getLog().debugSimTime(this, "DENM content: Sensor Type: {}", lastReceivedMessage.getWarningType().toString());
getLog().debugSimTime(this, "DENM content: Event position: {}", lastReceivedMessage.getEventLocation());
getLog().debugSimTime(this, "DENM content: Event Strength: {}", lastReceivedMessage.getEventStrength());
getLog().debugSimTime(this, "DENM content: Road Id of the Sender: {}", lastReceivedMessage.getEventRoadId());
}

@Override
public void onAcknowledgementReceived(ReceivedAcknowledgement acknowledgement) {

}

@Override
public void onCamBuilding(CamBuilder camBuilder) {

}

@Override
public void onMessageTransmitted(V2xMessageTransmission v2xMessageTransmission) {

}

/**
* This method is called by mosaic-application when the simulation has finished.
*/
@Override
public void onShutdown() {
getLog().infoSimTime(this, "Shutdown application");
getLog().infoSimTime(this, "Shutdown server.");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class WeatherWarningApp extends AbstractApplication<VehicleOperatingSyste
/**
* Flag that is set if the route has already been changed.
*/
private boolean routeChanged = false;
private boolean triedToChangeRoute = false;

/**
* This is the speed for the DEN message sent for rerouting.
Expand Down Expand Up @@ -110,17 +110,20 @@ public void onMessageReceived(ReceivedV2xMessage receivedV2xMessage) {
return;
}

// Message was received via cell from the WeatherServer
if (msg.getRouting().getSource().getSourceName().equals("server_0")) {
getLog().infoSimTime(this, "Received message from cell from WeatherServer");
// Message was received via cell from the WeatherServer
getLog().infoSimTime(this, "Received message over cell from WeatherServer");
}
else {
getLog().infoSimTime(this, "Received message from {}", msg.getRouting().getSource().getSourceName());
}

getLog().infoSimTime(this, "Processing DEN message");

getLog().debug("Handle Environment Warning Message. Processing...");

if (routeChanged) {
getLog().infoSimTime(this, "Route already changed");
if (triedToChangeRoute) {
getLog().infoSimTime(this, "Route change already tried once.");
} else {
reactUponDENMessageChangeRoute(denm);
}
Expand Down Expand Up @@ -152,7 +155,7 @@ private void detectSensors() {
if (strength > 0) {
// Method which is called to react on new or changed environment events
reactOnEnvironmentData(currentType, strength);
return;
return; // the early exit discards other possible environmental warnings, ok for this tutorial purpose
}
}

Expand Down Expand Up @@ -203,7 +206,7 @@ private void reactOnEnvironmentData(SensorType type, int strength) {
* with a builder and build a geoBroadCast for the circle area defined in dest.
*/
if (useCellNetwork()) {
mr = getOs().getCellModule().createMessageRouting().geoBroadcastBasedOnUnicast(dest);
mr = getOs().getCellModule().createMessageRouting().topoCast("server_0");
} else {
mr = getOs().getAdHocModule().createMessageRouting().geoBroadCast(dest);
}
Expand Down Expand Up @@ -249,10 +252,10 @@ private void reactUponDENMessageChangeRoute(Denm denm) {
// Retrieve only the connection id and throw away the edge id
// NOTE: a route info id has the format connectionId_edgeId
if (connection.equals(affectedConnectionId)) {
getLog().infoSimTime(this, "The Event is on the vehicle's route {} = {}", connection, affectedConnectionId);
getLog().infoSimTime(this, "The event occurred on connection with id={}, which is part of vehicle's route with id={}", connection, routeInfo.getId());

circumnavigateAffectedRoad(denm, affectedConnectionId);
routeChanged = true;
triedToChangeRoute = true;
return;
}
}
Expand Down Expand Up @@ -290,7 +293,7 @@ private void circumnavigateAffectedRoad(Denm denm, final String affectedRoadId)
*/
CandidateRoute newRoute = response.getBestRoute();
if (newRoute != null) {
getLog().infoSimTime(this, "Sending Change Route Command at position: {}", denm.getSenderPosition());
getLog().infoSimTime(this, "Sending Change Route Command at position: {}", getOs().getPosition());
navigationModule.switchRoute(newRoute);
}
}
Expand Down
Loading

0 comments on commit c55829d

Please sign in to comment.