diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java index 96bbd7928c5..a5f4cdcf143 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java @@ -1,20 +1,21 @@ package org.matsim.contrib.parking.parkingsearch.DynAgent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Plan; -import org.matsim.contrib.parking.parkingsearch.events.RemoveParkingActivityEvent; -import org.matsim.contrib.parking.parkingsearch.events.ReserveParkingLocationEvent; -import org.matsim.contrib.parking.parkingsearch.events.SelectNewParkingLocationEvent; -import org.matsim.contrib.parking.parkingsearch.events.StartParkingSearchEvent; +import org.matsim.contrib.parking.parkingsearch.ParkingUtils; +import org.matsim.contrib.parking.parkingsearch.events.*; import org.matsim.contrib.parking.parkingsearch.manager.FacilityBasedParkingManager; import org.matsim.contrib.parking.parkingsearch.manager.ParkingSearchManager; import org.matsim.contrib.parking.parkingsearch.search.NearestParkingSpotSearchLogic; import org.matsim.contrib.parking.parkingsearch.search.ParkingSearchLogic; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.framework.MobsimTimer; +import org.matsim.core.population.PopulationUtils; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.utils.collections.Tuple; import org.matsim.vehicles.Vehicle; @@ -26,6 +27,7 @@ */ public class NearestParkingDynLeg extends ParkingDynLeg { private boolean parkingAtEndOfLeg = true; + private boolean passangerInteractionAtParkingFacilityAtEndOfLeg = false; private boolean reachedDestinationWithoutParking = false; private boolean alreadyReservedParking = false; private boolean driveToBaseWithoutParking = false; @@ -34,18 +36,19 @@ public class NearestParkingDynLeg extends ParkingDynLeg { private final int planIndexNextActivity; private Plan plan; private Id nextSelectedParkingLink = null; + protected static final Logger log = LogManager.getLogger(NearestParkingDynLeg.class); public NearestParkingDynLeg(Leg currentPlannedLeg, NetworkRoute route, Plan plan, int planIndexNextActivity, ParkingSearchLogic logic, ParkingSearchManager parkingManager, Id vehicleId, MobsimTimer timer, EventsManager events) { super(currentPlannedLeg.getMode(), route, logic, parkingManager, vehicleId, timer, events); this.followingActivity = (Activity) plan.getPlanElements().get(planIndexNextActivity); - followingActivity.setStartTime(timer.getTimeOfDay()); this.currentPlannedLeg = currentPlannedLeg; this.plan = plan; this.planIndexNextActivity = planIndexNextActivity; - if (followingActivity.getAttributes().getAsMap().containsKey("parking") && followingActivity.getAttributes().getAttribute("parking").equals( - "noParking")) + if (ParkingUtils.checkIfActivityHasNoParking(followingActivity)) parkingAtEndOfLeg = false; + if (ParkingUtils.checkIfActivityHasPassengerInteraction(followingActivity)) + passangerInteractionAtParkingFacilityAtEndOfLeg = true; } @Override @@ -85,7 +88,7 @@ public void movedOverNode(Id newLinkId) { @Override public Id getNextLinkId() { - if (!parkingMode && parkingAtEndOfLeg) { + if (!passangerInteractionAtParkingFacilityAtEndOfLeg && (!parkingMode && parkingAtEndOfLeg)) { parkingMode = true; this.events.processEvent(new StartParkingSearchEvent(timer.getTimeOfDay(), vehicleId, currentLinkId)); } @@ -98,12 +101,18 @@ public Id getNextLinkId() { return linkIds.get(currentLinkIdx + 1); } else { + if (passangerInteractionAtParkingFacilityAtEndOfLeg && !hasFoundParking && followingActivity.getLinkId().equals(currentLinkId)) { + createWaitingActivityUntilPassengerInteractionIsPossible(currentLinkId, vehicleId, timer.getTimeOfDay()); + this.events + .processEvent(new StartWaitingForParkingEvent(timer.getTimeOfDay(), vehicleId, currentLinkId)); + } if (hasFoundParking || reachedDestinationWithoutParking) { // easy, we can just park where at our destination link - if (hasFoundParking) { + if (hasFoundParking && !passangerInteractionAtParkingFacilityAtEndOfLeg) { + //calculate parkingTime for parking_activity double parkingDuration; double expectedDrivingDurationToPickup; - double drivingDurationFromDropOff = timer.getTimeOfDay() - currentPlannedLeg.getDepartureTime().seconds(); + double drivingDurationFromGetOff = timer.getTimeOfDay() - currentPlannedLeg.getDepartureTime().seconds(); if (nextSelectedParkingLink.equals(currentLinkId)) { expectedDrivingDurationToPickup = ((NearestParkingSpotSearchLogic) this.logic).getExpectedTravelTime( @@ -112,7 +121,9 @@ public Id getNextLinkId() { expectedDrivingDurationToPickup = ((NearestParkingSpotSearchLogic) this.logic).getExpectedTravelTime( currentPlannedLeg.getRoute().getStartLinkId(), timer.getTimeOfDay(), currentLinkId); } - parkingDuration = followingActivity.getMaximumDuration().seconds() - drivingDurationFromDropOff - expectedDrivingDurationToPickup; + parkingDuration = followingActivity.getMaximumDuration().seconds() + - drivingDurationFromGetOff - expectedDrivingDurationToPickup + - ((FacilityBasedParkingManager) parkingManager).getParkStageActivityDuration(); followingActivity.setMaximumDuration(parkingDuration); } this.logic.reset(); @@ -125,10 +136,19 @@ public Id getNextLinkId() { } } // need to find the next link - double nextPickupTime = followingActivity.getStartTime().seconds() + followingActivity.getMaximumDuration().seconds(); - double maxParkingDuration = followingActivity.getMaximumDuration().seconds() - (followingActivity.getStartTime().seconds() - timer.getTimeOfDay()); + double nextPickupTime; + double maxParkingDuration; + if (passangerInteractionAtParkingFacilityAtEndOfLeg){ + nextPickupTime = 0.; + maxParkingDuration = followingActivity.getMaximumDuration().seconds(); + } + else { + nextPickupTime = currentPlannedLeg.getDepartureTime().seconds() + followingActivity.getMaximumDuration().seconds(); + maxParkingDuration = nextPickupTime - timer.getTimeOfDay(); + } Id nextLinkId = ((NearestParkingSpotSearchLogic) this.logic).getNextLink(currentLinkId, route.getEndLinkId(), vehicleId, mode, - timer.getTimeOfDay(), maxParkingDuration, nextPickupTime); + timer.getTimeOfDay(), maxParkingDuration, nextPickupTime, passangerInteractionAtParkingFacilityAtEndOfLeg, + followingActivity.getCoord()); if (((NearestParkingSpotSearchLogic) this.logic).isNextParkingActivitySkipped() && parkingAtEndOfLeg) { removeNextActivityAndFollowingLeg(); parkingAtEndOfLeg = false; @@ -163,9 +183,19 @@ public Id getNextLinkId() { } } + private void createWaitingActivityUntilPassengerInteractionIsPossible(Id newLinkId, Id vehicleId, double now) { + Activity waitingActivity = PopulationUtils.createActivityFromLinkId(ParkingUtils.WaitingForParkingActivityType, newLinkId); + ParkingUtils.setNoParkingForActivity(waitingActivity); + plan.getPlanElements().add(planIndexNextActivity, waitingActivity); + hasFoundParking = true; + ((FacilityBasedParkingManager) parkingManager).addVehicleForWaitingForParking(newLinkId, vehicleId, now); + } + private void removeNextActivityAndFollowingLeg() { plan.getPlanElements().remove(planIndexNextActivity); plan.getPlanElements().remove(planIndexNextActivity); +// log.info( +// plan.getPerson().getId().toString() + ": Parking activity after getOff point '" + ((Activity)plan.getPlanElements().get(planIndexNextActivity - 2)).getType() + "' is removed, because no parking facility was found."); } public boolean driveToBaseWithoutParking() { diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java index c799cbc1355..381bfd331d2 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java @@ -1,5 +1,5 @@ /** - * + * */ package org.matsim.contrib.parking.parkingsearch.DynAgent.agentLogic; @@ -9,7 +9,6 @@ import org.matsim.api.core.v01.population.Route; import org.matsim.contrib.dynagent.DynAction; import org.matsim.contrib.parking.parkingsearch.DynAgent.BenensonDynLeg; -import org.matsim.contrib.parking.parkingsearch.DynAgent.agentLogic.ParkingAgentLogic; import org.matsim.contrib.parking.parkingsearch.manager.ParkingSearchManager; import org.matsim.contrib.parking.parkingsearch.manager.vehicleteleportationlogic.VehicleTeleportationLogic; import org.matsim.contrib.parking.parkingsearch.routing.ParkingRouter; @@ -29,37 +28,37 @@ public class BenensonParkingAgentLogic extends ParkingAgentLogic { /** * @param plan * @param parkingManager - * @param walkLegFactory + * @param walkRouter * @param parkingRouter * @param events * @param parkingLogic * @param timer * @param teleportationLogic */ - - + + public BenensonParkingAgentLogic(Plan plan, ParkingSearchManager parkingManager, RoutingModule walkRouter, Network network, ParkingRouter parkingRouter, EventsManager events, ParkingSearchLogic parkingLogic, MobsimTimer timer, VehicleTeleportationLogic teleportationLogic, ParkingSearchConfigGroup configGroup) { super(plan, parkingManager, walkRouter, network, parkingRouter, events, parkingLogic, timer, teleportationLogic, configGroup); } - + @Override protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. - + Leg currentPlannedLeg = (Leg) currentPlanElement; Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isinitialLocation)){ + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isInitialLocation)){ this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; Leg currentLeg = (Leg) this.currentPlanElement; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new BenensonDynLeg(currentLeg.getMode(), actualRoute, parkingLogic, parkingManager, currentlyAssignedVehicleId, timer, events); } else throw new RuntimeException("parking location mismatch"); - + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java index dbe7b937923..b7358bc6a39 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java @@ -1,5 +1,5 @@ /** - * + * */ package org.matsim.contrib.parking.parkingsearch.DynAgent.agentLogic; @@ -31,22 +31,22 @@ public MemoryBasedParkingAgentLogic(Plan plan, ParkingSearchManager parkingManag super(plan, parkingManager, walkRouter, network, parkingRouter, events, parkingLogic, timer, teleportationLogic, configGroup); } - + @Override protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. - + Leg currentPlannedLeg = (Leg) currentPlanElement; Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isinitialLocation)){ + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isInitialLocation)){ this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; Leg currentLeg = (Leg) this.currentPlanElement; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new DistanceMemoryDynLeg(currentLeg.getMode(), actualRoute, parkingLogic, parkingManager, currentlyAssignedVehicleId, timer, events); } else throw new RuntimeException("parking location mismatch"); - + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java index faec3310574..f3a7e671b14 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java @@ -10,6 +10,7 @@ import org.matsim.contrib.dynagent.StaticPassengerDynLeg; import org.matsim.contrib.parking.parkingsearch.DynAgent.NearestParkingDynLeg; import org.matsim.contrib.parking.parkingsearch.ParkingUtils; +import org.matsim.contrib.parking.parkingsearch.manager.FacilityBasedParkingManager; import org.matsim.contrib.parking.parkingsearch.manager.ParkingSearchManager; import org.matsim.contrib.parking.parkingsearch.manager.vehicleteleportationlogic.VehicleTeleportationLogic; import org.matsim.contrib.parking.parkingsearch.routing.ParkingRouter; @@ -54,50 +55,35 @@ public DynAction computeNextAction(DynAction oldAction, double now) { if (lastParkActionState.equals(LastParkActionState.CARTRIP) && ((NearestParkingDynLeg) oldAction).driveToBaseWithoutParking()) this.lastParkActionState = LastParkActionState.WALKFROMPARK; - switch (lastParkActionState) { - case ACTIVITY: - return nextStateAfterActivity(oldAction, now); - - case CARTRIP: - return nextStateAfterCarTrip(oldAction, now); - - case NONCARTRIP: - return nextStateAfterNonCarTrip(oldAction, now); - - case PARKACTIVITY: - return nextStateAfterParkActivity(oldAction, now); - - case UNPARKACTIVITY: - return nextStateAfterUnParkActivity(oldAction, now); - - case WALKFROMPARK: - return nextStateAfterWalkFromPark(oldAction, now); - - case WALKTOPARK: - return nextStateAfterWalkToPark(oldAction, now); - - } - throw new RuntimeException("unreachable code"); - } + return switch (lastParkActionState) { + case ACTIVITY -> nextStateAfterActivity(oldAction, now); + case CARTRIP -> nextStateAfterCarTrip(oldAction, now); + case NONCARTRIP -> nextStateAfterNonCarTrip(oldAction, now); + case PARKACTIVITY -> nextStateAfterParkActivity(oldAction, now); + case UNPARKACTIVITY -> nextStateAfterUnParkActivity(oldAction, now); + case WALKFROMPARK -> nextStateAfterWalkFromPark(oldAction, now); + case WALKTOPARK -> nextStateAfterWalkToPark(oldAction, now); + }; + } @Override protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. Leg currentPlannedLeg = (Leg) currentPlanElement; + currentPlannedLeg.setDepartureTime(timer.getTimeOfDay()); Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); actualRoute.setVehicleId(currentlyAssignedVehicleId); if (!plannedRoute.getStartLinkId().equals(actualRoute.getStartLinkId())) currentPlannedLeg.setRoute(actualRoute); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now)) || (isinitialLocation)) { + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now)) || (isInitialLocation)) { this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; // Leg currentLeg = (Leg) this.currentPlanElement; int planIndexNextActivity = planIndex + 1; Activity nextPlanElement = (Activity) plan.getPlanElements().get(planIndexNextActivity); - if (nextPlanElement.getAttributes().getAsMap().containsKey("parking") && nextPlanElement.getAttributes().getAttribute("parking").equals( - "noParking")) + if (ParkingUtils.checkIfActivityHasNoParking(nextPlanElement)) this.lastParkActionState = LastParkActionState.WALKFROMPARK; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new NearestParkingDynLeg(currentPlannedLeg, actualRoute, plan, planIndexNextActivity, parkingLogic, parkingManager, @@ -133,6 +119,22 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { // we could either depart by car or not next if (plan.getPlanElements().size() >= planIndex + 1) { + if (plan.getPlanElements().get(planIndex) instanceof Activity && ((Activity) plan.getPlanElements().get(planIndex)).getType().equals( + ParkingUtils.WaitingForParkingActivityType)) { + //now the waiting activity has finished and we can park now + this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now); + return nextStateAfterNonCarTrip(oldAction, now); + } + if (plan.getPlanElements().get(planIndex + 1) instanceof Activity) + return nextStateAfterNonCarTrip(oldAction, now); + if (plan.getPlanElements().get(planIndex) instanceof Activity && ((Activity) plan.getPlanElements().get(planIndex)).getType().contains("_GetOff")) { + ((Activity) plan.getPlanElements().get(planIndex)).setEndTime(now); + ((Activity) plan.getPlanElements().get(planIndex + 4)).setStartTime(now + ((Activity) plan.getPlanElements().get(planIndex + 2)).getMaximumDuration().seconds()); + // checks if it is possible to stay from getOff until getIn + boolean possibleToStay = checkIfParkingIsPossibleUntilNextActivities(this.planIndex,this.planIndex + 2); + if (possibleToStay) + return nextStateAfterNonCarTrip(oldAction, now); + } planIndex++; this.currentPlanElement = plan.getPlanElements().get(planIndex); Leg currentLeg = (Leg) currentPlanElement; @@ -141,7 +143,7 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { Id parkLink = this.parkingManager.getVehicleParkingLocation(vehicleId); if (parkLink == null) { - //this is the first activity of a day and our parking manager does not provide informations about initial stages. We suppose the car is parked where we are + //this is the first activity of a day and our parking manager does not provide information about initial stages. We suppose the car is parked where we are parkLink = agent.getCurrentLinkId(); } @@ -151,14 +153,13 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { Facility toFacility = new LinkWrapperFacility(network.getLinks().get(teleportedParkLink)); List walkTrip = walkRouter.calcRoute( DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); - if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg)) { + if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg walkLeg)) { String message = "walkRouter returned something else than a single Leg, e.g. it routes walk on the network with non_network_walk to access the network. Not implemented in parking yet!"; log.error(message); throw new RuntimeException(message); } - Leg walkLeg = (Leg) walkTrip.get(0); this.currentlyAssignedVehicleId = vehicleId; - this.stageInteractionType = ParkingUtils.PARKACTIVITYTYPE; + this.stageInteractionType = ParkingUtils.ParkingStageInteractionType; if (!walkLeg.getTravelTime().equals(OptionalTime.defined(0.))) { this.lastParkActionState = LastParkActionState.WALKTOPARK; return new StaticPassengerDynLeg(walkLeg.getRoute(), walkLeg.getMode()); @@ -188,10 +189,96 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { protected DynAction nextStateAfterWalkToPark(DynAction oldAction, double now) { //walk2park is complete, we can unpark. this.lastParkActionState = LastParkActionState.UNPARKACTIVITY; - PlanElement beforePlanElement = plan.getPlanElements().get(planIndex - 1); - if (beforePlanElement.getAttributes().getAsMap().containsKey("parking") && beforePlanElement.getAttributes().getAttribute("parking").equals( - "noParking")) - return nextStateAfterUnParkActivity(oldAction, now); + Activity beforePlanElement = (Activity) plan.getPlanElements().get(planIndex - 1); + if (ParkingUtils.checkIfActivityHasNoParking(beforePlanElement)) + return nextStateAfterUnParkActivity(oldAction, now); // wenn kein Parken dann einfach weiter return new IdleDynActivity(this.stageInteractionType, now + configGroup.getUnparkduration()); } + + @Override + protected DynAction nextStateAfterCarTrip(DynAction oldAction, double now) { + if (this.plan.getPlanElements().get(planIndex + 1) instanceof Activity && ((Activity) this.plan.getPlanElements().get( + planIndex + 1)).getType().equals(ParkingUtils.WaitingForParkingActivityType)) { + //next activity is waiting for parking. Thats why we have no parkVehicleHere at this moment + this.lastParkActionState = LastParkActionState.PARKACTIVITY; + this.currentlyAssignedVehicleId = null; + this.parkingLogic.reset(); + return new IdleDynActivity(this.stageInteractionType, now + configGroup.getParkduration()); + } + // car trip is complete, we have found a parking space (not part of the logic), block it and start to park + if (this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now)) { + this.lastParkActionState = LastParkActionState.PARKACTIVITY; + this.currentlyAssignedVehicleId = null; + this.parkingLogic.reset(); + return new IdleDynActivity(this.stageInteractionType, now + configGroup.getParkduration()); + } else throw new RuntimeException("No parking possible"); + } + + @Override + protected DynAction nextStateAfterNonCarTrip(DynAction oldAction, double now) { + + this.currentPlanElement = plan.getPlanElements().get(planIndex + 1); + Activity nextPlannedActivity = (Activity) this.currentPlanElement; + // checks if you can extend parking here until getIn + if (nextPlannedActivity.getType().equals(ParkingUtils.ParkingActivityType) && plan.getPlanElements().get(planIndex + 2) instanceof Leg) { + checkIfParkingIsPossibleUntilNextActivities(planIndex + 1,planIndex + 1); + } + // switch back to activity + planIndex++; + this.lastParkActionState = LastParkActionState.ACTIVITY; + final double endTime; + if (nextPlannedActivity.getEndTime().isUndefined()) { + if (nextPlannedActivity.getMaximumDuration().isUndefined()) { + endTime = Double.POSITIVE_INFINITY; + //last activity of a day + } else { + endTime = now + nextPlannedActivity.getMaximumDuration().seconds(); + } + } else { + endTime = nextPlannedActivity.getEndTime().seconds(); + } + return new IdleDynActivity(nextPlannedActivity.getType(), endTime); + + } + + private boolean checkIfParkingIsPossibleUntilNextActivities(int indexOfCurrentActivity, int indexOfParkingActivity) { + int indexOfFollowingActivity = indexOfCurrentActivity + 2; + Activity followingActivity = ((Activity) plan.getPlanElements().get(indexOfFollowingActivity)); + //checks if it is possible to stay from the current getOff until the getIn + if (indexOfFollowingActivity == indexOfParkingActivity) { + Activity currentActivity = ((Activity) plan.getPlanElements().get(this.planIndex)); + Activity activityAfterFollowing = ((Activity) plan.getPlanElements().get(this.planIndex + 4)); + if (agent.getCurrentLinkId().equals(activityAfterFollowing.getLinkId()) && !ParkingUtils.checkIfActivityHasNoParking( + (Activity) currentPlanElement)) { + boolean canParkAtFacilityUntilGetIn = ((FacilityBasedParkingManager) parkingManager).canParkAtThisFacilityUntilEnd( + agent.getCurrentLinkId(), + followingActivity.getMaximumDuration().seconds(), currentActivity.getMaximumDuration().seconds(), + activityAfterFollowing.getMaximumDuration().seconds(), timer.getTimeOfDay()); + if (canParkAtFacilityUntilGetIn) { + plan.getPlanElements().remove(this.planIndex + 3); + plan.getPlanElements().remove(this.planIndex + 1); + ((FacilityBasedParkingManager) parkingManager).registerStayFromGetOffUntilGetIn(this.agent.getVehicle().getId()); + return true; + } + } + } + // checks if the now started parking activity can extend until the end of the following GetIn activity + else if (indexOfCurrentActivity == indexOfParkingActivity) { + Activity currentActivity = ((Activity) plan.getPlanElements().get(this.planIndex + 1)); + if (agent.getCurrentLinkId().equals(followingActivity.getLinkId()) && !ParkingUtils.checkIfActivityHasNoParking( + followingActivity)) { + boolean canParkAtFacilityUntilGetIn = ((FacilityBasedParkingManager) parkingManager).canParkAtThisFacilityUntilEnd( + agent.getCurrentLinkId(), + currentActivity.getMaximumDuration().seconds(), 0., + followingActivity.getMaximumDuration().seconds(), timer.getTimeOfDay()); + if (canParkAtFacilityUntilGetIn) { + plan.getPlanElements().remove(indexOfParkingActivity + 1); + currentActivity.setEndTime(followingActivity.getStartTime().seconds()); + ((FacilityBasedParkingManager) parkingManager).registerParkingBeforeGetIn(this.agent.getVehicle().getId()); + return true; + } + } + } + return false; + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java index 2bda5aa8698..dd2fb4fa74b 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java @@ -59,25 +59,25 @@ /** * @author jbischoff - * */ public class ParkingAgentLogic implements DynAgentLogic { - public enum LastParkActionState { + public enum LastParkActionState { - // we have the following cases of ending dynacts: - NONCARTRIP, // non-car trip arrival: start Activity - CARTRIP, // car-trip arrival: add park-car activity - PARKACTIVITY, // park-car activity: get next PlanElement & add walk leg to activity location - WALKFROMPARK ,// walk-leg to act: start next PlanElement Activity - ACTIVITY, // ordinary activity: get next Leg, if car: go to car, otherwise add ordinary leg by other mode - WALKTOPARK, // walk-leg to car: add unpark activity - UNPARKACTIVITY // unpark activity: find the way to the next route & start leg + // we have the following cases of ending dynacts: + NONCARTRIP, // non-car trip arrival: start Activity + CARTRIP, // car-trip arrival: add park-car activity + PARKACTIVITY, // park-car activity: get next PlanElement & add walk leg to activity location + WALKFROMPARK,// walk-leg to act: start next PlanElement Activity + ACTIVITY, // ordinary activity: get next Leg, if car: go to car, otherwise add ordinary leg by other mode + WALKTOPARK, // walk-leg to car: add unpark activity + UNPARKACTIVITY // unpark activity: find the way to the next route & start leg } + protected LastParkActionState lastParkActionState; protected DynAgent agent; protected int planIndex; -// protected Iterator planElemIter; + // protected Iterator planElemIter; protected Plan plan; protected PlanElement currentPlanElement; protected ParkingSearchManager parkingManager; @@ -88,20 +88,18 @@ public enum LastParkActionState { protected EventsManager events; protected ParkingSearchLogic parkingLogic; protected VehicleTeleportationLogic teleportationLogic; - protected boolean isinitialLocation = true; + protected boolean isInitialLocation = true; protected Id currentlyAssignedVehicleId = null; protected String stageInteractionType = null; protected ParkingSearchConfigGroup configGroup; protected static final Logger log = LogManager.getLogger(ParkingAgentLogic.class); /** - * @param plan - * (always starts with Activity) + * @param plan (always starts with Activity) */ - public ParkingAgentLogic(Plan plan, ParkingSearchManager parkingManager, RoutingModule walkRouter, Network network, - ParkingRouter parkingRouter, EventsManager events, ParkingSearchLogic parkingLogic, MobsimTimer timer, - VehicleTeleportationLogic teleportationLogic, ParkingSearchConfigGroup configGroup) { -// planElemIter = plan.getPlanElements().iterator(); + public ParkingAgentLogic(Plan plan, ParkingSearchManager parkingManager, RoutingModule walkRouter, Network network, + ParkingRouter parkingRouter, EventsManager events, ParkingSearchLogic parkingLogic, MobsimTimer timer, + VehicleTeleportationLogic teleportationLogic, ParkingSearchConfigGroup configGroup) { this.plan = plan; this.parkingManager = parkingManager; this.walkRouter = walkRouter; @@ -141,32 +139,17 @@ public DynAction computeNextAction(DynAction oldAction, double now) { // ordinary activity: get next Leg, if car: go to car, otherwise add ordinary leg by other mode // walk-leg to car: add unpark activity // unpark activity: find the way to the next route & start leg - switch (lastParkActionState){ - case ACTIVITY: - return nextStateAfterActivity(oldAction, now); - - case CARTRIP: - return nextStateAfterCarTrip(oldAction,now); - - case NONCARTRIP: - return nextStateAfterNonCarTrip(oldAction,now); - - case PARKACTIVITY: - return nextStateAfterParkActivity(oldAction,now); - - case UNPARKACTIVITY: - return nextStateAfterUnParkActivity(oldAction,now); - - case WALKFROMPARK: - return nextStateAfterWalkFromPark(oldAction,now); - - case WALKTOPARK: - return nextStateAfterWalkToPark(oldAction,now); - - } - throw new RuntimeException("unreachable code"); - - } + return switch (lastParkActionState) { + case ACTIVITY -> nextStateAfterActivity(oldAction, now); + case CARTRIP -> nextStateAfterCarTrip(oldAction, now); + case NONCARTRIP -> nextStateAfterNonCarTrip(oldAction, now); + case PARKACTIVITY -> nextStateAfterParkActivity(oldAction, now); + case UNPARKACTIVITY -> nextStateAfterUnParkActivity(oldAction, now); + case WALKFROMPARK -> nextStateAfterWalkFromPark(oldAction, now); + case WALKTOPARK -> nextStateAfterWalkToPark(oldAction, now); + }; + + } protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. @@ -174,15 +157,14 @@ protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now Leg currentPlannedLeg = (Leg) currentPlanElement; Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isinitialLocation)){ + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now)) || (isInitialLocation)) { this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; Leg currentLeg = (Leg) this.currentPlanElement; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new ParkingDynLeg(currentLeg.getMode(), actualRoute, parkingLogic, parkingManager, currentlyAssignedVehicleId, timer, events); - } - else throw new RuntimeException("parking location mismatch"); + } else throw new RuntimeException("parking location mismatch"); } @@ -200,15 +182,15 @@ protected DynAction nextStateAfterWalkFromPark(DynAction oldAction, double now) protected DynAction nextStateAfterParkActivity(DynAction oldAction, double now) { // add a walk leg after parking Leg currentPlannedLeg = (Leg) currentPlanElement; - Facility fromFacility = new LinkWrapperFacility (network.getLinks().get(agent.getCurrentLinkId())); - Facility toFacility = new LinkWrapperFacility (network.getLinks().get(currentPlannedLeg.getRoute().getEndLinkId())); - List walkTrip = walkRouter.calcRoute(DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); - if (walkTrip.size() != 1 || ! (walkTrip.get(0) instanceof Leg)) { + Facility fromFacility = new LinkWrapperFacility(network.getLinks().get(agent.getCurrentLinkId())); + Facility toFacility = new LinkWrapperFacility(network.getLinks().get(currentPlannedLeg.getRoute().getEndLinkId())); + List walkTrip = walkRouter.calcRoute( + DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); + if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg walkLeg)) { String message = "walkRouter returned something else than a single Leg, e.g. it routes walk on the network with non_network_walk to access the network. Not implemented in parking yet!"; log.error(message); throw new RuntimeException(message); } - Leg walkLeg = (Leg) walkTrip.get(0); this.lastParkActionState = LastParkActionState.WALKFROMPARK; this.stageInteractionType = null; return new StaticPassengerDynLeg(walkLeg.getRoute(), walkLeg.getMode()); @@ -223,11 +205,11 @@ protected DynAction nextStateAfterNonCarTrip(DynAction oldAction, double now) { final double endTime; if (nextPlannedActivity.getEndTime().isUndefined()) { if (nextPlannedActivity.getMaximumDuration().isUndefined()) { - endTime = Double.POSITIVE_INFINITY; - //last activity of a day - } else { + endTime = Double.POSITIVE_INFINITY; + //last activity of a day + } else { endTime = now + nextPlannedActivity.getMaximumDuration().seconds(); - } + } } else { endTime = nextPlannedActivity.getEndTime().seconds(); } @@ -237,13 +219,12 @@ protected DynAction nextStateAfterNonCarTrip(DynAction oldAction, double now) { protected DynAction nextStateAfterCarTrip(DynAction oldAction, double now) { // car trip is complete, we have found a parking space (not part of the logic), block it and start to park - if (this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now)){ - this.lastParkActionState = LastParkActionState.PARKACTIVITY; - this.currentlyAssignedVehicleId = null; - this.parkingLogic.reset(); + if (this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now)) { + this.lastParkActionState = LastParkActionState.PARKACTIVITY; + this.currentlyAssignedVehicleId = null; + this.parkingLogic.reset(); return new IdleDynActivity(this.stageInteractionType, now + configGroup.getParkduration()); - } - else throw new RuntimeException ("No parking possible"); + } else throw new RuntimeException("No parking possible"); } protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { @@ -263,19 +244,18 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { Facility fromFacility = new LinkWrapperFacility(network.getLinks().get(agent.getCurrentLinkId())); Id teleportedParkLink = this.teleportationLogic.getVehicleLocation(agent.getCurrentLinkId(), vehicleId, parkLink, now, - currentLeg.getMode()); + currentLeg.getMode()); Facility toFacility = new LinkWrapperFacility(network.getLinks().get(teleportedParkLink)); List walkTrip = walkRouter.calcRoute( - DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); - if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg)) { + DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); + if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg walkLeg)) { String message = "walkRouter returned something else than a single Leg, e.g. it routes walk on the network with non_network_walk to access the network. Not implemented in parking yet!"; log.error(message); throw new RuntimeException(message); } - Leg walkLeg = (Leg) walkTrip.get(0); this.lastParkActionState = LastParkActionState.WALKTOPARK; this.currentlyAssignedVehicleId = vehicleId; - this.stageInteractionType = ParkingUtils.PARKACTIVITYTYPE; + this.stageInteractionType = ParkingUtils.ParkingStageInteractionType; return new StaticPassengerDynLeg(walkLeg.getRoute(), walkLeg.getMode()); } else if (currentLeg.getMode().equals(TransportMode.pt)) { if (currentLeg.getRoute() instanceof TransitPassengerRoute) { @@ -292,8 +272,8 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { } } else throw new RuntimeException( - "no more leg to follow but activity is ending\nLastPlanElement: " + currentPlanElement.toString() + "\n Agent " + this.agent.getId() + "\nTime: " + Time.writeTime( - now)); + "no more leg to follow but activity is ending\nLastPlanElement: " + currentPlanElement.toString() + "\n Agent " + this.agent.getId() + "\nTime: " + Time.writeTime( + now)); } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java index fc5abd290c6..c3f2a38eb87 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java @@ -21,18 +21,21 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Activity; import java.util.ArrayList; import java.util.List; import java.util.Random; /** - * @author jbischoff, tschlenther + * @author jbischoff, tschlenther, Ricardo Ewert * */ public class ParkingUtils { - static public final String PARKACTIVITYTYPE = "parking"; + static public final String ParkingStageInteractionType = "parking"; + static public final String ParkingActivityType = "parking_activity"; + static public final String WaitingForParkingActivityType = "waitingForParkingSpace_activity"; static public final int NO_OF_LINKS_TO_GET_ON_ROUTE = 5; @@ -143,4 +146,45 @@ public static List getOutgoingLinksForMode(Link link, String mode) { return outGoingModeLinks; } + /** + * Checks if the activity has parking while the activity. + * + * @param followingActivity + * @return + */ + public static boolean checkIfActivityHasNoParking(Activity followingActivity) { + return followingActivity.getAttributes().getAsMap().containsKey("parking") && followingActivity.getAttributes().getAttribute( + "parking").equals("noParking"); + + } + + /** + * Sets that while this activity we simulate no parking activities. + * + * @param activity + */ + public static void setNoParkingForActivity(Activity activity) { + activity.getAttributes().putAttribute("parking", "noParking"); + } + + /** + * This activity has a passenger interaction. This would mean that the location is fixed, and can not be changed. + * + * @param activity + */ + public static void setPassangerInteractionForActivity(Activity activity) { + activity.getAttributes().putAttribute("parking", "PassangerInteraction"); + } + + /** + * Checks if the activity has a passanger interaction. This would mean that the location is fixed, and can not be changed. + * + * @param activity + * @return + */ + public static boolean checkIfActivityHasPassengerInteraction(Activity activity) { + return activity.getAttributes().getAsMap().containsKey("parking") && activity.getAttributes().getAttribute( + "parking").equals( + "PassangerInteraction"); + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java index 9203fe45526..41e370c8065 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java @@ -26,9 +26,13 @@ import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.mobsim.framework.events.MobsimBeforeSimStepEvent; +import org.matsim.core.mobsim.framework.events.MobsimInitializedEvent; +import org.matsim.core.mobsim.framework.listeners.MobsimBeforeSimStepListener; +import org.matsim.core.mobsim.framework.listeners.MobsimInitializedListener; +import org.matsim.core.mobsim.qsim.QSim; import org.matsim.core.utils.io.IOUtils; - import java.io.BufferedWriter; import java.io.IOException; import java.util.List; @@ -38,7 +42,7 @@ * */ -public class ParkingListener implements IterationEndsListener { +public class ParkingListener implements IterationEndsListener, MobsimBeforeSimStepListener, MobsimInitializedListener { @Inject ParkingSearchManager manager; @@ -59,7 +63,7 @@ private void writeStatsByTimesteps(List produceBeneStatistics, int itera BufferedWriter bw = IOUtils.getBufferedWriter(output.getIterationFilename(iteration, "parkingStatsPerTimeSteps.csv")); try { - String header = "time;rejectedReservations;foundParking;unpark"; + String header = "time;rejectedParkingRequest;foundParking;unpark"; bw.write(header); bw.newLine(); for (String s : produceBeneStatistics){ @@ -82,7 +86,7 @@ private void writeStats(List produceStatistics, int iteration) { BufferedWriter bw = IOUtils.getBufferedWriter(output.getIterationFilename(iteration, "parkingStats.csv")); try { - String header = "linkId;X;Y;parkingFacility;capacity;EndOccupation;reservationsRequests;numberOfParkedVehicles;rejectedReservations"; + String header = "linkId;X;Y;parkingFacility;capacity;EndOccupation;reservationsRequests;numberOfParkedVehicles;rejectedParkingRequest;numberOfWaitingActivities;numberOfStaysFromGetOffUntilGetIn;numberOfParkingBeforeGetIn"; bw.write(header); bw.newLine(); for (String s : produceStatistics){ @@ -99,4 +103,15 @@ private void writeStats(List produceStatistics, int iteration) { } + @Override + public void notifyMobsimBeforeSimStep(MobsimBeforeSimStepEvent event) { + ((FacilityBasedParkingManager) manager).checkFreeCapacitiesForWaitingVehicles((QSim) event.getQueueSimulation(), event.getSimulationTime()); + } + + @Override + public void notifyMobsimInitialized(final MobsimInitializedEvent e) { + QSim qSim = (QSim) e.getQueueSimulation(); + ((FacilityBasedParkingManager) manager).setQSim(qSim); + + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java index e475acbb181..50587d72059 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java @@ -1,202 +1,202 @@ -/* *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) ${year} by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.contrib.parking.parkingsearch.evaluation; - -import com.google.inject.Inject; -import org.apache.commons.lang3.mutable.MutableDouble; -import org.apache.logging.log4j.LogManager; -import org.matsim.api.core.v01.Coord; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.Scenario; -import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; -import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; -import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; -import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; -import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; -import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; -import org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler; -import org.matsim.api.core.v01.events.handler.VehicleLeavesTrafficEventHandler; -import org.matsim.api.core.v01.network.Link; -import org.matsim.api.core.v01.network.Network; -import org.matsim.contrib.parking.parkingsearch.ParkingUtils; -import org.matsim.core.controler.events.IterationEndsEvent; -import org.matsim.core.controler.listener.IterationEndsListener; -import org.matsim.core.gbl.MatsimRandom; -import org.matsim.core.utils.collections.Tuple; -import org.matsim.core.utils.io.IOUtils; -import org.matsim.facilities.ActivityFacility; -import org.matsim.vehicles.Vehicle; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.util.*; -import java.util.Map.Entry; - -public class ParkingSlotVisualiser implements PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler, VehicleLeavesTrafficEventHandler, VehicleEntersTrafficEventHandler, IterationEndsListener { - - Network network; - - protected Map, ParkingSlotManager> slotsOnLink = new HashMap, ParkingSlotManager>(); - protected Map, Double> midnightParkers = new HashMap, Double>(); - protected Map, ParkingSlotManager> vehiclesResponsibleManager = new HashMap<>(); - Random r = MatsimRandom.getLocalInstance(); - protected List parkings = new ArrayList<>(); - - Map, Id> parkedVehicles = new HashMap, Id>(); - - /** - * - */ - @Inject - public ParkingSlotVisualiser(Scenario scenario) { - this.network = scenario.getNetwork(); - Map, ActivityFacility> parkingFacilities = scenario.getActivityFacilities().getFacilitiesForActivityType( - ParkingUtils.PARKACTIVITYTYPE); - initialize(parkingFacilities); - } - - public ParkingSlotVisualiser(Network network, Map, ActivityFacility> parkingFacilities) { - this.network = network; - initialize(parkingFacilities); - } - - private void initialize(Map, ActivityFacility> parkingFacilities) { - Map, MutableDouble> nrOfSlotsPerLink = new HashMap, MutableDouble>(); - for (ActivityFacility fac : parkingFacilities.values()) { - Id linkId = fac.getLinkId(); - if (nrOfSlotsPerLink.containsKey(linkId)) { - nrOfSlotsPerLink.get(linkId).add(fac.getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity()); - } else { - nrOfSlotsPerLink.put(linkId, new MutableDouble(fac.getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity())); - } - } - - for (Id linkID : nrOfSlotsPerLink.keySet()) { -// LogManager.getLogger(getClass()).info("initialize parking visualisation for link " + linkID); - this.slotsOnLink.put(linkID, new ParkingSlotManager(network.getLinks().get(linkID), nrOfSlotsPerLink.get(linkID).intValue())); - } - } - - - @Override - public void reset(int iteration) { - for (Id link : this.slotsOnLink.keySet()) { - this.slotsOnLink.get(link).setAllParkingTimesToZero(); - } - } - - @Override - public void handleEvent(VehicleLeavesTrafficEvent event) { - if (this.slotsOnLink.containsKey(event.getLinkId())) { - this.vehiclesResponsibleManager.put(event.getVehicleId(), this.slotsOnLink.get(event.getLinkId())); - } - } - - @Override - public void handleEvent(PersonLeavesVehicleEvent event) { - ParkingSlotManager manager = this.vehiclesResponsibleManager.remove(event.getVehicleId()); - if (manager != null) { - Tuple parkingTuple = manager.processParking(event.getTime(), event.getVehicleId()); - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); - this.parkedVehicles.put(event.getVehicleId(), manager.getLinkId()); - } - } - - - @Override - public void handleEvent(PersonEntersVehicleEvent event) { - if (this.parkedVehicles.containsKey(event.getVehicleId())) { - ParkingSlotManager manager = this.slotsOnLink.get(this.parkedVehicles.get(event.getVehicleId())); - Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); - this.parkedVehicles.remove(event.getVehicleId()); - } else { - midnightParkers.put(event.getVehicleId(), event.getTime()); - } - } - - /* (non-Javadoc) - * @see org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler#handleEvent(org.matsim.api.core.v01.events.VehicleEntersTrafficEvent) - */ - @Override - public void handleEvent(VehicleEntersTrafficEvent event) { - if (this.midnightParkers.containsKey(event.getVehicleId())) { - if (this.slotsOnLink.containsKey(event.getLinkId())) { - ParkingSlotManager manager = this.slotsOnLink.get(event.getLinkId()); - Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); - if (parkingTuple != null) { - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); - } - } - this.midnightParkers.remove(event.getVehicleId()); - } - } - - public void finishDay() { - - for (Id linkId : this.slotsOnLink.keySet()) { - ParkingSlotManager manager = this.slotsOnLink.get(linkId); - Map, Tuple> occupiedSlots = manager.getOccupiedSlots(); - - double endOfDay = 30 * 3600; - for (Entry, Tuple> e : occupiedSlots.entrySet()) { - Tuple parkingTuple = e.getValue(); - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + e.getKey()); - - // set back to 0 - } - - List> freeSlots = manager.getFreeSlots(); - for (Tuple parkingTuple : freeSlots) { - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); - } - } - } - - public void plotSlotOccupation(String filename) { - String head = "LinkId;from;To;X;Y;OccupiedByVehicle"; - BufferedWriter bw = IOUtils.getBufferedWriter(filename); - try { - bw.write(head); - for (String s : this.parkings) { - bw.newLine(); - bw.write(s); - } - bw.flush(); - bw.close(); - } catch (IOException e) { - e.printStackTrace(); - } - LogManager.getLogger(getClass()).info("FINISHED WRITING PARKING SLOT VISUALISATION FILE TO: " + filename); - } - - @Override - public void notifyIterationEnds(IterationEndsEvent event) { - String path = event.getServices().getControlerIO().getIterationFilename(event.getIteration(), - "ParkingSlots_it" + event.getIteration() + ".csv"); - this.finishDay(); - this.plotSlotOccupation(path); - } -} - +/* *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) ${year} by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.contrib.parking.parkingsearch.evaluation; + +import com.google.inject.Inject; +import org.apache.commons.lang3.mutable.MutableDouble; +import org.apache.logging.log4j.LogManager; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; +import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; +import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; +import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; +import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; +import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; +import org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler; +import org.matsim.api.core.v01.events.handler.VehicleLeavesTrafficEventHandler; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.parking.parkingsearch.ParkingUtils; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.utils.collections.Tuple; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.facilities.ActivityFacility; +import org.matsim.vehicles.Vehicle; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; + +public class ParkingSlotVisualiser implements PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler, VehicleLeavesTrafficEventHandler, VehicleEntersTrafficEventHandler, IterationEndsListener { + + Network network; + + protected Map, ParkingSlotManager> slotsOnLink = new HashMap, ParkingSlotManager>(); + protected Map, Double> midnightParkers = new HashMap, Double>(); + protected Map, ParkingSlotManager> vehiclesResponsibleManager = new HashMap<>(); + Random r = MatsimRandom.getLocalInstance(); + protected List parkings = new ArrayList<>(); + + protected Map, Id> parkedVehicles = new HashMap, Id>(); + + /** + * + */ + @Inject + public ParkingSlotVisualiser(Scenario scenario) { + this.network = scenario.getNetwork(); + Map, ActivityFacility> parkingFacilities = scenario.getActivityFacilities().getFacilitiesForActivityType( + ParkingUtils.ParkingStageInteractionType); + initialize(parkingFacilities); + } + + public ParkingSlotVisualiser(Network network, Map, ActivityFacility> parkingFacilities) { + this.network = network; + initialize(parkingFacilities); + } + + private void initialize(Map, ActivityFacility> parkingFacilities) { + Map, MutableDouble> nrOfSlotsPerLink = new HashMap, MutableDouble>(); + for (ActivityFacility fac : parkingFacilities.values()) { + Id linkId = fac.getLinkId(); + if (nrOfSlotsPerLink.containsKey(linkId)) { + nrOfSlotsPerLink.get(linkId).add(fac.getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity()); + } else { + nrOfSlotsPerLink.put(linkId, new MutableDouble(fac.getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity())); + } + } + + for (Id linkID : nrOfSlotsPerLink.keySet()) { +// LogManager.getLogger(getClass()).info("initialize parking visualisation for link " + linkID); + this.slotsOnLink.put(linkID, new ParkingSlotManager(network.getLinks().get(linkID), nrOfSlotsPerLink.get(linkID).intValue())); + } + } + + + @Override + public void reset(int iteration) { + for (Id link : this.slotsOnLink.keySet()) { + this.slotsOnLink.get(link).setAllParkingTimesToZero(); + } + } + + @Override + public void handleEvent(VehicleLeavesTrafficEvent event) { + if (this.slotsOnLink.containsKey(event.getLinkId())) { + this.vehiclesResponsibleManager.put(event.getVehicleId(), this.slotsOnLink.get(event.getLinkId())); + } + } + + @Override + public void handleEvent(PersonLeavesVehicleEvent event) { + ParkingSlotManager manager = this.vehiclesResponsibleManager.remove(event.getVehicleId()); + if (manager != null) { + Tuple parkingTuple = manager.processParking(event.getTime(), event.getVehicleId()); + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); + this.parkedVehicles.put(event.getVehicleId(), manager.getLinkId()); + } + } + + + @Override + public void handleEvent(PersonEntersVehicleEvent event) { + if (this.parkedVehicles.containsKey(event.getVehicleId())) { + ParkingSlotManager manager = this.slotsOnLink.get(this.parkedVehicles.get(event.getVehicleId())); + Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); + this.parkedVehicles.remove(event.getVehicleId()); + } else { + midnightParkers.put(event.getVehicleId(), event.getTime()); + } + } + + /* (non-Javadoc) + * @see org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler#handleEvent(org.matsim.api.core.v01.events.VehicleEntersTrafficEvent) + */ + @Override + public void handleEvent(VehicleEntersTrafficEvent event) { + if (this.midnightParkers.containsKey(event.getVehicleId())) { + if (this.slotsOnLink.containsKey(event.getLinkId())) { + ParkingSlotManager manager = this.slotsOnLink.get(event.getLinkId()); + Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); + if (parkingTuple != null) { + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); + } + } + this.midnightParkers.remove(event.getVehicleId()); + } + } + + public void finishDay() { + + for (Id linkId : this.slotsOnLink.keySet()) { + ParkingSlotManager manager = this.slotsOnLink.get(linkId); + Map, Tuple> occupiedSlots = manager.getOccupiedSlots(); + + double endOfDay = 30 * 3600; + for (Entry, Tuple> e : occupiedSlots.entrySet()) { + Tuple parkingTuple = e.getValue(); + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + e.getKey()); + + // set back to 0 + } + + List> freeSlots = manager.getFreeSlots(); + for (Tuple parkingTuple : freeSlots) { + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); + } + } + } + + public void plotSlotOccupation(String filename) { + String head = "LinkId;from;To;X;Y;OccupiedByVehicle"; + BufferedWriter bw = IOUtils.getBufferedWriter(filename); + try { + bw.write(head); + for (String s : this.parkings) { + bw.newLine(); + bw.write(s); + } + bw.flush(); + bw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + LogManager.getLogger(getClass()).info("FINISHED WRITING PARKING SLOT VISUALISATION FILE TO: " + filename); + } + + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + String path = event.getServices().getControlerIO().getIterationFilename(event.getIteration(), + "ParkingSlots_it" + event.getIteration() + ".csv"); + this.finishDay(); + this.plotSlotOccupation(path); + } +} + diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEvent.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEvent.java new file mode 100644 index 00000000000..992fd8763e6 --- /dev/null +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEvent.java @@ -0,0 +1,68 @@ +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2016 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.contrib.parking.parkingsearch.events; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.network.Link; +import org.matsim.vehicles.Vehicle; + +import java.util.Map; + +/** + * @author jbischoff + */ + +public class StartWaitingForParkingEvent extends Event { + public static final String EVENT_TYPE = "started waiting for parking"; + public static final String ATTRIBUTE_VEHICLE = "vehicle"; + public static final String ATTRIBUTE_LINK = "link"; + private final Id linkId; + private final Id vehicleId; + + public StartWaitingForParkingEvent(final double time, Id vehicleId, Id linkId) { + super(time); + this.linkId = linkId; + this.vehicleId = vehicleId; + + } + + @Override + public String getEventType() { + return EVENT_TYPE; + } + + public Id getLinkId() { + return linkId; + } + + public Id getVehicleId() { + return vehicleId; + } + + @Override + public Map getAttributes() { + Map attr = super.getAttributes(); + attr.put(ATTRIBUTE_VEHICLE, this.vehicleId.toString()); + attr.put(ATTRIBUTE_LINK, this.linkId.toString()); + return attr; + } + +} diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEventHandler.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEventHandler.java new file mode 100644 index 00000000000..24d5beb7d33 --- /dev/null +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEventHandler.java @@ -0,0 +1,32 @@ +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2016 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.contrib.parking.parkingsearch.events; + +import org.matsim.core.events.handler.EventHandler; + +/** + * @author jbischoff + */ + +public interface StartWaitingForParkingEventHandler extends EventHandler { + + public void handleEvent(StartWaitingForParkingEvent event); + +} diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java index ce0cc3a9e4d..9b3b8eff107 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java @@ -26,26 +26,32 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.dynagent.DynAgent; import org.matsim.contrib.parking.parkingsearch.ParkingUtils; import org.matsim.contrib.parking.parkingsearch.sim.ParkingSearchConfigGroup; +import org.matsim.core.mobsim.qsim.QSim; import org.matsim.core.utils.misc.Time; import org.matsim.facilities.ActivityFacility; +import org.matsim.facilities.ActivityOption; import org.matsim.vehicles.Vehicle; import java.util.*; import java.util.Map.Entry; /** - * @author jbischoff, schlenther - * + * @author jbischoff, schlenther, Ricardo Ewert */ public class FacilityBasedParkingManager implements ParkingSearchManager { protected Map, Integer> capacity = new HashMap<>(); protected Map, MutableLong> occupation = new HashMap<>(); protected Map, MutableLong> reservationsRequests = new HashMap<>(); - protected Map, MutableLong> rejectedReservations = new HashMap<>(); + protected Map, MutableLong> rejectedParkingRequest = new HashMap<>(); protected Map, MutableLong> numberOfParkedVehicles = new HashMap<>(); + protected Map, MutableLong> numberOfWaitingActivities = new HashMap<>(); + protected Map, MutableLong> numberOfStaysFromGetOffUntilGetIn = new HashMap<>(); + protected Map, MutableLong> numberOfParkingBeforeGetIn = new HashMap<>(); + protected Map, TreeMap>> waitingVehicles = new HashMap<>(); protected TreeMap rejectedReservationsByTime = new TreeMap<>(); protected TreeMap foundParkingByTime = new TreeMap<>(); protected TreeMap unparkByTime = new TreeMap<>(); @@ -54,8 +60,10 @@ public class FacilityBasedParkingManager implements ParkingSearchManager { protected Map, Id> parkingReservation = new HashMap<>(); protected Map, Id> parkingLocationsOutsideFacilities = new HashMap<>(); protected Map, Set>> facilitiesPerLink = new HashMap<>(); - protected Network network; + protected Network network; + protected ParkingSearchConfigGroup psConfigGroup; protected boolean canParkOnlyAtFacilities; + private QSim qsim; private final int maxSlotIndex; private final int maxTime; private final int timeBinSize; @@ -63,14 +71,15 @@ public class FacilityBasedParkingManager implements ParkingSearchManager { @Inject public FacilityBasedParkingManager(Scenario scenario) { - ParkingSearchConfigGroup psConfigGroup = (ParkingSearchConfigGroup) scenario.getConfig().getModules().get(ParkingSearchConfigGroup.GROUP_NAME); + psConfigGroup = (ParkingSearchConfigGroup) scenario.getConfig().getModules().get( + ParkingSearchConfigGroup.GROUP_NAME); canParkOnlyAtFacilities = psConfigGroup.getCanParkOnlyAtFacilities(); this.network = scenario.getNetwork(); parkingFacilities = scenario.getActivityFacilities() - .getFacilitiesForActivityType(ParkingUtils.PARKACTIVITYTYPE); + .getFacilitiesForActivityType(ParkingUtils.ParkingStageInteractionType); LogManager.getLogger(getClass()).info(parkingFacilities.toString()); - this.timeBinSize = 15*60; - this.maxTime = 24 * 3600 -1; + this.timeBinSize = 15 * 60; + this.maxTime = 24 * 3600 - 1; this.maxSlotIndex = (this.maxTime / this.timeBinSize) + 1; this.startTime = 9 * 3600; @@ -82,10 +91,14 @@ public FacilityBasedParkingManager(Scenario scenario) { } parkingOnLink.add(fac.getId()); this.facilitiesPerLink.put(linkId, parkingOnLink); + this.waitingVehicles.computeIfAbsent(linkId, (k) -> new TreeMap<>()); this.occupation.put(fac.getId(), new MutableLong(0)); this.reservationsRequests.put(fac.getId(), new MutableLong(0)); - this.rejectedReservations.put(fac.getId(), new MutableLong(0)); + this.rejectedParkingRequest.put(fac.getId(), new MutableLong(0)); this.numberOfParkedVehicles.put(fac.getId(), new MutableLong(0)); + this.numberOfWaitingActivities.put(fac.getId(), new MutableLong(0)); + this.numberOfStaysFromGetOffUntilGetIn.put(fac.getId(), new MutableLong(0)); + this.numberOfParkingBeforeGetIn.put(fac.getId(), new MutableLong(0)); } int slotIndex = getTimeSlotIndex(startTime); while (slotIndex <= maxSlotIndex) { @@ -109,6 +122,39 @@ public boolean reserveSpaceIfVehicleCanParkHere(Id vehicleId, Id return canPark; } + /** + * Checks if it is possible if you can park at this link for the complete time. + * + * @param linkId + * @param stopDuration + * @param getOffDuration + * @param pickUpDuration + * @param now + * @return + */ + public boolean canParkAtThisFacilityUntilEnd(Id linkId, double stopDuration, double getOffDuration, double pickUpDuration, double now) { + Set> facilities = this.facilitiesPerLink.get(linkId); + if (facilities != null) { + double totalNeededParkingDuration = getOffDuration + stopDuration + pickUpDuration; + for (Id facility : facilities) { + double maxParkingDurationAtFacilityInHours = Double.MAX_VALUE; + if (this.parkingFacilities.get(facility).getAttributes().getAsMap().containsKey("maxParkingDurationInHours")) + maxParkingDurationAtFacilityInHours = 3600 * (double) this.parkingFacilities.get(facility).getAttributes().getAsMap().get( + "maxParkingDurationInHours"); + if (maxParkingDurationAtFacilityInHours > totalNeededParkingDuration) { + ActivityOption parkingOptions = this.parkingFacilities.get(facility).getActivityOptions().get("parking"); + if (!parkingOptions.getOpeningTimes().isEmpty()) { + if ((parkingOptions.getOpeningTimes().first().getStartTime() == 0 && parkingOptions.getOpeningTimes().first().getEndTime() == 24 * 3600)) + if (parkingOptions.getOpeningTimes().first().getStartTime() <= now && parkingOptions.getOpeningTimes().first().getEndTime() >= now + totalNeededParkingDuration) + return true; + } else + return true; + } + } + } + return false; + } + private boolean linkIdHasAvailableParkingForVehicle(Id linkId, Id vid) { // LogManager.getLogger(getClass()).info("link "+linkId+" vehicle "+vid); if (!this.facilitiesPerLink.containsKey(linkId) && !canParkOnlyAtFacilities) { @@ -125,8 +171,8 @@ private boolean linkIdHasAvailableParkingForVehicle(Id linkId, Id } Set> parkingFacilitiesAtLink = this.facilitiesPerLink.get(linkId); for (Id fac : parkingFacilitiesAtLink) { - double cap = this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE) - .getCapacity(); + double cap = this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType) + .getCapacity(); this.reservationsRequests.get(fac).increment(); if (this.occupation.get(fac).doubleValue() < cap) { // LogManager.getLogger(getClass()).info("occ: @@ -136,7 +182,7 @@ private boolean linkIdHasAvailableParkingForVehicle(Id linkId, Id return true; } - this.rejectedReservations.get(fac).increment(); + this.rejectedParkingRequest.get(fac).increment(); } return false; } @@ -150,7 +196,7 @@ public Id getVehicleParkingLocation(Id vehicleId) { @Override public boolean parkVehicleHere(Id vehicleId, Id linkId, double time) { - return parkVehicleAtLink(vehicleId, linkId, time); + return parkVehicleAtLink(vehicleId, linkId, time); } protected boolean parkVehicleAtLink(Id vehicleId, Id linkId, double time) { @@ -167,7 +213,7 @@ protected boolean parkVehicleAtLink(Id vehicleId, Id linkId, doub return true; } else { throw new RuntimeException("no parking reservation found for vehicle " + vehicleId.toString() - + "arrival on link " + linkId + " with parking restriction"); + + " arrival on link " + linkId + " with parking restriction"); } } } @@ -193,11 +239,14 @@ public List produceStatistics() { for (Entry, MutableLong> e : this.occupation.entrySet()) { Id linkId = this.parkingFacilities.get(e.getKey()).getLinkId(); double capacity = this.parkingFacilities.get(e.getKey()).getActivityOptions() - .get(ParkingUtils.PARKACTIVITYTYPE).getCapacity(); + .get(ParkingUtils.ParkingStageInteractionType).getCapacity(); double x = this.parkingFacilities.get(e.getKey()).getCoord().getX(); double y = this.parkingFacilities.get(e.getKey()).getCoord().getY(); - String s = linkId.toString() + ";" + x + ";" + y + ";" + e.getKey().toString() + ";" + capacity + ";" + e.getValue().toString() + ";" + this.reservationsRequests.get(e.getKey()).toString() + ";" + this.numberOfParkedVehicles.get(e.getKey()).toString() + ";" + this.rejectedReservations.get(e.getKey()).toString(); + String s = linkId.toString() + ";" + x + ";" + y + ";" + e.getKey().toString() + ";" + capacity + ";" + e.getValue().toString() + ";" + this.reservationsRequests.get( + e.getKey()).toString() + ";" + this.numberOfParkedVehicles.get(e.getKey()).toString() + ";" + this.rejectedParkingRequest.get( + e.getKey()).toString() + ";" + this.numberOfWaitingActivities.get( + e.getKey()).toString() + ";" + this.numberOfStaysFromGetOffUntilGetIn.get(e.getKey()).intValue() + ";" + this.numberOfParkingBeforeGetIn.get(e.getKey()).intValue(); stats.add(s); } return stats; @@ -208,31 +257,32 @@ public List produceTimestepsStatistics() { for (int time : rejectedReservationsByTime.keySet()) { String s = Time.writeTime(time, Time.TIMEFORMAT_HHMM) + ";" + rejectedReservationsByTime.get(time) + ";" + foundParkingByTime.get( - time) + ";" + unparkByTime.get(time); + time) + ";" + unparkByTime.get(time); stats.add(s); } return stats; } - public double getNrOfAllParkingSpacesOnLink (Id linkId){ + + public double getNrOfAllParkingSpacesOnLink(Id linkId) { double allSpaces = 0; Set> parkingFacilitiesAtLink = this.facilitiesPerLink.get(linkId); if (!(parkingFacilitiesAtLink == null)) { - for (Id fac : parkingFacilitiesAtLink){ - allSpaces += this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity(); + for (Id fac : parkingFacilitiesAtLink) { + allSpaces += this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity(); } } return allSpaces; } - public double getNrOfFreeParkingSpacesOnLink (Id linkId){ + public double getNrOfFreeParkingSpacesOnLink(Id linkId) { double allFreeSpaces = 0; Set> parkingFacilitiesAtLink = this.facilitiesPerLink.get(linkId); if (parkingFacilitiesAtLink == null) { return 0; } else { - for (Id fac : parkingFacilitiesAtLink){ - int cap = (int) this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity(); + for (Id fac : parkingFacilitiesAtLink) { + int cap = (int) this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity(); allFreeSpaces += (cap - this.occupation.get(fac).intValue()); } } @@ -243,11 +293,11 @@ public Map, ActivityFacility> getParkingFacilities() { return this.parkingFacilities; } - public void registerRejectedReservation(double now){ + public void registerRejectedReservation(double now) { rejectedReservationsByTime.get(getTimeSlotIndex(now) * timeBinSize).increment(); } - public TreeSet getTimeSteps(){ + public TreeSet getTimeSteps() { TreeSet timeSteps = new TreeSet<>(); int slotIndex = 0; while (slotIndex <= maxSlotIndex) { @@ -261,15 +311,77 @@ private int getTimeSlotIndex(final double time) { if (time > this.maxTime) { return this.maxSlotIndex; } - return ((int)time / this.timeBinSize); + return ((int) time / this.timeBinSize); + } + + /** + * Gives the duration of the staging activity of parking + * + * @return + */ + public double getParkStageActivityDuration() { + return psConfigGroup.getParkduration(); + } + + /** + * Gives the duration of the staging activity of unparking + * + * @return + */ + public double getUnParkStageActivityDuration() { + return psConfigGroup.getUnparkduration(); } @Override public void reset(int iteration) { - for (Id fac : this.rejectedReservations.keySet()) { - this.rejectedReservations.get(fac).setValue(0); + for (Id fac : this.rejectedParkingRequest.keySet()) { + this.rejectedParkingRequest.get(fac).setValue(0); this.reservationsRequests.get(fac).setValue(0); this.numberOfParkedVehicles.get(fac).setValue(0); + this.numberOfWaitingActivities.get(fac).setValue(0); + } + waitingVehicles.clear(); + } + + public void addVehicleForWaitingForParking(Id linkId, Id vehicleId, double now) { +// System.out.println(now + ": vehicle " +vehicleId.toString() + " starts waiting here: " + linkId.toString()); + waitingVehicles.get(linkId).put(now + getParkStageActivityDuration() + 1, vehicleId); + for (Id fac : this.facilitiesPerLink.get(linkId)) { + this.numberOfWaitingActivities.get(fac).increment(); + break; + } + + } + + public void checkFreeCapacitiesForWaitingVehicles(QSim qSim, double now) { + for (Id linkId : waitingVehicles.keySet()) { + if (!waitingVehicles.get(linkId).isEmpty()) { + for (Id fac : this.facilitiesPerLink.get(linkId)) { + int cap = (int) this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity(); + while (this.occupation.get(fac).intValue() < cap && !waitingVehicles.get(linkId).isEmpty()) { + double startWaitingTime = waitingVehicles.get(linkId).firstKey(); + if (startWaitingTime > now) + break; + Id vehcileId = waitingVehicles.get(linkId).remove(startWaitingTime); + DynAgent agent = (DynAgent) qSim.getAgents().get(Id.createPersonId(vehcileId.toString())); + reserveSpaceIfVehicleCanParkHere(vehcileId, linkId); + agent.endActivityAndComputeNextState(now); + qsim.rescheduleActivityEnd(agent); + } + } + } } } + + public void setQSim(QSim qSim) { + qsim = qSim; + } + + public void registerStayFromGetOffUntilGetIn(Id vehcileId) { + this.numberOfStaysFromGetOffUntilGetIn.get(parkingLocations.get(vehcileId)).increment(); + } + + public void registerParkingBeforeGetIn(Id vehcileId) { + this.numberOfParkingBeforeGetIn.get(parkingLocations.get(vehcileId)).increment(); + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java index 5311933db84..b9fbebe4699 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java @@ -1,5 +1,5 @@ /** - * + * */ package org.matsim.contrib.parking.parkingsearch.manager; @@ -23,90 +23,92 @@ */ public class ZoneParkingManager extends FacilityBasedParkingManager { - private HashMap>> linksOfZone; - private HashMap totalCapOfZone; - private HashMap occupationOfZone; - + private HashMap>> linksOfZone; + private HashMap totalCapOfZone; + private HashMap occupationOfZone; + /** * @param scenario */ @Inject public ZoneParkingManager(Scenario scenario, String[] pathToZoneTxtFiles) { super(scenario); - - this.linksOfZone = new HashMap>>(); - this.totalCapOfZone = new HashMap(); - this.occupationOfZone = new HashMap(); - - for(String zone: pathToZoneTxtFiles){ + + this.linksOfZone = new HashMap>>(); + this.totalCapOfZone = new HashMap(); + this.occupationOfZone = new HashMap(); + + for (String zone : pathToZoneTxtFiles) { readZone(zone); } - - for(String zone: this.linksOfZone.keySet()){ + + for (String zone : this.linksOfZone.keySet()) { calculateTotalZoneParkCapacity(zone); - this.occupationOfZone.put(zone,0.0); + this.occupationOfZone.put(zone, 0.0); } } - + /** * reads in a tabular file that declares which link id's are in the monitored zone - * the part between the last '/' and the file type extension in the given path is considered to be the zone name + * the part between the last '/' and the file type extension in the given path is considered to be the zone name * @param pathToZoneFile */ - void readZone(String pathToZoneFile){ - String zone = pathToZoneFile.substring(pathToZoneFile.lastIndexOf("/")+1, pathToZoneFile.lastIndexOf(".")); - + void readZone(String pathToZoneFile) { + String zone = pathToZoneFile.substring(pathToZoneFile.lastIndexOf("/") + 1, pathToZoneFile.lastIndexOf(".")); + HashSet> links = new HashSet>(); - + TabularFileParserConfig config = new TabularFileParserConfig(); - config.setDelimiterTags(new String[] {"\t"}); - config.setFileName(pathToZoneFile); - config.setCommentTags(new String[] { "#" }); - new TabularFileParser().parse(config, new TabularFileHandler() { + config.setDelimiterTags(new String[]{"\t"}); + config.setFileName(pathToZoneFile); + config.setCommentTags(new String[]{"#"}); + new TabularFileParser().parse(config, new TabularFileHandler() { @Override public void startRow(String[] row) { Id linkId = Id.createLinkId(row[0]); links.add(linkId); } - - }); - - this.linksOfZone.put(zone, links); + + }); + + this.linksOfZone.put(zone, links); } - - private void calculateTotalZoneParkCapacity(String zoneName){ + + private void calculateTotalZoneParkCapacity(String zoneName) { double cap = 0.0; - for(Id link : this.linksOfZone.get(zoneName)){ + for (Id link : this.linksOfZone.get(zoneName)) { cap += getNrOfAllParkingSpacesOnLink(link); - } + } this.totalCapOfZone.put(zoneName, cap); } - + @Override public boolean parkVehicleHere(Id vehicleId, Id linkId, double time) { if (parkVehicleAtLink(vehicleId, linkId, time)) { - for(String zone : this.linksOfZone.keySet()){ - if(linksOfZone.get(zone).contains(linkId) && this.facilitiesPerLink.containsKey(linkId)){ + for (String zone : this.linksOfZone.keySet()) { + if (linksOfZone.get(zone).contains(linkId) && this.facilitiesPerLink.containsKey(linkId)) { double newOcc = this.occupationOfZone.get(zone) + 1; - if(this.totalCapOfZone.get(zone) vehicleId, Id linkId, double time) { if (!this.parkingLocations.containsKey(vehicleId)) { @@ -115,35 +117,36 @@ public boolean unParkVehicleHere(Id vehicleId, Id linkId, double } else { Id fac = this.parkingLocations.remove(vehicleId); this.occupation.get(fac).decrement(); - + Id parkingLink = this.parkingFacilities.get(fac).getLinkId(); - for(String zone : this.linksOfZone.keySet()){ - if(linksOfZone.get(zone).contains(parkingLink)){ + for (String zone : this.linksOfZone.keySet()) { + if (linksOfZone.get(zone).contains(parkingLink)) { double newOcc = this.occupationOfZone.get(zone) - 1; - if(newOcc < 0 ){ - //in iteration 0 agents can "leave parking spaces" (get into traffic), but the manager didn't record them to be parked + if (newOcc < 0) { + //in iteration 0 agents can "leave parking spaces" (get into traffic), but the manager didn't record them to be parked newOcc = 0; } - this.occupationOfZone.put(zone,newOcc); + this.occupationOfZone.put(zone, newOcc); } } - return true; + return true; } } - - - public double getOccupancyRatioOfZone(String zone){ - if(!(this.linksOfZone.keySet().contains(zone))) throw new RuntimeException("zone " + zone + " was not defined. thus, could'nt calculate occupancy ratio."); + + + public double getOccupancyRatioOfZone(String zone) { + if (!(this.linksOfZone.keySet().contains(zone))) + throw new RuntimeException("zone " + zone + " was not defined. thus, could'nt calculate occupancy ratio."); return (this.occupationOfZone.get(zone) / this.totalCapOfZone.get(zone)); } - - public Set getZones(){ + + public Set getZones() { return this.linksOfZone.keySet(); } - - public double getTotalCapacityOfZone(String zone){ + + public double getTotalCapacityOfZone(String zone) { return this.totalCapOfZone.get(zone); } - + } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java index 041e74c2198..d87bf0408fe 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java @@ -49,6 +49,7 @@ public class NearestParkingSpotSearchLogic implements ParkingSearchLogic { private NetworkRoute actualRoute = null; private final boolean canReserveParkingSlot; private final boolean canCheckParkingCapacitiesInAdvanced; + private double distanceFromBaseToAttraction = Double.NaN; private boolean useRandomLinkChoice; private int currentLinkIdx; private final HashSet> triedParking; @@ -79,22 +80,32 @@ public NearestParkingSpotSearchLogic(Network network, ParkingRouter parkingRoute * @param baseLinkId linkId of the origin destination where the parkingSearch starts */ public Id getNextLink(Id currentLinkId, Id baseLinkId, Id vehicleId, String mode, double now, - double maxParkingDuration, double nextPickupTime) { - + double maxParkingDuration, double nextPickupTime, boolean passangerInteractionAtParkingFacilityAtEndOfLeg, + Coord coordOfAttraction) { + double maxAdditionalDistanceToAttraction = Double.MAX_VALUE; + // if a passenger interaction take place at a facility the walking distance to the attraction should be not extended by the value of maxAdditionalDistanceToAttraction + if (passangerInteractionAtParkingFacilityAtEndOfLeg) { + if (Double.isNaN(distanceFromBaseToAttraction)) + findDistanceBetweenBaseLinkAndAttraction(baseLinkId, coordOfAttraction); + maxAdditionalDistanceToAttraction = 200.; + } if (actualRoute == null) { - actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, maxParkingDuration); - checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); - if (actualRoute != null) { - actualRoute.setVehicleId(vehicleId); - } + actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, + maxParkingDuration, + passangerInteractionAtParkingFacilityAtEndOfLeg, maxAdditionalDistanceToAttraction, coordOfAttraction); + if (!passangerInteractionAtParkingFacilityAtEndOfLeg) + checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); triedParking.clear(); } else if (currentLinkId.equals(actualRoute.getEndLinkId()) && !skipParkingActivity) { currentLinkIdx = 0; - actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, maxParkingDuration); - checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); - if (actualRoute != null) { - actualRoute.setVehicleId(vehicleId); - } + actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, + maxParkingDuration, + passangerInteractionAtParkingFacilityAtEndOfLeg, maxAdditionalDistanceToAttraction, coordOfAttraction); + if (!passangerInteractionAtParkingFacilityAtEndOfLeg) + checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); + } + if (actualRoute != null) { + actualRoute.setVehicleId(vehicleId); } //if no possible parking was found. The vehicle takes a random next link. Background assumption: parking only at given parking slots if (actualRoute == null) { @@ -111,6 +122,20 @@ public Id getNextLink(Id currentLinkId, Id baseLinkId, Id baseLinkId, Coord coordOfAttraction) { + for (ActivityFacility activityFacility : activityFacilities.values()) { + if (activityFacility.getLinkId().equals(baseLinkId)) + distanceFromBaseToAttraction = NetworkUtils.getEuclideanDistance(activityFacility.getCoord(), + coordOfAttraction); + } + } + /** * Checks if it is possible to drive to the new parking facility and to drive back to the base without extending the startTime of the following activity. * If the resulting parking time at the new facility is less then 5 minutes the vehicle will drive directly to the next activity location. @@ -175,7 +200,9 @@ public boolean isUseRandomLinkChoice() { } private NetworkRoute findRouteToNearestParkingFacility(Id baseLinkId, Id currentLinkId, boolean canCheckParkingCapacitiesInAdvanced, - double now, double maxParkingDuration) { + double now, double maxParkingDuration, + boolean passangerInteractionAtParkingFacilityAtEndOfLeg, double maxDistanceFromBase, + Coord coordOfAttraction) { TreeMap euclideanDistanceToParkingFacilities = new TreeMap<>(); ActivityFacility nearstActivityFacility = null; NetworkRoute selectedRoute = null; @@ -183,29 +210,31 @@ private NetworkRoute findRouteToNearestParkingFacility(Id baseLinkId, Id now || parkingOptions.getOpeningTimes().first().getEndTime() < latestEndOfParking) - continue; + if (parkingOptions.getOpeningTimes().first().getStartTime() > now && parkingOptions.getOpeningTimes().first().getEndTime() < latestEndOfParking) + continue; } - //check if approx. the max parking time at facility will not exceed + //check if approx. the max parking time at facility will not exceed, assumption: "parking duration - 30 minutes" is parking Time. if (activityFacility.getAttributes().getAsMap().containsKey("maxParkingDurationInHours")) { //TODO vielleicht etwas sparsamer machen double maxParkingDurationAtFacility = 3600 * (double) activityFacility.getAttributes().getAsMap().get("maxParkingDurationInHours"); - if (maxParkingDuration > maxParkingDurationAtFacility) + if (maxParkingDuration - 30*60 > maxParkingDurationAtFacility) continue; - double expectedTravelTimeFromParkingToBase = getExpectedTravelTime(baseLinkId, now, activityFacility.getLinkId()); - double expectedTravelTimeFromCurrentToParking = getExpectedTravelTime(activityFacility.getLinkId(), now, currentLinkId); - double expectedParkingTime = maxParkingDuration - expectedTravelTimeFromCurrentToParking - expectedTravelTimeFromParkingToBase; - if (expectedParkingTime > maxParkingDurationAtFacility) + } + + //TODO beschreiben was passiert + if (passangerInteractionAtParkingFacilityAtEndOfLeg) { + double distanceBetweenThisParkingFacilityAndTheAttraction = NetworkUtils.getEuclideanDistance(activityFacility.getCoord(), + coordOfAttraction); + if (distanceBetweenThisParkingFacilityAndTheAttraction - distanceFromBaseToAttraction > maxDistanceFromBase) continue; } // create Euclidean distances to the parking activities to find routes only to the nearest facilities in the next step @@ -213,7 +242,11 @@ private NetworkRoute findRouteToNearestParkingFacility(Id baseLinkId, Id baseLinkId, Id maxParkingDurationAtFacility) + continue; + } counter++; + if (passangerInteractionAtParkingFacilityAtEndOfLeg && euclideanDistanceToParkingFacilities.size() > triedParking.size()) + if (triedParking.contains(activityFacility.getId())) + continue; + if (passangerInteractionAtParkingFacilityAtEndOfLeg && euclideanDistanceToParkingFacilities.size() == triedParking.size()) + triedParking.clear(); NetworkRoute possibleRoute = this.parkingRouter.getRouteFromParkingToDestination(activityFacility.getLinkId(), now, currentLinkId); + // reason is that we expect that the driver will always take the nearest possible getOff point to reduce the walk distance for the guests + if (passangerInteractionAtParkingFacilityAtEndOfLeg){ + selectedRoute = possibleRoute; + nearstActivityFacility = activityFacility; + break; + } double travelTimeToParking = possibleRoute.getTravelTime().seconds(); double travelTimeFromParking = travelTimeToParking; if (!baseLinkId.equals(currentLinkId)) { @@ -276,6 +328,7 @@ public void reset() { actualRoute = null; currentLinkIdx = 0; skipParkingActivity = false; + distanceFromBaseToAttraction = Double.NaN; } }