diff --git a/input/v6.1/berlin-v6.1.drt-config.xml b/input/v6.1/berlin-v6.1.drt-config.xml
new file mode 100644
index 00000000..3d6083f8
--- /dev/null
+++ b/input/v6.1/berlin-v6.1.drt-config.xml
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 402b7ab0..d3c53cff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -144,6 +144,14 @@
compile
+
+
+ org.matsim.contrib
+ drt-extensions
+ ${matsim.version}
+ compile
+
+
org.matsim.contrib
roadpricing
diff --git a/src/main/java/org/matsim/legacy/prepare/drt/DrtVehicleCreator.java b/src/main/java/org/matsim/legacy/prepare/drt/DrtVehicleCreator.java
index bcec32bf..1fb65a1e 100644
--- a/src/main/java/org/matsim/legacy/prepare/drt/DrtVehicleCreator.java
+++ b/src/main/java/org/matsim/legacy/prepare/drt/DrtVehicleCreator.java
@@ -80,44 +80,45 @@ public class DrtVehicleCreator {
public static void main(String[] args) {
- String networkFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin-v5.5-network.xml.gz";
- String populationFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin-v5.5-10pct.plans.xml.gz";
- String facilitiesFile = "";
- String drtServiceAreaShapeFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin-shp/berlin.shp";
- CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation("EPSG:31468", "EPSG:31468");
+ String networkFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v6.1/input/berlin-v6.1-network-with-pt.xml.gz";
+// String populationFile = "";
+// String facilitiesFile = "";
+ String drtServiceAreaShapeFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v6.1/input/shp/Berlin_25832.shp";
+ String scenarioCrs = "EPSG:25832";
+ String shapeCrs = "EPSG:25832";
-// String vehiclesFilePrefix = "berlin-drt-v5.5.spandau_b-drt-by-actLocations-sqrt-";
- String vehiclesFilePrefix = "berlin-drt-v5.5.drt-by-rndLocations-";
+// String vehiclesFilePrefix = "berlin-v6.1.spandau_b-drt-by-actLocations-sqrt-";
+ String vehiclesFilePrefix = "berlin-v6.1.drt-by-rndLocations-";
Set numbersOfVehicles = new HashSet<>();
- numbersOfVehicles.add(20);
- numbersOfVehicles.add(30);
- numbersOfVehicles.add(50);
- numbersOfVehicles.add(80);
+// numbersOfVehicles.add(20);
+// numbersOfVehicles.add(30);
+// numbersOfVehicles.add(50);
+// numbersOfVehicles.add(80);
numbersOfVehicles.add(100);
- numbersOfVehicles.add(120);
- numbersOfVehicles.add(150);
- numbersOfVehicles.add(200);
- numbersOfVehicles.add(250);
- numbersOfVehicles.add(300);
- numbersOfVehicles.add(400);
- numbersOfVehicles.add(500);
- numbersOfVehicles.add(600);
- numbersOfVehicles.add(700);
- numbersOfVehicles.add(800);
- numbersOfVehicles.add(900);
- numbersOfVehicles.add(1000);
- numbersOfVehicles.add(1200);
- numbersOfVehicles.add(1500);
- numbersOfVehicles.add(2000);
- numbersOfVehicles.add(2500);
- numbersOfVehicles.add(3000);
- numbersOfVehicles.add(4000);
- numbersOfVehicles.add(5000);
- numbersOfVehicles.add(10000);
+// numbersOfVehicles.add(120);
+// numbersOfVehicles.add(150);
+// numbersOfVehicles.add(200);
+// numbersOfVehicles.add(250);
+// numbersOfVehicles.add(300);
+// numbersOfVehicles.add(400);
+// numbersOfVehicles.add(500);
+// numbersOfVehicles.add(600);
+// numbersOfVehicles.add(700);
+// numbersOfVehicles.add(800);
+// numbersOfVehicles.add(900);
+// numbersOfVehicles.add(1000);
+// numbersOfVehicles.add(1200);
+// numbersOfVehicles.add(1500);
+// numbersOfVehicles.add(2000);
+// numbersOfVehicles.add(2500);
+// numbersOfVehicles.add(3000);
+// numbersOfVehicles.add(4000);
+// numbersOfVehicles.add(5000);
+// numbersOfVehicles.add(10000);
int seats = 4;
- DrtVehicleCreator tvc = new DrtVehicleCreator(networkFile, drtServiceAreaShapeFile, ct);
+ DrtVehicleCreator tvc = new DrtVehicleCreator(networkFile, drtServiceAreaShapeFile, shapeCrs, scenarioCrs);
// tvc.setLinkWeightsByActivities(populationFile, facilitiesFile);
// tvc.setWeightsToSquareRoot();
for (int numberOfVehicles: numbersOfVehicles) {
@@ -126,10 +127,11 @@ public static void main(String[] args) {
}
}
- public DrtVehicleCreator(String networkfile, String drtServiceAreaShapeFile, CoordinateTransformation ct) {
- this.ct = ct;
+ public DrtVehicleCreator(String networkfile, String drtServiceAreaShapeFile, String shapeCrs, String scenarioCrs) {
+ this.ct = TransformationFactory.getCoordinateTransformation(shapeCrs, scenarioCrs);
Config config = ConfigUtils.createConfig();
+ config.global().setCoordinateSystem(scenarioCrs);
config.network().setInputFile(networkfile);
this.scenario = ScenarioUtils.loadScenario(config);
diff --git a/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier.java b/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier.java
index 643222c7..7f4d228d 100644
--- a/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier.java
+++ b/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier.java
@@ -52,7 +52,7 @@ public OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier() {
drtModes = Arrays.asList(TransportMode.drt, "drt2", "drt_teleportation");
modeHierarchy.add( TransportMode.walk ) ;
- modeHierarchy.add( "bicycle" ); // TransportMode.bike is not registered as main mode, only "bicycle" ;
+ modeHierarchy.add( TransportMode.bike ); // TransportMode.bike is not registered as main mode, only "bicycle" ;
modeHierarchy.add( TransportMode.ride ) ;
modeHierarchy.add( TransportMode.car ) ;
modeHierarchy.add( "car2" ) ;
@@ -61,6 +61,7 @@ public OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier() {
}
modeHierarchy.add( TransportMode.pt ) ;
modeHierarchy.add( "freight" );
+ modeHierarchy.add( "truck" );
// NOTE: This hierarchical stuff is not so great: is park-n-ride a car trip or a pt trip? Could weigh it by distance, or by time spent
// in respective mode. Or have combined modes as separate modes. In any case, can't do it at the leg level, since it does not
diff --git a/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterModeIdentifier.java b/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterModeIdentifier.java
index 504e0d3b..0f9fe842 100644
--- a/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterModeIdentifier.java
+++ b/src/main/java/org/matsim/legacy/run/drt/OpenBerlinIntermodalPtDrtRouterModeIdentifier.java
@@ -48,7 +48,7 @@ public OpenBerlinIntermodalPtDrtRouterModeIdentifier() {
drtModes = Arrays.asList(TransportMode.drt, "drt2", "drt_teleportation");
modeHierarchy.add( TransportMode.walk ) ;
- modeHierarchy.add( "bicycle" ); // TransportMode.bike is not registered as main mode, only "bicycle" ;
+ modeHierarchy.add( TransportMode.bike );
modeHierarchy.add( TransportMode.ride ) ;
modeHierarchy.add( TransportMode.car ) ;
modeHierarchy.add( "car2" ) ;
diff --git a/src/main/java/org/matsim/run/OpenBerlinDrtScenario.java b/src/main/java/org/matsim/run/OpenBerlinDrtScenario.java
new file mode 100644
index 00000000..24e9f5b6
--- /dev/null
+++ b/src/main/java/org/matsim/run/OpenBerlinDrtScenario.java
@@ -0,0 +1,262 @@
+/* *********************************************************************** *
+ * project: org.matsim.*
+ * Controler.java
+ * *
+ * *********************************************************************** *
+ * *
+ * copyright : (C) 2007 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.run;
+
+import ch.sbb.matsim.config.SwissRailRaptorConfigGroup;
+import ch.sbb.matsim.routing.pt.raptor.RaptorIntermodalAccessEgress;
+import com.beust.jcommander.internal.Lists;
+import com.google.common.collect.ImmutableSet;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.matsim.api.core.v01.Scenario;
+import org.matsim.api.core.v01.TransportMode;
+import org.matsim.application.MATSimApplication;
+import org.matsim.contrib.drt.routing.DrtRoute;
+import org.matsim.contrib.drt.routing.DrtRouteFactory;
+import org.matsim.contrib.drt.run.DrtConfigGroup;
+import org.matsim.contrib.drt.run.DrtConfigs;
+import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
+import org.matsim.contrib.drt.run.MultiModeDrtModule;
+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.ConfigGroup;
+import org.matsim.core.config.ConfigUtils;
+import org.matsim.core.config.groups.QSimConfigGroup;
+import org.matsim.core.config.groups.ScoringConfigGroup;
+import org.matsim.core.controler.AbstractModule;
+import org.matsim.core.controler.Controler;
+import org.matsim.core.population.routes.RouteFactories;
+import org.matsim.core.router.AnalysisMainModeIdentifier;
+import org.matsim.core.router.MainModeIdentifier;
+import org.matsim.extensions.pt.fare.intermodalTripFareCompensator.IntermodalTripFareCompensatorConfigGroup;
+import org.matsim.extensions.pt.fare.intermodalTripFareCompensator.IntermodalTripFareCompensatorsConfigGroup;
+import org.matsim.extensions.pt.fare.intermodalTripFareCompensator.IntermodalTripFareCompensatorsModule;
+import org.matsim.extensions.pt.routing.EnhancedRaptorIntermodalAccessEgress;
+import org.matsim.extensions.pt.routing.ptRoutingModes.PtIntermodalRoutingModesConfigGroup;
+import org.matsim.extensions.pt.routing.ptRoutingModes.PtIntermodalRoutingModesModule;
+import org.matsim.legacy.run.BerlinExperimentalConfigGroup;
+import org.matsim.legacy.run.drt.BerlinShpUtils;
+import org.matsim.legacy.run.drt.OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier;
+import org.matsim.legacy.run.drt.OpenBerlinIntermodalPtDrtRouterModeIdentifier;
+import org.matsim.legacy.run.drt.RunDrtOpenBerlinScenario;
+import org.matsim.pt.transitSchedule.api.TransitSchedule;
+import org.matsim.pt.transitSchedule.api.TransitStopFacility;
+import picocli.CommandLine;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Extend the {@link OpenBerlinScenario} by DRT functionality.
+ * By default, a config is loaded where a drt mode is operated in all of Berlin with 10,000 vehicles.
+ * Alternatively, you can provide another drt-only config using the {@code --drt-config} comand line option.
+ * This run script then configures drt to be perceived just like pt and to be fully tariff-integrated into pt.
+ */
+public class OpenBerlinDrtScenario extends OpenBerlinScenario{
+
+ //TODO: write tests
+
+ private static final Logger log = LogManager.getLogger(OpenBerlinDrtScenario.class);
+
+ @CommandLine.Option(names = "--drt-config",
+ defaultValue = "input/v6.1/berlin-v6.1.drt-config.xml",
+ description = "Path to drt (only) config. Should contain only additional stuff to base config. Otherwise overrides.")
+ private String drtConfig;
+
+ public static void main(String[] args) {
+ MATSimApplication.run(OpenBerlinDrtScenario.class, args);
+ }
+
+ @Override
+ protected List getCustomModules() {
+ List customModules = super.getCustomModules();
+ customModules.addAll(Lists.newArrayList(
+ new BerlinExperimentalConfigGroup(),
+ new DvrpConfigGroup(),
+ new MultiModeDrtConfigGroup(),
+ new SwissRailRaptorConfigGroup(),
+ new IntermodalTripFareCompensatorsConfigGroup(),
+ new PtIntermodalRoutingModesConfigGroup()));
+ return customModules;
+ }
+
+ @Override
+ protected Config prepareConfig(Config config) {
+ super.prepareConfig(config);
+
+ ConfigUtils.loadConfig(config, drtConfig);
+
+ //modify output directory and runId
+ config.controller().setOutputDirectory(config.controller().getOutputDirectory() + "-drt");
+ config.controller().setRunId(config.controller().getRunId() + "-drt");
+
+ //drt only works with the following sim start time interpretation
+ config.qsim().setSimStarttimeInterpretation(QSimConfigGroup.StarttimeInterpretation.onlyUseStarttime);
+
+ MultiModeDrtConfigGroup multiModeDrtCfg = MultiModeDrtConfigGroup.get(config);
+ DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtCfg, config.scoring(), config.routing());
+
+ Set drtModes = new HashSet<>();
+
+ ScoringConfigGroup.ModeParams ptParams = config.scoring().getModes().get(TransportMode.pt);
+ IntermodalTripFareCompensatorsConfigGroup compensatorsConfig = ConfigUtils.addOrGetModule(config, IntermodalTripFareCompensatorsConfigGroup.class);
+
+ for (DrtConfigGroup drtCfg : multiModeDrtCfg.getModalElements()) {
+ drtModes.add(drtCfg.getMode());
+
+ //copy all scoring params from pt
+ ScoringConfigGroup.ModeParams modeParams = new ScoringConfigGroup.ModeParams(drtCfg.getMode());
+ modeParams.setConstant(ptParams.getConstant());
+ modeParams.setMarginalUtilityOfDistance(ptParams.getMarginalUtilityOfDistance());
+ modeParams.setMarginalUtilityOfTraveling(ptParams.getMarginalUtilityOfTraveling());
+ modeParams.setDailyUtilityConstant(ptParams.getDailyUtilityConstant());
+
+ //assume that the drt is fully integrated in pt, i.e. fare integration
+ modeParams.setMonetaryDistanceRate(ptParams.getMonetaryDistanceRate());
+ modeParams.setDailyMonetaryConstant(ptParams.getDailyMonetaryConstant());
+ config.scoring().addModeParams(modeParams);
+ }
+
+ //assume that (all) the drt is fully integrated in pt, i.e. fare integration
+ IntermodalTripFareCompensatorConfigGroup drtCompensationCfg = new IntermodalTripFareCompensatorConfigGroup();
+ drtCompensationCfg.setCompensationCondition(IntermodalTripFareCompensatorConfigGroup.CompensationCondition.PtModeUsedAnywhereInTheDay);
+ drtCompensationCfg.setCompensationMoneyPerDay(ptParams.getDailyMonetaryConstant());
+ drtCompensationCfg.setNonPtModes(ImmutableSet
+ .builder()
+ .addAll(drtModes)
+ .build());
+ compensatorsConfig.addParameterSet(drtCompensationCfg);
+
+ //include drt in mode-choice and add mode params.
+ //by using a Set, it should be assured that they aren't included twice.
+ drtModes.addAll(Arrays.asList(config.subtourModeChoice().getModes()));
+ config.subtourModeChoice().setModes(drtModes.toArray(String[]::new));
+
+ //Here (or when extending this class), you can configure the dvrp and the drt config groups.
+ //Of course you can configure on the xml (config) level, alternatively.
+ //for example you can configure prices and compensations, service area etc.,
+ //whether dvrp modes should operate on a mode-specific sub-network or on the entire car-network,
+ //how the time-constraints for the dispatch should be parameterized etc.
+
+ return config;
+ }
+
+ @Override
+ protected void prepareScenario(Scenario scenario) {
+ super.prepareScenario(scenario);
+
+ //if the input plans contain DrtRoutes, this will cause problems later in the DrtRouteFactory
+ //to avoid this, the DrtRouteFactory would have to get set before loading the scenario, just like in Open Berlin v5.x
+ RouteFactories routeFactories = scenario.getPopulation().getFactory().getRouteFactories();
+ routeFactories.setRouteFactory(DrtRoute.class, new DrtRouteFactory());
+
+ //if the drt mode is configured as a dvrp network mode and if it has a service area
+ //the drt mode is added to the links in the service area with a buffer of +2000 meter (per default or otherwise configured in BerlinExperimentalConfigGroup)
+ //and transit stops 200m around the service area are tagged to be be served by the corresponding drt.
+ prepareNetworkAndTransitScheduleForDrt(scenario);
+
+ //Here (or when extending this class), you can mutate the scenario (e.g. population, network, ...)
+ }
+
+ @Override
+ protected void prepareControler(Controler controler) {
+ super.prepareControler(controler);
+
+ // drt + dvrp modules
+ controler.addOverridingModule(new MultiModeDrtModule());
+ controler.addOverridingModule(new DvrpModule());
+ controler.configureQSimComponents(DvrpQSimComponents.activateAllModes(MultiModeDrtConfigGroup.get(controler.getConfig())));
+
+ controler.addOverridingModule(new AbstractModule() {
+
+ @Override
+ public void install() {
+ bind(AnalysisMainModeIdentifier.class).to(OpenBerlinIntermodalPtDrtRouterAnalysisModeIdentifier.class);
+ bind(MainModeIdentifier.class).to(OpenBerlinIntermodalPtDrtRouterModeIdentifier.class);
+ bind(RaptorIntermodalAccessEgress.class).to(EnhancedRaptorIntermodalAccessEgress.class);
+
+ }
+ });
+
+ // yyyy there is fareSModule (with S) in config. ?!?! kai, jul'19
+ controler.addOverridingModule(new IntermodalTripFareCompensatorsModule());
+ controler.addOverridingModule(new PtIntermodalRoutingModesModule());
+ }
+
+ /**
+ * This code is copied from matsim-berlin v5.x {@code RunDrtOpenBerlinScenario.prepareScenario()} and sub-methods.
+ * @param scenario network and transit schedule are mutated as side effects.
+ */
+ private static void prepareNetworkAndTransitScheduleForDrt(Scenario scenario) {
+ BerlinExperimentalConfigGroup berlinCfg = ConfigUtils.addOrGetModule(scenario.getConfig(), BerlinExperimentalConfigGroup.class);
+ DvrpConfigGroup dvrpConfigGroup = DvrpConfigGroup.get(scenario.getConfig());
+
+ for (DrtConfigGroup drtCfg : MultiModeDrtConfigGroup.get(scenario.getConfig()).getModalElements()) {
+ String drtServiceAreaShapeFile = drtCfg.drtServiceAreaShapeFile;
+ if (drtServiceAreaShapeFile != null && !drtServiceAreaShapeFile.equals("") && !drtServiceAreaShapeFile.equals("null")) {
+
+ if (dvrpConfigGroup.networkModes.contains(drtCfg.getMode())){
+ // Michal says restricting drt to a drt network roughly the size of the service area helps to speed up.
+ // This is even more true since drt started to route on a freespeed TT matrix (Nov '20).
+ // A buffer of 10km to the service area Berlin includes the A10 on some useful stretches outside Berlin.
+ if (berlinCfg.getTagDrtLinksBufferAroundServiceAreaShp() >= 0.0) {
+ //TODO: inline/move method ?
+ RunDrtOpenBerlinScenario.addDRTmode(scenario, drtCfg.getMode(), drtServiceAreaShapeFile, berlinCfg.getTagDrtLinksBufferAroundServiceAreaShp());
+ }
+ }
+
+ tagTransitStopsInServiceArea(scenario.getTransitSchedule(),
+ "drtStopFilter", "station_S/U/RE/RB_drtServiceArea",
+ drtServiceAreaShapeFile,
+ "stopFilter", "station_S/U/RE/RB",
+ // some S+U stations are located slightly outside the shp File, e.g. U7 Neukoelln, U8
+ // Hermannstr., so allow buffer around the shape.
+ // This does not mean that a drt vehicle can pick the passenger up outside the service area,
+ // rather the passenger has to walk the last few meters from the drt drop off to the station.
+ 200.0);
+ }
+ }
+ }
+
+ private static void tagTransitStopsInServiceArea(TransitSchedule transitSchedule,
+ String newAttributeName, String newAttributeValue,
+ String drtServiceAreaShapeFile,
+ String oldFilterAttribute, String oldFilterValue,
+ double bufferAroundServiceArea) {
+ log.info("Tagging pt stops marked for intermodal access/egress in the service area.");
+ BerlinShpUtils shpUtils = new BerlinShpUtils(drtServiceAreaShapeFile);
+ for (TransitStopFacility stop : transitSchedule.getFacilities().values()) {
+ if (stop.getAttributes().getAttribute(oldFilterAttribute) != null) {
+ if (stop.getAttributes().getAttribute(oldFilterAttribute).equals(oldFilterValue)) {
+ if (shpUtils.isCoordInDrtServiceAreaWithBuffer(stop.getCoord(), bufferAroundServiceArea)) {
+ stop.getAttributes().putAttribute(newAttributeName, newAttributeValue);
+ }
+ }
+ }
+ }
+ }
+
+
+}