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 03597df11..82714ce56 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 @@ -39,6 +39,7 @@ import org.eclipse.mosaic.interactions.electricity.VehicleChargingDenial; import org.eclipse.mosaic.interactions.environment.EnvironmentSensorUpdates; import org.eclipse.mosaic.interactions.environment.LidarUpdates; +import org.eclipse.mosaic.interactions.mapping.AgentRegistration; import org.eclipse.mosaic.interactions.mapping.ChargingStationRegistration; import org.eclipse.mosaic.interactions.mapping.RsuRegistration; import org.eclipse.mosaic.interactions.mapping.ServerRegistration; @@ -266,6 +267,8 @@ protected void processInteraction(final Interaction interaction) throws Internal this.process((RsuRegistration) interaction); } else if (interaction.getTypeId().startsWith(ChargingStationRegistration.TYPE_ID)) { this.process((ChargingStationRegistration) interaction); + } else if (interaction.getTypeId().startsWith(AgentRegistration.TYPE_ID)) { + this.process((AgentRegistration) interaction); } else if (interaction.getTypeId().startsWith(TrafficLightRegistration.TYPE_ID)) { this.process((TrafficLightRegistration) interaction); } else if (interaction.getTypeId().startsWith(VehicleRegistration.TYPE_ID)) { @@ -373,6 +376,10 @@ private void process(final TrafficLightRegistration trafficLightRegistration) { .addTrafficLightGroup(trafficLightRegistration.getTrafficLightGroup()); } + private void process(final AgentRegistration agentRegistration) { + UnitSimulator.UnitSimulator.registerAgent(agentRegistration); + } + private void process(final VehicleRegistration vehicleRegistration) { String vehicleName = vehicleRegistration.getMapping().getName(); vehicleRegistrations.put(vehicleName, vehicleRegistration); 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..f091e577d 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 @@ -77,7 +77,10 @@ public enum ErrorRegister { TRAFFIC_MANAGEMENT_CENTER_NoEventResource(0x01000091, "Process event with no resource."), // 0x01000100 to 0x0100010F Servers SERVER_UnknownEvent(0x01000100, "Process unknown event."), - SERVER_NoEventResource(0x0100101, "Process event with no resource."); + SERVER_NoEventResource(0x0100101, "Process event with no resource."), + // 0x01000110 to 0x0100011F Agents + AGENT_UnknownEvent(0x01000110, "Process unknown event."), + AGENT_NoEventResource(0x0100111, "Process event with no resource."); /** * The code of the error. diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/UnitSimulator.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/UnitSimulator.java index 33410aaf0..00a22d60d 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/UnitSimulator.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/UnitSimulator.java @@ -18,6 +18,7 @@ import org.eclipse.mosaic.fed.application.ambassador.eventresources.RemoveVehicles; import org.eclipse.mosaic.fed.application.ambassador.eventresources.StartApplications; import org.eclipse.mosaic.fed.application.ambassador.simulation.AbstractSimulationUnit; +import org.eclipse.mosaic.fed.application.ambassador.simulation.AgentUnit; import org.eclipse.mosaic.fed.application.ambassador.simulation.ChargingStationUnit; import org.eclipse.mosaic.fed.application.ambassador.simulation.ElectricVehicleUnit; import org.eclipse.mosaic.fed.application.ambassador.simulation.RoadSideUnit; @@ -26,6 +27,7 @@ import org.eclipse.mosaic.fed.application.ambassador.simulation.TrafficManagementCenterUnit; import org.eclipse.mosaic.fed.application.ambassador.simulation.VehicleUnit; import org.eclipse.mosaic.interactions.environment.EnvironmentSensorActivation; +import org.eclipse.mosaic.interactions.mapping.AgentRegistration; import org.eclipse.mosaic.interactions.mapping.ChargingStationRegistration; import org.eclipse.mosaic.interactions.mapping.RsuRegistration; import org.eclipse.mosaic.interactions.mapping.ServerRegistration; @@ -92,6 +94,11 @@ public enum UnitSimulator implements EventProcessor { */ private final Map vehicles = new HashMap<>(); + /** + * Map containing all the ids with the corresponding agent units. + */ + private final Map agents = new HashMap<>(); + /** * Map containing all the ids with the corresponding {@link AbstractSimulationUnit}. */ @@ -133,6 +140,15 @@ public Map getVehicles() { return vehicles; } + /** + * Returns the map containing all the ids with the corresponding agents. + * + * @return the map containing all the ids with the corresponding agents. + */ + public Map getAgents() { + return agents; + } + /** * Returns the map containing all the ids with the corresponding TMCs. * @@ -186,6 +202,8 @@ private void addSimulationUnit(final AbstractSimulationUnit unit) { servers.put(unit.getId(), server); } else if (unit instanceof VehicleUnit vehicle) { vehicles.put(unit.getId(), vehicle); + } else if (unit instanceof AgentUnit agent) { + agents.put(unit.getId(), agent); } else { throw new RuntimeException(ErrorRegister.UNIT_SIMULATOR_UnknownSimulationUnitToPutInMap.toString()); } @@ -213,6 +231,8 @@ private void removeSimulationUnit(final AbstractSimulationUnit unit) { servers.remove(unit.getId()); } else if (unit instanceof VehicleUnit) { vehicles.remove(unit.getId()); + } else if (unit instanceof AgentUnit) { + agents.remove(unit.getId()); } else { throw new RuntimeException(ErrorRegister.UNIT_SIMULATOR_UnknownSimulationUnitToRemoveFromMap.toString()); } @@ -236,6 +256,7 @@ public void removeAllSimulationUnits() { vehicles.clear(); tmcs.clear(); servers.clear(); + agents.clear(); allUnits.clear(); } @@ -455,6 +476,30 @@ private void doSensorRegistration(final long time, final String id) { simulationUnit.sendInteractionToRti(environmentSensorActivation); } + + /** + * Registers an Agent. Unit is only registered if it is equipped with an application + * + * @param agentRegistration the interaction containing the mapping of the agent + */ + public void registerAgent(AgentRegistration agentRegistration) { + if (!agentRegistration.getMapping().hasApplication()) { + log.warn("An agent will not move without any application."); + return; + } + final AgentUnit agent = new AgentUnit(agentRegistration.getMapping(), agentRegistration.getOrigin(), agentRegistration.getDestination()); + agent.setGroup(agentRegistration.getMapping().getGroup()); + + addSimulationUnit(agent); + + final Event event = new Event( + agentRegistration.getTime(), + this, new StartApplications(agent.getId(), agentRegistration.getMapping()), + Event.NICE_MAX_PRIORITY + ); + SimulationKernel.SimulationKernel.getEventManager().addEvent(event); + } + @Override public void processEvent(Event event) { final Object resource = event.getResource(); diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/AgentUnit.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/AgentUnit.java new file mode 100644 index 000000000..8f54d49f8 --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/AgentUnit.java @@ -0,0 +1,164 @@ +/* + * 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; + +import org.eclipse.mosaic.fed.application.ambassador.ErrorRegister; +import org.eclipse.mosaic.fed.application.ambassador.SimulationKernel; +import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.CamBuilder; +import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.AgentPtRoutingModule; +import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.RoutingNavigationModule; +import org.eclipse.mosaic.fed.application.app.api.navigation.PtRoutingModule; +import org.eclipse.mosaic.fed.application.app.api.navigation.RoutingModule; +import org.eclipse.mosaic.fed.application.app.api.os.AgentOperatingSystem; +import org.eclipse.mosaic.interactions.agent.AgentRouteChange; +import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.objects.agent.AgentRoute; +import org.eclipse.mosaic.lib.objects.mapping.AgentMapping; +import org.eclipse.mosaic.lib.objects.vehicle.VehicleDeparture; +import org.eclipse.mosaic.lib.objects.vehicle.VehicleRoute; +import org.eclipse.mosaic.lib.routing.CandidateRoute; +import org.eclipse.mosaic.lib.routing.IllegalRouteException; +import org.eclipse.mosaic.lib.routing.pt.PtRoute; +import org.eclipse.mosaic.lib.util.scheduling.Event; + +import com.google.common.collect.Lists; + +import java.util.List; + +public class AgentUnit extends AbstractSimulationUnit implements AgentOperatingSystem { + + private final RoutingModule vehicleRoutingModule; + private final PtRoutingModule ptRoutingModule; + private final GeoPoint originPosition; + private final GeoPoint destinationPosition; + + public AgentUnit(AgentMapping agentMapping, final GeoPoint originPosition, final GeoPoint destinationPosition) { + super(agentMapping.getName(), originPosition); + setRequiredOperatingSystem(AgentOperatingSystem.class); + + vehicleRoutingModule = new RoutingNavigationModule(this); + ptRoutingModule = new AgentPtRoutingModule(agentMapping.getWalkingSpeed()); + + this.originPosition = originPosition; + this.destinationPosition = destinationPosition; + } + + @Override + public void usePrivateVehicle(String vehicleType, CandidateRoute route) { + try { + VehicleRoute rtiRoute = SimulationKernel.SimulationKernel.getCentralNavigationComponent().createAndPropagateRoute( + route, getSimulationTime() + ); + + if (rtiRoute == null) { + throw new IllegalRouteException("Provided route could not be propagated to RTI."); + } + + final List agentLegs = Lists.newArrayList(new AgentRoute.PrivateVehicleLeg( + getSimulationTime(), + vehicleType, + new VehicleDeparture.Builder(rtiRoute.getId()) + .departureSpeed(VehicleDeparture.DepartureSpeedMode.PRECISE, 0) + .create() + )); + sendInteractionToRti(new AgentRouteChange( + getSimulationTime(), getId(), new AgentRoute(agentLegs) + )); + + } catch (IllegalRouteException e) { + throw new RuntimeException("Invalid route provided.", e); + } + } + + @Override + public void useSharedVehicle(String vehicleId) { + final List agentLegs = Lists.newArrayList(new AgentRoute.SharedVehicleLeg( + getSimulationTime(), + vehicleId + )); + + sendInteractionToRti(new AgentRouteChange( + getSimulationTime(), getId(), new AgentRoute(agentLegs) + )); + } + + @Override + public void usePublicTransport(PtRoute publicTransportRoute) { + final List agentLegs = publicTransportRoute.getLegs().stream().map(leg -> { + if (leg instanceof PtRoute.PtLeg ptLeg) { + return new AgentRoute.PublicTransportLeg(leg.getDepartureTime(), ptLeg.getStops()); + } + if (leg instanceof PtRoute.WalkLeg walkLeg) { + return new AgentRoute.WalkLeg(leg.getDepartureTime(), walkLeg.getWaypoints()); + } + throw new IllegalArgumentException("Unsupported leg type found in public transport route."); + }).toList(); + + if (agentLegs.isEmpty()) { + return; + } + sendInteractionToRti(new AgentRouteChange( + getSimulationTime(), getId(), new AgentRoute(agentLegs) + )); + } + + @Override + public GeoPoint getOriginPosition() { + return originPosition; + } + + @Override + public GeoPoint getDestinationPosition() { + return destinationPosition; + } + + @Override + public PtRoutingModule getPtRoutingModule() { + return ptRoutingModule; + } + + @Override + public RoutingModule getRoutingModule() { + return vehicleRoutingModule; + } + + @Override + public void processEvent(Event event) throws Exception { + // never remove the preProcessEvent call! + final boolean preProcessed = super.preProcessEvent(event); + + // failsafe + if (preProcessed) { + return; + } + + final Object resource = event.getResource(); + + // failsafe + if (resource == null) { + getOsLog().error("Event has no resource: {}", event); + throw new RuntimeException(ErrorRegister.AGENT_NoEventResource.toString()); + } + + getOsLog().error("Unknown event resource: {}", event); + throw new RuntimeException(ErrorRegister.AGENT_UnknownEvent.toString()); + } + + @Override + public CamBuilder assembleCamMessage(CamBuilder camBuilder) { + throw new UnsupportedOperationException("Agents are not able to send CAMs"); + } +} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/navigation/AgentPtRoutingModule.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/navigation/AgentPtRoutingModule.java new file mode 100644 index 000000000..10ccd0e6a --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/navigation/AgentPtRoutingModule.java @@ -0,0 +1,41 @@ +/* + * 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.navigation; + +import org.eclipse.mosaic.fed.application.ambassador.SimulationKernel; +import org.eclipse.mosaic.fed.application.app.api.navigation.PtRoutingModule; +import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.routing.pt.PtRoutingParameters; +import org.eclipse.mosaic.lib.routing.pt.PtRoutingRequest; +import org.eclipse.mosaic.lib.routing.pt.PtRoutingResponse; + +public class AgentPtRoutingModule implements PtRoutingModule { + + private final double defaultWalkingSpeed; + + public AgentPtRoutingModule(double defaultWalkingSpeed) { + this.defaultWalkingSpeed = defaultWalkingSpeed; + } + + @Override + public PtRoutingResponse calculateRoute(long requestTime, GeoPoint origin, GeoPoint destination, PtRoutingParameters routingParameters) { + PtRoutingRequest routingRequest = new PtRoutingRequest(requestTime, origin, destination, routingParameters); + if (routingParameters.getWalkingSpeedMps() == null) { + routingParameters.walkingSpeedMps(defaultWalkingSpeed); + } + return SimulationKernel.SimulationKernel.getCentralNavigationComponent().findPtRoute(routingRequest); + } +} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/navigation/CentralNavigationComponent.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/navigation/CentralNavigationComponent.java index cdf472db5..d08afed52 100644 --- a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/navigation/CentralNavigationComponent.java +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/ambassador/simulation/navigation/CentralNavigationComponent.java @@ -247,23 +247,35 @@ public VehicleRoute switchRoute(VehicleData vehicleData, CandidateRoute rawRoute return requestStaticRouteChange(vehicleData, knownRoute, currentRoute, time); } else { // generate a new route - VehicleRoute route = vehicleRouting.createRouteForRTI(rawRoute); - - // propagate the new route - try { - log.debug("Propagate unknown route {}.", route.getId()); - propagateRoute(route, time); - } catch (InternalFederateException e) { - log.error("[CNC.switchRoute]: unable to send propagate a new route."); + VehicleRoute route = createAndPropagateRoute(rawRoute, time); + + if (route == null) { + log.error("[CNC.switchRoute]: unable to propagate new route."); return currentRoute; } - - // change route for sumo return requestStaticRouteChange(vehicleData, route, currentRoute, time); } } } + /** + * Creates a {@link VehicleRoute} from a {@link CandidateRoute} and propagates it + * to all ambassadors by triggering a {@link VehicleRouteRegistration}. + * + * @param rawRoute The raw route object. + * @param time The current simulation time. Used when sending the {@link VehicleRouteRegistration}. + */ + public VehicleRoute createAndPropagateRoute(CandidateRoute rawRoute, long time) throws IllegalRouteException { + VehicleRoute route = vehicleRouting.createRouteForRTI(rawRoute); + try { + log.debug("Propagate unknown route {}.", route.getId()); + propagateRoute(route, time); + return route; + } catch (InternalFederateException e) { + return null; + } + } + /** * Helper-method for {@link #switchRoute}. * diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/navigation/PtRoutingModule.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/navigation/PtRoutingModule.java new file mode 100644 index 000000000..68f8a20e5 --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/navigation/PtRoutingModule.java @@ -0,0 +1,38 @@ +/* + * 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.app.api.navigation; + +import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.routing.pt.PtRoutingParameters; +import org.eclipse.mosaic.lib.routing.pt.PtRoutingResponse; + +/** + * Interface to access public transport routing functionalities for agents. + */ +public interface PtRoutingModule { + + /** + * Calculates a public transport route from the provided origin to the provided destination position. + * + * @param requestTime The time at which the public transport route should begin earliest. + * @param origin The destination position of the required route. + * @param destination The destination position of the required route. + * @param routingParameters Properties defining the way routes are calculated (e.g. number of routes, weighting). + * @return The response including a public transport route towards the target. + */ + PtRoutingResponse calculateRoute(long requestTime, GeoPoint origin, GeoPoint destination, PtRoutingParameters routingParameters); + +} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/AgentOperatingSystem.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/AgentOperatingSystem.java new file mode 100644 index 000000000..181374329 --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/AgentOperatingSystem.java @@ -0,0 +1,64 @@ +/* + * 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.app.api.os; + +import org.eclipse.mosaic.fed.application.app.api.os.modules.CellCommunicative; +import org.eclipse.mosaic.fed.application.app.api.os.modules.PtRoutable; +import org.eclipse.mosaic.fed.application.app.api.os.modules.Routable; +import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.routing.CandidateRoute; +import org.eclipse.mosaic.lib.routing.pt.PtRoute; + +/** + * An agent represents a person in the simulation which is able to use public transport + * facilities, can walk, or use private or shared vehicles for transportation. An agent does + * not move until its mapped application provides instructions, such as using public transport + * or a private car.
+ * + * This interface extends the basic {@link OperatingSystem} and is implemented + * by the {@link org.eclipse.mosaic.fed.application.ambassador.simulation.AgentUnit}. + */ +public interface AgentOperatingSystem + extends OperatingSystem, CellCommunicative, Routable, PtRoutable { + + /** + * Changes the next leg of the agent to use a private vehicle. The {@link #getRoutingModule()} should be used + * to calculate {@link CandidateRoute}s for such vehicle trip. + */ + void usePrivateVehicle(String vehicleType, CandidateRoute route); + + /** + * Changes the next leg of the agent to use vehicle which already exists in the simulation, such as a shared vehicle or shuttle bus. + */ + void useSharedVehicle(String vehicleId); + + /** + * Changes the next leg(s) of the agent to use public transportation. The provided public transport route + * would contain one or more legs of type public transport, or walking. The {@link #getPtRoutingModule()} should be used + * to calculate such routes. + */ + void usePublicTransport(PtRoute publicTransportRoute); + + /** + * Provides the origin position of the agent as defined in the mapping configuration. + */ + GeoPoint getOriginPosition(); + + /** + * Provides the destination position of the agent as defined in the mapping configuration. + */ + GeoPoint getDestinationPosition(); +} diff --git a/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/modules/PtRoutable.java b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/modules/PtRoutable.java new file mode 100644 index 000000000..47310538a --- /dev/null +++ b/fed/mosaic-application/src/main/java/org/eclipse/mosaic/fed/application/app/api/os/modules/PtRoutable.java @@ -0,0 +1,32 @@ +/* + * 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.fed.application.app.api.os.modules; + +import org.eclipse.mosaic.fed.application.app.api.navigation.PtRoutingModule; + +/** + * Interface to mark an {@link org.eclipse.mosaic.fed.application.app.api.os.OperatingSystem} as + * an owner of a {@link PtRoutingModule} to calculates public transport routes from A to B, thus making it pt-routable. + */ +public interface PtRoutable { + + /** + * Returns a public transport routing module to calculate arbitrary routes from any point to any other. + * + * @return the {@link PtRoutingModule} of the unit. + */ + PtRoutingModule getPtRoutingModule(); +} diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java index b0186e0d5..1b62a5c4d 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/SpawningFramework.java @@ -17,6 +17,7 @@ import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; +import org.eclipse.mosaic.fed.mapping.ambassador.spawning.AgentSpawner; import org.eclipse.mosaic.fed.mapping.ambassador.spawning.ChargingStationSpawner; import org.eclipse.mosaic.fed.mapping.ambassador.spawning.RoadSideUnitSpawner; import org.eclipse.mosaic.fed.mapping.ambassador.spawning.ServerSpawner; @@ -28,6 +29,7 @@ import org.eclipse.mosaic.fed.mapping.config.CMappingAmbassador; import org.eclipse.mosaic.fed.mapping.config.CMappingConfiguration; import org.eclipse.mosaic.fed.mapping.config.CPrototype; +import org.eclipse.mosaic.fed.mapping.config.units.CAgent; import org.eclipse.mosaic.fed.mapping.config.units.CChargingStation; import org.eclipse.mosaic.fed.mapping.config.units.COriginDestinationMatrixMapper; import org.eclipse.mosaic.fed.mapping.config.units.CRoadSideUnit; @@ -68,6 +70,7 @@ public class SpawningFramework { private final Map> typeDistributions = new HashMap<>(); private final Map tls = new HashMap<>(); private final List vehicleFlowGenerators = new ArrayList<>(); + private final List agents = new ArrayList<>(); private final List rsus = new ArrayList<>(); private final List tmcs = new ArrayList<>(); private final List servers = new ArrayList<>(); @@ -131,6 +134,17 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration, } } } + + if (mappingConfiguration.agents != null) { + for (CAgent agentConfiguration : mappingConfiguration.agents) { + if (agentConfiguration != null) { + AgentSpawner agentSpawner = new AgentSpawner(agentConfiguration); + agents.add(agentSpawner); + spawners.add(agentSpawner); + } + } + } + // RSUs if (mappingConfiguration.rsus != null) { for (CRoadSideUnit roadSideUnitConfiguration : mappingConfiguration.rsus) { @@ -400,6 +414,14 @@ private void completeSpawnerDefinitions() { spawner.configure(config); } } + + for (AgentSpawner spawner : agents) { + spawner.fillInPrototype(getPrototypeByName(spawner.getPrototypeName())); + + if (config != null) { + spawner.configure(config); + } + } } /** diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/spawning/AgentSpawner.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/spawning/AgentSpawner.java new file mode 100644 index 000000000..832e03a1c --- /dev/null +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/ambassador/spawning/AgentSpawner.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020 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.mapping.ambassador.spawning; + +import org.eclipse.mosaic.fed.mapping.ambassador.SpawningFramework; +import org.eclipse.mosaic.fed.mapping.config.CMappingConfiguration; +import org.eclipse.mosaic.fed.mapping.config.CPrototype; +import org.eclipse.mosaic.fed.mapping.config.units.CAgent; +import org.eclipse.mosaic.interactions.mapping.AgentRegistration; +import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.objects.UnitNameGenerator; +import org.eclipse.mosaic.rti.TIME; +import org.eclipse.mosaic.rti.api.IllegalValueException; +import org.eclipse.mosaic.rti.api.InternalFederateException; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class responsible for configuring Road Side Units to be added to the simulation. + */ +public class AgentSpawner extends UnitSpawner implements Spawner { + + private static final Logger LOG = LoggerFactory.getLogger(AgentSpawner.class); + + private final GeoPoint origin; + private final GeoPoint destination; + + private long startingTime; + private double walkingSpeed; + + public AgentSpawner(CAgent agentConfiguration) { + super(agentConfiguration.applications, agentConfiguration.name, agentConfiguration.group); + this.startingTime = Double.valueOf(agentConfiguration.startingTime * TIME.SECOND).longValue(); + this.origin = agentConfiguration.origin; + this.destination = agentConfiguration.destination; + this.walkingSpeed = agentConfiguration.walkingSpeed; + } + + public void configure(CMappingConfiguration mappingParameterizationConfiguration) { + if (mappingParameterizationConfiguration.start != null) { + this.startingTime = Double.valueOf(mappingParameterizationConfiguration.start * TIME.SECOND).longValue(); + } + } + + public void init(SpawningFramework spawningFramework) throws InternalFederateException { + String name = UnitNameGenerator.nextAgentName(); + AgentRegistration interaction = new AgentRegistration(startingTime, name, group, origin, destination, getApplications(), walkingSpeed); + try { + LOG.info("Creating Agent: {}", this); + spawningFramework.getRti().triggerInteraction(interaction); + } catch (IllegalValueException e) { + LOG.error("Exception while sending Interaction in AgentSpawner.init()"); + throw new InternalFederateException("Exception while sending Interaction in AgentSpawner.init()", e); + } + } + + @Override + public void fillInPrototype(CPrototype prototypeConfiguration) { + super.fillInPrototype(prototypeConfiguration); + + if (prototypeConfiguration != null && prototypeConfiguration.maxSpeed != null) { + walkingSpeed = prototypeConfiguration.maxSpeed; + } + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("startingTime", startingTime) + .append("origin", origin) + .append("destination", destination) + .append("applications", applications) + .build(); + } +} diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CMappingAmbassador.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CMappingAmbassador.java index db84ccbe4..33a5097a8 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CMappingAmbassador.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/CMappingAmbassador.java @@ -15,6 +15,7 @@ package org.eclipse.mosaic.fed.mapping.config; +import org.eclipse.mosaic.fed.mapping.config.units.CAgent; import org.eclipse.mosaic.fed.mapping.config.units.CChargingStation; import org.eclipse.mosaic.fed.mapping.config.units.COriginDestinationMatrixMapper; import org.eclipse.mosaic.fed.mapping.config.units.CRoadSideUnit; @@ -76,6 +77,11 @@ public class CMappingAmbassador { */ public List vehicles; + /** + * List of agents. + */ + public List agents; + /** * List of additional traffic that will be spawned using OD-matrices. */ diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/units/CAgent.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/units/CAgent.java new file mode 100644 index 000000000..5c065dffa --- /dev/null +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/units/CAgent.java @@ -0,0 +1,68 @@ +/* + * 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.mapping.config.units; + +import org.eclipse.mosaic.lib.geo.GeoPoint; +import org.eclipse.mosaic.lib.math.SpeedUtils; +import org.eclipse.mosaic.lib.util.gson.TimeFieldAdapter; +import org.eclipse.mosaic.lib.util.gson.UnitFieldAdapter; + +import com.google.gson.annotations.JsonAdapter; + +import java.util.List; + +public class CAgent { + + /** + * Time at which the agent will be created. + */ + @JsonAdapter(TimeFieldAdapter.DoubleSeconds.class) + public double startingTime = 0.0; + + /** + * The name of the prototype to be matched against this object. All + * properties which are not specified will then be replaced. + */ + public String name; + + /** + * The group name. + */ + public String group; + + /** + * Specify the applications to be used for this object. If none are + * specified, none are used + */ + public List applications; + + /** + * Point from which the vehicles will be spawned. + */ + public GeoPoint origin; + + /** + * Point to which the vehicles will travel. + */ + public GeoPoint destination; + + /** + * Walking speed of this agent. + */ + @JsonAdapter(UnitFieldAdapter.SpeedMS.class) + public double walkingSpeed = SpeedUtils.kmh2ms(5); + +} diff --git a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/units/CVehicle.java b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/units/CVehicle.java index 1b4fd6652..29df80762 100644 --- a/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/units/CVehicle.java +++ b/fed/mosaic-mapping/src/main/java/org/eclipse/mosaic/fed/mapping/config/units/CVehicle.java @@ -127,9 +127,9 @@ public enum SpawningMode { * Example configuration file: *
      * {
-     *    "prototypeDeserializers":[
+     *    "prototypes":[
      *        {
-     *           "name":"PKW",
+     *           "name":"Car",
      *           "accel":2.5,
      *           "decel":4.5,
      *           "length":5.0,
@@ -141,9 +141,9 @@ public enum SpawningMode {
      *        {
      *            "route":"0",
      *            "types":[
-     *                { "name":"PKW" },
+     *                { "name":"Car" },
      *                {
-     *                    "name":"PKW",
+     *                    "name":"Car",
      *                    "accel":2.0,
      *                    "length":7.0
      *                }
diff --git a/fed/mosaic-mapping/src/main/resources/CMappingAmbassadorScheme.json b/fed/mosaic-mapping/src/main/resources/CMappingAmbassadorScheme.json
index f4d749e32..1aaff8828 100644
--- a/fed/mosaic-mapping/src/main/resources/CMappingAmbassadorScheme.json
+++ b/fed/mosaic-mapping/src/main/resources/CMappingAmbassadorScheme.json
@@ -18,10 +18,15 @@
             "$ref": "#/definitions/typeDistribution"
         },
         "vehicles": {
-            "description": "Array of vehicles to be spawned in the simulation. This property describes the vehicles populatingthe simulation. It is possible to create a single vehicle (maxNumberVehicles should be '1' in that case) or a streamof one or multiple vehicles. The type(s) are defined in the field types. When more than one type is defined theweights in the prototype can be used to balance them against each other.",
+            "description": "Array of vehicles to be spawned in the simulation. This property describes the vehicles populating the simulation. It is possible to create a single vehicle (maxNumberVehicles should be '1' in that case) or a stream of one or multiple vehicles. The type(s) are defined in the field types. When more than one type is defined the weights in the prototype can be used to balance them against each other.",
             "type": "array",
             "items": { "$ref": "#/definitions/vehicle" }
         },
+        "agents": {
+            "description": "Array of agents to be spawned in the simulation.",
+            "type": "array",
+            "items": { "$ref": "#/definitions/agent" }
+        },
         "matrixMappers": {
             "description": "Array of items to define additional traffic that will be spawned using OD-matrices.",
             "type": "array",
@@ -388,6 +393,49 @@
                 { "required": [ "typeDistribution", "origin", "destination" ] }
             ]
         },
+        "agent": {
+            "title": "agent",
+            "description": "An agent has an origin and destination point. The trip selection is done via mapped applications.",
+            "type": "object",
+            "properties": {
+                "startingTime": {
+                    "description": "Time in seconds at which the agent will be created.",
+                    "anyOf": [
+                        { "type": "string", "maxLength": 15 },
+                        { "type": "number", "minimum": 0, "default": 0.0 }
+                    ]
+                },
+                "origin": {
+                    "description": "Point at which the agent will be spawned.",
+                    "$ref": "#/definitions/geoPoint"
+                },
+                "destination": {
+                    "description": "Point to which the agent will travel.",
+                    "$ref": "#/definitions/geoPoint"
+                },
+                "name": {
+                    "description": "Used to be matched with a prototype. If a prototype name matches this name, all properties not set in this object will be overwritten by those defined in the prototype.",
+                    "type": "string"
+                },
+                "group": {
+                    "description": "The group name is used for (statistical) evaluation purposes with the StatisticOutput and ITEF. It allows to summarize multiple agent entities.",
+                    "type": "string"
+                },
+                "applications": {
+                    "description": "Array of strings that specifies the applications to be used for this object.",
+                    "type": "array",
+                    "items": { "type": "string" }
+                },
+                "walkingSpeed": {
+                    "description": "Speed which is used for walking, in m/s.",
+                    "anyOf": [
+                        { "type": "string", "maxLength": 15 },
+                        { "type": "number", "minimum": 0, "default": 1.39 }
+                    ]
+                }
+            },
+            "required": [ "startingTime", "origin", "destination" ]
+        },
         "matrixMapper": {
             "title": "matrixMapper",
             "description": "Object to define a mapper for an Origin-Destination (OD) matrix. The mapper contains a list of points (with varying radius) and a matrix (arrays) of flow values. It creates a series of conventional vehicles spawners from the specified data.",
diff --git a/legal/templates/license-header-2025.txt b/legal/templates/license-header-2025.txt
new file mode 100644
index 000000000..71c590ef6
--- /dev/null
+++ b/legal/templates/license-header-2025.txt
@@ -0,0 +1,12 @@
+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
\ No newline at end of file
diff --git a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/agent/AgentRouteChange.java b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/agent/AgentRouteChange.java
new file mode 100644
index 000000000..f321b1f53
--- /dev/null
+++ b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/agent/AgentRouteChange.java
@@ -0,0 +1,43 @@
+/*
+ * 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.interactions.agent;
+
+import org.eclipse.mosaic.lib.objects.agent.AgentRoute;
+import org.eclipse.mosaic.rti.api.Interaction;
+
+public class AgentRouteChange extends Interaction {
+
+    private static final long serialVersionUID = 1L;
+
+    public final static String TYPE_ID = createTypeIdentifier(AgentRouteChange.class);
+
+    private final String agentId;
+    private final AgentRoute route;
+
+    public AgentRouteChange(long time, String agentId, AgentRoute route) {
+        super(time);
+        this.route = route;
+        this.agentId = agentId;
+    }
+
+    public String getAgentId() {
+        return agentId;
+    }
+
+    public AgentRoute getRoute() {
+        return this.route;
+    }
+}
\ No newline at end of file
diff --git a/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/mapping/AgentRegistration.java b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/mapping/AgentRegistration.java
new file mode 100644
index 000000000..d754716b0
--- /dev/null
+++ b/lib/mosaic-interactions/src/main/java/org/eclipse/mosaic/interactions/mapping/AgentRegistration.java
@@ -0,0 +1,56 @@
+/*
+ * 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.interactions.mapping;
+
+import org.eclipse.mosaic.lib.geo.GeoPoint;
+import org.eclipse.mosaic.lib.objects.mapping.AgentMapping;
+import org.eclipse.mosaic.rti.api.Interaction;
+
+import java.util.List;
+
+/**
+ * Registers a new agent as defined in the mapping configuration.
+ */
+public class AgentRegistration extends Interaction {
+
+    private static final long serialVersionUID = 1L;
+
+    public final static String TYPE_ID = createTypeIdentifier(AgentRegistration.class);
+
+    private final GeoPoint origin;
+    private final GeoPoint destination;
+    private final AgentMapping agentMapping;
+
+    public AgentRegistration(long time, String name, String group, GeoPoint origin, GeoPoint destination, final List applications, double walkingSpeed) {
+        super(time);
+        this.origin = origin;
+        this.destination = destination;
+        this.agentMapping = new AgentMapping(name, group, applications, walkingSpeed);
+    }
+
+    public GeoPoint getOrigin() {
+        return origin;
+    }
+
+    public GeoPoint getDestination() {
+        return destination;
+    }
+
+    public AgentMapping getMapping() {
+        return agentMapping;
+    }
+
+}
diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitNameGenerator.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitNameGenerator.java
index 35f058e43..8ff095d25 100644
--- a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitNameGenerator.java
+++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitNameGenerator.java
@@ -38,6 +38,10 @@ public static String nextVehicleName() {
         return nextUnitName(UnitType.VEHICLE);
     }
 
+    public static String nextAgentName() {
+        return nextUnitName(UnitType.AGENT);
+    }
+
     public static String nextRsuName() {
         return nextUnitName(UnitType.ROAD_SIDE_UNIT);
     }
@@ -62,6 +66,10 @@ public static boolean isVehicle(String name) {
         return isUnitType(UnitType.VEHICLE, name);
     }
 
+    public static boolean isAgent(String name) {
+        return isUnitType(UnitType.AGENT, name);
+    }
+
     public static boolean isRsu(String name) {
         return isUnitType(UnitType.ROAD_SIDE_UNIT, name);
     }
diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitType.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitType.java
index 235c4e0b0..2b548bfb4 100644
--- a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitType.java
+++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/UnitType.java
@@ -18,6 +18,7 @@
 public enum UnitType {
 
     VEHICLE("veh"),
+    AGENT("agent"),
     ROAD_SIDE_UNIT("rsu"),
     TRAFFIC_MANAGEMENT_CENTER("tmc"),
     TRAFFIC_LIGHT("tl"),
diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/addressing/IpResolver.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/addressing/IpResolver.java
index fe824da5a..acb9e8e36 100644
--- a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/addressing/IpResolver.java
+++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/addressing/IpResolver.java
@@ -81,6 +81,7 @@ public IpResolver(CIpResolver configuration) {
         Objects.requireNonNull(configuration.tlNet, "Invalid IpResolver configuration: No tlNet given");
         Objects.requireNonNull(configuration.csNet, "Invalid IpResolver configuration: No csNet given");
         Objects.requireNonNull(configuration.serverNet, "Invalid IpResolver configuration: No serverNet given");
+        Objects.requireNonNull(configuration.agentNet, "Invalid IpResolver configuration: No agentNet given");
         try {
             this.netMask = (Inet4Address) Inet4Address.getByName(configuration.netMask);
 
@@ -90,6 +91,7 @@ public IpResolver(CIpResolver configuration) {
             unitNetworks.put(UnitType.TRAFFIC_LIGHT, (Inet4Address) Inet4Address.getByName(configuration.tlNet));
             unitNetworks.put(UnitType.CHARGING_STATION, (Inet4Address) Inet4Address.getByName(configuration.csNet));
             unitNetworks.put(UnitType.SERVER, (Inet4Address) Inet4Address.getByName(configuration.serverNet));
+            unitNetworks.put(UnitType.AGENT, (Inet4Address) Inet4Address.getByName(configuration.agentNet));
 
         } catch (UnknownHostException ex) {
             throw new RuntimeException("Could not parse IP addresses from configuration");
diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/agent/AgentRoute.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/agent/AgentRoute.java
new file mode 100644
index 000000000..4fe2aa780
--- /dev/null
+++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/agent/AgentRoute.java
@@ -0,0 +1,135 @@
+/*
+ * 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.lib.objects.agent;
+
+import org.eclipse.mosaic.lib.geo.GeoPoint;
+import org.eclipse.mosaic.lib.objects.traffic.PublicTransportStop;
+import org.eclipse.mosaic.lib.objects.vehicle.VehicleDeparture;
+
+import com.google.common.collect.Lists;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A multi-modal route for an agent which consists of one or more legs. Each
+ * leg can use a different modality, such as public transport, walking, or using
+ * a private or shared vehicle.
+ */
+public class AgentRoute implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final List legs = Lists.newArrayList();
+
+    public AgentRoute(List legs) {
+        this.legs.addAll(legs);
+    }
+
+    /**
+     * Returns all legs of the agent route.
+     */
+    public List getLegs() {
+        return legs;
+    }
+
+    public static abstract class Leg implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        private final long departureTime;
+
+        private Leg(long departureTime) {
+            this.departureTime = departureTime;
+        }
+
+        public long getDepartureTime() {
+            return departureTime;
+        }
+    }
+
+    public static class PrivateVehicleLeg extends Leg {
+
+        private static final long serialVersionUID = 1L;
+
+        private final String vehicleType;
+        private final VehicleDeparture departure;
+
+        public PrivateVehicleLeg(long departureTime, String vehicleType, VehicleDeparture departure) {
+            super(departureTime);
+            this.vehicleType = vehicleType;
+            this.departure = departure;
+        }
+
+        public String getVehicleType() {
+            return vehicleType;
+        }
+
+        public VehicleDeparture getDeparture() {
+            return departure;
+        }
+    }
+
+    public static class SharedVehicleLeg extends Leg {
+
+        private static final long serialVersionUID = 1L;
+
+        private final String vehicleId;
+
+        public SharedVehicleLeg(long departureTime, String vehicleId) {
+            super(departureTime);
+            this.vehicleId = vehicleId;
+        }
+
+        public String getVehicleId() {
+            return vehicleId;
+        }
+    }
+
+    public static class PublicTransportLeg extends Leg {
+
+        private static final long serialVersionUID = 1L;
+
+        private final List stops = new ArrayList<>();
+
+        public PublicTransportLeg(long departureTime, List stops) {
+            super(departureTime);
+            this.stops.addAll(stops);
+        }
+
+        public final List getStops() {
+            return stops;
+        }
+    }
+
+    public static class WalkLeg extends Leg {
+
+        private static final long serialVersionUID = 1L;
+
+        private final List waypoints = new ArrayList<>();
+
+        public WalkLeg(long departureTime, List waypoints) {
+            super(departureTime);
+            this.waypoints.addAll(waypoints);
+        }
+
+        public final List getWaypoints() {
+            return waypoints;
+        }
+    }
+
+}
diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/mapping/AgentMapping.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/mapping/AgentMapping.java
new file mode 100644
index 000000000..81446be53
--- /dev/null
+++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/mapping/AgentMapping.java
@@ -0,0 +1,41 @@
+/*
+ * 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.lib.objects.mapping;
+
+import java.util.List;
+
+public class AgentMapping extends UnitMapping {
+
+    private static final long serialVersionUID = 1L;
+
+    private final double walkingSpeed;
+
+    /**
+     * Contains configuration of an agent.
+     * @param name name of the unit
+     * @param group group that the unit belongs to
+     * @param applications a list of applications to be mapped onto the unit
+     * @param walkingSpeed the speed this agent has when walking
+     */
+    public AgentMapping(final String name, final String group, final List applications, double walkingSpeed) {
+        super(name, group, applications);
+        this.walkingSpeed = walkingSpeed;
+    }
+
+    public double getWalkingSpeed() {
+        return walkingSpeed;
+    }
+}
diff --git a/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/traffic/PublicTransportStop.java b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/traffic/PublicTransportStop.java
new file mode 100644
index 000000000..ab7ceb1a9
--- /dev/null
+++ b/lib/mosaic-objects/src/main/java/org/eclipse/mosaic/lib/objects/traffic/PublicTransportStop.java
@@ -0,0 +1,29 @@
+/*
+ * 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.lib.objects.traffic;
+
+import org.eclipse.mosaic.lib.geo.GeoPoint;
+
+/**
+ * Each public transport stop consists of its geolocation and the planned arrival and departure time at the stop.
+ *
+ * @param location The geographic location of the stop.
+ * @param arrivalTime The time when arriving at this stop. {@code null} for the first stop of a leg.
+ * @param departureTime The time when leaving this stop. {@code null} for the last stop of a leg.
+ */
+public record PublicTransportStop(GeoPoint location, Long arrivalTime, Long departureTime) {
+
+}
diff --git a/lib/mosaic-objects/src/test/java/org/eclipse/mosaic/lib/objects/addressing/IpResolverTest.java b/lib/mosaic-objects/src/test/java/org/eclipse/mosaic/lib/objects/addressing/IpResolverTest.java
index 07d15463f..43a76f1d1 100644
--- a/lib/mosaic-objects/src/test/java/org/eclipse/mosaic/lib/objects/addressing/IpResolverTest.java
+++ b/lib/mosaic-objects/src/test/java/org/eclipse/mosaic/lib/objects/addressing/IpResolverTest.java
@@ -27,85 +27,95 @@
 import java.net.UnknownHostException;
 
 public class IpResolverTest {
-    
-    private final String testConfig = 
-"       {\n" +
-"			netMask: \"255.255.0.0\",\n" +
-"			vehicleNet: \"10.1.0.0\",\n" +
-"			rsuNet: \"10.2.0.0\",\n" +
-"			tlNet: \"10.3.0.0\",\n" +
-"			csNet: \"10.4.0.0\",\n" +
-"			strictAddressing: true\n" +
-"        }";
-    
+
+    private final String testConfig = """
+            {
+                "netMask": "255.255.0.0",
+                "vehicleNet": "10.1.0.0",
+                "rsuNet": "10.2.0.0",
+                "tlNet": "10.3.0.0",
+                "csNet": "10.4.0.0",
+                "agentNet": "10.10.0.0"
+            }
+            """;
+
     @Rule
     public IpResolverRule ipResolverRule = new IpResolverRule(testConfig);
-    
+
     @Test
     public void testCorrectSetup() {
         assertEquals(65534, IpResolver.getSingleton().getMaxRange());
     }
-    
+
     @Test
     public void testRoundTripVEHs() {
-        for (int i = 0; i< IpResolver.getSingleton().getMaxRange(); ++i) {
+        for (int i = 0; i < IpResolver.getSingleton().getMaxRange(); ++i) {
             final String name = "veh_" + i;
             Inet4Address nameToIp = IpResolver.getSingleton().nameToIp(name);
             String ipToName = IpResolver.getSingleton().ipToName(nameToIp);
             assertEquals(name, ipToName);
         }
     }
-    
+
     @Test
     public void testRoundTripRSUs() {
-        for (int i = 0; i< IpResolver.getSingleton().getMaxRange(); ++i) {
+        for (int i = 0; i < IpResolver.getSingleton().getMaxRange(); ++i) {
             final String name = "rsu_" + i;
             Inet4Address nameToIp = IpResolver.getSingleton().nameToIp(name);
             String ipToName = IpResolver.getSingleton().ipToName(nameToIp);
             assertEquals(name, ipToName);
         }
     }
-    
+
     @Test
     public void testRoundTripTLs() {
-        for (int i = 0; i< IpResolver.getSingleton().getMaxRange(); ++i) {
+        for (int i = 0; i < IpResolver.getSingleton().getMaxRange(); ++i) {
             final String name = "rsu_" + i;
             Inet4Address nameToIp = IpResolver.getSingleton().nameToIp(name);
             String ipToName = IpResolver.getSingleton().ipToName(nameToIp);
             assertEquals(name, ipToName);
         }
     }
-    
+
     @Test
     public void testRoundTripCSs() {
-        for (int i = 0; i< IpResolver.getSingleton().getMaxRange(); ++i) {
+        for (int i = 0; i < IpResolver.getSingleton().getMaxRange(); ++i) {
             final String name = "cs_" + i;
             Inet4Address nameToIp = IpResolver.getSingleton().nameToIp(name);
             String ipToName = IpResolver.getSingleton().ipToName(nameToIp);
             assertEquals(name, ipToName);
         }
     }
-    
-    @Test(expected=IllegalArgumentException.class)
+
+    @Test
+    public void testRoundTripAgents() {
+        for (int i = 0; i < IpResolver.getSingleton().getMaxRange(); ++i) {
+            final String name = "agent_" + i;
+            Inet4Address nameToIp = IpResolver.getSingleton().nameToIp(name);
+            String ipToName = IpResolver.getSingleton().ipToName(nameToIp);
+            assertEquals(name, ipToName);
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
     public void testIPv4AddressExhausted() {
-        final String name = "cs_" + IpResolver.getSingleton().getMaxRange()+1;
+        final String name = "cs_" + IpResolver.getSingleton().getMaxRange() + 1;
         // should throw an exception
         IpResolver.getSingleton().nameToIp(name);
     }
-    
+
     @Test
     public void testArrayIntConversion() {
-        try{
-            Inet4Address testAddress = (Inet4Address)Inet4Address.getByName("10.1.0.1");
+        try {
+            Inet4Address testAddress = (Inet4Address) Inet4Address.getByName("10.1.0.1");
             byte testArray[] = testAddress.getAddress();
             assertEquals(167837697, IpResolver.getSingleton().addressArrayToFlat(testArray));
-            
+
             byte testArray2[] = {10, 1, 0, 2};
             Assert.assertArrayEquals(testArray2, IpResolver.getSingleton().addressFlatToArray(167837698));
-        }
-        catch (UnknownHostException ex) {}
+        } catch (UnknownHostException ex) {}
     }
-    
+
     @Test
     public void testAddressAssignment() {
         Inet4Address ad1, ad2, ad3, ad4, ad5, ad6;
@@ -116,25 +126,29 @@ public void testAddressAssignment() {
         ad5 = IpResolver.getSingleton().registerHost("tl_65534");
         boolean exceptionThrown = false;
         try {
-            ad6 = IpResolver.getSingleton().registerHost("tl_65535");
-        } catch(RuntimeException ex) {
+            IpResolver.getSingleton().registerHost("tl_65535");
+        } catch (RuntimeException ex) {
             exceptionThrown = true;
         }
+        ad6 = IpResolver.getSingleton().registerHost("agent_1337");
+
         Assert.assertTrue(exceptionThrown);
-        byte array1[] = {10,1,0,7};
-        byte array2[] = {10,2,0,0};
-        byte array3[] = {10,3,0,100};
-        byte array4[] = {10,4,3,-24};
-        byte array5[] = {10,3,-1,-2};
+        byte[] array1 = {10, 1, 0, 7};
+        byte[] array2 = {10, 2, 0, 0};
+        byte[] array3 = {10, 3, 0, 100};
+        byte[] array4 = {10, 4, (byte) 3, (byte) 232};
+        byte[] array5 = {10, 3, (byte) 255, (byte) 254};
+        byte[] array6 = {10, 10, (byte) 5, (byte) 57};
         Assert.assertArrayEquals(array1, ad1.getAddress());
         Assert.assertArrayEquals(array2, ad2.getAddress());
         Assert.assertArrayEquals(array3, ad3.getAddress());
         Assert.assertArrayEquals(array4, ad4.getAddress());
         Assert.assertArrayEquals(array5, ad5.getAddress());
-        
+        Assert.assertArrayEquals(array6, ad6.getAddress());
+
         Inet4Address lookedUp = IpResolver.getSingleton().lookup("veh_7");
         assertEquals(ad1, lookedUp);
         lookedUp = IpResolver.getSingleton().lookup("veh_10");
-        Assert.assertNull(lookedUp);        
+        Assert.assertNull(lookedUp);
     }
 }
\ No newline at end of file
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/MultiModalLeg.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/MultiModalLeg.java
deleted file mode 100644
index 81c4b75a5..000000000
--- a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/MultiModalLeg.java
+++ /dev/null
@@ -1,136 +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.lib.routing.pt;
-
-import org.eclipse.mosaic.lib.objects.vehicle.VehicleDeparture;
-
-/**
- * A leg of a multi-modal-journey consists of a planned departure and planned arrival time, and
- * details about the transport mode, such as the walking path or the public transport route.
- */
-public class MultiModalLeg {
-
-    public enum Type {
-        /**
-         * For legs which uses public transport.
-         */
-        PUBLIC_TRANSPORT,
-        /**
-         * For legs which will require foot work.
-         */
-        WALKING,
-        /**
-         * For legs which require to spawn a new vehicle.
-         */
-        VEHICLE_PRIVATE,
-        /**
-         * For legs which uses a shared vehicle which already exists in the simulation.
-         */
-        VEHICLE_SHARED
-    }
-
-    private final Type legType;
-    private final long departureTime;
-    private final long arrivalTime;
-
-    /**
-     * For legs which uses public transport.
-     */
-    private PtLeg publicTransportationLeg = null;
-
-    /**
-     * For legs which will require foot work.
-     */
-    private WalkLeg walkLeg = null;
-
-    /**
-     * For legs which require to spawn a new vehicle.
-     */
-    private VehicleDeparture vehicleLeg = null;
-
-    /**
-     * For legs which uses a shared vehicle which already exists in the simulation.
-     */
-    private String sharedVehicleId = null;
-
-    /**
-     * Creates a new leg in which a new vehicle must be spawned.
-     */
-    public MultiModalLeg(VehicleDeparture vehicleLeg, long departureTime, long arrivalTime) {
-        this.legType = Type.VEHICLE_PRIVATE;
-        this.vehicleLeg = vehicleLeg;
-
-        this.departureTime = departureTime;
-        this.arrivalTime = arrivalTime;
-    }
-
-    /**
-     * Creates a new leg which uses public transport.
-     */
-    public MultiModalLeg(PtLeg ptRoute, long departureTime, long arrivalTime) {
-        this.legType = Type.PUBLIC_TRANSPORT;
-        this.publicTransportationLeg = ptRoute;
-
-        this.departureTime = departureTime;
-        this.arrivalTime = arrivalTime;
-    }
-
-    /**
-     * Creates a new leg which uses walking mode.
-     */
-    public MultiModalLeg(WalkLeg walkLeg, long departureTime, long arrivalTime) {
-        this.legType = Type.WALKING;
-        this.walkLeg = walkLeg;
-
-        this.departureTime = departureTime;
-        this.arrivalTime = arrivalTime;
-    }
-
-    /**
-     * Creates a new leg which uses a shared vehicle by a given vehicle ID.
-     */
-    public MultiModalLeg(String vehicleId, long departureTime, long arrivalTime) {
-        this.legType = Type.VEHICLE_PRIVATE;
-        this.sharedVehicleId = vehicleId;
-
-        this.departureTime = departureTime;
-        this.arrivalTime = arrivalTime;
-    }
-
-    public long getArrivalTime() {
-        return arrivalTime;
-    }
-
-    public long getDepartureTime() {
-        return departureTime;
-    }
-
-    public Type getLegType() {
-        return legType;
-    }
-
-    /**
-     * TODO: we should redesign this class somehow that we don't have to return Object here.
-     */
-    public Object getLeg() {
-        return switch (legType) {
-            case VEHICLE_PRIVATE -> vehicleLeg;
-            case VEHICLE_SHARED -> sharedVehicleId;
-            case PUBLIC_TRANSPORT -> publicTransportationLeg;
-            case WALKING -> walkLeg;
-        };
-    }
-}
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/MultiModalRoute.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/MultiModalRoute.java
deleted file mode 100644
index a696586a5..000000000
--- a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/MultiModalRoute.java
+++ /dev/null
@@ -1,39 +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.lib.routing.pt;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A multi-modal route which consists of multiple legs.
- */
-public class MultiModalRoute {
-
-    private final List legs = new ArrayList<>();
-
-    public MultiModalRoute(List legs) {
-        this.legs.addAll(legs);
-    }
-
-    /**
-     * Returns the individual legs of this multi-modal route.
-     */
-    public List getLegs() {
-        return legs;
-    }
-
-}
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtLeg.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtLeg.java
deleted file mode 100644
index 903beaa6c..000000000
--- a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtLeg.java
+++ /dev/null
@@ -1,50 +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.lib.routing.pt;
-
-import org.eclipse.mosaic.lib.geo.GeoPoint;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A public transport leg contains all pt stops of the route.
- */
-public class PtLeg {
-
-    /**
-     * Each public transport stop consists of its geo-location and the planned arrival and departure time at this stop.
-     *
-     * @param location The geographic location of the stop.
-     * @param arrivalTime The time when arriving at this stop. {@code null} for the first stop of the leg.
-     * @param departureTime The time when leaving this stop. {@code null} for the last stop of the leg.
-     */
-    public record PtStop(GeoPoint location, Long arrivalTime, Long departureTime) {}
-
-    private final List stops = new ArrayList<>();
-
-    public PtLeg(List stops) {
-        this.stops.addAll(stops);
-    }
-
-    /**
-     * Returns the list of stops along the public transport route.
-     */
-    public List getStops() {
-        return stops;
-    }
-
-}
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoute.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoute.java
new file mode 100644
index 000000000..2620a4795
--- /dev/null
+++ b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoute.java
@@ -0,0 +1,102 @@
+/*
+ * 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.lib.routing.pt;
+
+import org.eclipse.mosaic.lib.geo.GeoPoint;
+import org.eclipse.mosaic.lib.objects.traffic.PublicTransportStop;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A public transport route which consists of multiple legs, which either
+ * use a public transport facility, or walking..
+ */
+public class PtRoute {
+
+    private final List legs = new ArrayList<>();
+
+    public PtRoute(Leg... legs) {
+        this(Arrays.asList(legs));
+    }
+
+    public PtRoute(List legs) {
+        this.legs.addAll(legs);
+    }
+
+    /**
+     * Returns the individual legs of this multi-modal route.
+     */
+    public List getLegs() {
+        return legs;
+    }
+
+    public static abstract class Leg {
+
+        private final long departureTime;
+        private final long arrivalTime;
+
+        protected Leg(long departureTime, long arrivalTime) {
+            this.departureTime = departureTime;
+            this.arrivalTime = arrivalTime;
+        }
+
+        public long getArrivalTime() {
+            return arrivalTime;
+        }
+
+        public long getDepartureTime() {
+            return departureTime;
+        }
+    }
+
+    public static class PtLeg extends Leg {
+
+        private final List stops = new ArrayList<>();
+
+        public PtLeg(long departureTime, long arrivalTime, List stops) {
+            super(departureTime, arrivalTime);
+            this.stops.addAll(stops);
+        }
+
+        /**
+         * Returns the list of stops along the public transport route.
+         */
+        public List getStops() {
+            return stops;
+        }
+
+    }
+
+    public static class WalkLeg extends Leg {
+
+        private final List waypoints = new ArrayList<>();
+
+        public WalkLeg(long departureTime, long arrivalTime, List waypoints) {
+            super(departureTime, arrivalTime);
+            this.waypoints.addAll(waypoints);
+        }
+
+        /**
+         * Returns the list of geographical positions which form the walking route.
+         */
+        public final List getWaypoints() {
+            return waypoints;
+        }
+    }
+
+}
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRouting.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRouting.java
index fb86da19c..acb1855aa 100644
--- a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRouting.java
+++ b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRouting.java
@@ -17,6 +17,7 @@
 
 import org.eclipse.mosaic.lib.geo.GeoPoint;
 import org.eclipse.mosaic.lib.math.SpeedUtils;
+import org.eclipse.mosaic.lib.objects.traffic.PublicTransportStop;
 import org.eclipse.mosaic.lib.routing.config.CPublicTransportRouting;
 
 import com.google.common.collect.Iterables;
@@ -59,7 +60,6 @@
 /**
  * Implementation of Public Transport Routing based on GraphHopper GTFS.
  * Uses a GTFS file for public transport schedule and an OSM file for walking paths to get access to public transport stations.
- *
  */
 public class PtRouting {
 
@@ -136,7 +136,12 @@ public PtRoutingResponse findPtRoute(PtRoutingRequest request) {
         );
         // ghRequest.setBlockedRouteTypes(request.getRoutingParameters().excludedPtModes);//FIXME generalize this
         ghRequest.setEarliestDepartureTime(departureTime);
-        ghRequest.setWalkSpeedKmH(SpeedUtils.ms2kmh(request.getRoutingParameters().getWalkingSpeedMps()));
+
+        if (request.getRoutingParameters().getWalkingSpeedMps() == null) {
+            ghRequest.setWalkSpeedKmH(5);
+        } else {
+            ghRequest.setWalkSpeedKmH(SpeedUtils.ms2kmh(request.getRoutingParameters().getWalkingSpeedMps()));
+        }
 
         final Future responseFuture = routingExecution.submit(() -> ptRouter.route(ghRequest));
         final GHResponse route;
@@ -153,41 +158,41 @@ public PtRoutingResponse findPtRoute(PtRoutingRequest request) {
             throw new RuntimeException("Could not finish route calculation. Exceeded timeout.", e);
         }
 
-        final List legs = convertToMultiModalLegs(route.getBest());
+        final PtRoute ptRoute = convertToPtRoute(route.getBest());
 
-        return new PtRoutingResponse(new MultiModalRoute(legs));
+        return new PtRoutingResponse(ptRoute);
     }
 
-    private List convertToMultiModalLegs(ResponsePath ghBestRoute) {
-        List legs = new ArrayList<>();
+    private PtRoute convertToPtRoute(ResponsePath ghBestRoute) {
+        final List legs = new ArrayList<>();
         for (Trip.Leg leg : ghBestRoute.getLegs()) {
             if (leg instanceof Trip.PtLeg ptLeg) {
-                List newStops = new ArrayList<>();
+                final List newStops = new ArrayList<>();
                 for (Trip.Stop stop : ptLeg.stops) {
-                    newStops.add(new PtLeg.PtStop(
+                    newStops.add(new PublicTransportStop(
                             GeoPoint.lonLat(stop.geometry.getX(), stop.geometry.getY()),
                             fromScheduleTime(stop.arrivalTime),
                             fromScheduleTime(stop.departureTime)
                     ));
                 }
-                legs.add(new MultiModalLeg(
-                        new PtLeg(newStops),
+                legs.add(new PtRoute.PtLeg(
                         newStops.get(0).departureTime(),
-                        Iterables.getLast(newStops).arrivalTime()
+                        Iterables.getLast(newStops).arrivalTime(),
+                        newStops
                 ));
             } else if (leg instanceof Trip.WalkLeg walkLeg) {
-                List waypoints = new ArrayList<>();
+                final List waypoints = new ArrayList<>();
                 for (Coordinate coordinate : walkLeg.geometry.getCoordinates()) {
                     waypoints.add(GeoPoint.lonLat(coordinate.x, coordinate.y));
                 }
-                legs.add(new MultiModalLeg(
-                        new WalkLeg(waypoints),
+                legs.add(new PtRoute.WalkLeg(
                         fromScheduleTime(leg.getDepartureTime()),
-                        fromScheduleTime(leg.getArrivalTime())
+                        fromScheduleTime(leg.getArrivalTime()),
+                        waypoints
                 ));
             }
         }
-        return legs;
+        return new PtRoute(legs);
     }
 
     /**
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingParameters.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingParameters.java
index 08358b365..7ad62e769 100644
--- a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingParameters.java
+++ b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingParameters.java
@@ -17,21 +17,32 @@
 
 import org.eclipse.mosaic.lib.math.SpeedUtils;
 
+import javax.annotation.Nullable;
+
+/**
+ * Additional parameters used when calculating public transport routes.
+ */
 public class PtRoutingParameters {
 
-    private double walkingSpeedMps = SpeedUtils.kmh2ms(5);
+    private Double walkingSpeedMps = null;
 
+    /**
+     * Sets the walking speed in km/h.
+     */
     public PtRoutingParameters walkingSpeedKmh(double kmh) {
         walkingSpeedMps = SpeedUtils.kmh2ms(kmh);
         return this;
     }
 
+    /**
+     * Sets the walking speed in m/s
+     */
     public PtRoutingParameters walkingSpeedMps(double meterPerSecond) {
         walkingSpeedMps = meterPerSecond;
         return this;
     }
 
-    public double getWalkingSpeedMps() {
+    public @Nullable Double getWalkingSpeedMps() {
         return walkingSpeedMps;
     }
 }
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingResponse.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingResponse.java
index b60e57708..2ad20717b 100644
--- a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingResponse.java
+++ b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingResponse.java
@@ -19,4 +19,4 @@
  * The result of the routing request. Contains the multi-modal route which
  * matches the routing request at best.
  */
-public record PtRoutingResponse(MultiModalRoute bestRoute) { }
+public record PtRoutingResponse(PtRoute bestRoute) { }
diff --git a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/WalkLeg.java b/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/WalkLeg.java
deleted file mode 100644
index ff7d98931..000000000
--- a/lib/mosaic-routing/src/main/java/org/eclipse/mosaic/lib/routing/pt/WalkLeg.java
+++ /dev/null
@@ -1,40 +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.lib.routing.pt;
-
-import org.eclipse.mosaic.lib.geo.GeoPoint;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A walking leg contains a linestring of geographical points which form the walking route.
- */
-public class WalkLeg {
-
-    private final List waypoints = new ArrayList<>();
-
-    public WalkLeg(List waypoints) {
-        this.waypoints.addAll(waypoints);
-    }
-
-    /**
-     * Returns the list of geographical positions which form the walking route.
-     */
-    public final List getWaypoints() {
-        return waypoints;
-    }
-}
diff --git a/lib/mosaic-routing/src/test/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingTest.java b/lib/mosaic-routing/src/test/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingTest.java
index 3098d23c4..b2688379c 100644
--- a/lib/mosaic-routing/src/test/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingTest.java
+++ b/lib/mosaic-routing/src/test/java/org/eclipse/mosaic/lib/routing/pt/PtRoutingTest.java
@@ -16,6 +16,7 @@
 package org.eclipse.mosaic.lib.routing.pt;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import org.eclipse.mosaic.lib.geo.GeoPoint;
 import org.eclipse.mosaic.lib.junit.GeoProjectionRule;
@@ -83,11 +84,11 @@ public void findRoute_findPublicTransportRoute() {
         ));
 
         // ASSERT
-        MultiModalRoute route = response.bestRoute();
+        PtRoute route = response.bestRoute();
         assertEquals(3, route.getLegs().size());
-        assertEquals(MultiModalLeg.Type.WALKING, route.getLegs().get(0).getLegType());
-        assertEquals(MultiModalLeg.Type.PUBLIC_TRANSPORT, route.getLegs().get(1).getLegType());
-        assertEquals(MultiModalLeg.Type.WALKING, route.getLegs().get(2).getLegType());
+        assertTrue(route.getLegs().get(0) instanceof PtRoute.WalkLeg);
+        assertTrue(route.getLegs().get(1) instanceof PtRoute.PtLeg);
+        assertTrue(route.getLegs().get(2) instanceof PtRoute.WalkLeg);
     }
 
     @Test
@@ -102,9 +103,9 @@ public void findRoute_IWalkFasterThanTheBus() {
         ));
 
         // ASSERT
-        MultiModalRoute route = response.bestRoute();
+        PtRoute route = response.bestRoute();
         assertEquals(1, route.getLegs().size());
-        assertEquals(MultiModalLeg.Type.WALKING, route.getLegs().get(0).getLegType());
+        assertTrue(route.getLegs().get(0) instanceof PtRoute.WalkLeg);
     }
 
 }
diff --git a/pom.xml b/pom.xml
index 6b7b7c17f..56af28e4b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -535,6 +535,7 @@
                             
${parent.dir}/legal/templates/license-header-2022.txt
${parent.dir}/legal/templates/license-header-2023.txt
${parent.dir}/legal/templates/license-header-2024.txt
+
${parent.dir}/legal/templates/license-header-2025.txt
diff --git a/rti/mosaic-rti-api/src/main/java/org/eclipse/mosaic/rti/config/CIpResolver.java b/rti/mosaic-rti-api/src/main/java/org/eclipse/mosaic/rti/config/CIpResolver.java index b066594c1..100e13329 100644 --- a/rti/mosaic-rti-api/src/main/java/org/eclipse/mosaic/rti/config/CIpResolver.java +++ b/rti/mosaic-rti-api/src/main/java/org/eclipse/mosaic/rti/config/CIpResolver.java @@ -26,4 +26,5 @@ public class CIpResolver { public String csNet = "13.0.0.0"; public String serverNet = "14.0.0.0"; public String tmcNet = "15.0.0.0"; + public String agentNet = "20.0.0.0"; } \ No newline at end of file diff --git a/rti/mosaic-starter/etc/runtime.json b/rti/mosaic-starter/etc/runtime.json index 07ac4416a..7770d55f0 100644 --- a/rti/mosaic-starter/etc/runtime.json +++ b/rti/mosaic-starter/etc/runtime.json @@ -11,6 +11,7 @@ "deploy": false, "start": false, "subscriptions": [ + "AgentRegistration", "RsuRegistration", "TmcRegistration", "ServerRegistration",