Skip to content

Commit

Permalink
Merge pull request #3686 from matsim-org/vehicularDepartureHandler
Browse files Browse the repository at this point in the history
Vehicular departure handler
  • Loading branch information
kainagel authored Jan 25, 2025
2 parents f9b164e + 95e9546 commit 110ce7e
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.matsim.core.mobsim.qsim.interfaces.DepartureHandler;
import org.matsim.core.mobsim.qsim.interfaces.MobsimEngine;
import org.matsim.core.mobsim.qsim.pt.TransitDriverAgent;
import org.matsim.core.mobsim.qsim.qnetsimengine.NetworkModeDepartureHandler;
import org.matsim.core.mobsim.qsim.qnetsimengine.QLinkI;
import org.matsim.core.mobsim.qsim.qnetsimengine.QNetsimEngineI;
import org.matsim.core.mobsim.qsim.qnetsimengine.QVehicle;
Expand All @@ -56,13 +57,18 @@
*
* @author nkuehnel / MOIA, hrewald
*
* Remarks @kainagel: <ul>
* <li> I have renamed the VehicularDepartureHandler to {@link NetworkModeDepartureHandler}. Also, this is now an interface, bound against a default implementation. </li>
* <li>There are probably more changes to come, like _replacing_ the {@link NetworkModeDepartureHandler} rather than adding another {@link DepartureHandler} which effectively over-writes it. </li>
* </ul>
*
*/
public class FISS implements DepartureHandler, MobsimEngine {

private static final Logger LOG = LogManager.getLogger(FISS.class);

private final QNetsimEngineI qNetsimEngine;
private final DepartureHandler delegate;
private final DepartureHandler delegate;
private final FISSConfigGroup fissConfigGroup;
private final TeleportationEngine teleport;
private final Network network;
Expand All @@ -72,10 +78,10 @@ public class FISS implements DepartureHandler, MobsimEngine {
private final MatsimServices matsimServices;


FISS(MatsimServices matsimServices, QNetsimEngineI qNetsimEngine, Scenario scenario, EventsManager eventsManager, FISSConfigGroup fissConfigGroup,
TravelTime travelTime) {
FISS( MatsimServices matsimServices, QNetsimEngineI qNetsimEngine, Scenario scenario, EventsManager eventsManager, FISSConfigGroup fissConfigGroup,
TravelTime travelTime, NetworkModeDepartureHandler networkModeDepartureHandler ) {
this.qNetsimEngine = qNetsimEngine;
this.delegate = qNetsimEngine.getDepartureHandler();
this.delegate = networkModeDepartureHandler;
this.fissConfigGroup = fissConfigGroup;
this.teleport = new DefaultTeleportationEngine(scenario, eventsManager);
this.travelTime = travelTime;
Expand All @@ -84,8 +90,8 @@ public class FISS implements DepartureHandler, MobsimEngine {
this.matsimServices = matsimServices;
}

@Override
public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
@Override
public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
if (this.fissConfigGroup.sampledModes.contains(agent.getMode())) {
if (random.nextDouble() < fissConfigGroup.sampleFactor || agent instanceof TransitDriverAgent || this.switchOffFISS()) {
return delegate.handleDeparture(now, agent, linkId);
Expand All @@ -97,7 +103,7 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
NetworkRoute networkRoute = (NetworkRoute) currentLeg.getRoute();
Person person = planAgent.getCurrentPlan().getPerson();
Vehicle vehicle = this.matsimServices.getScenario().getVehicles().getVehicles()
.get(networkRoute.getVehicleId());
.get(networkRoute.getVehicleId());

// update travel time with travel times of last iteration
double newTravelTime = 0.0;
Expand All @@ -120,7 +126,7 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
if (removedVehicle == null) {
throw new RuntimeException(
"Could not remove parked vehicle with id " + vehicleId + " on the link id "
// + linkId
// + linkId
+ vehicle.getCurrentLink().getId()
+ ". Maybe it is currently used by someone else?"
+ " (In which case ignoring this exception would lead to duplication of this vehicle.) "
Expand All @@ -132,7 +138,7 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
if (removedVehicle != null) {
Id<Link> destinationLinkId = agent.getDestinationLinkId();
QLinkI qLinkDest = (QLinkI) this.qNetsimEngine.getNetsimNetwork()
.getNetsimLink(destinationLinkId);
.getNetsimLink(destinationLinkId);
qLinkDest.addParkedVehicle(removedVehicle);
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.matsim.core.config.groups.QSimConfigGroup;
import org.matsim.core.controler.MatsimServices;
import org.matsim.core.mobsim.qsim.AbstractQSimModule;
import org.matsim.core.mobsim.qsim.qnetsimengine.NetworkModeDepartureHandler;
import org.matsim.core.mobsim.qsim.qnetsimengine.QNetsimEngineI;
import org.matsim.core.router.util.TravelTime;

Expand All @@ -36,11 +37,12 @@ protected void configureQSim() {

@Provides
@Singleton
FISS provideMultiModalDepartureHandler(MatsimServices matsimServices, QNetsimEngineI qNetsimEngine,
QSimConfigGroup qsimConfig, Scenario scenario, EventsManager eventsManager,
@Named(TransportMode.car) TravelTime travelTime) {
FISS provideMultiModalDepartureHandler( MatsimServices matsimServices, QNetsimEngineI qNetsimEngine,
QSimConfigGroup qsimConfig, Scenario scenario, EventsManager eventsManager,
@Named(TransportMode.car) TravelTime travelTime, NetworkModeDepartureHandler networkModeDepartureHandler ) {
Config config = scenario.getConfig();
FISSConfigGroup fissConfigGroup = ConfigUtils.addOrGetModule(config, FISSConfigGroup.class);
return new FISS(matsimServices, qNetsimEngine, scenario, eventsManager, fissConfigGroup, travelTime);
return new FISS(matsimServices, qNetsimEngine, scenario, eventsManager, fissConfigGroup, travelTime, networkModeDepartureHandler );
}
// yyyyyy I am not sure if the above @Provides is really necessary. Could as well inject the FISS class directly. kai, jan'25
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ public class JointModesDepartureHandler implements DepartureHandler , MobsimEngi

public JointModesDepartureHandler(
final QNetsimEngineI netsimEngine) {
this( new NetsimWrappingQVehicleProvider( netsimEngine ),
netsimEngine.getDepartureHandler() );
// this( new NetsimWrappingQVehicleProvider( netsimEngine ),
// netsimEngine.getVehicularDepartureHandler() );
throw new RuntimeException("this execution path is no longer possible. You have to set the NetworkModeDepartureHandler (aka VehicularDepartureHandler) upstream. kai, jan'25");
}

public JointModesDepartureHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ abstract class AbstractQNetsimEngine<A extends AbstractQNetsimEngineRunner> impl

private final Map<Id<Vehicle>, QVehicle> vehicles = new HashMap<>();
private final QSim qsim;
private final VehicularDepartureHandler dpHandler;
private final NetworkModeDepartureHandler dpHandler;
// private final Set<QLinkI> linksToActivateInitially = new HashSet<>();
protected final int numOfThreads;
protected final QNetwork qNetwork;
Expand All @@ -89,7 +89,13 @@ abstract class AbstractQNetsimEngine<A extends AbstractQNetsimEngineRunner> impl
private List<A> engines;
private InternalInterface internalInterface = null;

AbstractQNetsimEngine(final QSim sim, QNetworkFactory netsimNetworkFactory) {
AbstractQNetsimEngine(final QSim sim, QNetworkFactory netsimNetworkFactory, NetworkModeDepartureHandler dpHandler) {
if ( netsimNetworkFactory==null ) {
throw new RuntimeException( "this execution path is no longer allowed; network factory needs to come from elsewhere (in general via injection). kai, jun'23" );
}
Gbl.assertNotNull( dpHandler );
this.dpHandler = dpHandler;

this.qsim = sim;

final Config config = sim.getScenario().getConfig();
Expand All @@ -105,7 +111,10 @@ abstract class AbstractQNetsimEngine<A extends AbstractQNetsimEngineRunner> impl
default:
throw new RuntimeException("Unknown vehicle behavior option.");
}
dpHandler = new VehicularDepartureHandler(this, vehicleBehavior, qSimConfigGroup);

// this.dpHandler = new NetworkModeDepartureHandlerDefaultImpl(this, vehicleBehavior, qSimConfigGroup);
// // VehicularDepartureHandler is the generalized departure handler for vehicles routed on the network. yyyy why is it created here
// // manually when it is also made available via injection? kai, jan'25

if(qSimConfigGroup.getLinkDynamics().equals(LinkDynamics.SeepageQ)) {
log.info("Seepage is allowed. Seep mode(s) is(are) " + qSimConfigGroup.getSeepModes() + ".");
Expand All @@ -114,18 +123,8 @@ abstract class AbstractQNetsimEngine<A extends AbstractQNetsimEngineRunner> impl
}
}

if (netsimNetworkFactory != null){
qNetwork = new QNetwork( sim.getScenario().getNetwork(), netsimNetworkFactory ) ;
} else {
throw new RuntimeException( "this execution path is no longer allowed; network factory needs to come from elsewhere (in general via injection). kai, jun'23" );
// Scenario scenario = sim.getScenario();
// EventsManager events = sim.getEventsManager() ;
// final DefaultQNetworkFactory netsimNetworkFactory2 = new DefaultQNetworkFactory( events, scenario );
// MobsimTimer mobsimTimer = sim.getSimTimer() ;
// AgentCounter agentCounter = sim.getAgentCounter() ;
// netsimNetworkFactory2.initializeFactory(agentCounter, mobsimTimer, ii );
// qNetwork = new QNetwork(sim.getScenario().getNetwork(), netsimNetworkFactory2 );
}
qNetwork = new QNetwork( sim.getScenario().getNetwork(), netsimNetworkFactory ) ;

qNetwork.initialize(this, sim.getAgentCounter(), sim.getSimTimer() );

this.numOfThreads = sim.getScenario().getConfig().qsim().getNumberOfThreads();
Expand Down Expand Up @@ -154,8 +153,7 @@ static AbstractAgentSnapshotInfoBuilder createAgentSnapshotInfoBuilder(Scenario

@Override
public final void onPrepareSim() {
this.infoTime =
Math.floor(internalInterface.getMobsim().getSimTimer().getSimStartTime() / INFO_PERIOD) * INFO_PERIOD;
this.infoTime = Math.floor(internalInterface.getMobsim().getSimTimer().getSimStartTime() / INFO_PERIOD) * INFO_PERIOD;
/*
* infoTime may be < simStartTime, this ensures to print out the
* info at the very first timestep already
Expand Down Expand Up @@ -273,12 +271,14 @@ public final int getNumberOfSimulatedNodes() {
}

public final NetsimNetwork getNetsimNetwork() {
// yy isn't this available from injection? kai, jan'25
return this.qNetwork;
}

public final VehicularDepartureHandler getDepartureHandler() {
return dpHandler;
}
// public final NetworkModeDepartureHandler getVehicularDepartureHandler() {
// return dpHandler;
// }
// get from injection

public final Map<Id<Vehicle>, QVehicle> getVehicles() {
return Collections.unmodifiableMap(this.vehicles);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.matsim.core.mobsim.qsim.qnetsimengine;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.core.mobsim.framework.MobsimAgent;
import org.matsim.core.mobsim.qsim.interfaces.DepartureHandler;

/**
* marker interface in order to be able to bind that specific departure handler for network mode departures. kai, jan'25
*/
public interface NetworkModeDepartureHandler extends DepartureHandler{

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.util.Collection;

import com.google.inject.Inject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
Expand All @@ -29,32 +30,30 @@
import org.matsim.core.config.groups.QSimConfigGroup.VehicleBehavior;
import org.matsim.core.mobsim.framework.MobsimAgent;
import org.matsim.core.mobsim.framework.MobsimDriverAgent;
import org.matsim.core.mobsim.qsim.interfaces.DepartureHandler;
import org.matsim.vehicles.Vehicle;

class VehicularDepartureHandler implements DepartureHandler {
class NetworkModeDepartureHandlerDefaultImpl implements NetworkModeDepartureHandler {

private static final Logger log = LogManager.getLogger(VehicularDepartureHandler.class);
private static final Logger log = LogManager.getLogger( NetworkModeDepartureHandlerDefaultImpl.class );

private int cntTeleportVehicle = 0;

private final VehicleBehavior vehicleBehavior;

private final QNetsimEngineI qNetsimEngine;

private final Collection<String> transportModes;
private final Collection<String> networkModes;

VehicularDepartureHandler(QNetsimEngineI qNetsimEngine, VehicleBehavior vehicleBehavior, QSimConfigGroup qsimConfig) {
@Inject /* deliberately package-private */ NetworkModeDepartureHandlerDefaultImpl( QNetsimEngineI qNetsimEngine, QSimConfigGroup qsimConfig ) {
this.qNetsimEngine = qNetsimEngine;
this.vehicleBehavior = vehicleBehavior;
this.transportModes =qsimConfig.getMainModes();
this.vehicleBehavior = qsimConfig.getVehicleBehavior();
this.networkModes =qsimConfig.getMainModes();
}

@Override
public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
if (this.transportModes.contains(agent.getMode())) {
@Override public boolean handleDeparture( double now, MobsimAgent agent, Id<Link> linkId ) {
if (this.networkModes.contains(agent.getMode() )) {
if ( agent instanceof MobsimDriverAgent ) {
handleCarDeparture(now, (MobsimDriverAgent)agent, linkId);
handleNetworkModeDeparture(now, (MobsimDriverAgent)agent, linkId );
return true;
} else {
throw new UnsupportedOperationException("wrong agent type to depart on a network mode");
Expand All @@ -63,7 +62,7 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
return false;
}

private void handleCarDeparture(double now, MobsimDriverAgent agent, Id<Link> linkId) {
private void handleNetworkModeDeparture( double now, MobsimDriverAgent agent, Id<Link> linkId ) {
// The situation where a leg starts and ends at the same link used to be
// handled specially, for all agents except AbstractTransitDriverAgents.
// This however caused some problems in some cases, as apparently for taxicabs.
Expand All @@ -79,8 +78,7 @@ private void handleCarDeparture(double now, MobsimDriverAgent agent, Id<Link> li
// log a maximum of information, to help the user identifying the cause of the problem
final String msg = "could not find requested vehicle "+vehicleId+" in simulation for agent "+agent+" with id "+agent.getId()+" on link "+agent.getCurrentLinkId()+" at time "+now+".";
log.error( msg );
log.error( "Note that, with AgentSource and if the agent starts on a leg, the "
+ "vehicle needs to be inserted BEFORE the agent!") ;
log.error( "Note that, with AgentSource and if the agent starts on a leg, the vehicle needs to be inserted BEFORE the agent!") ;
throw new RuntimeException( msg+" aborting ...") ;
}
teleportVehicleTo(vehicle, linkId);
Expand Down Expand Up @@ -117,7 +115,6 @@ private void teleportVehicleTo(QVehicle vehicle, Id<Link> linkId) {
QVehicle result = qlinkOld.removeParkedVehicle(vehicle.getId());
if ( result==null ) {
throw new RuntimeException( "Could not remove parked vehicle with id " + vehicle.getId() +" on the link id "
// + linkId
+ vehicle.getCurrentLink().getId()
+ ". Maybe it is currently used by someone else?"
+ " (In which case ignoring this exception would lead to duplication of this vehicle.) "
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ interface NetsimInternalInterface {

int getNumberOfSimulatedNodes();

VehicularDepartureHandler getDepartureHandler();
// NetworkModeDepartureHandler getVehicularDepartureHandler();
// get from injection

Map<Id<Vehicle>, QVehicle> getVehicles();

void printEngineRunTimes();

NetsimInternalInterface getNetsimInternalInterface();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ public final class QNetsimEngineModule extends AbstractQSimModule {
@Override
protected void configureQSim() {
bind(QNetsimEngineI.class).to(QNetsimEngineWithThreadpool.class).in( Singleton.class );
bind(VehicularDepartureHandler.class).toProvider(QNetsimEngineDepartureHandlerProvider.class).in( Singleton.class );
// in the two lines above, I changed "asEagerSingleton" to "in( Singleton.class )", since forcing construction early often leads to problems. kai, jun'23
bind( NetworkModeDepartureHandler.class ).to(NetworkModeDepartureHandlerDefaultImpl.class ).in( Singleton.class );

if ( this.getConfig().qsim().isUseLanes() ) {
bind(QNetworkFactory.class).to( QLanesNetworkFactory.class ).in( Singleton.class ) ;
bind( DefaultQNetworkFactory.class ).in( Singleton.class );
// (need this here because QLanesNetworkFactory uses it as a delegate. maybe some other design would be better? kai, jun'23)
// (need this here because QLanesNetworkFactory uses it as a delegate.)
} else {
bind(QNetworkFactory.class).to( DefaultQNetworkFactory.class ).in( Singleton.class) ;
}
// I added in(Singleton.class) above. Might cause problems with parallel implementations? kai, jun'23

// defining this here so we do not have to hedge against null:
Multibinder.newSetBinder( this.binder(), LinkSpeedCalculator.class );
Expand All @@ -51,7 +49,13 @@ protected void configureQSim() {
// Multibinder.newSetBinder( this.binder(), LinkSpeedCalculator.class ).addBinding().to...
// yyyy maybe move as generalized syntax to AbstractQSimModule

addQSimComponentBinding( COMPONENT_NAME ).to( VehicularDepartureHandler.class );
// ---
// the following will automatically register the corresponding capabilities with the qsim:

addQSimComponentBinding( COMPONENT_NAME ).to( NetworkModeDepartureHandler.class );
// (this will register the DepartureHandler functionality)

addQSimComponentBinding( COMPONENT_NAME ).to( QNetsimEngineI.class );
// (this will register the MobsimEngine functionality)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ final class QNetsimEngineWithThreadpool extends AbstractQNetsimEngine<QNetsimEng
// this(sim, null);
// }

@Inject QNetsimEngineWithThreadpool(final QSim sim, QNetworkFactory netsimNetworkFactory) {
super(sim, netsimNetworkFactory);
@Inject QNetsimEngineWithThreadpool(final QSim sim, QNetworkFactory netsimNetworkFactory, NetworkModeDepartureHandler networkModeDepartureHandler) {
super(sim, netsimNetworkFactory, networkModeDepartureHandler);
this.numOfRunners = this.numOfThreads;
}

Expand Down

0 comments on commit 110ce7e

Please sign in to comment.