Skip to content

Commit c352cf4

Browse files
authored
feat(app): introduce new LiDAR module (#440)
* 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
1 parent 6650436 commit c352cf4

File tree

6 files changed

+237
-6
lines changed

6 files changed

+237
-6
lines changed

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ buildNumber.properties
6262

6363
# MOSAIC
6464

65-
tmp/
6665
*.log
6766
credentials.cached
68-
*.lcs
67+
*.lcs
68+
.tiles

fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage;
2323
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.CentralNavigationComponent;
2424
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.CentralPerceptionComponent;
25+
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.DefaultLidarSensorModule;
2526
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.EnvironmentBasicSensorModule;
2627
import org.eclipse.mosaic.fed.application.ambassador.util.EventNicenessPriorityRegister;
2728
import org.eclipse.mosaic.fed.application.app.api.MosaicApplication;
@@ -37,6 +38,7 @@
3738
import org.eclipse.mosaic.interactions.electricity.VehicleBatteryUpdates;
3839
import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial;
3940
import org.eclipse.mosaic.interactions.environment.EnvironmentSensorUpdates;
41+
import org.eclipse.mosaic.interactions.environment.LidarUpdates;
4042
import org.eclipse.mosaic.interactions.mapping.ChargingStationRegistration;
4143
import org.eclipse.mosaic.interactions.mapping.RsuRegistration;
4244
import org.eclipse.mosaic.interactions.mapping.ServerRegistration;
@@ -298,6 +300,8 @@ protected void processInteraction(final Interaction interaction) throws Internal
298300
this.process((TrafficLightUpdates) interaction);
299301
} else if (interaction.getTypeId().startsWith(VehicleUpdates.TYPE_ID)) {
300302
this.process((VehicleUpdates) interaction);
303+
} else if (interaction.getTypeId().startsWith(LidarUpdates.TYPE_ID)) {
304+
this.process((LidarUpdates) interaction);
301305
} else if (interaction.getTypeId().startsWith(VehicleBatteryUpdates.TYPE_ID)) {
302306
this.process((VehicleBatteryUpdates) interaction);
303307
} else if (interaction.getTypeId().startsWith(VehicleRoutesInitialization.TYPE_ID)) {
@@ -524,8 +528,8 @@ private void process(final EnvironmentSensorUpdates environmentSensorUpdates) {
524528
// store the sensor data immediately, the sensor event hold their intermittent time
525529
final AbstractSimulationUnit simulationUnit = UnitSimulator.UnitSimulator.getUnitFromId(environmentSensorUpdates.getUnitId());
526530
// we don't simulate vehicles without application or correct environment sensor implementation
527-
if (!(simulationUnit instanceof Perceptive sensible) ||
528-
!(sensible.getBasicSensorModule() instanceof EnvironmentBasicSensorModule sensor)) {
531+
if (!(simulationUnit instanceof Perceptive sensible)
532+
|| !(sensible.getBasicSensorModule() instanceof EnvironmentBasicSensorModule sensor)) {
529533
return;
530534
}
531535
for (EnvironmentEvent event : environmentSensorUpdates.getEvents()) {
@@ -693,6 +697,26 @@ private void process(final VehicleUpdates vehicleUpdates) {
693697
addEvent(triggerGarbageCollection);
694698
}
695699

700+
private void process(final LidarUpdates lidarUpdates) {
701+
for (LidarUpdates.LidarUpdate lidarUpdate : lidarUpdates.getUpdated()) {
702+
final AbstractSimulationUnit simulationUnit = UnitSimulator.UnitSimulator.getUnitFromId(lidarUpdate.unitId());
703+
704+
// we don't simulate vehicles without application or correct lidar sensor implementation
705+
if (!(simulationUnit instanceof Perceptive sensible)
706+
|| !(sensible.getLidarSensorModule() instanceof DefaultLidarSensorModule sensor)) {
707+
return;
708+
}
709+
710+
final Event event = new Event(
711+
lidarUpdates.getTime(),
712+
e -> sensor.updatePointCloud(lidarUpdate.pointCloud()),
713+
null,
714+
EventNicenessPriorityRegister.LIDAR_UPDATED
715+
);
716+
addEvent(event);
717+
}
718+
}
719+
696720
private void addVehicleIfNotYetAdded(long time, String unitName) {
697721
final VehicleRegistration vehicleRegistration = vehicleRegistrations.remove(unitName);
698722
if (vehicleRegistration != null) {

fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/VehicleUnit.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.CamBuilder;
2121
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.RoadPositionFactory;
2222
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.RoutingNavigationModule;
23+
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.DefaultLidarSensorModule;
2324
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.EnvironmentBasicSensorModule;
2425
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.NopPerceptionModule;
2526
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.PerceptionModuleOwner;
@@ -69,6 +70,9 @@ public class VehicleUnit extends AbstractSimulationUnit implements VehicleOperat
6970
@Nonnull
7071
private final BasicSensorModule basicSensorModule;
7172

73+
@Nonnull
74+
private final LidarSensorModule lidarSensorModule;
75+
7276
@Nonnull
7377
private VehicleParameters vehicleParameters;
7478

@@ -99,6 +103,7 @@ public VehicleUnit(String vehicleName, VehicleType vehicleType, final GeoPoint i
99103
}
100104

101105
basicSensorModule = new EnvironmentBasicSensorModule();
106+
lidarSensorModule = new DefaultLidarSensorModule(this.getId());
102107
}
103108

104109
@Override
@@ -111,7 +116,7 @@ private void refineRoadPosition() {
111116
}
112117

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

384389
@Override
385390
public LidarSensorModule getLidarSensorModule() {
386-
throw new UnsupportedOperationException("Not yet implemented");
391+
return lidarSensorModule;
387392
}
388393
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright (c) 2024 Fraunhofer FOKUS and others. All rights reserved.
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information regarding copyright ownership.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*
13+
* Contact: [email protected]
14+
*/
15+
16+
package org.eclipse.mosaic.fed.application.ambassador.simulation.perception;
17+
18+
import org.eclipse.mosaic.fed.application.ambassador.SimulationKernel;
19+
import org.eclipse.mosaic.fed.application.app.api.perception.LidarSensorModule;
20+
import org.eclipse.mosaic.interactions.vehicle.VehicleSensorActivation;
21+
import org.eclipse.mosaic.lib.spatial.PointCloud;
22+
import org.eclipse.mosaic.rti.api.IllegalValueException;
23+
import org.eclipse.mosaic.rti.api.InternalFederateException;
24+
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
import java.util.function.Consumer;
28+
29+
public class DefaultLidarSensorModule implements LidarSensorModule {
30+
31+
private boolean enabled;
32+
private final String unitId;
33+
34+
private PointCloud currentPointcloud;
35+
private final List<Consumer<PointCloud>> callbacks = new ArrayList<>();
36+
37+
public DefaultLidarSensorModule(String unitId) {
38+
this.unitId = unitId;
39+
}
40+
41+
@Override
42+
public void enable(double range) {
43+
this.enabled = true;
44+
45+
// Create a VehicleSensorActivation interaction to be sent to the RTI
46+
VehicleSensorActivation interaction = new VehicleSensorActivation(
47+
SimulationKernel.SimulationKernel.getCurrentSimulationTime(),
48+
unitId,
49+
range,
50+
VehicleSensorActivation.SensorType.LIDAR
51+
);
52+
53+
// Send the interaction to the RTI, thereby enabling the LiDAR sensor
54+
try {
55+
SimulationKernel.SimulationKernel.getInteractable().triggerInteraction(interaction);
56+
} catch (IllegalValueException | InternalFederateException ex) {
57+
throw new RuntimeException(ex);
58+
}
59+
}
60+
61+
@Override
62+
public boolean isEnabled() {
63+
return enabled;
64+
}
65+
66+
@Override
67+
public void disable() {
68+
this.enabled = false;
69+
70+
// Create a VehicleSensorActivation interaction to be sent to the RTI that disables the LiDAR sensor
71+
VehicleSensorActivation interaction = new VehicleSensorActivation(
72+
SimulationKernel.SimulationKernel.getCurrentSimulationTime(),
73+
unitId,
74+
0,
75+
VehicleSensorActivation.SensorType.LIDAR
76+
);
77+
78+
// Send the interaction to the RTI, thereby disabling the LiDAR sensor
79+
try {
80+
SimulationKernel.SimulationKernel.getInteractable().triggerInteraction(interaction);
81+
} catch (IllegalValueException | InternalFederateException ex) {
82+
throw new RuntimeException(ex);
83+
}
84+
}
85+
86+
@Override
87+
public void reactOnSensorUpdate(Consumer<PointCloud> callback) {
88+
this.callbacks.add(callback);
89+
}
90+
91+
@Override
92+
public PointCloud getPointCloud() {
93+
if (!enabled) {
94+
return null;
95+
}
96+
return this.currentPointcloud;
97+
}
98+
99+
/**
100+
* This method is called by the ApplicationAmbassador when it received new LidarUpdates from the federate.
101+
* It sets the most current pointcloud to the one received and triggers the callback for every application that set one.
102+
* @param pointCloud The most current pointcloud.
103+
*/
104+
public void updatePointCloud(PointCloud pointCloud) {
105+
this.currentPointcloud = pointCloud;
106+
for (Consumer<PointCloud> callback : callbacks) {
107+
callback.accept(pointCloud);
108+
}
109+
}
110+
}

fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class EventNicenessPriorityRegister {
2424
public final static long VEHICLE_ADDED = -99_999_900;
2525
public final static long VEHICLE_UPDATED = -99_999_800;
2626
public final static long VEHICLE_REMOVED = -99_999_700;
27+
public final static long LIDAR_UPDATED = -99_999_650;
2728

2829
// update traffic detectors
2930
public final static long UPDATE_TRAFFIC_DETECTORS = -99_999_600;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2024 Fraunhofer FOKUS and others. All rights reserved.
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information regarding copyright ownership.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*
13+
* Contact: [email protected]
14+
*/
15+
16+
package org.eclipse.mosaic.interactions.environment;
17+
18+
import static org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE;
19+
20+
import org.eclipse.mosaic.lib.spatial.PointCloud;
21+
import org.eclipse.mosaic.rti.api.Interaction;
22+
23+
import org.apache.commons.lang3.builder.EqualsBuilder;
24+
import org.apache.commons.lang3.builder.HashCodeBuilder;
25+
import org.apache.commons.lang3.builder.ToStringBuilder;
26+
27+
import java.io.Serializable;
28+
import java.util.List;
29+
import java.util.stream.Collectors;
30+
31+
public class LidarUpdates extends Interaction implements Serializable {
32+
33+
public record LidarUpdate(String unitId, PointCloud pointCloud) implements Serializable {}
34+
35+
private static final long serialVersionUID = 1L;
36+
37+
/**
38+
* String identifying the type of this interaction.
39+
*/
40+
public final static String TYPE_ID = createTypeIdentifier(LidarUpdates.class);
41+
42+
/**
43+
* List of {@link PointCloud} containing LiDAR data from the simulator.
44+
*/
45+
private List<LidarUpdate> updated;
46+
47+
public LidarUpdates(long time, List<LidarUpdate> updated) {
48+
super(time);
49+
this.updated = updated;
50+
}
51+
52+
public List<LidarUpdate> getUpdated() {
53+
return this.updated;
54+
}
55+
56+
@Override
57+
public int hashCode() {
58+
return new HashCodeBuilder(5, 17)
59+
.append(updated)
60+
.toHashCode();
61+
}
62+
63+
@Override
64+
public boolean equals(Object obj) {
65+
if (obj == null) {
66+
return false;
67+
}
68+
if (obj == this) {
69+
return true;
70+
}
71+
if (obj.getClass() != getClass()) {
72+
return false;
73+
}
74+
75+
LidarUpdates other = (LidarUpdates) obj;
76+
return new EqualsBuilder()
77+
.append(this.updated, other.updated)
78+
.isEquals();
79+
}
80+
81+
@Override
82+
public String toString() {
83+
return new ToStringBuilder(this, SHORT_PREFIX_STYLE)
84+
.appendSuper(super.toString())
85+
.append("updated", "Updated LiDAR data for vehicles ["
86+
+ this.updated.stream().map(LidarUpdate::unitId).collect(Collectors.joining(", ")) + "]")
87+
.toString();
88+
}
89+
90+
}
91+

0 commit comments

Comments
 (0)