org.matsim.contrib.drt.routing.StopBasedDrtRoutingModule.java Source code

Java tutorial

Introduction

Here is the source code for org.matsim.contrib.drt.routing.StopBasedDrtRoutingModule.java

Source

/* *********************************************************************** *
 * project: org.matsim.*
 *                                                                         *
 * *********************************************************************** *
 *                                                                         *
 * copyright       : (C) 2017 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.routing;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

import org.apache.commons.lang3.tuple.Pair;
import org.apache.log4j.Logger;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Activity;
import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.core.router.RoutingModule;
import org.matsim.core.router.StageActivityTypes;
import org.matsim.facilities.Facility;
import org.matsim.pt.transitSchedule.api.TransitStopFacility;

import com.google.inject.Inject;
import com.google.inject.name.Named;

/**
 * @author jbischoff
 * @author michalm (Michal Maciejewski)
 */
public class StopBasedDrtRoutingModule implements RoutingModule {
    private static final Logger LOGGER = Logger.getLogger(StopBasedDrtRoutingModule.class);

    public interface AccessEgressStopFinder {
        Pair<TransitStopFacility, TransitStopFacility> findStops(Facility<?> fromFacility, Facility<?> toFacility);
    }

    private final StageActivityTypes drtStageActivityType = new DrtStageActivityType();
    private final PopulationFactory populationFactory;
    private final RoutingModule walkRouter;
    private final AccessEgressStopFinder stopFinder;
    private final DrtConfigGroup drtCfg;
    private final DrtRoutingModule drtRoutingModule;

    @Inject
    public StopBasedDrtRoutingModule(PopulationFactory populationFactory, DrtRoutingModule drtRoutingModule,
            @Named(TransportMode.walk) RoutingModule walkRouter, AccessEgressStopFinder stopFinder,
            DrtConfigGroup drtCfg) {
        this.populationFactory = populationFactory;
        this.drtRoutingModule = drtRoutingModule;
        this.walkRouter = walkRouter;
        this.stopFinder = stopFinder;
        this.drtCfg = drtCfg;
    }

    @Override
    public List<? extends PlanElement> calcRoute(Facility<?> fromFacility, Facility<?> toFacility,
            double departureTime, Person person) {
        Pair<TransitStopFacility, TransitStopFacility> stops = stopFinder.findStops(fromFacility, toFacility);

        TransitStopFacility accessFacility = stops.getLeft();
        if (accessFacility == null) {
            printError(() -> "No access stop found, agent will walk. Agent Id:\t" + person.getId());
            return (walkRouter.calcRoute(fromFacility, toFacility, departureTime, person));
        }

        TransitStopFacility egressFacility = stops.getRight();
        if (egressFacility == null) {
            printError(() -> "No egress stop found, agent will walk. Agent Id:\t" + person.getId());
            return (walkRouter.calcRoute(fromFacility, toFacility, departureTime, person));
        }

        if (accessFacility.getLinkId() == egressFacility.getLinkId()) {
            printError(() -> "Start and end stop are the same, agent will walk. Agent Id:\t" + person.getId());
            return (walkRouter.calcRoute(fromFacility, toFacility, departureTime, person));
        }

        List<PlanElement> trip = new ArrayList<>();

        Leg walkToAccessStopLeg = createDrtWalkLeg(fromFacility, accessFacility, departureTime, person);
        trip.add(walkToAccessStopLeg);

        trip.add(createDrtStageActivity(accessFacility));

        double drtLegStartTime = departureTime + walkToAccessStopLeg.getTravelTime() + 1;
        Leg drtLeg = (Leg) drtRoutingModule.calcRoute(accessFacility, egressFacility, drtLegStartTime, person)
                .get(0);
        trip.add(drtLeg);

        trip.add(createDrtStageActivity(egressFacility));

        double walkFromStopStartTime = drtLeg.getDepartureTime() + drtLeg.getTravelTime() + 1;
        trip.add(createDrtWalkLeg(egressFacility, toFacility, walkFromStopStartTime, person));

        return trip;
    }

    private Leg createDrtWalkLeg(Facility<?> fromFacility, Facility<?> toFacility, double departureTime,
            Person person) {
        Leg leg = (Leg) walkRouter.calcRoute(fromFacility, toFacility, departureTime, person).get(0);
        leg.setMode(DrtStageActivityType.DRT_WALK);
        return leg;
    }

    private Activity createDrtStageActivity(Facility<?> stopFacility) {
        Activity activity = populationFactory.createActivityFromCoord(DrtStageActivityType.DRT_STAGE_ACTIVITY,
                stopFacility.getCoord());
        activity.setMaximumDuration(1);
        activity.setLinkId(stopFacility.getLinkId());
        return activity;
    }

    private void printError(Supplier<String> supplier) {
        if (drtCfg.isPrintDetailedWarnings()) {
            Logger.getLogger(getClass()).error(supplier.get());
        }
    }

    @Override
    public StageActivityTypes getStageActivityTypes() {
        return drtStageActivityType;
    }

    static Coord getFacilityCoord(Facility<?> facility, Network network) {
        Coord coord = facility.getCoord();
        if (coord == null) {
            coord = network.getLinks().get(facility.getLinkId()).getCoord();
            if (coord == null)
                throw new RuntimeException("From facility has neither coordinates nor link Id. Should not happen.");
        }
        return coord;
    }
}