From e934a582a5961c151c1319aa3729ad027801ad75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Wed, 11 Dec 2024 16:17:06 +0100 Subject: [PATCH 1/8] provide the charging stations within a certain area --- .gitignore | 3 +- .../ambassador/ApplicationAmbassador.java | 17 +++ .../simulation/ElectricVehicleUnit.java | 25 +++++ .../util/EventNicenessPriorityRegister.java | 3 + .../app/api/ElectricVehicleApplication.java | 3 + .../os/ElectricVehicleOperatingSystem.java | 8 ++ .../app/TestElectricVehicleApplication.java | 6 ++ .../app/empty/ElectricVehicleNoopApp.java | 6 ++ .../ChargingStationDiscoveryResponse.java | 99 +++++++++++++++++ ...ehicleChargingStationDiscoveryRequest.java | 101 ++++++++++++++++++ 10 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java create mode 100644 lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java diff --git a/.gitignore b/.gitignore index 9a893b9cb..47a931b09 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,5 @@ buildNumber.properties *.log credentials.cached *.lcs -.tiles \ No newline at end of file +.tiles +/logs/ diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java index cb8e8d787..7e91d6ede 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java @@ -34,6 +34,7 @@ import org.eclipse.mosaic.interactions.communication.V2xFullMessageReception; import org.eclipse.mosaic.interactions.communication.V2xMessageAcknowledgement; import org.eclipse.mosaic.interactions.communication.V2xMessageReception; +import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.ChargingStationUpdate; import org.eclipse.mosaic.interactions.electricity.VehicleBatteryUpdates; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; @@ -304,6 +305,8 @@ protected void processInteraction(final Interaction interaction) throws Internal this.process((LidarUpdates) interaction); } else if (interaction.getTypeId().startsWith(VehicleBatteryUpdates.TYPE_ID)) { this.process((VehicleBatteryUpdates) interaction); + } else if (interaction.getTypeId().startsWith(ChargingStationDiscoveryResponse.TYPE_ID)) { + this.process((ChargingStationDiscoveryResponse) interaction); } else if (interaction.getTypeId().startsWith(VehicleRoutesInitialization.TYPE_ID)) { this.process((VehicleRoutesInitialization) interaction); } else if (interaction.getTypeId().startsWith(VehicleTypesInitialization.TYPE_ID)) { @@ -335,6 +338,20 @@ private void process(final VehicleBatteryUpdates vehicleBatteryUpdates) { } } + + private void process(final ChargingStationDiscoveryResponse response) { + final AbstractSimulationUnit simulationUnit = UnitSimulator.UnitSimulator.getUnitFromId(response.getVehicleId()); + if (simulationUnit == null) { + return; + } + final Event event = new Event( + response.getTime(), + simulationUnit, + response, + EventNicenessPriorityRegister.CHARGING_STATIONS_DISCOVERY + ); + addEvent(event); + } private void process(final VehicleTypesInitialization vehicleTypesInitialization) { SimulationKernel.SimulationKernel.getVehicleTypes().putAll(vehicleTypesInitialization.getTypes()); } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java index 1a0c18bb7..16f8a0843 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java @@ -18,10 +18,16 @@ import org.eclipse.mosaic.fed.application.ambassador.SimulationKernel; import org.eclipse.mosaic.fed.application.app.api.ElectricVehicleApplication; import org.eclipse.mosaic.fed.application.app.api.os.ElectricVehicleOperatingSystem; +import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.interactions.electricity.VehicleChargingStartRequest; +import org.eclipse.mosaic.interactions.electricity.VehicleChargingStationDiscoveryRequest; import org.eclipse.mosaic.interactions.electricity.VehicleChargingStopRequest; +import org.eclipse.mosaic.lib.geo.GeoArea; +import org.eclipse.mosaic.lib.geo.GeoCircle; import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.geo.MutableGeoPoint; +import org.eclipse.mosaic.lib.geo.Polygon; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; import org.eclipse.mosaic.lib.objects.vehicle.VehicleType; @@ -51,6 +57,12 @@ private void onVehicleChargingDenial(final VehicleChargingDenial vehicleCharging } } + private void onCharginStationDiscoveryResponse(ChargingStationDiscoveryResponse response) { + for (ElectricVehicleApplication application: getApplicationsIterator(ElectricVehicleApplication.class)) { + application.onChargingStationDiscoveryResponse(response); + } + } + @Override protected boolean handleEventResource(Object resource, long eventType) { if (resource instanceof BatteryData data) { @@ -63,6 +75,11 @@ protected boolean handleEventResource(Object resource, long eventType) { return true; } + if (resource instanceof ChargingStationDiscoveryResponse response) { + onCharginStationDiscoveryResponse((ChargingStationDiscoveryResponse) response); + return true; + } + return super.handleEventResource(resource, eventType); } @@ -103,4 +120,12 @@ public void sendChargingStopRequest() { ); sendInteractionToRti(vehicleChargingStopRequest); } + + public void sendChargingStationDiscoveryRequest(GeoCircle searchArea) { + VehicleChargingStationDiscoveryRequest request = new VehicleChargingStationDiscoveryRequest( + this.getSimulationTime(), + this.getId(), + searchArea); + sendInteractionToRti(request); + } } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java index e0d8e8f8c..247f85e53 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java @@ -46,4 +46,7 @@ public class EventNicenessPriorityRegister { // batteryUpdated public final static long BATTERY_UPDATED = -99_998_900; + + // discover charging stations + public final static long CHARGING_STATIONS_DISCOVERY = -99_998_900; } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java index f9934d8a3..09a14a529 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java @@ -15,6 +15,7 @@ package org.eclipse.mosaic.fed.application.app.api; +import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; @@ -42,4 +43,6 @@ public interface ElectricVehicleApplication extends VehicleApplication, Applicat * @param vehicleChargingDenial The interaction containing further information about the rejected charging request */ void onVehicleChargingDenial(final VehicleChargingDenial vehicleChargingDenial); + + void onChargingStationDiscoveryResponse(ChargingStationDiscoveryResponse response); } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java index f8d5dc778..a8b92baa0 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java @@ -15,6 +15,7 @@ package org.eclipse.mosaic.fed.application.app.api.os; +import org.eclipse.mosaic.lib.geo.GeoCircle; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; import javax.annotation.Nullable; @@ -45,4 +46,11 @@ public interface ElectricVehicleOperatingSystem extends VehicleOperatingSystem { * Sends a request to stop charging the battery of the vehicle. */ void sendChargingStopRequest(); + + /** + * Sends a request to locate all charging stations in the provided area. + * + * @param searchArea The area where the charging stations are search + */ + void sendChargingStationDiscoveryRequest(GeoCircle searchArea); } diff --git a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java index bebf6e78a..1fc093349 100644 --- a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java +++ b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java @@ -25,6 +25,7 @@ import org.eclipse.mosaic.fed.application.app.empty.ElectricVehicleNoopApp; import org.eclipse.mosaic.interactions.application.ApplicationInteraction; import org.eclipse.mosaic.interactions.communication.V2xMessageTransmission; +import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.lib.objects.traffic.SumoTraciResult; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; @@ -108,6 +109,11 @@ public void onVehicleChargingDenial(VehicleChargingDenial vehicleChargingDenial) thisApplicationSpy.onVehicleChargingDenial(vehicleChargingDenial); } + @Override + public void onChargingStationDiscoveryResponse(ChargingStationDiscoveryResponse response) { + + } + @Override public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull VehicleData updatedVehicleData) { thisApplicationSpy.onVehicleUpdated(previousVehicleData, updatedVehicleData); diff --git a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java index 7838a6f3d..bfb10ec2c 100644 --- a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java +++ b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java @@ -25,6 +25,7 @@ import org.eclipse.mosaic.fed.application.app.api.os.ElectricVehicleOperatingSystem; import org.eclipse.mosaic.interactions.application.ApplicationInteraction; import org.eclipse.mosaic.interactions.communication.V2xMessageTransmission; +import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.lib.objects.traffic.SumoTraciResult; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; @@ -70,6 +71,11 @@ public void onBatteryDataUpdated(@Nullable BatteryData previousBatteryData, @Non public void onVehicleChargingDenial(VehicleChargingDenial vehicleChargingDenial) { } + @Override + public void onChargingStationDiscoveryResponse(ChargingStationDiscoveryResponse response) { + + } + @Override public void onAcknowledgementReceived(ReceivedAcknowledgement acknowledgedMessage) { } diff --git a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java new file mode 100644 index 000000000..f307ac6d9 --- /dev/null +++ b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java @@ -0,0 +1,99 @@ +/* + * 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.interactions.electricity; + +import static org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE; + +import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; +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.util.Collection; + +/** + * An {@link Interaction} that contains a list of {@link ChargingStationData} objects as a response to a {@link VehicleChargingStationDiscoveryRequest}. + */ +public class ChargingStationDiscoveryResponse extends Interaction { + public ChargingStationDiscoveryResponse(long time, String vehicleId, Collection chargingStations) { + super(time); + + this.chargingStations = chargingStations; + this.vehicleId = vehicleId; + } + + /** + * String identifying the type of this interaction. + */ + public static final String TYPE_ID = createTypeIdentifier(ChargingStationDiscoveryResponse.class); + + /** + * The queried list {@link ChargingStationData} originating from the {@link VehicleChargingStationDiscoveryRequest}. + */ + private final Collection chargingStations; + + /** + * The ID of the requesting vehicle. + */ + private final String vehicleId; + + public String getVehicleId() { + return vehicleId; + } + + public Collection getChargingStations() { + return chargingStations; + } + + @Override + public int hashCode() { + return new HashCodeBuilder(9, 97) + .append(vehicleId) + .append(chargingStations) + .toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + + ChargingStationDiscoveryResponse other = (ChargingStationDiscoveryResponse) obj; + return new EqualsBuilder() + .append(this.vehicleId, other.vehicleId) + .append(this.chargingStations, other.chargingStations) + .isEquals(); + } + + @Override + public String toString() { + return new ToStringBuilder(this, SHORT_PREFIX_STYLE) + .appendSuper(super.toString()) + .append("vehicleId", vehicleId) + .append("chargingStations", chargingStations.stream().map(ChargingStationData::toString)) + .toString(); + } + +} diff --git a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java new file mode 100644 index 000000000..1f71d7330 --- /dev/null +++ b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java @@ -0,0 +1,101 @@ +/* + * 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.interactions.electricity; + +import static org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE; + +import org.eclipse.mosaic.lib.geo.GeoCircle; +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.Serial; + +/** + * An {@link Interaction} used by electric vehicles to find charging stations ({@link org.eclipse.mosaic.lib.objects.electricity.ChargingStationData}) in a certain area. + */ +public class VehicleChargingStationDiscoveryRequest extends Interaction { + public VehicleChargingStationDiscoveryRequest(long time, String vehicleId, GeoCircle searchArea) { + super(time); + + this.vehicleId = vehicleId; + this.searchArea = searchArea; + } + + @Serial + private static final long serialVersionUID = 1L; + + /** + * String identifying the type of this interaction. + */ + public static final String TYPE_ID = createTypeIdentifier(VehicleChargingStationDiscoveryRequest.class); + + /** + * String identifying the vehicle sending this interaction. + */ + private final String vehicleId; + + /** + * An area given by a point and a radius in which the requested {@link org.eclipse.mosaic.lib.objects.electricity.ChargingStationData} objects are. + */ + private final GeoCircle searchArea; + + public String getVehicleId() { + return vehicleId; + } + + public GeoCircle getSearchArea() { + return searchArea; + } + + @Override + public int hashCode() { + return new HashCodeBuilder(9, 97) + .append(vehicleId) + .append(searchArea) + .toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + + VehicleChargingStationDiscoveryRequest other = (VehicleChargingStationDiscoveryRequest) obj; + return new EqualsBuilder() + .append(this.vehicleId, other.vehicleId) + .append(this.searchArea, other.searchArea) + .isEquals(); + } + + @Override + public String toString() { + return new ToStringBuilder(this, SHORT_PREFIX_STYLE) + .appendSuper(super.toString()) + .append("vehicleId", vehicleId) + .append("searchArea", searchArea) + .toString(); + } +} From 434bb9a20085dde5d5a25b5458661e15c608e15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Tue, 21 Jan 2025 13:00:54 +0100 Subject: [PATCH 2/8] ChargingStations discovery is synchronous (related to mosaic-extended#965) --- .../ambassador/ApplicationAmbassador.java | 32 +++--- .../application/ambassador/ErrorRegister.java | 3 + .../ambassador/SimulationKernel.java | 18 +++ .../simulation/ElectricVehicleUnit.java | 31 ++--- .../objects/ChargingStationObject.java | 107 ++++++++++++++++++ .../providers/ChargingStationIndex.java | 59 ++++++++++ .../providers/ChargingStationTree.java | 66 +++++++++++ .../app/api/ElectricVehicleApplication.java | 3 - .../os/ElectricVehicleOperatingSystem.java | 8 +- .../app/TestElectricVehicleApplication.java | 6 - .../app/empty/ElectricVehicleNoopApp.java | 6 - .../ChargingStationDiscoveryResponse.java | 99 ---------------- ...ehicleChargingStationDiscoveryRequest.java | 101 ----------------- .../electricity/ChargingStationData.java | 2 + 14 files changed, 284 insertions(+), 257 deletions(-) create mode 100644 fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java create mode 100644 fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java create mode 100644 fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java delete mode 100644 lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java delete mode 100644 lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java index 7e91d6ede..68db90b73 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java @@ -20,6 +20,8 @@ import org.eclipse.mosaic.fed.application.ambassador.simulation.TrafficLightGroupUnit; import org.eclipse.mosaic.fed.application.ambassador.simulation.TrafficManagementCenterUnit; import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage; +import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.providers.ChargingStationIndex; +import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.providers.ChargingStationTree; 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; @@ -34,7 +36,6 @@ import org.eclipse.mosaic.interactions.communication.V2xFullMessageReception; import org.eclipse.mosaic.interactions.communication.V2xMessageAcknowledgement; import org.eclipse.mosaic.interactions.communication.V2xMessageReception; -import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.ChargingStationUpdate; import org.eclipse.mosaic.interactions.electricity.VehicleBatteryUpdates; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; @@ -55,6 +56,7 @@ import org.eclipse.mosaic.interactions.traffic.VehicleUpdates; import org.eclipse.mosaic.interactions.trafficsigns.VehicleSeenTrafficSignsUpdate; import org.eclipse.mosaic.interactions.vehicle.VehicleRouteRegistration; +import org.eclipse.mosaic.lib.geo.GeoPoint; import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; import org.eclipse.mosaic.lib.objects.environment.EnvironmentEvent; import org.eclipse.mosaic.lib.objects.traffic.InductionLoopInfo; @@ -157,6 +159,12 @@ public ApplicationAmbassador(AmbassadorParameter ambassadorParameter) { SimulationKernel.SimulationKernel.setCentralPerceptionComponent(centralPerceptionComponent); } + if (SimulationKernel.SimulationKernel.chargingStationIndex == null) { + // use same bucketsize as TrafficLightTree (see: CPercetion.java) (bucketsize := number of direct children per tree node) + ChargingStationIndex chargingStationIndex = new ChargingStationTree(20); + SimulationKernel.SimulationKernel.setChargingStationIndex(chargingStationIndex); + } + // add all application jar files addJarFiles(); } @@ -305,8 +313,6 @@ protected void processInteraction(final Interaction interaction) throws Internal this.process((LidarUpdates) interaction); } else if (interaction.getTypeId().startsWith(VehicleBatteryUpdates.TYPE_ID)) { this.process((VehicleBatteryUpdates) interaction); - } else if (interaction.getTypeId().startsWith(ChargingStationDiscoveryResponse.TYPE_ID)) { - this.process((ChargingStationDiscoveryResponse) interaction); } else if (interaction.getTypeId().startsWith(VehicleRoutesInitialization.TYPE_ID)) { this.process((VehicleRoutesInitialization) interaction); } else if (interaction.getTypeId().startsWith(VehicleTypesInitialization.TYPE_ID)) { @@ -338,20 +344,6 @@ private void process(final VehicleBatteryUpdates vehicleBatteryUpdates) { } } - - private void process(final ChargingStationDiscoveryResponse response) { - final AbstractSimulationUnit simulationUnit = UnitSimulator.UnitSimulator.getUnitFromId(response.getVehicleId()); - if (simulationUnit == null) { - return; - } - final Event event = new Event( - response.getTime(), - simulationUnit, - response, - EventNicenessPriorityRegister.CHARGING_STATIONS_DISCOVERY - ); - addEvent(event); - } private void process(final VehicleTypesInitialization vehicleTypesInitialization) { SimulationKernel.SimulationKernel.getVehicleTypes().putAll(vehicleTypesInitialization.getTypes()); } @@ -380,6 +372,9 @@ private void process(final ServerRegistration serverRegistration) { private void process(final ChargingStationRegistration chargingStationRegistration) { UnitSimulator.UnitSimulator.registerChargingStation(chargingStationRegistration); + String id = chargingStationRegistration.getMapping().getName(); + GeoPoint position = chargingStationRegistration.getMapping().getPosition(); + SimulationKernel.SimulationKernel.chargingStationIndex.addChargingStation(id, position); } private void process(final TrafficLightRegistration trafficLightRegistration) { @@ -457,6 +452,8 @@ private void process(final ChargingStationUpdate chargingStationUpdate) { final AbstractSimulationUnit simulationUnit = UnitSimulator.UnitSimulator.getUnitFromId(chargingStationData.getName()); + SimulationKernel.SimulationKernel.chargingStationIndex.updateChargingStation(chargingStationUpdate.getUpdatedChargingStation()); + if (simulationUnit == null) { return; } @@ -466,6 +463,7 @@ private void process(final ChargingStationUpdate chargingStationUpdate) { chargingStationData, EventNicenessPriorityRegister.UPDATE_CHARGING_STATION ); + addEvent(event); } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ErrorRegister.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ErrorRegister.java index dac46e344..532f9dff6 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ErrorRegister.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ErrorRegister.java @@ -47,6 +47,9 @@ public enum ErrorRegister { SIMULATION_KERNEL_CentralNavigationComponentAlreadySet(0x01000029, "The CentralNavigationComponent was already set."), SIMULATION_KERNEL_CentralPerceptionComponentNotSet(0x01000200, "The CentralPerceptionComponent was not set."), SIMULATION_KERNEL_CentralPerceptionComponentAlreadySet(0x01000201, "The CentralPerceptionComponent was already set."), + SIMULATION_KERNEL_ChargingStationIndexAlreadySet(0x01000202, "The ChargingStationIndex was already set"), + SIMULATION_KERNEL_ChargingStationIndexNotSet(0x01000203, "The ChargingStationIndex was not set"), + // 0x01000030 to 0x0100003F unit simulator UNIT_SIMULATOR_IdAlreadyAssigned(0x01000030, "The id is already assigned."), UNIT_SIMULATOR_IdFromUnitIsNotInMap(0x01000031, "The unit with the id couldn't be found."), diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java index 6d815bab0..c594190b3 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java @@ -16,6 +16,7 @@ package org.eclipse.mosaic.fed.application.ambassador; import org.eclipse.mosaic.fed.application.ambassador.simulation.AbstractSimulationUnit; +import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.providers.ChargingStationIndex; 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.EnvironmentBasicSensorModule; @@ -94,6 +95,8 @@ public enum SimulationKernel { */ transient CentralPerceptionComponent centralPerceptionComponent; + transient ChargingStationIndex chargingStationIndex; + /** * Map containing all the routes with the corresponding edge-id's. */ @@ -259,6 +262,21 @@ public void setCentralPerceptionComponent(CentralPerceptionComponent centralPerc this.centralPerceptionComponent = centralPerceptionComponent; } + public void setChargingStationIndex(ChargingStationIndex chargingStationIndex) { + if (this.chargingStationIndex != null) { + throw new RuntimeException(ErrorRegister.SIMULATION_KERNEL_ChargingStationIndexAlreadySet.toString()); + } + + this.chargingStationIndex = chargingStationIndex; + } + + public ChargingStationIndex getChargingStationIndex() { + if (this.chargingStationIndex == null) { + throw new RuntimeException(ErrorRegister.SIMULATION_KERNEL_ChargingStationIndexNotSet.toString()); + } + + return this.chargingStationIndex; + } public CentralPerceptionComponent getCentralPerceptionComponent() { if (centralPerceptionComponent == null) { throw new RuntimeException(ErrorRegister.SIMULATION_KERNEL_CentralPerceptionComponentNotSet.toString()); diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java index 16f8a0843..72f818899 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java @@ -16,21 +16,21 @@ package org.eclipse.mosaic.fed.application.ambassador.simulation; import org.eclipse.mosaic.fed.application.ambassador.SimulationKernel; +import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.objects.ChargingStationObject; import org.eclipse.mosaic.fed.application.app.api.ElectricVehicleApplication; import org.eclipse.mosaic.fed.application.app.api.os.ElectricVehicleOperatingSystem; -import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.interactions.electricity.VehicleChargingStartRequest; -import org.eclipse.mosaic.interactions.electricity.VehicleChargingStationDiscoveryRequest; import org.eclipse.mosaic.interactions.electricity.VehicleChargingStopRequest; -import org.eclipse.mosaic.lib.geo.GeoArea; import org.eclipse.mosaic.lib.geo.GeoCircle; import org.eclipse.mosaic.lib.geo.GeoPoint; -import org.eclipse.mosaic.lib.geo.MutableGeoPoint; -import org.eclipse.mosaic.lib.geo.Polygon; +import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; import org.eclipse.mosaic.lib.objects.vehicle.VehicleType; +import java.util.List; +import java.util.stream.Collectors; + /** * This class represents an electric vehicle in the application simulator. It extends {@link VehicleUnit} * with further functionality. @@ -57,12 +57,6 @@ private void onVehicleChargingDenial(final VehicleChargingDenial vehicleCharging } } - private void onCharginStationDiscoveryResponse(ChargingStationDiscoveryResponse response) { - for (ElectricVehicleApplication application: getApplicationsIterator(ElectricVehicleApplication.class)) { - application.onChargingStationDiscoveryResponse(response); - } - } - @Override protected boolean handleEventResource(Object resource, long eventType) { if (resource instanceof BatteryData data) { @@ -75,11 +69,6 @@ protected boolean handleEventResource(Object resource, long eventType) { return true; } - if (resource instanceof ChargingStationDiscoveryResponse response) { - onCharginStationDiscoveryResponse((ChargingStationDiscoveryResponse) response); - return true; - } - return super.handleEventResource(resource, eventType); } @@ -121,11 +110,9 @@ public void sendChargingStopRequest() { sendInteractionToRti(vehicleChargingStopRequest); } - public void sendChargingStationDiscoveryRequest(GeoCircle searchArea) { - VehicleChargingStationDiscoveryRequest request = new VehicleChargingStationDiscoveryRequest( - this.getSimulationTime(), - this.getId(), - searchArea); - sendInteractionToRti(request); + public List getChargingStationsByArea(GeoCircle searchArea) { + return SimulationKernel.SimulationKernel.getChargingStationIndex().getChargingStationsInCircle(searchArea) + .stream().map(ChargingStationObject::getChargingStationData) + .collect(Collectors.toList()); } } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java new file mode 100644 index 000000000..af4a9c3d6 --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2025 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.fed.application.ambassador.simulation.electric.objects; + +import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.index.objects.PointBoundingBox; +import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.index.objects.SpatialObject; +import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.index.objects.SpatialObjectBoundingBox; +import org.eclipse.mosaic.lib.geo.CartesianPoint; +import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +public class ChargingStationObject extends SpatialObject { + /** + * The data object that stores all static and dynamic information of the charging station. + */ + private ChargingStationData chargingStationData; + + /** + * The bounding box of a charging station is represented by a single point. + */ + private transient PointBoundingBox boundingBox; + + public ChargingStationObject(String id) { + super(id); + } + + + public ChargingStationObject setChargingStationData(ChargingStationData chargingStationData) { + this.chargingStationData = chargingStationData; + return this; + } + + public ChargingStationData getChargingStationData() { + return chargingStationData; + } + + @Override + public ChargingStationObject setPosition(CartesianPoint position) { + cartesianPosition.set(position); + position.toVector3d(this); + return this; + } + + @Override + public SpatialObjectBoundingBox getBoundingBox() { + if (boundingBox == null) { + boundingBox = new PointBoundingBox(this); + } + return boundingBox; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + ChargingStationObject that = (ChargingStationObject) o; + + return new EqualsBuilder() + .appendSuper(super.equals(o)) + .append(chargingStationData, that.chargingStationData) + .append(boundingBox, that.boundingBox) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(5, 11) + .appendSuper(super.hashCode()) + .append(chargingStationData) + .toHashCode(); + } + + /** + * Returns a hard copy of the {@link ChargingStationObject}, this should be used + * when the data of a perceived traffic light is to be altered or stored in memory. + * + * @return a copy of the {@link ChargingStationObject} + */ + @Override + public ChargingStationObject copy() { + return new ChargingStationObject(getId()) + .setChargingStationData(chargingStationData) + .setPosition(getProjectedPosition()); + + } +} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java new file mode 100644 index 000000000..d35003448 --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 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.fed.application.ambassador.simulation.electric.providers; + +import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.objects.ChargingStationObject; +import org.eclipse.mosaic.lib.geo.GeoCircle; +import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class ChargingStationIndex { + + /** + * Stores {@link ChargingStationObject}s for fast removal and position update. + */ + final Map indexedChargingStations = new HashMap<>(); + + /** + * Method called to initialize index after configuration has been read. + */ + public abstract void initialize(); + + /** + * Perform action before an update of the {@link ChargingStationIndex} takes place. + */ + public abstract void onChargingStationUpdate(); + + public abstract int getNumberOfChargingStations(); + + public abstract List getChargingStationsInCircle(GeoCircle circle); + + public void addChargingStation(String id, GeoPoint position) { + indexedChargingStations.computeIfAbsent(id, ChargingStationObject::new) + .setPosition(position.toCartesian()); + } + + public void updateChargingStation(ChargingStationData chargingStationData) { + onChargingStationUpdate(); + indexedChargingStations.get(chargingStationData.getName()) + .setChargingStationData(chargingStationData); + } + +} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java new file mode 100644 index 000000000..86f7c51da --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 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.fed.application.ambassador.simulation.electric.providers; + +import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.objects.ChargingStationObject; +import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.index.objects.SpatialObjectAdapter; +import org.eclipse.mosaic.lib.geo.GeoCircle; +import org.eclipse.mosaic.lib.spatial.KdTree; +import org.eclipse.mosaic.lib.spatial.SpatialTreeTraverser; + +import java.util.ArrayList; +import java.util.List; + +/** + * {@link ChargingStationIndex} using a KD-Tree to store charging stations. + */ +public class ChargingStationTree extends ChargingStationIndex { + private final int bucketSize; + + private KdTree chargingStationTree; + + private SpatialTreeTraverser.InRadius treeTraverser; + + public ChargingStationTree(int bucketSize) { + this.bucketSize = bucketSize; + } + + @Override + public void initialize() { + // initialization at first update + } + + @Override + public ListgetChargingStationsInCircle(GeoCircle circle) { + treeTraverser.setup(circle.getCenter().toVector3d(), circle.getRadius()); + treeTraverser.traverse(chargingStationTree); + return treeTraverser.getResult(); + } + + @Override + public void onChargingStationUpdate() { + if (chargingStationTree == null) { // initialize before first update is called + List allChargingStations = new ArrayList<>(indexedChargingStations.values()); + chargingStationTree = new KdTree<>(new SpatialObjectAdapter<>(), allChargingStations, bucketSize); + treeTraverser = new SpatialTreeTraverser.InRadius<>(); + } + } + + @Override + public int getNumberOfChargingStations() { + return chargingStationTree.getRoot().size(); + } +} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java index 09a14a529..f9934d8a3 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/ElectricVehicleApplication.java @@ -15,7 +15,6 @@ package org.eclipse.mosaic.fed.application.app.api; -import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; @@ -43,6 +42,4 @@ public interface ElectricVehicleApplication extends VehicleApplication, Applicat * @param vehicleChargingDenial The interaction containing further information about the rejected charging request */ void onVehicleChargingDenial(final VehicleChargingDenial vehicleChargingDenial); - - void onChargingStationDiscoveryResponse(ChargingStationDiscoveryResponse response); } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java index a8b92baa0..31d7e2887 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java @@ -16,8 +16,10 @@ package org.eclipse.mosaic.fed.application.app.api.os; import org.eclipse.mosaic.lib.geo.GeoCircle; +import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; +import java.util.List; import javax.annotation.Nullable; /** @@ -48,9 +50,9 @@ public interface ElectricVehicleOperatingSystem extends VehicleOperatingSystem { void sendChargingStopRequest(); /** - * Sends a request to locate all charging stations in the provided area. + * Locate all charging stations in the provided area. * - * @param searchArea The area where the charging stations are search + * @param searchArea The area where the charging stations are searched */ - void sendChargingStationDiscoveryRequest(GeoCircle searchArea); + List getChargingStationsByArea(GeoCircle searchArea); } diff --git a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java index 1fc093349..bebf6e78a 100644 --- a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java +++ b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/TestElectricVehicleApplication.java @@ -25,7 +25,6 @@ import org.eclipse.mosaic.fed.application.app.empty.ElectricVehicleNoopApp; import org.eclipse.mosaic.interactions.application.ApplicationInteraction; import org.eclipse.mosaic.interactions.communication.V2xMessageTransmission; -import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.lib.objects.traffic.SumoTraciResult; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; @@ -109,11 +108,6 @@ public void onVehicleChargingDenial(VehicleChargingDenial vehicleChargingDenial) thisApplicationSpy.onVehicleChargingDenial(vehicleChargingDenial); } - @Override - public void onChargingStationDiscoveryResponse(ChargingStationDiscoveryResponse response) { - - } - @Override public void onVehicleUpdated(@Nullable VehicleData previousVehicleData, @Nonnull VehicleData updatedVehicleData) { thisApplicationSpy.onVehicleUpdated(previousVehicleData, updatedVehicleData); diff --git a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java index bfb10ec2c..7838a6f3d 100644 --- a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java +++ b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/app/empty/ElectricVehicleNoopApp.java @@ -25,7 +25,6 @@ import org.eclipse.mosaic.fed.application.app.api.os.ElectricVehicleOperatingSystem; import org.eclipse.mosaic.interactions.application.ApplicationInteraction; import org.eclipse.mosaic.interactions.communication.V2xMessageTransmission; -import org.eclipse.mosaic.interactions.electricity.ChargingStationDiscoveryResponse; import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.lib.objects.traffic.SumoTraciResult; import org.eclipse.mosaic.lib.objects.vehicle.BatteryData; @@ -71,11 +70,6 @@ public void onBatteryDataUpdated(@Nullable BatteryData previousBatteryData, @Non public void onVehicleChargingDenial(VehicleChargingDenial vehicleChargingDenial) { } - @Override - public void onChargingStationDiscoveryResponse(ChargingStationDiscoveryResponse response) { - - } - @Override public void onAcknowledgementReceived(ReceivedAcknowledgement acknowledgedMessage) { } diff --git a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java deleted file mode 100644 index f307ac6d9..000000000 --- a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/ChargingStationDiscoveryResponse.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.interactions.electricity; - -import static org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE; - -import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; -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.util.Collection; - -/** - * An {@link Interaction} that contains a list of {@link ChargingStationData} objects as a response to a {@link VehicleChargingStationDiscoveryRequest}. - */ -public class ChargingStationDiscoveryResponse extends Interaction { - public ChargingStationDiscoveryResponse(long time, String vehicleId, Collection chargingStations) { - super(time); - - this.chargingStations = chargingStations; - this.vehicleId = vehicleId; - } - - /** - * String identifying the type of this interaction. - */ - public static final String TYPE_ID = createTypeIdentifier(ChargingStationDiscoveryResponse.class); - - /** - * The queried list {@link ChargingStationData} originating from the {@link VehicleChargingStationDiscoveryRequest}. - */ - private final Collection chargingStations; - - /** - * The ID of the requesting vehicle. - */ - private final String vehicleId; - - public String getVehicleId() { - return vehicleId; - } - - public Collection getChargingStations() { - return chargingStations; - } - - @Override - public int hashCode() { - return new HashCodeBuilder(9, 97) - .append(vehicleId) - .append(chargingStations) - .toHashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj == this) { - return true; - } - if (obj.getClass() != getClass()) { - return false; - } - - ChargingStationDiscoveryResponse other = (ChargingStationDiscoveryResponse) obj; - return new EqualsBuilder() - .append(this.vehicleId, other.vehicleId) - .append(this.chargingStations, other.chargingStations) - .isEquals(); - } - - @Override - public String toString() { - return new ToStringBuilder(this, SHORT_PREFIX_STYLE) - .appendSuper(super.toString()) - .append("vehicleId", vehicleId) - .append("chargingStations", chargingStations.stream().map(ChargingStationData::toString)) - .toString(); - } - -} diff --git a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java deleted file mode 100644 index 1f71d7330..000000000 --- a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/electricity/VehicleChargingStationDiscoveryRequest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.interactions.electricity; - -import static org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE; - -import org.eclipse.mosaic.lib.geo.GeoCircle; -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.Serial; - -/** - * An {@link Interaction} used by electric vehicles to find charging stations ({@link org.eclipse.mosaic.lib.objects.electricity.ChargingStationData}) in a certain area. - */ -public class VehicleChargingStationDiscoveryRequest extends Interaction { - public VehicleChargingStationDiscoveryRequest(long time, String vehicleId, GeoCircle searchArea) { - super(time); - - this.vehicleId = vehicleId; - this.searchArea = searchArea; - } - - @Serial - private static final long serialVersionUID = 1L; - - /** - * String identifying the type of this interaction. - */ - public static final String TYPE_ID = createTypeIdentifier(VehicleChargingStationDiscoveryRequest.class); - - /** - * String identifying the vehicle sending this interaction. - */ - private final String vehicleId; - - /** - * An area given by a point and a radius in which the requested {@link org.eclipse.mosaic.lib.objects.electricity.ChargingStationData} objects are. - */ - private final GeoCircle searchArea; - - public String getVehicleId() { - return vehicleId; - } - - public GeoCircle getSearchArea() { - return searchArea; - } - - @Override - public int hashCode() { - return new HashCodeBuilder(9, 97) - .append(vehicleId) - .append(searchArea) - .toHashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj == this) { - return true; - } - if (obj.getClass() != getClass()) { - return false; - } - - VehicleChargingStationDiscoveryRequest other = (VehicleChargingStationDiscoveryRequest) obj; - return new EqualsBuilder() - .append(this.vehicleId, other.vehicleId) - .append(this.searchArea, other.searchArea) - .isEquals(); - } - - @Override - public String toString() { - return new ToStringBuilder(this, SHORT_PREFIX_STYLE) - .appendSuper(super.toString()) - .append("vehicleId", vehicleId) - .append("searchArea", searchArea) - .toString(); - } -} diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java index 23b36d90c..9f059edb5 100644 --- a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java +++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java @@ -57,6 +57,8 @@ public ChargingStationData(long time, String name, GeoPoint position, List getChargingSpots() { return Lists.newArrayList(chargingSpots.values()); } From b7ad846f832460360e4e19265b791a664e997d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Wed, 22 Jan 2025 14:53:54 +0100 Subject: [PATCH 3/8] resolving pull request issues --- legal/templates/license-header-2025.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 legal/templates/license-header-2025.txt diff --git a/legal/templates/license-header-2025.txt b/legal/templates/license-header-2025.txt new file mode 100644 index 000000000..e69de29bb From a0cf89b85513944a7e3b5fa8946051496f6bfbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Mon, 3 Feb 2025 12:14:15 +0100 Subject: [PATCH 4/8] - Removed the file: ChargingStationTree.java - Merged contents of ChargingStationTree into ChargingStationIndex - ChargingStationIndex is not abstract anymore - small changes regarding function naming and removal of empty lines --- .../ambassador/ApplicationAmbassador.java | 3 +- .../simulation/ElectricVehicleUnit.java | 2 +- .../objects/ChargingStationObject.java | 1 - .../providers/ChargingStationIndex.java | 50 ++++++++++---- .../providers/ChargingStationTree.java | 66 ------------------- .../util/EventNicenessPriorityRegister.java | 3 - .../os/ElectricVehicleOperatingSystem.java | 2 +- .../electricity/ChargingStationData.java | 34 +++++++++- 8 files changed, 73 insertions(+), 88 deletions(-) delete mode 100644 fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java index dfb30af5f..2a7b7ac4d 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassador.java @@ -21,7 +21,6 @@ import org.eclipse.mosaic.fed.application.ambassador.simulation.TrafficManagementCenterUnit; import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedV2xMessage; import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.providers.ChargingStationIndex; -import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.providers.ChargingStationTree; 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; @@ -163,7 +162,7 @@ public ApplicationAmbassador(AmbassadorParameter ambassadorParameter) { if (SimulationKernel.SimulationKernel.chargingStationIndex == null) { // use same bucketsize as TrafficLightTree (see: CPercetion.java) (bucketsize := number of direct children per tree node) - ChargingStationIndex chargingStationIndex = new ChargingStationTree(20); + ChargingStationIndex chargingStationIndex = new ChargingStationIndex(20); SimulationKernel.SimulationKernel.setChargingStationIndex(chargingStationIndex); } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java index 72f818899..f83f21a22 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java @@ -110,7 +110,7 @@ public void sendChargingStopRequest() { sendInteractionToRti(vehicleChargingStopRequest); } - public List getChargingStationsByArea(GeoCircle searchArea) { + public List getChargingStationsInArea(GeoCircle searchArea) { return SimulationKernel.SimulationKernel.getChargingStationIndex().getChargingStationsInCircle(searchArea) .stream().map(ChargingStationObject::getChargingStationData) .collect(Collectors.toList()); diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java index af4a9c3d6..104958531 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/objects/ChargingStationObject.java @@ -39,7 +39,6 @@ public ChargingStationObject(String id) { super(id); } - public ChargingStationObject setChargingStationData(ChargingStationData chargingStationData) { this.chargingStationData = chargingStationData; return this; diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java index d35003448..7fef278ea 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java @@ -16,44 +16,72 @@ package org.eclipse.mosaic.fed.application.ambassador.simulation.electric.providers; import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.objects.ChargingStationObject; +import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.index.objects.SpatialObjectAdapter; import org.eclipse.mosaic.lib.geo.GeoCircle; import org.eclipse.mosaic.lib.geo.GeoPoint; import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; +import org.eclipse.mosaic.lib.spatial.KdTree; +import org.eclipse.mosaic.lib.spatial.SpatialTreeTraverser; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -public abstract class ChargingStationIndex { +public class ChargingStationIndex { + + private final int bucketSize; /** * Stores {@link ChargingStationObject}s for fast removal and position update. */ final Map indexedChargingStations = new HashMap<>(); - /** - * Method called to initialize index after configuration has been read. - */ - public abstract void initialize(); + private KdTree chargingStationTree; - /** - * Perform action before an update of the {@link ChargingStationIndex} takes place. - */ - public abstract void onChargingStationUpdate(); + private SpatialTreeTraverser.InRadius treeTraverser; - public abstract int getNumberOfChargingStations(); + public ChargingStationIndex(int bucketSize) { + this.bucketSize = bucketSize; + } - public abstract List getChargingStationsInCircle(GeoCircle circle); + /** + * Method called to initialize index after configuration has been read. + */ + public void initialize() { + // initialization at first update + } public void addChargingStation(String id, GeoPoint position) { indexedChargingStations.computeIfAbsent(id, ChargingStationObject::new) .setPosition(position.toCartesian()); } + /** + * Perform action before an update of the {@link ChargingStationIndex} takes place. + */ public void updateChargingStation(ChargingStationData chargingStationData) { onChargingStationUpdate(); indexedChargingStations.get(chargingStationData.getName()) .setChargingStationData(chargingStationData); } + public ListgetChargingStationsInCircle(GeoCircle circle) { + treeTraverser.setup(circle.getCenter().toVector3d(), circle.getRadius()); + treeTraverser.traverse(chargingStationTree); + return treeTraverser.getResult(); + } + + public void onChargingStationUpdate() { + if (chargingStationTree == null) { // initialize before first update is called + List allChargingStations = new ArrayList<>(indexedChargingStations.values()); + chargingStationTree = new KdTree<>(new SpatialObjectAdapter<>(), allChargingStations, bucketSize); + treeTraverser = new SpatialTreeTraverser.InRadius<>(); + } + } + + public int getNumberOfChargingStations() { + return chargingStationTree.getRoot().size(); + } + } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java deleted file mode 100644 index 86f7c51da..000000000 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationTree.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2025 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.fed.application.ambassador.simulation.electric.providers; - -import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.objects.ChargingStationObject; -import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.index.objects.SpatialObjectAdapter; -import org.eclipse.mosaic.lib.geo.GeoCircle; -import org.eclipse.mosaic.lib.spatial.KdTree; -import org.eclipse.mosaic.lib.spatial.SpatialTreeTraverser; - -import java.util.ArrayList; -import java.util.List; - -/** - * {@link ChargingStationIndex} using a KD-Tree to store charging stations. - */ -public class ChargingStationTree extends ChargingStationIndex { - private final int bucketSize; - - private KdTree chargingStationTree; - - private SpatialTreeTraverser.InRadius treeTraverser; - - public ChargingStationTree(int bucketSize) { - this.bucketSize = bucketSize; - } - - @Override - public void initialize() { - // initialization at first update - } - - @Override - public ListgetChargingStationsInCircle(GeoCircle circle) { - treeTraverser.setup(circle.getCenter().toVector3d(), circle.getRadius()); - treeTraverser.traverse(chargingStationTree); - return treeTraverser.getResult(); - } - - @Override - public void onChargingStationUpdate() { - if (chargingStationTree == null) { // initialize before first update is called - List allChargingStations = new ArrayList<>(indexedChargingStations.values()); - chargingStationTree = new KdTree<>(new SpatialObjectAdapter<>(), allChargingStations, bucketSize); - treeTraverser = new SpatialTreeTraverser.InRadius<>(); - } - } - - @Override - public int getNumberOfChargingStations() { - return chargingStationTree.getRoot().size(); - } -} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java index 247f85e53..e0d8e8f8c 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/util/EventNicenessPriorityRegister.java @@ -46,7 +46,4 @@ public class EventNicenessPriorityRegister { // batteryUpdated public final static long BATTERY_UPDATED = -99_998_900; - - // discover charging stations - public final static long CHARGING_STATIONS_DISCOVERY = -99_998_900; } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java index 31d7e2887..d2f7b92c6 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/ElectricVehicleOperatingSystem.java @@ -54,5 +54,5 @@ public interface ElectricVehicleOperatingSystem extends VehicleOperatingSystem { * * @param searchArea The area where the charging stations are searched */ - List getChargingStationsByArea(GeoCircle searchArea); + List getChargingStationsInArea(GeoCircle searchArea); } diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java index 9f059edb5..a9aae14a1 100644 --- a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java +++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/electricity/ChargingStationData.java @@ -19,6 +19,8 @@ import org.eclipse.mosaic.lib.objects.UnitData; import com.google.common.collect.Lists; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; import java.util.ArrayList; import java.util.HashMap; @@ -56,9 +58,6 @@ public ChargingStationData(long time, String name, GeoPoint position, List this.chargingSpots.put(chargingSpot.getChargingSpotId(), chargingSpot)); } - - - public List getChargingSpots() { return Lists.newArrayList(chargingSpots.values()); } @@ -126,6 +125,35 @@ public String toString() { + getPosition() + "]"; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + ChargingStationData that = (ChargingStationData) o; + return new EqualsBuilder() + .appendSuper(super.equals(that)) + .append(getTime(), that.getTime()) + .append(getPosition(), that.getPosition()) + .append(getChargingSpots(), that.getChargingSpots()) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(5, 11) + .appendSuper(super.hashCode()) + .append(getTime()) + .append(getPosition()) + .append(getChargingSpots()) + .toHashCode(); + } + public static class Builder { private final long time; private final String name; From 0d05e632363d49494129f1e656ba351c81292a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Tue, 4 Feb 2025 12:08:30 +0100 Subject: [PATCH 5/8] resolving PR issues --- .../fed/application/ambassador/SimulationKernel.java | 1 + .../ambassador/simulation/ElectricVehicleUnit.java | 2 +- .../electric/providers/ChargingStationIndex.java | 7 ------- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java index c594190b3..29836491b 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/SimulationKernel.java @@ -277,6 +277,7 @@ public ChargingStationIndex getChargingStationIndex() { return this.chargingStationIndex; } + public CentralPerceptionComponent getCentralPerceptionComponent() { if (centralPerceptionComponent == null) { throw new RuntimeException(ErrorRegister.SIMULATION_KERNEL_CentralPerceptionComponentNotSet.toString()); diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java index f83f21a22..e2a9cbd01 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/ElectricVehicleUnit.java @@ -113,6 +113,6 @@ public void sendChargingStopRequest() { public List getChargingStationsInArea(GeoCircle searchArea) { return SimulationKernel.SimulationKernel.getChargingStationIndex().getChargingStationsInCircle(searchArea) .stream().map(ChargingStationObject::getChargingStationData) - .collect(Collectors.toList()); + .toList(); } } diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java index 7fef278ea..7fd9ff042 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java @@ -45,13 +45,6 @@ public ChargingStationIndex(int bucketSize) { this.bucketSize = bucketSize; } - /** - * Method called to initialize index after configuration has been read. - */ - public void initialize() { - // initialization at first update - } - public void addChargingStation(String id, GeoPoint position) { indexedChargingStations.computeIfAbsent(id, ChargingStationObject::new) .setPosition(position.toCartesian()); From fb7ce5a6a2da2e6b597c5ddac4d3771b71a6cded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Wed, 5 Feb 2025 16:17:28 +0100 Subject: [PATCH 6/8] Fixing Unit tests: ApplicationAmbassadorTest.processInteraction_ChargingStationRegistration(...) --- .../application/ambassador/ApplicationAmbassadorTest.java | 7 +++++++ .../fed/application/ambassador/InteractionTestHelper.java | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java index 7bef0f93a..95016ad9a 100644 --- a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java +++ b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java @@ -15,6 +15,7 @@ package org.eclipse.mosaic.fed.application.ambassador; +import static org.eclipse.mosaic.lib.geo.GeoPoint.latLon; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; @@ -64,6 +65,8 @@ import org.eclipse.mosaic.lib.objects.vehicle.VehicleData; import org.eclipse.mosaic.lib.objects.vehicle.VehicleRoute; import org.eclipse.mosaic.lib.objects.vehicle.VehicleType; +import org.eclipse.mosaic.lib.transform.GeoProjection; +import org.eclipse.mosaic.lib.transform.Wgs84Projection; import org.eclipse.mosaic.lib.util.junit.TestUtils; import org.eclipse.mosaic.lib.util.scheduling.Event; import org.eclipse.mosaic.rti.TIME; @@ -764,6 +767,10 @@ public void processInteraction_VehicleRouteRegistration() throws InternalFederat public void processInteraction_ChargingStationRegistration() throws InternalFederateException, IOException { final ApplicationAmbassador ambassador = createAmbassador(); + // init geo projection + GeoPoint BERLIN = latLon(52.5, 13.4); + GeoProjection.initialize(new Wgs84Projection(BERLIN).failIfOutsideWorld()); + // init ambassador ambassador.initialize(0L, END_TIME); diff --git a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/InteractionTestHelper.java b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/InteractionTestHelper.java index 7b72f574a..66548ace1 100644 --- a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/InteractionTestHelper.java +++ b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/InteractionTestHelper.java @@ -67,7 +67,7 @@ static ChargingStationRegistration createChargingStationRegistration(String id, id, "group_0", getApplications(withApp, TestChargingStationApplication.class), - GeoPoint.lonLat(0, 0), + GeoPoint.lonLat(52.520008, 13.404954), Collections.emptyList() ); } From a94ffd68dd16dd882085b04413d21c326b366228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Mon, 10 Feb 2025 12:02:17 +0100 Subject: [PATCH 7/8] fixing PR issues --- .../providers/ChargingStationIndex.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java index 7fd9ff042..0bcd0b51c 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java @@ -54,25 +54,27 @@ public void addChargingStation(String id, GeoPoint position) { * Perform action before an update of the {@link ChargingStationIndex} takes place. */ public void updateChargingStation(ChargingStationData chargingStationData) { - onChargingStationUpdate(); + initSearchTree(); indexedChargingStations.get(chargingStationData.getName()) .setChargingStationData(chargingStationData); } - public ListgetChargingStationsInCircle(GeoCircle circle) { + private void initSearchTree() { + if (chargingStationTree != null) { + return; + } + + List allChargingStations = new ArrayList<>(indexedChargingStations.values()); + chargingStationTree = new KdTree<>(new SpatialObjectAdapter<>(), allChargingStations, bucketSize); + treeTraverser = new SpatialTreeTraverser.InRadius<>(); + } + + public List getChargingStationsInCircle(GeoCircle circle) { treeTraverser.setup(circle.getCenter().toVector3d(), circle.getRadius()); treeTraverser.traverse(chargingStationTree); return treeTraverser.getResult(); } - public void onChargingStationUpdate() { - if (chargingStationTree == null) { // initialize before first update is called - List allChargingStations = new ArrayList<>(indexedChargingStations.values()); - chargingStationTree = new KdTree<>(new SpatialObjectAdapter<>(), allChargingStations, bucketSize); - treeTraverser = new SpatialTreeTraverser.InRadius<>(); - } - } - public int getNumberOfChargingStations() { return chargingStationTree.getRoot().size(); } From d64cf824754c618e2b3c5d421ae3138abab34f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Kn=C3=B6pp?= Date: Wed, 12 Feb 2025 12:59:36 +0100 Subject: [PATCH 8/8] - implement lazy updates in ChargingStationIndex.java, tree is re-construced when the tree is queried IF a CS was added - implement KdTree.size() (returned constant 0) - udpated Unitest to insert, update and query three CSs --- .../providers/ChargingStationIndex.java | 35 +++++++++++++++---- .../ambassador/ApplicationAmbassadorTest.java | 33 +++++++++++++++++ .../eclipse/mosaic/lib/spatial/KdTree.java | 12 ++++++- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java index 0bcd0b51c..97350ff95 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/electric/providers/ChargingStationIndex.java @@ -1,4 +1,4 @@ -/* + /* * Copyright (c) 2025 Fraunhofer FOKUS and others. All rights reserved. * * See the NOTICE file(s) distributed with this work for additional @@ -28,8 +28,11 @@ import java.util.List; import java.util.Map; -public class ChargingStationIndex { - + /** + * A {@link ChargingStationIndex} holds Charging Stations in a tree structure, sorted by their position. + * The tree is initialized and gets updated lazily when a search is performed. + */ + public class ChargingStationIndex { private final int bucketSize; /** @@ -41,41 +44,59 @@ public class ChargingStationIndex { private SpatialTreeTraverser.InRadius treeTraverser; + private boolean needsTreeUpdate = false; + public ChargingStationIndex(int bucketSize) { this.bucketSize = bucketSize; } + /** + * Adds a Charging Station to the tree. + * Be sure to add {@link ChargingStationData} using updateChargingStation(ChargingStationData chargingStationData). + * + * The CS is inserted into the tree when it is queried (e.g. getChargingStationsInCircle(...) or getNumberOfChargingStations(...)) + * @param id + * @param position + */ public void addChargingStation(String id, GeoPoint position) { + if (chargingStationTree != null) { + throw new RuntimeException("ChargingStationTree has already been initialized, " + + "make sure to add all objects before calling updateCharginStation() for the first time. "); + } + + needsTreeUpdate = true; indexedChargingStations.computeIfAbsent(id, ChargingStationObject::new) .setPosition(position.toCartesian()); } /** - * Perform action before an update of the {@link ChargingStationIndex} takes place. + * Replaces the stations data object. */ public void updateChargingStation(ChargingStationData chargingStationData) { - initSearchTree(); indexedChargingStations.get(chargingStationData.getName()) .setChargingStationData(chargingStationData); } - private void initSearchTree() { - if (chargingStationTree != null) { + private void updateSearchTree() { + if (!needsTreeUpdate) { return; } List allChargingStations = new ArrayList<>(indexedChargingStations.values()); chargingStationTree = new KdTree<>(new SpatialObjectAdapter<>(), allChargingStations, bucketSize); treeTraverser = new SpatialTreeTraverser.InRadius<>(); + needsTreeUpdate = false; } public List getChargingStationsInCircle(GeoCircle circle) { + updateSearchTree(); treeTraverser.setup(circle.getCenter().toVector3d(), circle.getRadius()); treeTraverser.traverse(chargingStationTree); return treeTraverser.getResult(); } public int getNumberOfChargingStations() { + updateSearchTree(); return chargingStationTree.getRoot().size(); } diff --git a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java index 95016ad9a..4963f0ee5 100644 --- a/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java +++ b/fed/mosaic-application/src/test/java/org/eclipse/mosaic/fed/application/ambassador/ApplicationAmbassadorTest.java @@ -29,6 +29,7 @@ import org.eclipse.mosaic.fed.application.ambassador.eventresources.StartApplications; import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedAcknowledgement; +import org.eclipse.mosaic.fed.application.ambassador.simulation.electric.objects.ChargingStationObject; 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.app.TestAgentApplication; @@ -52,8 +53,10 @@ import org.eclipse.mosaic.interactions.traffic.VehicleTypesInitialization; import org.eclipse.mosaic.interactions.traffic.VehicleUpdates; import org.eclipse.mosaic.interactions.vehicle.VehicleRouteRegistration; +import org.eclipse.mosaic.lib.geo.GeoCircle; import org.eclipse.mosaic.lib.geo.GeoPoint; import org.eclipse.mosaic.lib.junit.IpResolverRule; +import org.eclipse.mosaic.lib.objects.electricity.ChargingStationData; import org.eclipse.mosaic.lib.objects.traffic.InductionLoopInfo; import org.eclipse.mosaic.lib.objects.traffic.LaneAreaDetectorInfo; import org.eclipse.mosaic.lib.objects.trafficlight.TrafficLightGroup; @@ -85,6 +88,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.ArgumentMatchers; +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.stubbing.Answer; @@ -774,15 +778,44 @@ public void processInteraction_ChargingStationRegistration() throws InternalFede // init ambassador ambassador.initialize(0L, END_TIME); + // register charging stations TestChargingStationApplication app = testAddUnit( ambassador, "cs_0", InteractionTestHelper.createChargingStationRegistration("cs_0", 5, true) ); + testAddUnit( + ambassador, + "cs_1", + InteractionTestHelper.createChargingStationRegistration("cs_1", 5, true) + ); + testAddUnit( + ambassador, + "cs_2", + InteractionTestHelper.createChargingStationRegistration("cs_2", 5, true) + ); + + // add initial data to charging stations + GeoPoint position = app.getOperatingSystem().getInitialPosition(); + SimulationKernel.SimulationKernel.getChargingStationIndex().updateChargingStation(new ChargingStationData(0, "cs_0", position, new ArrayList<>())); + SimulationKernel.SimulationKernel.getChargingStationIndex().updateChargingStation(new ChargingStationData(0, "cs_1", position, new ArrayList<>())); + SimulationKernel.SimulationKernel.getChargingStationIndex().updateChargingStation(new ChargingStationData(0, "cs_2", position, new ArrayList<>())); // verify that setUp has been called on the application of the unit Mockito.verify(app.getApplicationSpy()).onStartup(); + // verify that the charging stations were added + List stations = SimulationKernel.SimulationKernel.getChargingStationIndex() + .getChargingStationsInCircle(new GeoCircle(position, 10000)); + int numberOfStations = SimulationKernel.SimulationKernel.getChargingStationIndex().getNumberOfChargingStations(); + + + // assert added stations are present in tree + assertEquals(numberOfStations, 3); + assertEquals(stations.get(0).getChargingStationData().getName(), "cs_1"); + assertEquals(stations.get(2).getChargingStationData().getName(), "cs_0"); + assertEquals(stations.get(1).getChargingStationData().getName(), "cs_2"); + // tears down all applications ambassador.processTimeAdvanceGrant(recentAdvanceTime); ambassador.processTimeAdvanceGrant(END_TIME); diff --git a/lib/mosaic-geomath/src/main/java/org/eclipse/mosaic/lib/spatial/KdTree.java b/lib/mosaic-geomath/src/main/java/org/eclipse/mosaic/lib/spatial/KdTree.java index a32f5c943..81ee3634d 100644 --- a/lib/mosaic-geomath/src/main/java/org/eclipse/mosaic/lib/spatial/KdTree.java +++ b/lib/mosaic-geomath/src/main/java/org/eclipse/mosaic/lib/spatial/KdTree.java @@ -86,7 +86,17 @@ private void split(List items) { @Override public int size() { - return 0; + int nodeSize = root.getItems().size(); + + if (children == null) { + return nodeSize; + } + + + return nodeSize + + root.getChildren().stream() + .map(Node::size) + .reduce(0, (a, b) -> a+b); } @Override