diff --git a/contribs/accessibility/pom.xml b/contribs/accessibility/pom.xml index 45d1f56723b..4b3a78553b5 100644 --- a/contribs/accessibility/pom.xml +++ b/contribs/accessibility/pom.xml @@ -83,5 +83,11 @@ gt-jdbc-postgis ${geotools.version} + + org.matsim.contrib + drt + 16.0-SNAPSHOT + compile + diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java index c4677dd3fd3..86afb7ad1eb 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java @@ -158,6 +158,10 @@ public ControlerListener get() { calculator = new NetworkModeAccessibilityExpContributionCalculator(mode, nwModeTravelTime, nwModeTravelDisutility, scenario); } else if ( TransportMode.pt.equals( mode ) ){ calculator = new SwissRailRaptorAccessibilityContributionCalculator( mode, config.scoring(), scenario ); + } else if ( Modes4Accessibility.estimatedDrt.name().equals( mode )) { + final TravelTime travelTime = travelTimes.get(TransportMode.car); // TODO: replace with drt + final TravelDisutilityFactory travelDisutilityFactory = travelDisutilityFactories.get(TransportMode.car); //TODO: replace with DRT + calculator = new EstimatedDrtAccessibilityContributionCalculator(mode, travelTime, travelDisutilityFactory, scenario); } else if ( Modes4Accessibility.matrixBasedPt.name().equals( mode ) ) { throw new RuntimeException("currently not supported because implementation not consistent with guice grapher. kai, sep'19") ; // calculator = new LeastCostPathCalculatorAccessibilityContributionCalculator( diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/EstimatedDrtAccessibilityContributionCalculator.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/EstimatedDrtAccessibilityContributionCalculator.java new file mode 100644 index 00000000000..6848a36a185 --- /dev/null +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/EstimatedDrtAccessibilityContributionCalculator.java @@ -0,0 +1,178 @@ +package org.matsim.contrib.accessibility; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.BasicLocation; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.contrib.accessibility.utils.*; +import org.matsim.contrib.drt.estimator.DrtEstimator; +import org.matsim.contrib.drt.estimator.impl.EuclideanDistanceBasedDrtEstimator; +import org.matsim.contrib.roadpricing.RoadPricingScheme; +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.costcalculators.TravelDisutilityFactory; +import org.matsim.core.router.util.TravelDisutility; +import org.matsim.core.router.util.TravelTime; +import org.matsim.core.utils.misc.OptionalTime; +import org.matsim.facilities.ActivityFacilities; +import org.matsim.facilities.ActivityFacility; +import org.matsim.utils.leastcostpathtree.LeastCostPathTree; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author thibautd, dziemke + */ +final class EstimatedDrtAccessibilityContributionCalculator implements AccessibilityContributionCalculator { + private static final Logger LOG = LogManager.getLogger( NetworkModeAccessibilityExpContributionCalculator.class ); + + private final String mode; + private final TravelDisutilityFactory travelDisutilityFactory; + private final TravelTime travelTime; + private final Scenario scenario; + + private final TravelDisutility travelDisutility; + private final ScoringConfigGroup scoringConfigGroup; + private final NetworkConfigGroup networkConfigGroup; + + private Network subNetwork; + + private final EuclideanDistanceBasedDrtEstimator drtEstimator; + + private final double betaWalkTT; + + private final double betaDrtTT; + private final double walkSpeed_m_s; + + private Node fromNode = null; + private final LeastCostPathTree lcpt; + + private Map, ArrayList> aggregatedMeasurePoints; + private Map, AggregationObject> aggregatedOpportunities; + + + + public EstimatedDrtAccessibilityContributionCalculator(String mode, final TravelTime travelTime, final TravelDisutilityFactory travelDisutilityFactory, Scenario scenario) { + this.mode = mode; + this.travelTime = travelTime; + this.travelDisutilityFactory = travelDisutilityFactory; + this.scenario = scenario; + this.scoringConfigGroup = scenario.getConfig().scoring(); + this.networkConfigGroup = scenario.getConfig().network(); + + Gbl.assertNotNull(travelDisutilityFactory); + this.travelDisutility = travelDisutilityFactory.createTravelDisutility(travelTime); + + + this.lcpt = new LeastCostPathTree(travelTime, travelDisutility); + + // TODO: should the marginal utility of traveling for drt be same as for car? + betaWalkTT = scoringConfigGroup.getModes().get(TransportMode.walk).getMarginalUtilityOfTraveling() - scoringConfigGroup.getPerforming_utils_hr(); + betaDrtTT = scoringConfigGroup.getModes().get(TransportMode.car).getMarginalUtilityOfTraveling() - scoringConfigGroup.getPerforming_utils_hr(); + + this.walkSpeed_m_s = scenario.getConfig().routing().getTeleportedModeSpeeds().get(TransportMode.walk); + + //TODO: realistic parameters? + this.drtEstimator = new EuclideanDistanceBasedDrtEstimator(scenario.getNetwork(), 1.2, 1.0, 0, 5 * 3600, 0, 1, 0); + + } + + + @Override + public void initialize(ActivityFacilities measuringPoints, ActivityFacilities opportunities) { + LOG.warn("Initializing calculator for mode " + mode + "..."); + LOG.warn("Full network has " + scenario.getNetwork().getNodes().size() + " nodes."); + subNetwork = NetworkUtils.createNetwork(networkConfigGroup); + Set modeSet = new HashSet<>(); + modeSet.add(TransportMode.car); + TransportModeNetworkFilter filter = new TransportModeNetworkFilter(scenario.getNetwork()); + filter.filter(subNetwork, modeSet); + if (subNetwork.getNodes().size() == 0) { + throw new RuntimeException("Network has 0 nodes for mode " + mode + ". Something is wrong."); + } + LOG.warn("sub-network for mode " + modeSet + " now has " + subNetwork.getNodes().size() + " nodes."); + + this.aggregatedMeasurePoints = AccessibilityUtils.aggregateMeasurePointsWithSameNearestNode(measuringPoints, subNetwork); + this.aggregatedOpportunities = AccessibilityUtils.aggregateOpportunitiesWithSameNearestNode(opportunities, subNetwork, scenario.getConfig()); + + + } + + + @Override + public void notifyNewOriginNode(Id fromNodeId, Double departureTime) { + this.fromNode = subNetwork.getNodes().get(fromNodeId); + this.lcpt.calculate(subNetwork, fromNode, departureTime); + + } + + + @Override + public double computeContributionOfOpportunity(ActivityFacility origin, + Map, AggregationObject> aggregatedOpportunities, Double departureTime) { + double expSum = 0.; + + Link nearestLink = NetworkUtils.getNearestLinkExactly(subNetwork, origin.getCoord()); + Distances distance = NetworkUtil.getDistances2NodeViaGivenLink(origin.getCoord(), nearestLink, fromNode); + double walkTravelTimeMeasuringPoint2Road_h = distance.getDistancePoint2Intersection() / (this.walkSpeed_m_s * 3600); + // Orthogonal walk to nearest link + double walkUtilityMeasuringPoint2Road = (walkTravelTimeMeasuringPoint2Road_h * betaWalkTT); + // Travel on section of first link to first node + double distanceFraction = distance.getDistanceIntersection2Node() / nearestLink.getLength(); + double congestedCarUtilityRoad2Node = -travelDisutility.getLinkTravelDisutility(nearestLink, departureTime, null, null) * distanceFraction; + + // Combine all utility components (using the identity: exp(a+b) = exp(a) * exp(b)) + double modeSpecificConstant = AccessibilityUtils.getModeSpecificConstantForAccessibilities(TransportMode.car, scoringConfigGroup); // TODO: update from car to drt + + for (final AggregationObject destination : aggregatedOpportunities.values()) { + + // utility during DRT ride + DrtEstimator.Estimate estimate = drtEstimator.estimate(origin.getCoord(), destination.getNearestBasicLocation().getCoord(), OptionalTime.defined(departureTime)); + + double totalTime = (estimate.waitingTime() + estimate.rideTime()) / 3600; + double utilityDrt = betaDrtTT * totalTime; + + // Pre-computed effect of all opportunities reachable from destination network node + double sumExpVjkWalk = destination.getSum(); + + expSum += Math.exp(this.scoringConfigGroup.getBrainExpBeta() * (walkUtilityMeasuringPoint2Road + modeSpecificConstant + + congestedCarUtilityRoad2Node + utilityDrt)) * sumExpVjkWalk; + } + return expSum; + } + + + @Override + public EstimatedDrtAccessibilityContributionCalculator duplicate() { + LOG.info("Creating another EstimatedDrtAccessibilityContributionCalculator object."); + EstimatedDrtAccessibilityContributionCalculator estimatedDrtAccessibilityContributionCalculator = + new EstimatedDrtAccessibilityContributionCalculator(this.mode, this.travelTime, this.travelDisutilityFactory, this.scenario); + estimatedDrtAccessibilityContributionCalculator.subNetwork = this.subNetwork; + estimatedDrtAccessibilityContributionCalculator.aggregatedMeasurePoints = this.aggregatedMeasurePoints; + estimatedDrtAccessibilityContributionCalculator.aggregatedOpportunities = this.aggregatedOpportunities; + return estimatedDrtAccessibilityContributionCalculator; + } + + + @Override + public Map, ArrayList> getAggregatedMeasurePoints() { + return aggregatedMeasurePoints; + } + + + @Override + public Map, AggregationObject> getAgregatedOpportunities() { + return aggregatedOpportunities; + } +} diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/Modes4Accessibility.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/Modes4Accessibility.java index 1aed991d7e4..901340ba5d2 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/Modes4Accessibility.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/Modes4Accessibility.java @@ -1,5 +1,5 @@ package org.matsim.contrib.accessibility; -public enum Modes4Accessibility {freespeed, car, walk, bike, pt, matrixBasedPt} +public enum Modes4Accessibility {freespeed, car, walk, bike, pt, estimatedDrt, matrixBasedPt} // yy might make sense to replace this by a String (as for the normal matsim router), but configurability right now is not sufficient at the level here, and may never be. -// kai/dominik, feb'17 \ No newline at end of file +// kai/dominik, feb'17 diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/SwissRailRaptorAccessibilityContributionCalculator.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/SwissRailRaptorAccessibilityContributionCalculator.java index 6fcd4466276..61ac67d7bc3 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/SwissRailRaptorAccessibilityContributionCalculator.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/SwissRailRaptorAccessibilityContributionCalculator.java @@ -41,7 +41,7 @@ * @author dziemke */ class SwissRailRaptorAccessibilityContributionCalculator implements AccessibilityContributionCalculator { - private static final Logger LOG = LogManager.getLogger( SwissRailRaptorAccessibilityContributionCalculator.class ); + private static final Logger LOG = LogManager.getLogger( EstimatedDrtAccessibilityContributionCalculator.class ); private SwissRailRaptor raptor; private String mode; private ScoringConfigGroup scoringConfigGroup; diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java index dd3a2492ce9..760594e2798 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java @@ -59,6 +59,11 @@ public EuclideanDistanceBasedDrtEstimator(Network network, double networkDistanc public Estimate estimate(DrtRoute route, OptionalTime departureTime) { Coord fromCoord = network.getLinks().get(route.getStartLinkId()).getToNode().getCoord(); Coord toCoord = network.getLinks().get(route.getEndLinkId()).getToNode().getCoord(); + + return estimate(fromCoord, toCoord, departureTime); + } + + public Estimate estimate(Coord fromCoord, Coord toCoord , OptionalTime departureTime) { double euclideanDistance = CoordUtils.calcEuclideanDistance(fromCoord, toCoord); double typicalRideDuration = euclideanDistance * slope + intercept; double typicalRideDistance = networkDistanceFactor * euclideanDistance;