Skip to content

Commit

Permalink
added todos, refactored, added detour factors to access/egress walks
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobrehmann committed Sep 25, 2024
1 parent 3f36d0b commit 526548f
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.matsim.contrib.accessibility;

import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.locationtech.jts.util.Assert;
Expand All @@ -11,15 +10,14 @@
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.contrib.accessibility.utils.*;
import org.matsim.contrib.drt.routing.DrtStopFacility;
import org.matsim.contrib.drt.routing.DrtStopFacilityImpl;
import org.matsim.contrib.dvrp.router.ClosestAccessEgressFacilityFinder;
import org.matsim.contrib.dvrp.router.DvrpRoutingModule;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.groups.NetworkConfigGroup;
import org.matsim.core.config.groups.ScoringConfigGroup;
import org.matsim.core.gbl.Gbl;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.network.algorithms.TransportModeNetworkFilter;
import org.matsim.core.router.*;
import org.matsim.core.router.costcalculators.TravelDisutilityFactory;
import org.matsim.core.router.speedy.SpeedyALTFactory;
Expand Down Expand Up @@ -155,8 +153,10 @@ public double computeContributionOfOpportunity(ActivityFacility origin,

// use walk router to calculate access walk time. Since it is a walk trip, there should only be a single leg.
List<? extends PlanElement> planElementsAccess = tripRouter.calcRoute(TransportMode.walk, origin, nearestStopAccess, departureTime, null, null);
double accessTime_h = ((Leg) planElementsAccess.get(0)).getTravelTime().seconds() / 3600;
double utility_access = accessTime_h * betaWalkTT_h;
Leg accessLeg = extractLeg(planElementsAccess, TransportMode.walk);
double accessTime_h = accessLeg.getTravelTime().seconds() / 3600;
double accessDist_m = accessLeg.getRoute().getDistance();
double utility_access = accessTime_h * betaWalkTT_h + accessDist_m * betaWalkDist_m;

// now we iterate through drt stops, each of which has a set of opportunities connected to it (those which are closest to that stop)
// we calculate sum of utilities to travel from the origin drt stop to all drt stops that have at least one opportunity close to it
Expand All @@ -166,35 +166,57 @@ public double computeContributionOfOpportunity(ActivityFacility origin,
Facility nearestStopEgress = (Facility) destination.getNearestBasicLocation();

//TODO: replace actual person with a fake person, or find workaround.
List<? extends PlanElement> planElementsMain = tripRouter.calcRoute(TransportMode.car, nearestStopAccess, nearestStopEgress, departureTime, scenario.getPopulation().getPersons().get(Id.createPersonId("1213")), null);

double directRideDistance_m = ((Leg) planElementsMain.get(2)).getRoute().getDistance();
List<? extends PlanElement> planElements = tripRouter.calcRoute(TransportMode.car, nearestStopAccess, nearestStopEgress, departureTime, scenario.getPopulation().getPersons().get(Id.createPersonId("1213")), null);
Leg mainLeg = extractLeg(planElements, TransportMode.car);
double directRideDistance_m = mainLeg.getRoute().getDistance();

// todo: insert CL's DRT Estimator here instead of hardcoding parameters here.
double waitTime_s = 103.34; //TODO
double rideTime_s = 47.84 + 0.1087 * directRideDistance_m;
double totalTime_h = (waitTime_s + rideTime_s) / 3600;
double utilityDrtTime = betaDrtTT_h * totalTime_h;
double utilityDrtDistance = betaDrtDist_m * directRideDistance_m;
double utilityDrtDistance = betaDrtDist_m * directRideDistance_m; // Todo: this doesn't include the detours

// Pre-computed effect of all opportunities reachable from destination network node
double sumExpVjkWalk = destination.getSum();

double utilityDrtConstant = AccessibilityUtils.getModeSpecificConstantForAccessibilities(TransportMode.drt, scoringConfigGroup);

double drtUtility = utility_access + utilityDrtTime + utilityDrtDistance + Math.log(sumExpVjkWalk) + utilityDrtConstant;
double drtUtility =
utility_access +
utilityDrtTime +
utilityDrtDistance +
Math.log(sumExpVjkWalk) / scoringConfigGroup.getBrainExpBeta() + // todo should this be included in the comparison?
utilityDrtConstant;

// Calculate utility of direct walk
// Does this have to be euclidean distance? Couldn't the walk be routed on the network, so that physical boundaries such as rivers would be respected.
final Coord toCoord = destination.getNearestBasicLocation().getCoord();
double directDistance_m = CoordUtils.calcEuclideanDistance(origin.getCoord(), toCoord);
double directWalkUtility =
directDistance_m / walkSpeed_m_h * betaWalkTT_h + // utility based on travel time
directDistance_m * betaWalkDist_m + // utility based on travel distance
AccessibilityUtils.getModeSpecificConstantForAccessibilities(TransportMode.walk, scoringConfigGroup); // ASC
// todo: why is sumExpVjkWalk included in drtUtility but not in directWalkUtility...
// should we really be aggregating around drt stops. Should we not handle each opportuninity seperately, so we can actually compare direct walk times?
List<? extends PlanElement> planElementsDirectWalk = tripRouter.calcRoute(TransportMode.walk, origin, (DrtStopFacilityImpl) destination.getNearestBasicLocation(), departureTime, null, null);
Leg directWalkLeg = extractLeg(planElementsDirectWalk, TransportMode.walk);
double directWalkTime_h = directWalkLeg.getTravelTime().seconds() / 3600;
double directWalkDist_m = directWalkLeg.getRoute().getDistance();
double directWalkUtility = directWalkTime_h * betaWalkTT_h +
directWalkDist_m * betaWalkDist_m +
AccessibilityUtils.getModeSpecificConstantForAccessibilities(TransportMode.walk, scoringConfigGroup);

// final Coord toCoord = destination.getNearestBasicLocation().getCoord();
// double directDistance_m = CoordUtils.calcEuclideanDistance(origin.getCoord(), toCoord);
//// double directWalkUtility =
// directDistance_m / walkSpeed_m_h * betaWalkTT_h + // utility based on travel time
// directDistance_m * betaWalkDist_m + // utility based on travel distance
// AccessibilityUtils.getModeSpecificConstantForAccessibilities(TransportMode.walk, scoringConfigGroup); // ASC

// Utilities for traveling are generally negative (unless there is a high ASC).
// We choose walk if it's utility is higher (less negative) than that of DRT
double travelUtility = Math.max(directWalkUtility, drtUtility);
// the access drt stop is same as the egress drt stop (which means they don't actually take drt)
double travelUtility;

if (nearestStopAccess.equals(nearestStopEgress) || directWalkUtility > drtUtility) {
travelUtility = directWalkUtility;
} else {
travelUtility = drtUtility;
}

// this is added to the sum of utilities from the measuring point
expSum += Math.exp(this.scoringConfigGroup.getBrainExpBeta() * travelUtility);
Expand All @@ -203,6 +225,16 @@ public double computeContributionOfOpportunity(ActivityFacility origin,
return expSum;
}

private static Leg extractLeg(List<? extends PlanElement> planElementsMain, String mode) {
List<Leg> legList = planElementsMain.stream().filter(pe -> pe instanceof Leg && ((Leg) pe).getMode().equals(mode)).map(pe -> (Leg) pe).toList();

if (legList.size() != 1) {
throw new RuntimeException("for these accesibility calculations, there should be exactly one leg");
}

return legList.get(0);
}


@Override
public EstimatedDrtAccessibilityContributionCalculator duplicate() {
Expand Down Expand Up @@ -242,7 +274,8 @@ private Map<Id<? extends BasicLocation>, AggregationObject> aggregateOpportuniti
DrtStopFacility nearestStop = (DrtStopFacility) ((ClosestAccessEgressFacilityFinder) stopFinder).findClosestStop(opportunity);

List<? extends PlanElement> planElements = tripRouter.calcRoute(TransportMode.walk, nearestStop, opportunity, 10 * 3600., null, null);// departure time shouldn't matter for walk
double egressTime_s = ((Leg) planElements.get(0)).getTravelTime().seconds();
Leg leg = extractLeg(planElements, TransportMode.walk);
double egressTime_s = leg.getTravelTime().seconds();

double VjkWalkTravelTime = egressTime_s / 3600 * betaWalkTT_h; // a.k.a utility_egress

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package org.matsim.contrib.accessibility.run;

import org.junit.Rule;
import org.junit.Test;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.contrib.accessibility.AccessibilityConfigGroup;
import org.matsim.contrib.accessibility.AccessibilityModule;
import org.matsim.contrib.accessibility.Modes4Accessibility;
import org.matsim.contrib.drt.run.*;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.run.DvrpModule;
import org.matsim.contrib.dvrp.run.DvrpQSimComponents;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.groups.FacilitiesConfigGroup;
import org.matsim.core.controler.Controler;
import org.matsim.core.controler.OutputDirectoryHierarchy;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.examples.ExamplesUtils;
import org.matsim.facilities.ActivityFacilities;
import org.matsim.facilities.ActivityFacility;
import org.matsim.testcases.MatsimTestUtils;
import org.matsim.vis.otfvis.OTFVisConfigGroup;

import java.net.URL;

public class DrtAccessibilityTest {
@Rule
public MatsimTestUtils utils = new MatsimTestUtils();

@Test
public void testRunDrtStopbasedExample() {
Id.resetCaches();

// C O N F I G
URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"),
"mielec_stop_based_drt_config.xml");
Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(),
new OTFVisConfigGroup());

// drt
MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config);
for (DrtConfigGroup drtConfig : multiModeDrtConfig.getModalElements()) {
drtConfig.maxWalkDistance = 100_000;
}

// accessibility
AccessibilityConfigGroup acg = ConfigUtils.addOrGetModule(config, AccessibilityConfigGroup.class) ;
acg.setTileSize_m(100);
acg.setAreaOfAccessibilityComputation(AccessibilityConfigGroup.AreaOfAccesssibilityComputation.fromBoundingBox);
acg.setBoundingBoxBottom(-15181.2948);
acg.setBoundingBoxTop(4967.218);
acg.setBoundingBoxLeft(-4934.1583);
acg.setBoundingBoxRight(12641.5889);
acg.setUseParallelization(false);
acg.setComputingAccessibilityForMode(Modes4Accessibility.estimatedDrt, true);
acg.setComputingAccessibilityForMode(Modes4Accessibility.freespeed, false);

// misc
config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists);
config.controller().setOutputDirectory(utils.getOutputDirectory());
config.routing().setRoutingRandomness(0);

DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfig, config.scoring(), config.routing());

