@SuppressWarnings("static-method") private boolean checkNextLinkSemantics( Link currentLink, Id<Link> nextLinkId, QLinkInternalI nextQLink, QVehicle veh) { if (nextQLink == null) { // throw new IllegalStateException log.warn( "The link id " + nextLinkId + " is not available in the simulation network, but vehicle " + veh.getId() + " plans to travel on that link from link " + veh.getCurrentLink().getId()); return false; } if (currentLink.getToNode() != nextQLink.getLink().getFromNode()) { // throw new RuntimeException log.warn( "Cannot move vehicle " + veh.getId() + " from link " + currentLink.getId() + " to link " + nextQLink.getLink().getId()); return false; } return true; }
private void moveLink(final QLinkInternalI link, final double now) { if (link instanceof QLinkLanesImpl) { // This cannot be moved to QLinkLanesImpl since we want to be able to serve other lanes if one // lane is blocked. // kai, feb'12 // yyyy but somehow I think this should be solved "under the hood" in QLinkLanesImpl. kai, // sep'13 // zzzz the above yyyy solution would get really ugly with the current interface and the code // in the // else {} branch: link.isNotOfferingVehicle():boolean would return sequentially the state of // the single // lanes. Each call would have side effects on a state machine within QLinkLanesImpl. // Proposal: think // about a better interface first, then solve under the hood. dg, mar'14 for (QLaneI lane : ((QLinkLanesImpl) link).getToNodeQueueLanes()) { while (!lane.isNotOfferingVehicle()) { QVehicle veh = lane.getFirstVehicle(); Id<Link> nextLink = veh.getDriver().chooseNextLinkId(); if (!(lane.hasGreenForToLink(nextLink) && moveVehicleOverNode(veh, lane, now))) { break; } } } } else { while (!link.isNotOfferingVehicle()) { QVehicle veh = link.getFirstVehicle(); if (!moveVehicleOverNode(veh, link, now)) { break; } } } }
/** * @return <code>true</code> if the vehicle was successfully moved over the node, <code>false * </code> otherwise (e.g. in case where the next link is jammed) */ private boolean moveVehicleOverNode( final QVehicle veh, final QInternalI fromLaneBuffer, final double now) { Id<Link> nextLinkId = veh.getDriver().chooseNextLinkId(); Link currentLink = veh.getCurrentLink(); if ((!fromLaneBuffer.hasGreenForToLink(nextLinkId))) { // there is no longer a stuck check for red links. This means that // in case of an infinite red time the simulation will not stop automatically because // vehicles waiting in front of the red signal will never reach their destination. dg, mar'14 return false; } if (nextLinkId == null) { log.error( "Agent has no or wrong route! agentId=" + veh.getDriver().getId() + " currentLink=" + currentLink.getId().toString() + ". The agent is removed from the simulation."); moveVehicleFromInlinkToAbort(veh, fromLaneBuffer, now); return true; } QLinkInternalI nextQueueLink = network.getNetsimLinks().get(nextLinkId); if (!checkNextLinkSemantics(currentLink, nextLinkId, nextQueueLink, veh)) { moveVehicleFromInlinkToAbort(veh, fromLaneBuffer, now); return true; } if (nextQueueLink.isAcceptingFromUpstream()) { moveVehicleFromInlinkToOutlink(veh, fromLaneBuffer, nextQueueLink); return true; } if (vehicleIsStuck(fromLaneBuffer, now)) { /* We just push the vehicle further after stucktime is over, regardless * of if there is space on the next link or not.. optionally we let them * die here, we have a config setting for that! */ if (network.simEngine.getMobsim().getScenario().getConfig().qsim().isRemoveStuckVehicles()) { moveVehicleFromInlinkToAbort(veh, fromLaneBuffer, now); return false; } else { moveVehicleFromInlinkToOutlink(veh, fromLaneBuffer, nextQueueLink); return true; // (yyyy why is this returning `true'? Since this is a fix to avoid gridlock, this should // proceed in small steps. // kai, feb'12) } } return false; }
private void moveVehicleFromInlinkToAbort( final QVehicle veh, final QInternalI fromLane, final double now) { fromLane.popFirstVehicle(); // first treat the passengers: for (PassengerAgent pp : veh.getPassengers()) { if (pp instanceof MobsimAgent) { ((MobsimAgent) pp).setStateToAbort(now); network.simEngine.internalInterface.arrangeNextAgentState((MobsimAgent) pp); } else if (wrnCnt < 1) { wrnCnt++; log.warn( "encountering PassengerAgent that cannot be cast into a MobsimAgent; cannot say if this is a problem"); log.warn(Gbl.ONLYONCE); } } // now treat the driver: veh.getDriver().setStateToAbort(now); network.simEngine.internalInterface.arrangeNextAgentState(veh.getDriver()); }
private static void moveVehicleFromInlinkToOutlink( final QVehicle veh, final QInternalI fromLane, QLinkInternalI nextQueueLink) { fromLane.popFirstVehicle(); veh.getDriver().notifyMoveOverNode(nextQueueLink.getLink().getId()); nextQueueLink.addFromUpstream(veh); }