diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/DefaultRaptorStopFinder.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/DefaultRaptorStopFinder.java index 073d6955b91..6636713979c 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/DefaultRaptorStopFinder.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/DefaultRaptorStopFinder.java @@ -207,24 +207,24 @@ private void addInitialStopsForParamSet(Facility fromFacility, Facility toFacili // the router for the access/egress mode could not find a route, skip that access/egress mode continue; } - if (stopFacility != stop) { - if (direction == Direction.ACCESS) { - Leg transferLeg = PopulationUtils.createLeg(TransportMode.walk); - Route transferRoute = RouteUtils.createGenericRouteImpl(stopFacility.getLinkId(), stop.getLinkId()); - double accessTime = TransitScheduleUtils.getStopAccessTime(stop); - transferRoute.setTravelTime(accessTime); - transferRoute.setDistance(0); - transferLeg.setRoute(transferRoute); - transferLeg.setTravelTime(accessTime); + double accessTime = TransitScheduleUtils.getStopAccessTime(stop); + double egressTime = TransitScheduleUtils.getStopEgressTime(stop); + if ((stopFacility != stop) || accessTime>0.0 || egressTime>0.0) { + if (direction == Direction.ACCESS) { + Leg transferLeg = PopulationUtils.createLeg(TransportMode.walk); + Route transferRoute = RouteUtils.createGenericRouteImpl(stopFacility.getLinkId(), stop.getLinkId()); + transferRoute.setTravelTime(accessTime); + transferRoute.setDistance(0); + transferLeg.setRoute(transferRoute); + transferLeg.setTravelTime(accessTime); - List tmp = new ArrayList<>(routeParts.size() + 1); - tmp.addAll(routeParts); - tmp.add(transferLeg); - routeParts = tmp; - } else { - Leg transferLeg = PopulationUtils.createLeg(TransportMode.walk); - Route transferRoute = RouteUtils.createGenericRouteImpl(stop.getLinkId(), stopFacility.getLinkId()); - double egressTime = TransitScheduleUtils.getStopEgressTime(stop); + List tmp = new ArrayList<>(routeParts.size() + 1); + tmp.addAll(routeParts); + tmp.add(transferLeg); + routeParts = tmp; + } else { + Leg transferLeg = PopulationUtils.createLeg(TransportMode.walk); + Route transferRoute = RouteUtils.createGenericRouteImpl(stop.getLinkId(), stopFacility.getLinkId()); transferRoute.setTravelTime(egressTime); transferRoute.setDistance(0); transferLeg.setRoute(transferRoute); diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorIntermodalTest.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorIntermodalTest.java index 7ec0a2f552c..15fcc06606c 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorIntermodalTest.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorIntermodalTest.java @@ -32,6 +32,7 @@ import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.facilities.Facility; import org.matsim.pt.PtConstants; +import org.matsim.pt.transitSchedule.TransitScheduleUtils; import org.matsim.pt.transitSchedule.api.Departure; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -39,6 +40,7 @@ import org.matsim.pt.transitSchedule.api.TransitSchedule; import org.matsim.pt.transitSchedule.api.TransitScheduleFactory; import org.matsim.pt.transitSchedule.api.TransitStopFacility; +import org.matsim.testcases.MatsimTestUtils; import org.matsim.utils.objectattributes.attributable.AttributesImpl; import java.util.ArrayList; @@ -1220,6 +1222,69 @@ public List calcRoute(RoutingRequest request) { Assert.assertEquals(Id.create("to", Link.class), leg.getRoute().getEndLinkId()); } + @Test + public void testIntermodalTripWithAccessAndEgressTimesAtStops() { + IntermodalFixture f = new IntermodalFixture(); + f.scenario.getTransitSchedule().getFacilities().values() + .forEach(stopFacility -> TransitScheduleUtils.setSymmetricStopAccessEgressTime(stopFacility,120.0)); + PlanCalcScoreConfigGroup.ModeParams walk = new PlanCalcScoreConfigGroup.ModeParams(TransportMode.walk); + walk.setMarginalUtilityOfTraveling(0.0); + f.config.planCalcScore().addModeParams(walk); + + Map routingModules = new HashMap<>(); + routingModules.put(TransportMode.walk, + new TeleportationRoutingModule(TransportMode.walk, f.scenario, 1.1, 1.3)); + routingModules.put(TransportMode.bike, + new TeleportationRoutingModule(TransportMode.bike, f.scenario, 3, 1.4)); + + f.srrConfig.setUseIntermodalAccessEgress(true); + IntermodalAccessEgressParameterSet walkAccess = new IntermodalAccessEgressParameterSet(); + walkAccess.setMode(TransportMode.walk); + walkAccess.setMaxRadius(1000); + walkAccess.setInitialSearchRadius(1000); + f.srrConfig.addIntermodalAccessEgress(walkAccess); + IntermodalAccessEgressParameterSet bikeAccess = new IntermodalAccessEgressParameterSet(); + bikeAccess.setMode(TransportMode.bike); + bikeAccess.setMaxRadius(1500); + bikeAccess.setInitialSearchRadius(1500); + bikeAccess.setStopFilterAttribute("bikeAccessible"); + bikeAccess.setLinkIdAttribute("accessLinkId_bike"); + bikeAccess.setStopFilterValue("true"); + f.srrConfig.addIntermodalAccessEgress(bikeAccess); + + SwissRailRaptorData data = SwissRailRaptorData.create(f.scenario.getTransitSchedule(), null, RaptorUtils.createStaticConfig(f.config), f.scenario.getNetwork(), null); + DefaultRaptorStopFinder stopFinder = new DefaultRaptorStopFinder(new DefaultRaptorIntermodalAccessEgress(), routingModules); + SwissRailRaptor raptor = new SwissRailRaptor.Builder(data, f.scenario.getConfig()).with(stopFinder).build(); + + Facility fromFac = new FakeFacility(new Coord(10000, 10500), Id.create("from", Link.class)); + Facility toFac = new FakeFacility(new Coord(50000, 10500), Id.create("to", Link.class)); + + List legs = raptor.calcRoute(DefaultRoutingRequest.withoutAttributes(fromFac, toFac, 7*3600, f.dummyPerson)); + for (PlanElement leg : legs) { + System.out.println(leg); + } + + Assert.assertEquals("wrong number of legs.", 5, legs.size()); + Leg leg = (Leg) legs.get(1); + Assert.assertEquals(TransportMode.walk, leg.getMode()); + Assert.assertEquals(Id.create("pt_2", Link.class), leg.getRoute().getStartLinkId()); + Assert.assertEquals(Id.create("pt_2", Link.class), leg.getRoute().getEndLinkId()); + Assert.assertEquals(120.0,leg.getTravelTime().seconds(), MatsimTestUtils.EPSILON); + leg = (Leg) legs.get(2); + Assert.assertEquals(TransportMode.pt, leg.getMode()); + Assert.assertEquals(Id.create("pt_2", Link.class), leg.getRoute().getStartLinkId()); + Assert.assertEquals(Id.create("pt_5", Link.class), leg.getRoute().getEndLinkId()); + leg = (Leg) legs.get(3); + Assert.assertEquals(TransportMode.walk, leg.getMode()); + Assert.assertEquals(Id.create("pt_5", Link.class), leg.getRoute().getStartLinkId()); + Assert.assertEquals(Id.create("bike_5", Link.class), leg.getRoute().getEndLinkId()); + Assert.assertEquals(120.0,leg.getTravelTime().seconds(), MatsimTestUtils.EPSILON); + leg = (Leg) legs.get(4); + Assert.assertEquals(TransportMode.bike, leg.getMode()); + Assert.assertEquals(Id.create("bike_5", Link.class), leg.getRoute().getStartLinkId()); + Assert.assertEquals(Id.create("to", Link.class), leg.getRoute().getEndLinkId()); + } + /* for test of intermodal routing requiring transfers at the beginning or end of the pt trip, diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java index 4eb2d0f01c5..6c728fe3d47 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java @@ -37,6 +37,7 @@ import org.matsim.facilities.ActivityFacility; import org.matsim.pt.router.TransitRouter; import org.matsim.pt.routes.TransitPassengerRoute; +import org.matsim.pt.transitSchedule.TransitScheduleUtils; import org.matsim.pt.transitSchedule.api.Departure; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -153,6 +154,28 @@ public void testWalkDurations() { assertEquals(Math.ceil(expectedEgressWalkTime), ((Leg)legs.get(2)).getTravelTime().seconds(), MatsimTestUtils.EPSILON); } + + @Test + public void testStationAccessEgressTimes() { + Fixture f = new Fixture(); + f.init(); + RaptorParameters raptorParams = RaptorUtils.createParameters(f.config); + f.schedule.getFacilities().values().forEach(facility-> TransitScheduleUtils.setSymmetricStopAccessEgressTime(facility,120.0)); + TransitRouter router = createTransitRouter(f.schedule, f.config, f.network); + Coord fromCoord = new Coord(3800, 5100); + Coord toCoord = new Coord(16100, 5050); + List legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 5.0*3600, null)); + assertEquals(3, legs.size()); + assertEquals(TransportMode.walk, ((Leg)legs.get(0)).getMode()); + assertEquals(TransportMode.pt, ((Leg)legs.get(1)).getMode()); + assertEquals(TransportMode.walk, ((Leg)legs.get(2)).getMode()); + + double expectedAccessWalkTime = 120.0 + CoordUtils.calcEuclideanDistance(f.schedule.getFacilities().get(Id.create("0", TransitStopFacility.class)).getCoord(), fromCoord) / raptorParams.getBeelineWalkSpeed(); + assertEquals(Math.ceil(expectedAccessWalkTime), ((Leg)legs.get(0)).getTravelTime().seconds(), MatsimTestUtils.EPSILON); + double expectedEgressWalkTime = 120.0 + CoordUtils.calcEuclideanDistance(f.schedule.getFacilities().get(Id.create("6", TransitStopFacility.class)).getCoord(), toCoord) / raptorParams.getBeelineWalkSpeed(); + assertEquals(Math.ceil(expectedEgressWalkTime), ((Leg)legs.get(2)).getTravelTime().seconds(), MatsimTestUtils.EPSILON); + } + @Test public void testWalkDurations_range() { Fixture f = new Fixture();