-
Notifications
You must be signed in to change notification settings - Fork 457
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3631 from moia-oss/spatialprefilterdrt
DRT: request specific prefiltering of fleet (incl spatial implementation)
- Loading branch information
Showing
11 changed files
with
508 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
...sim/contrib/drt/extension/insertion/spatialFilter/DrtSpatialRequestFleetFilterParams.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* *********************************************************************** * | ||
* project: org.matsim.* | ||
* * | ||
* *********************************************************************** * | ||
* * | ||
* copyright : (C) 2024 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.drt.extension.insertion.spatialFilter; | ||
|
||
import com.google.common.base.Verify; | ||
import jakarta.validation.constraints.Positive; | ||
import jakarta.validation.constraints.PositiveOrZero; | ||
import org.matsim.contrib.common.util.ReflectiveConfigGroupWithConfigurableParameterSets; | ||
import org.matsim.core.config.Config; | ||
|
||
/** | ||
* @author steffenaxer | ||
*/ | ||
public class DrtSpatialRequestFleetFilterParams extends ReflectiveConfigGroupWithConfigurableParameterSets { | ||
|
||
public static final String SET_NAME = "spatialRequestFleetFilter"; | ||
|
||
public DrtSpatialRequestFleetFilterParams() { | ||
super(SET_NAME); | ||
} | ||
|
||
@Parameter | ||
@Positive | ||
@Comment("Expansion factor for the iterative expansion of search radius until max expansion or the" + | ||
"minimum number of candidates is reached. Must be positive.") | ||
public double expansionFactor = 2; | ||
|
||
@Parameter | ||
@PositiveOrZero | ||
@Comment("Minimum expansion in map units (meters in most projections).") | ||
public double minExpansion = 1000; | ||
|
||
@Parameter | ||
@PositiveOrZero | ||
@Comment("Maximum expansion in map units (meters in most projections).") | ||
public double maxExpansion = 5000; | ||
|
||
@Parameter | ||
@Comment("Returns the unfiltered fleet if the filter did not keep enough candidates.") | ||
public boolean returnAllIfEmpty = true; | ||
|
||
@Parameter | ||
@Positive | ||
@Comment("Minimum number of vehicle candidates the filter has to find.") | ||
public int minCandidates = 1; | ||
|
||
@Parameter | ||
@PositiveOrZero | ||
@Comment("Update interval of the periodically built spatial search tree of vehicle positions.") | ||
public double updateInterval = 5 * 600; | ||
|
||
@Override | ||
protected void checkConsistency(Config config) { | ||
super.checkConsistency(config); | ||
Verify.verify(expansionFactor > 0, "Expansion factor must be greater than zero"); | ||
Verify.verify(minExpansion <= maxExpansion, "Max expansion must not be smaller than minimum expansion"); | ||
Verify.verify(minExpansion >= 0, "Expansion must be greater than zero"); | ||
Verify.verify(minCandidates > 0, "Minimum number of candidates must be positive"); | ||
Verify.verify(updateInterval >= 0, "Update interval must not be negative"); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
...contrib/drt/extension/insertion/spatialFilter/SpatialFilterInsertionSearchQSimModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* *********************************************************************** * | ||
* project: org.matsim.* | ||
* * | ||
* *********************************************************************** * | ||
* * | ||
* copyright : (C) 2024 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.drt.extension.insertion.spatialFilter; | ||
|
||
import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; | ||
import org.matsim.contrib.drt.optimizer.insertion.RequestFleetFilter; | ||
import org.matsim.contrib.drt.run.DrtConfigGroup; | ||
import org.matsim.contrib.dvrp.fleet.Fleet; | ||
import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; | ||
import org.matsim.core.mobsim.framework.MobsimTimer; | ||
|
||
/** | ||
* @author nkuehnel | MOIA | ||
*/ | ||
public class SpatialFilterInsertionSearchQSimModule extends AbstractDvrpModeQSimModule { | ||
|
||
|
||
private final DrtSpatialRequestFleetFilterParams drtSpatialRequestFleetFilterParams; | ||
|
||
public SpatialFilterInsertionSearchQSimModule(DrtConfigGroup drtCfg) { | ||
super(drtCfg.getMode()); | ||
if(drtCfg instanceof DrtWithExtensionsConfigGroup withExtensionsConfigGroup && | ||
withExtensionsConfigGroup.getSpatialRequestFleetFilterParams().isPresent()) { | ||
drtSpatialRequestFleetFilterParams = withExtensionsConfigGroup.getSpatialRequestFleetFilterParams().get(); | ||
} else { | ||
throw new RuntimeException("Requires DrtSpatialRequestFleetFilterParams to be set. Use DrtWithExtensionsConfigGroup " + | ||
"to do so."); | ||
} | ||
} | ||
|
||
public record SpatialInsertionFilterSettings(double expansionIncrement, double minExpansion, double maxExpansion, | ||
boolean returnAllIfEmpty, int minCandidates, double updateInterval){} | ||
|
||
@Override | ||
protected void configureQSim() { | ||
bindModal(RequestFleetFilter.class).toProvider(modalProvider(getter -> | ||
new SpatialRequestFleetFilter(getter.getModal(Fleet.class), getter.get(MobsimTimer.class), drtSpatialRequestFleetFilterParams) | ||
)); | ||
} | ||
} |
143 changes: 143 additions & 0 deletions
143
...a/org/matsim/contrib/drt/extension/insertion/spatialFilter/SpatialRequestFleetFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* *********************************************************************** * | ||
* project: org.matsim.* | ||
* * | ||
* *********************************************************************** * | ||
* * | ||
* copyright : (C) 2024 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.drt.extension.insertion.spatialFilter; | ||
|
||
import org.locationtech.jts.geom.Envelope; | ||
import org.locationtech.jts.geom.Point; | ||
import org.locationtech.jts.index.strtree.STRtree; | ||
import org.matsim.api.core.v01.Id; | ||
import org.matsim.api.core.v01.network.Link; | ||
import org.matsim.contrib.drt.optimizer.VehicleEntry; | ||
import org.matsim.contrib.drt.optimizer.insertion.RequestFleetFilter; | ||
import org.matsim.contrib.drt.passenger.DrtRequest; | ||
import org.matsim.contrib.drt.schedule.DrtStopTask; | ||
import org.matsim.contrib.dvrp.fleet.DvrpVehicle; | ||
import org.matsim.contrib.dvrp.fleet.Fleet; | ||
import org.matsim.contrib.dvrp.schedule.DriveTask; | ||
import org.matsim.contrib.dvrp.schedule.Schedule; | ||
import org.matsim.contrib.dvrp.schedule.StayTask; | ||
import org.matsim.contrib.dvrp.schedule.Task; | ||
import org.matsim.contrib.dvrp.tracker.OnlineDriveTaskTracker; | ||
import org.matsim.core.mobsim.framework.MobsimTimer; | ||
import org.matsim.core.utils.geometry.GeometryUtils; | ||
|
||
import java.util.*; | ||
|
||
import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.getBaseTypeOrElseThrow; | ||
|
||
/** | ||
* Filter that periodically updates a spatial search tree with current vehicle positions. | ||
* For a given request, only returns "nearby" vehicles. | ||
* Suitable for large scenarios with a certain degree of spatial coverage | ||
* Reduces insertion generation downstream. | ||
* | ||
* The spatial filter will start with a minimum expansion around the request origin and will | ||
* iteratively expand further by the increment factor until either the maximum expansion or | ||
* a minimum number of candidates is found. | ||
* | ||
* | ||
* @author nuehnel / MOIA | ||
*/ | ||
public class SpatialRequestFleetFilter implements RequestFleetFilter { | ||
|
||
private STRtree tree = new STRtree(); | ||
|
||
private final Fleet fleet; | ||
private final MobsimTimer mobsimTimer; | ||
private final double expansionIncrementFactor; | ||
private final double maxExpansion; | ||
private final double minExpansion; | ||
|
||
private final boolean returnAllIfEmpty; | ||
|
||
private final int minCandidates; | ||
|
||
private final double updateInterval; | ||
|
||
public SpatialRequestFleetFilter(Fleet fleet, MobsimTimer mobsimTimer, | ||
DrtSpatialRequestFleetFilterParams params) { | ||
this.fleet = fleet; | ||
this.mobsimTimer = mobsimTimer; | ||
this.expansionIncrementFactor = params.expansionFactor; | ||
this.minExpansion = params.minExpansion; | ||
this.maxExpansion = params.maxExpansion; | ||
this.returnAllIfEmpty = params.returnAllIfEmpty; | ||
this.minCandidates = params.minCandidates; | ||
this.updateInterval = params.updateInterval; | ||
} | ||
|
||
@Override | ||
public Collection<VehicleEntry> filter(DrtRequest drtRequest, Map<Id<DvrpVehicle>, VehicleEntry> vehicleEntries, double now) { | ||
if ((mobsimTimer.getTimeOfDay() % updateInterval) == 0) { | ||
buildTree(); | ||
} | ||
return filterEntries(vehicleEntries, drtRequest); | ||
} | ||
|
||
private Collection<VehicleEntry> filterEntries(Map<Id<DvrpVehicle>, VehicleEntry> vehicleEntries, DrtRequest drtRequest) { | ||
List<Id<DvrpVehicle>> result = Collections.emptyList(); | ||
Point point = GeometryUtils.createGeotoolsPoint(drtRequest.getFromLink().getToNode().getCoord()); | ||
|
||
for (double expansion = minExpansion; expansion <= maxExpansion && result.size() < minCandidates; expansion*= expansionIncrementFactor) { | ||
Envelope envelopeInternal = point.getEnvelopeInternal(); | ||
envelopeInternal.expandBy(expansion); | ||
result = tree.query(envelopeInternal); | ||
} | ||
|
||
if(result.size() < minCandidates) { | ||
if(returnAllIfEmpty) { | ||
return vehicleEntries.values(); | ||
} | ||
return Collections.emptySet(); | ||
} | ||
return extract(vehicleEntries, result); | ||
} | ||
|
||
private Collection<VehicleEntry> extract(Map<Id<DvrpVehicle>, VehicleEntry> vehicleEntries, List<Id<DvrpVehicle>> result) { | ||
Set<VehicleEntry> extracted = new LinkedHashSet<>(); | ||
for (Id<DvrpVehicle> dvrpVehicleId : result) { | ||
extracted.add(vehicleEntries.get(dvrpVehicleId)); | ||
} | ||
return extracted; | ||
} | ||
|
||
private void buildTree() { | ||
tree = new STRtree(); | ||
for (DvrpVehicle vehicle : fleet.getVehicles().values()) { | ||
Schedule schedule = vehicle.getSchedule(); | ||
Task startTask; | ||
Link start; | ||
if (schedule.getStatus() == Schedule.ScheduleStatus.STARTED) { | ||
startTask = schedule.getCurrentTask(); | ||
start = switch (getBaseTypeOrElseThrow(startTask)) { | ||
case DRIVE -> { | ||
var driveTask = (DriveTask) startTask; | ||
var diversionPoint = ((OnlineDriveTaskTracker) driveTask.getTaskTracker()).getDiversionPoint(); | ||
yield diversionPoint != null ? diversionPoint.link : //diversion possible | ||
driveTask.getPath().getToLink();// too late for diversion | ||
} | ||
case STOP -> ((DrtStopTask) startTask).getLink(); | ||
case STAY -> ((StayTask) startTask).getLink(); | ||
}; | ||
tree.insert(GeometryUtils.createGeotoolsPoint(start.getCoord()).getEnvelopeInternal(), vehicle.getId()); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.