// S C E N A R I O
Scenario scenario = DrtControlerCreator.createScenarioWithDrtRouteFactory(config);
ScenarioUtils.loadScenario(scenario);

// Creating test opportunities (facilities); one on each link with same ID as link and coord on center of link
final ActivityFacilities opportunities = scenario.getActivityFacilities();
ActivityFacility facility1 = opportunities.getFactory().createActivityFacility(Id.create("1", ActivityFacility.class), new Coord(3150.8321, -2587.9409));
opportunities.addActivityFacility(facility1);
// ActivityFacility facility2 = opportunities.getFactory().createActivityFacility(Id.create("2", ActivityFacility.class), new Coord(200, 200));
// opportunities.addActivityFacility(facility2);
scenario.getConfig().facilities().setFacilitiesSource(FacilitiesConfigGroup.FacilitiesSource.setInScenario);


// C O N T R O L E R

Controler controler = new Controler(scenario);
controler.addOverridingModule(new DvrpModule());
controler.addOverridingModule(new MultiModeDrtModule());
controler.configureQSimComponents(DvrpQSimComponents.activateAllModes(multiModeDrtConfig));

final AccessibilityModule module = new AccessibilityModule();

// final TinyDRTAccessibilityTest.ResultsComparator resultsComparator = new TinyDRTAccessibilityTest.ResultsComparator();
//
// resultsComparator.setConfig(config);
// module.addFacilityDataExchangeListener(resultsComparator);
controler.addOverridingModule(module);

controler.run();

// var expectedStats = Stats.newBuilder()
// .rejectionRate(0.05)
// .rejections(17)
// .waitAverage(260.41)
// .inVehicleTravelTimeMean(374.87)
// .totalTravelTimeMean(635.28)
// .build();

// verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats);
}
}

0 comments on commit 526548f

Please sign in to comment.