Skip to content

Commit

Permalink
feat(app): introduce new LiDAR module (#440)
Browse files Browse the repository at this point in the history
* feat: Added LidarData and LidarUpdates
* feat: Added new LidarUpdates interaction to ApplicationAmbassador
* feat(module): Added new DefaultLidarSensorModule and interaction functionality

Note: to use this, a simulator which produces LiDAR point clouds is required, such as Carla or PHABMACS
  • Loading branch information
FunKuchen authored Dec 10, 2024
1 parent 6650436 commit c352cf4
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 6 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ buildNumber.properties

# MOSAIC

tmp/
*.log
credentials.cached
*.lcs
*.lcs
.tiles
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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.perception.DefaultLidarSensorModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.EnvironmentBasicSensorModule;
import org.eclipse.mosaic.fed.application.ambassador.util.EventNicenessPriorityRegister;
import org.eclipse.mosaic.fed.application.app.api.MosaicApplication;
Expand All @@ -37,6 +38,7 @@
import org.eclipse.mosaic.interactions.electricity.VehicleBatteryUpdates;
import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial;
import org.eclipse.mosaic.interactions.environment.EnvironmentSensorUpdates;
import org.eclipse.mosaic.interactions.environment.LidarUpdates;
import org.eclipse.mosaic.interactions.mapping.ChargingStationRegistration;
import org.eclipse.mosaic.interactions.mapping.RsuRegistration;
import org.eclipse.mosaic.interactions.mapping.ServerRegistration;
Expand Down Expand Up @@ -298,6 +300,8 @@ protected void processInteraction(final Interaction interaction) throws Internal
this.process((TrafficLightUpdates) interaction);
} else if (interaction.getTypeId().startsWith(VehicleUpdates.TYPE_ID)) {
this.process((VehicleUpdates) interaction);
} else if (interaction.getTypeId().startsWith(LidarUpdates.TYPE_ID)) {
this.process((LidarUpdates) interaction);
} else if (interaction.getTypeId().startsWith(VehicleBatteryUpdates.TYPE_ID)) {
this.process((VehicleBatteryUpdates) interaction);
} else if (interaction.getTypeId().startsWith(VehicleRoutesInitialization.TYPE_ID)) {
Expand Down Expand Up @@ -524,8 +528,8 @@ 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 application or correct environment sensor implementation
if (!(simulationUnit instanceof Perceptive sensible) ||
!(sensible.getBasicSensorModule() instanceof EnvironmentBasicSensorModule sensor)) {
if (!(simulationUnit instanceof Perceptive sensible)
|| !(sensible.getBasicSensorModule() instanceof EnvironmentBasicSensorModule sensor)) {
return;
}
for (EnvironmentEvent event : environmentSensorUpdates.getEvents()) {
Expand Down Expand Up @@ -693,6 +697,26 @@ private void process(final VehicleUpdates vehicleUpdates) {
addEvent(triggerGarbageCollection);
}

private void process(final LidarUpdates lidarUpdates) {
for (LidarUpdates.LidarUpdate lidarUpdate : lidarUpdates.getUpdated()) {
final AbstractSimulationUnit simulationUnit = UnitSimulator.UnitSimulator.getUnitFromId(lidarUpdate.unitId());

// we don't simulate vehicles without application or correct lidar sensor implementation
if (!(simulationUnit instanceof Perceptive sensible)
|| !(sensible.getLidarSensorModule() instanceof DefaultLidarSensorModule sensor)) {
return;
}

final Event event = new Event(
lidarUpdates.getTime(),
e -> sensor.updatePointCloud(lidarUpdate.pointCloud()),
null,
EventNicenessPriorityRegister.LIDAR_UPDATED
);
addEvent(event);
}
}

private void addVehicleIfNotYetAdded(long time, String unitName) {
final VehicleRegistration vehicleRegistration = vehicleRegistrations.remove(unitName);
if (vehicleRegistration != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.CamBuilder;
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.RoadPositionFactory;
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.RoutingNavigationModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.DefaultLidarSensorModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.EnvironmentBasicSensorModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.NopPerceptionModule;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.PerceptionModuleOwner;
Expand Down Expand Up @@ -69,6 +70,9 @@ public class VehicleUnit extends AbstractSimulationUnit implements VehicleOperat
@Nonnull
private final BasicSensorModule basicSensorModule;

@Nonnull
private final LidarSensorModule lidarSensorModule;

@Nonnull
private VehicleParameters vehicleParameters;

Expand Down Expand Up @@ -99,6 +103,7 @@ public VehicleUnit(String vehicleName, VehicleType vehicleType, final GeoPoint i
}

basicSensorModule = new EnvironmentBasicSensorModule();
lidarSensorModule = new DefaultLidarSensorModule(this.getId());
}

@Override
Expand All @@ -111,7 +116,7 @@ private void refineRoadPosition() {
}

private void updateVehicleInfo(final VehicleData currentVehicleData) {
VehicleData previousVehicleData = getVehicleData();
final VehicleData previousVehicleData = getVehicleData();
// set the new vehicle info reference
navigationModule.setVehicleData(currentVehicleData);
// and don't forget to set the new position from the vehicle info
Expand Down Expand Up @@ -383,6 +388,6 @@ public BasicSensorModule getBasicSensorModule() {

@Override
public LidarSensorModule getLidarSensorModule() {
throw new UnsupportedOperationException("Not yet implemented");
return lidarSensorModule;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* 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: [email protected]
*/

package org.eclipse.mosaic.fed.application.ambassador.simulation.perception;

import org.eclipse.mosaic.fed.application.ambassador.SimulationKernel;
import org.eclipse.mosaic.fed.application.app.api.perception.LidarSensorModule;
import org.eclipse.mosaic.interactions.vehicle.VehicleSensorActivation;
import org.eclipse.mosaic.lib.spatial.PointCloud;
import org.eclipse.mosaic.rti.api.IllegalValueException;
import org.eclipse.mosaic.rti.api.InternalFederateException;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class DefaultLidarSensorModule implements LidarSensorModule {

private boolean enabled;
private final String unitId;

private PointCloud currentPointcloud;
private final List<Consumer<PointCloud>> callbacks = new ArrayList<>();

public DefaultLidarSensorModule(String unitId) {
this.unitId = unitId;
}

@Override
public void enable(double range) {
this.enabled = true;

// Create a VehicleSensorActivation interaction to be sent to the RTI
VehicleSensorActivation interaction = new VehicleSensorActivation(
SimulationKernel.SimulationKernel.getCurrentSimulationTime(),
unitId,
range,
VehicleSensorActivation.SensorType.LIDAR
);

// Send the interaction to the RTI, thereby enabling the LiDAR sensor
try {
SimulationKernel.SimulationKernel.getInteractable().triggerInteraction(interaction);
} catch (IllegalValueException | InternalFederateException ex) {
throw new RuntimeException(ex);
}
}

@Override
public boolean isEnabled() {
return enabled;
}

@Override
public void disable() {
this.enabled = false;

// Create a VehicleSensorActivation interaction to be sent to the RTI that disables the LiDAR sensor
VehicleSensorActivation interaction = new VehicleSensorActivation(
SimulationKernel.SimulationKernel.getCurrentSimulationTime(),
unitId,
0,
VehicleSensorActivation.SensorType.LIDAR
);

// Send the interaction to the RTI, thereby disabling the LiDAR sensor
try {
SimulationKernel.SimulationKernel.getInteractable().triggerInteraction(interaction);
} catch (IllegalValueException | InternalFederateException ex) {
throw new RuntimeException(ex);
}
}

@Override
public void reactOnSensorUpdate(Consumer<PointCloud> callback) {
this.callbacks.add(callback);
}

@Override
public PointCloud getPointCloud() {
if (!enabled) {
return null;
}
return this.currentPointcloud;
}

/**
* This method is called by the ApplicationAmbassador when it received new LidarUpdates from the federate.
* It sets the most current pointcloud to the one received and triggers the callback for every application that set one.
* @param pointCloud The most current pointcloud.
*/
public void updatePointCloud(PointCloud pointCloud) {
this.currentPointcloud = pointCloud;
for (Consumer<PointCloud> callback : callbacks) {
callback.accept(pointCloud);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class EventNicenessPriorityRegister {
public final static long VEHICLE_ADDED = -99_999_900;
public final static long VEHICLE_UPDATED = -99_999_800;
public final static long VEHICLE_REMOVED = -99_999_700;
public final static long LIDAR_UPDATED = -99_999_650;

// update traffic detectors
public final static long UPDATE_TRAFFIC_DETECTORS = -99_999_600;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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: [email protected]
*/

package org.eclipse.mosaic.interactions.environment;

import static org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE;

import org.eclipse.mosaic.lib.spatial.PointCloud;
import org.eclipse.mosaic.rti.api.Interaction;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;

public class LidarUpdates extends Interaction implements Serializable {

public record LidarUpdate(String unitId, PointCloud pointCloud) implements Serializable {}

private static final long serialVersionUID = 1L;

/**
* String identifying the type of this interaction.
*/
public final static String TYPE_ID = createTypeIdentifier(LidarUpdates.class);

/**
* List of {@link PointCloud} containing LiDAR data from the simulator.
*/
private List<LidarUpdate> updated;

public LidarUpdates(long time, List<LidarUpdate> updated) {
super(time);
this.updated = updated;
}

public List<LidarUpdate> getUpdated() {
return this.updated;
}

@Override
public int hashCode() {
return new HashCodeBuilder(5, 17)
.append(updated)
.toHashCode();
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}

LidarUpdates other = (LidarUpdates) obj;
return new EqualsBuilder()
.append(this.updated, other.updated)
.isEquals();
}

@Override
public String toString() {
return new ToStringBuilder(this, SHORT_PREFIX_STYLE)
.appendSuper(super.toString())
.append("updated", "Updated LiDAR data for vehicles ["
+ this.updated.stream().map(LidarUpdate::unitId).collect(Collectors.joining(", ")) + "]")
.toString();
}

}

0 comments on commit c352cf4

Please sign in to comment.