Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parking tests and comments #3637

Merged
merged 11 commits into from
Dec 11, 2024
Prev Previous commit
Next Next commit
left some comments
  • Loading branch information
paulheinr committed Dec 11, 2024
commit b4989470df7e22c661065d8b76cddd6c471d3cb3
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

package org.matsim.contrib.dynagent;

import java.util.List;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.ActivityEndEvent;
import org.matsim.api.core.v01.events.ActivityStartEvent;
Expand All @@ -40,6 +38,8 @@
import org.matsim.pt.transitSchedule.api.TransitStopFacility;
import org.matsim.vehicles.Vehicle;

import java.util.List;

public final class DynAgent implements MobsimDriverPassengerAgent {
private final DynAgentLogic agentLogic;

Expand Down Expand Up @@ -83,11 +83,11 @@ private void computeNextAction(DynAction oldDynAction, double now) {
DynAction nextDynAction = agentLogic.computeNextAction(oldDynAction, now);

if (nextDynAction instanceof DynActivity) {
dynActivity = (DynActivity)nextDynAction;
dynActivity = (DynActivity) nextDynAction;
state = MobsimAgent.State.ACTIVITY;
events.processEvent(new ActivityStartEvent(now, id, currentLinkId, null, dynActivity.getActivityType()));
} else {
dynLeg = (DynLeg)nextDynAction;
dynLeg = (DynLeg) nextDynAction;
state = MobsimAgent.State.LEG;
}
}
Expand Down Expand Up @@ -145,7 +145,7 @@ public String getMode() {
// VehicleUsingAgent
@Override
public final Id<Vehicle> getPlannedVehicleId() {
Id<Vehicle> vehId = ((DriverDynLeg)dynLeg).getPlannedVehicleId();
Id<Vehicle> vehId = ((DriverDynLeg) dynLeg).getPlannedVehicleId();
// according to BasicPlanAgentImpl
return vehId != null ? vehId : Id.create(id, Vehicle.class);
}
Expand Down Expand Up @@ -177,13 +177,13 @@ public Id<Link> getDestinationLinkId() {
// DriverAgent
@Override
public Id<Link> chooseNextLinkId() {
return ((DriverDynLeg)dynLeg).getNextLinkId();
return ((DriverDynLeg) dynLeg).getNextLinkId();
}

// DriverAgent
@Override
public void notifyMoveOverNode(Id<Link> newLinkId) {
((DriverDynLeg)dynLeg).movedOverNode(newLinkId);
((DriverDynLeg) dynLeg).movedOverNode(newLinkId);
currentLinkId = newLinkId;
}

Expand Down Expand Up @@ -226,26 +226,28 @@ public boolean isWantingToArriveOnCurrentLink() {
// PTPassengerAgent
@Override
public boolean getEnterTransitRoute(TransitLine line, TransitRoute transitRoute, List<TransitRouteStop> stopsToCome,
TransitVehicle transitVehicle) {
return ((PTPassengerDynLeg)dynLeg).getEnterTransitRoute(line, transitRoute, stopsToCome, transitVehicle);
TransitVehicle transitVehicle) {
return ((PTPassengerDynLeg) dynLeg).getEnterTransitRoute(line, transitRoute, stopsToCome, transitVehicle);
}

// PTPassengerAgent
// yyyy seems a bit odd, that this and the following methods are implemented for DynAgent as not every DynAgent is a PTPassengerAgent. paul,
// nov'24
@Override
public boolean getExitAtStop(TransitStopFacility stop) {
return ((PTPassengerDynLeg)dynLeg).getExitAtStop(stop);
return ((PTPassengerDynLeg) dynLeg).getExitAtStop(stop);
}

// PTPassengerAgent
@Override
public Id<TransitStopFacility> getDesiredAccessStopId() {
return ((PTPassengerDynLeg)dynLeg).getDesiredAccessStopId();
return ((PTPassengerDynLeg) dynLeg).getDesiredAccessStopId();
}

// PTPassengerAgent
@Override
public Id<TransitStopFacility> getDesiredDestinationStopId() {
return ((PTPassengerDynLeg)dynLeg).getDesiredDestinationStopId();
return ((PTPassengerDynLeg) dynLeg).getDesiredDestinationStopId();
}

// PTPassengerAgent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,30 @@
/**
* @author schlenther
* <p>
* Benenson et al defined 3 phases of parking search
* Benenson et al. defined 3 phases of parking search
* OBSERVING: observation of parking situation while driving towards destination
* SEARCH_WHILE_APPROACH: estimating the amount of free parking lots on the way to destination
* and if applicable parking before arriving
* SEARCH_FOR_NEXT: taking the next free parking space if it isn't too far away from destination
*/
enum ParkingMode {
DRIVING, OBSERVING, SEARCH_WHILE_APPROACH, SEARCH_FOR_NEXT
DRIVING, OBSERVING, SEARCH_WHILE_APPROACH, SEARCH_FOR_NEXT
}

public class BenensonDynLeg extends ParkingDynLeg{
public class BenensonDynLeg extends ParkingDynLeg {

private static final Logger logger = LogManager.getLogger(BenensonDynLeg.class);
private static final boolean logForDebug = false;

private double totalObservedParkingSpaces = 0.0;
private double observedFreeParkingSpaces = 0.0;
private double firstDestinationLinkEnterTime = 0;
private ParkingMode legStage = ParkingMode.DRIVING;
private double firstDestinationLinkEnterTime = 0;
private ParkingMode legStage = ParkingMode.DRIVING;

public BenensonDynLeg(String mode, NetworkRoute route, ParkingSearchLogic logic,
ParkingSearchManager parkingManager, Id<Vehicle> vehicleId, MobsimTimer timer, EventsManager events) {
ParkingSearchManager parkingManager, Id<Vehicle> vehicleId, MobsimTimer timer, EventsManager events) {
super(mode, route, logic, parkingManager, vehicleId, timer, events);
if (!(logic instanceof BenensonParkingSearchLogic)){
if (!(logic instanceof BenensonParkingSearchLogic)) {
throw new RuntimeException();
}
}
Expand All @@ -55,56 +55,68 @@ public void movedOverNode(Id<Link> newLinkId) {
currentLinkId = newLinkId;
if (this.legStage == ParkingMode.DRIVING) {

if (((BenensonParkingSearchLogic) this.logic).transitionToObservingBehaviour(currentLinkId, this.route.getEndLinkId())) {
this.legStage = ParkingMode.OBSERVING;
if (((BenensonParkingSearchLogic) this.logic).transitionToObservingBehaviour(currentLinkId, this.route.getEndLinkId())) {
this.legStage = ParkingMode.OBSERVING;
this.events.processEvent(new StartParkingSearchEvent(timer.getTimeOfDay(), vehicleId, currentLinkId));
if(logForDebug)logger.error("vehicle " + this.vehicleId + " goes into observing on link " + this.currentLinkId);
if (logForDebug) {
logger.error("vehicle " + this.vehicleId + " goes into observing on link " + this.currentLinkId);
}
}
}
if(this.legStage == ParkingMode.OBSERVING ){
if (this.legStage == ParkingMode.OBSERVING) {
memorizeParkingSituationAndIsSomethingFree();

if (((BenensonParkingSearchLogic) this.logic).transitionToParkingBehaviour(currentLinkId, this.route.getEndLinkId())) {
this.legStage = ParkingMode.SEARCH_WHILE_APPROACH;
if(logForDebug)logger.error("vehicle " + this.vehicleId + " goes into parking on link " + this.currentLinkId);
if (((BenensonParkingSearchLogic) this.logic).transitionToParkingBehaviour(currentLinkId, this.route.getEndLinkId())) {
this.legStage = ParkingMode.SEARCH_WHILE_APPROACH;
if (logForDebug) {
logger.error("vehicle " + this.vehicleId + " goes into parking on link " + this.currentLinkId);
}
}
}
if(this.legStage == ParkingMode.SEARCH_WHILE_APPROACH){
if(currentLinkId.equals(route.getEndLinkId())){
if (this.legStage == ParkingMode.SEARCH_WHILE_APPROACH) {
if (currentLinkId.equals(route.getEndLinkId())) {
this.legStage = ParkingMode.SEARCH_FOR_NEXT;
this.firstDestinationLinkEnterTime = timer.getTimeOfDay();
}
else{
if(memorizeParkingSituationAndIsSomethingFree()){
this.firstDestinationLinkEnterTime = timer.getTimeOfDay();
} else {
if (memorizeParkingSituationAndIsSomethingFree()) {
double pUnoccupied = 0;
if(this.totalObservedParkingSpaces > 0){
if (this.totalObservedParkingSpaces > 0) {
pUnoccupied = this.observedFreeParkingSpaces / this.totalObservedParkingSpaces;
}
if ( ((BenensonParkingSearchLogic)this.logic).wantToParkHere(pUnoccupied, currentLinkId, route.getEndLinkId())){
if (logForDebug) logger.error("vehicle " + this.vehicleId + " would like to park on link" + currentLinkId
+ "\n \t pUnoccupied = " + pUnoccupied + "\n\t totalObservedParkingSpaces = " + totalObservedParkingSpaces + "\n\t observedFreeSpaces = " + this.observedFreeParkingSpaces);
hasFoundParking = parkingManager.reserveSpaceIfVehicleCanParkHere(vehicleId, currentLinkId);
}
}
else{
if(logForDebug)logger.error("nothing free for vehicle " + vehicleId + " on link " + currentLinkId);
if (((BenensonParkingSearchLogic) this.logic).wantToParkHere(pUnoccupied, currentLinkId, route.getEndLinkId())) {
if (logForDebug) {
logger.error("vehicle " + this.vehicleId + " would like to park on link" + currentLinkId
+ "\n \t pUnoccupied = " + pUnoccupied + "\n\t totalObservedParkingSpaces = " + totalObservedParkingSpaces + "\n\t " +
"observedFreeSpaces = " + this.observedFreeParkingSpaces);
}
hasFoundParking = parkingManager.reserveSpaceIfVehicleCanParkHere(vehicleId, currentLinkId);
}
} else {
if (logForDebug) {
logger.error("nothing free for vehicle " + vehicleId + " on link " + currentLinkId);
}
}
}
}
if (this.legStage == ParkingMode.SEARCH_FOR_NEXT){
if (logForDebug) logger.error("vehicle " + this.vehicleId + " is in PHASE3 on link " + this.currentLinkId);
//if( ((BenensonParkingSearchLogic)this.logic).isDriverInAcceptableDistance(currentLinkId, route.getEndLinkId(), this.firstDestLinkEnterTimer, timer.getTimeOfDay()) ){
if (this.legStage == ParkingMode.SEARCH_FOR_NEXT) {
if (logForDebug) {
logger.error("vehicle " + this.vehicleId + " is in PHASE3 on link " + this.currentLinkId);
}
//if( ((BenensonParkingSearchLogic)this.logic).isDriverInAcceptableDistance(currentLinkId, route.getEndLinkId(), this
// .firstDestLinkEnterTimer, timer.getTimeOfDay()) ){

hasFoundParking = parkingManager.reserveSpaceIfVehicleCanParkHere(vehicleId, currentLinkId);
hasFoundParking = parkingManager.reserveSpaceIfVehicleCanParkHere(vehicleId, currentLinkId);

if (logForDebug) logger.error("vehicle " + this.vehicleId + " tries in PHASE3 to park on link " + this.currentLinkId + ", " +
(int) (timer.getTimeOfDay() - this.firstDestinationLinkEnterTime) / 60 + ":" + (int) (timer.getTimeOfDay() - this.firstDestinationLinkEnterTime) % 60
+ " min after passing destination. Result: " + hasFoundParking);
//}
}
}
if (logForDebug) {
logger.error("vehicle " + this.vehicleId + " tries in PHASE3 to park on link " + this.currentLinkId + ", " +
(int) (timer.getTimeOfDay() - this.firstDestinationLinkEnterTime) / 60 + ":" + (int) (timer.getTimeOfDay() - this.firstDestinationLinkEnterTime) % 60
+ " min after passing destination. Result: " + hasFoundParking);
}
//}
}
}

/**
/**
* returns true if there is at least one empty slot on the current link
*/
private boolean memorizeParkingSituationAndIsSomethingFree() {
Expand All @@ -124,13 +136,14 @@ public Id<Link> getNextLinkId() {
return route.getEndLinkId();
}
return linkIds.get(currentLinkIdx + 1);
}
else {
} else {
if (hasFoundParking) {
if(logForDebug)logger.error("vehicle " + this.vehicleId + " has found a parking on link " + this.currentLinkId + " after passing " + Math.abs((this.route.getLinkIds().size() - this.currentLinkIdx - 3)) + " links");
if (logForDebug) {
logger.error("vehicle " + this.vehicleId + " has found a parking on link " + this.currentLinkId + " after passing " + Math.abs((this.route.getLinkIds()
.size() - this.currentLinkIdx - 3)) + " links");
}
return null;
}
else {
} else {
if (this.currentAndNextParkLink != null) {
if (currentAndNextParkLink.getFirst().equals(currentLinkId)) {
// we already calculated this
Expand All @@ -139,15 +152,15 @@ public Id<Link> getNextLinkId() {
}

Id<Link> nextLinkId;
if(this.legStage == ParkingMode.SEARCH_FOR_NEXT){
nextLinkId = ((BenensonParkingSearchLogic) this.logic).getNextLinkRandomInAcceptableDistance(currentLinkId, this.route.getEndLinkId(),
vehicleId, firstDestinationLinkEnterTime, this.timer.getTimeOfDay(), mode);
}
else{
if (this.legStage == ParkingMode.SEARCH_FOR_NEXT) {
nextLinkId = ((BenensonParkingSearchLogic) this.logic).getNextLinkRandomInAcceptableDistance(currentLinkId,
this.route.getEndLinkId(),
vehicleId, firstDestinationLinkEnterTime, this.timer.getTimeOfDay(), mode);
} else {
nextLinkId = ((BenensonParkingSearchLogic) (this.logic)).getNextLinkBenensonRouting(currentLinkId, route.getEndLinkId(), mode);
}
currentAndNextParkLink = new Tuple<>(currentLinkId, nextLinkId);
return nextLinkId;
}
currentAndNextParkLink = new Tuple<>(currentLinkId, nextLinkId);
return nextLinkId;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ public NearestParkingDynLeg(Leg currentPlannedLeg, NetworkRoute route, Plan plan
this.currentPlannedLeg = currentPlannedLeg;
this.plan = plan;
this.planIndexNextActivity = planIndexNextActivity;
if (ParkingUtils.checkIfActivityHasNoParking(followingActivity))
if (ParkingUtils.checkIfActivityHasNoParking(followingActivity)) {
parkingAtEndOfLeg = false;
if (ParkingUtils.checkIfActivityHasPassengerInteraction(followingActivity))
}
if (ParkingUtils.checkIfActivityHasPassengerInteraction(followingActivity)) {
passangerInteractionAtParkingFacilityAtEndOfLeg = true;
}
}

@Override
Expand All @@ -67,20 +69,22 @@ public void movedOverNode(Id<Link> newLinkId) {
if (hasFoundParking) {
this.events.processEvent(new ReserveParkingLocationEvent(timer.getTimeOfDay(), vehicleId, currentLinkId, currentLinkId));
nextSelectedParkingLink = currentLinkId;
} else
} else {
((FacilityBasedParkingManager) parkingManager).registerRejectedReservation(timer.getTimeOfDay());
}
}
}
} else if (followingActivity.getLinkId().equals(newLinkId)) {
if (alreadyReservedParking)
if (alreadyReservedParking) {
hasFoundParking = true;
else {
} else {
hasFoundParking = parkingManager.reserveSpaceIfVehicleCanParkHere(vehicleId, currentLinkId);
if (hasFoundParking) {
this.events.processEvent(new ReserveParkingLocationEvent(timer.getTimeOfDay(), vehicleId, currentLinkId, currentLinkId));
nextSelectedParkingLink = currentLinkId;
} else
} else {
((FacilityBasedParkingManager) parkingManager).registerRejectedReservation(timer.getTimeOfDay());
}
}
}
}
Expand Down Expand Up @@ -138,11 +142,10 @@ public Id<Link> getNextLinkId() {
// need to find the next link
double nextPickupTime;
double maxParkingDuration;
if (passangerInteractionAtParkingFacilityAtEndOfLeg){
if (passangerInteractionAtParkingFacilityAtEndOfLeg) {
nextPickupTime = 0.;
maxParkingDuration = followingActivity.getMaximumDuration().seconds();
}
else {
} else {
nextPickupTime = currentPlannedLeg.getDepartureTime().seconds() + followingActivity.getMaximumDuration().seconds();
maxParkingDuration = nextPickupTime - timer.getTimeOfDay();
}
Expand All @@ -163,11 +166,12 @@ public Id<Link> getNextLinkId() {
nextSelectedParkingLink = nextPlanedParkingLink;
if (((NearestParkingSpotSearchLogic) this.logic).canReserveParkingSlot()) {
alreadyReservedParking = parkingManager.reserveSpaceIfVehicleCanParkHere(vehicleId, nextSelectedParkingLink);
if (alreadyReservedParking)
if (alreadyReservedParking) {
this.events.processEvent(
new ReserveParkingLocationEvent(timer.getTimeOfDay(), vehicleId, currentLinkId, nextSelectedParkingLink));
else
} else {
((FacilityBasedParkingManager) parkingManager).registerRejectedReservation(timer.getTimeOfDay());
}
} else {
this.events.processEvent(
new SelectNewParkingLocationEvent(timer.getTimeOfDay(), vehicleId, currentLinkId, nextSelectedParkingLink));
Expand All @@ -176,13 +180,16 @@ public Id<Link> getNextLinkId() {
}
}
currentAndNextParkLink = new Tuple<>(currentLinkId, nextLinkId);
if (((NearestParkingSpotSearchLogic) this.logic).getNextRoute() != null)
if (((NearestParkingSpotSearchLogic) this.logic).getNextRoute() != null) {
currentPlannedLeg.setRoute(((NearestParkingSpotSearchLogic) this.logic).getNextRoute());
}
return nextLinkId;
}
}
}

//yyyy I assume, the vehicle is removed from the link's queue and thus waiting for parking does not influence the behaviour of the mobsim?
// Does this make sense? paul, nov'24
private void createWaitingActivityUntilPassengerInteractionIsPossible(Id<Link> newLinkId, Id<Vehicle> vehicleId, double now) {
Activity waitingActivity = PopulationUtils.createActivityFromLinkId(ParkingUtils.WaitingForParkingActivityType, newLinkId);
ParkingUtils.setNoParkingForActivity(waitingActivity);
Expand All @@ -195,7 +202,8 @@ 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.");
// 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() {
Expand Down
Loading
Loading