20 package org.matsim.core.mobsim.qsim.qnetsimengine;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.LinkedHashMap;
28 import java.util.LinkedHashSet;
29 import java.util.LinkedList;
30 import java.util.List;
32 import java.util.Queue;
34 import java.util.concurrent.ConcurrentHashMap;
36 import org.apache.logging.log4j.LogManager;
37 import org.apache.logging.log4j.Logger;
67 abstract class AbstractQLink
implements QLinkI {
78 private static final Logger log = LogManager.getLogger(AbstractQLink.class);
80 private final Link link;
83 private NetElementActivationRegistry netElementActivationRegistry;
88 private final Map<String, Object> customAttributes =
new HashMap<>();
91 private final Map<Id<Vehicle>,
QVehicle> parkedVehicles =
new ConcurrentHashMap<>(10);
94 private final Map<Id<Person>,
MobsimAgent> additionalAgentsOnLink =
new ConcurrentHashMap<>( ) ;
96 private final Map<Id<Vehicle>, Queue<MobsimDriverAgent>> driversWaitingForCars =
new LinkedHashMap<>();
98 private final Map<Id<Person>,
MobsimDriverAgent> driversWaitingForPassengers =
new LinkedHashMap<>();
100 private final Map<Id<Vehicle>, Set<MobsimAgent>> passengersWaitingForCars =
new LinkedHashMap<>();
107 private final Queue<QVehicle> waitingList =
new LinkedList<>();
109 private boolean active =
false;
111 private TransitQLink transitQLink;
113 private final QNodeI toQNode ;
123 this.toQNode = toNode ;
124 this.context = context;
125 this.netsimEngine = netsimEngine2;
126 this.linkSpeedCalculator = linkSpeedCalculator;
127 this.vehicleHandler = vehicleHandler;
131 public QNodeI getToNode() {
142 private void activateLink() {
144 netElementActivationRegistry.registerLinkAsActive(
this);
149 private static int wrnCnt = 0 ;
151 public final void addParkedVehicle(
MobsimVehicle vehicle,
boolean isInitial) {
154 if ( this.parkedVehicles.put(qveh.
getId(), qveh) != null ) {
157 log.warn(
"existing vehicle on link was just overwritten by other vehicle with same ID. Not clear what this means. Continuing anyways ...") ;
170 addParkedVehicle(vehicle,
true);
173 final boolean letVehicleArrive(
QVehicle qveh) {
175 addParkedVehicle(qveh,
false);
181 makeVehicleAvailableToNextDriver(qveh);
190 return this.parkedVehicles.remove(vehicleId);
195 return this.parkedVehicles.get(vehicleId);
198 private final void addDepartingVehicle(
MobsimVehicle mvehicle) {
200 this.waitingList.add(vehicle);
207 public void registerAdditionalAgentOnLink(
MobsimAgent planAgent) {
208 this.additionalAgentsOnLink.put(planAgent.
getId(), planAgent);
213 return this.additionalAgentsOnLink.remove(mobsimAgentId);
217 public Collection<MobsimAgent> getAdditionalAgentsOnLink() {
218 return Collections.unmodifiableCollection( this.additionalAgentsOnLink.values());
222 public void clearVehicles() {
229 Set<Id<Person>> stuckAgents =
new HashSet<>();
231 for (
QVehicle veh : this.parkedVehicles.values()) {
232 if (veh.getDriver() != null) {
234 if (veh.getDriver().getState() !=
State.
LEG)
continue;
236 if (stuckAgents.contains(veh.getDriver().getId()))
continue;
237 else stuckAgents.add(veh.getDriver().getId());
243 new PersonStuckEvent(now, veh.getDriver().getId(), veh.getCurrentLink().getId(), veh.getDriver().getMode()));
244 context.getAgentCounter().
incLost();
249 if (stuckAgents.contains(passenger.getId()))
continue;
250 else stuckAgents.add(passenger.getId());
256 context.getAgentCounter().
incLost();
260 this.parkedVehicles.clear();
261 for (
MobsimAgent driver : driversWaitingForPassengers.values()) {
262 if (stuckAgents.contains(driver.getId()))
continue;
263 else stuckAgents.add(driver.getId());
266 new PersonStuckEvent(now, driver.getId(), driver.getCurrentLinkId(), driver.getMode()));
267 context.getAgentCounter().
incLost();
270 driversWaitingForPassengers.clear();
273 for (Queue<MobsimDriverAgent> queue : driversWaitingForCars.values()) {
275 if (stuckAgents.contains(driver.getId()))
continue;
276 stuckAgents.add(driver.getId());
279 new PersonStuckEvent(now, driver.getId(), driver.getCurrentLinkId(), driver.getMode()));
280 context.getAgentCounter().
incLost();
284 driversWaitingForCars.clear();
285 for (Set<MobsimAgent> passengers : passengersWaitingForCars.values()) {
287 if (stuckAgents.contains(passenger.getId()))
continue;
288 else stuckAgents.add(passenger.getId());
291 new PersonStuckEvent(now, passenger.getId(), passenger.getCurrentLinkId(), passenger.getMode()));
292 this.context.getAgentCounter().
incLost();
293 this.context.getAgentCounter().
decLiving();
296 this.passengersWaitingForCars.clear();
298 for (
QVehicle veh : this.waitingList) {
299 if (stuckAgents.contains(veh.getDriver().getId()))
continue;
300 else stuckAgents.add(veh.getDriver().getId());
306 new PersonStuckEvent(now, veh.getDriver().getId(), veh.getCurrentLink().getId(), veh.getDriver().getMode()));
307 this.context.getAgentCounter().
incLost();
308 this.context.getAgentCounter().
decLiving();
310 this.waitingList.clear();
313 void makeVehicleAvailableToNextDriver(
QVehicle veh) {
325 Set<MobsimAgent> passengers = this.passengersWaitingForCars.get(vehicleId);
326 if (passengers != null) {
328 List<MobsimAgent> passengersToHandle =
new ArrayList<>(passengers);
330 this.unregisterPassengerAgentWaitingForCar(passenger, vehicleId);
331 this.insertPassengerIntoVehicle(passenger, vehicleId);
340 final Queue<MobsimDriverAgent> driversWaitingForCar = driversWaitingForCars.get(veh.
getId());
341 final boolean thereIsDriverWaiting = driversWaitingForCar != null && !driversWaitingForCar.isEmpty();
342 if ( thereIsDriverWaiting ) {
344 driversWaitingForPassengers.get( driversWaitingForCar.element().getId());
345 if (driverWaitingForPassengers != null)
return;
352 if (thereIsDriverWaiting && veh.
getDriver() == null) {
354 veh.
setDriver(driversWaitingForCar.remove());
355 if (driversWaitingForCar.isEmpty()) {
356 final Queue<MobsimDriverAgent> r = driversWaitingForCars.remove(veh.
getId());
357 assert r == driversWaitingForCar;
359 removeParkedVehicle( veh.
getId() );
360 this.letVehicleDepart(veh);
365 public final void letVehicleDepart(
QVehicle vehicle) {
369 if (driver == null)
throw new RuntimeException(
"Vehicle cannot depart without a driver!");
373 this.addDepartingVehicle(vehicle);
385 QVehicle vehicle = this.getParkedVehicle(vehicleId);
388 if (vehicle == null) {
389 registerPassengerAgentWaitingForCar(passenger, vehicleId);
394 log.warn(
"Passenger " + passenger.
getId().toString() +
395 " could not be inserted into vehicle " + vehicleId.toString() +
396 " since there is no free seat available!");
413 QVehicle ret = this.parkedVehicles.get(vehicleId);
418 public final Collection<MobsimVehicle> getAllVehicles() {
420 vehicles.addAll(this.parkedVehicles.values());
425 public final Map<String, Object> getCustomAttributes() {
426 return customAttributes;
429 void setNetElementActivationRegistry(NetElementActivationRegistry qSimEngineRunner) {
430 this.netElementActivationRegistry = qSimEngineRunner;
436 Queue<MobsimDriverAgent> queue = driversWaitingForCars.get( vehicleId );
438 if ( queue == null ) {
439 queue =
new LinkedList<>();
440 driversWaitingForCars.put( vehicleId , queue );
448 driversWaitingForPassengers.put(agent.
getId(), agent);
453 return driversWaitingForPassengers.remove(agentId);
458 Set<MobsimAgent> passengers = passengersWaitingForCars.get(vehicleId);
459 if (passengers == null) {
460 passengers =
new LinkedHashSet<>();
461 passengersWaitingForCars.put(vehicleId, passengers);
463 passengers.add(agent);
468 Set<MobsimAgent> passengers = passengersWaitingForCars.get(vehicleId);
469 if (passengers != null && passengers.remove(agent))
return agent;
474 public Set<MobsimAgent> getAgentsWaitingForCar(
Id<Vehicle> vehicleId) {
475 Set<MobsimAgent>
set = passengersWaitingForCars.get(vehicleId);
476 if (
set != null)
return Collections.unmodifiableSet(
set);
481 public Link getLink() {
489 void setActive(
boolean active) {
490 this.active = active;
493 Queue<QVehicle> getWaitingList() {
497 TransitQLink getTransitQLink() {
501 void setTransitQLink(TransitQLink transitQLink) {
502 this.transitQLink = transitQLink;
512 return AbstractQLink.this.toQNode ;
515 return AbstractQLink.this.link.getToNode() ;
520 return AbstractQLink.this.link.getFreespeed() ;
524 return AbstractQLink.this.link.getId() ;
530 return AbstractQLink.this.transitQLink.handleTransitStop(now, veh, driver, linkId) ;
534 AbstractQLink.this.addParkedVehicle(veh);
538 return AbstractQLink.this.letVehicleArrive(veh);
542 AbstractQLink.this.makeVehicleAvailableToNextDriver(veh);
546 AbstractQLink.this.activateLink();
560 return AbstractQLink.this.getAcceptingQLane() ;
564 return AbstractQLink.this.getOfferingQLanes() ;
568 return AbstractQLink.this.link.getFromNode() ;
572 return AbstractQLink.this.link.getFreespeed(now) ;
580 return AbstractQLink.this.link;
585 return qLinkInternalInterface ;
void setCurrentLinkToVehicle(QVehicle veh)
Collection< MobsimVehicle > getAllNonParkedVehicles()
static int getNumberOfLanesAsInt(final double time, final Link link)
static final String ONLYONCE
boolean letVehicleArrive(QVehicle veh)
void makeVehicleAvailableToNextDriver(QVehicle veh)
void handleVehicleDeparture(QVehicle vehicle, Link link)
void setCurrentLink(Link link)
void setDriver(DriverAgent driver)
double getFreespeed(double now)
void handleInitialVehicleArrival(QVehicle vehicle, Link link)
void processEvent(final Event event)
List< QLaneI > getOfferingQLanes()
int getNumberOfLanesAsInt(double now)
boolean handleVehicleArrival(QVehicle vehicle, Link link)
HandleTransitStopResult handleTransitStop(double now, QVehicle veh, TransitDriverAgent driver, Id< Link > linkId)
double getMaximumVelocityFromLinkSpeedCalculator(QVehicle veh, double now)
Id< Vehicle > getPlannedVehicleId()
static void assertNotNull(Object obj)
MobsimDriverAgent getDriver()
double getMaximumVelocity(QVehicle vehicle, Link link, double time)
QLaneI getAcceptingQLane()
void letVehicleArrive(QVehicle veh)
void addParkedVehicle(QVehicle veh)
boolean addPassenger(final PassengerAgent passenger)