diff --git a/Makefile b/Makefile index 7163bb0..d1adee5 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,7 @@ input/plans-longHaulFreight.xml.gz: input/$V/$N-$V-network.xml.gz --target-crs $(CRS)\ --shp input/shp/lausitz.shp --shp-crs $(CRS)\ --cut-on-boundary\ + --LegMode "longDistanceFreight"\ --output $@ # create facilities for commercial traffic input/commercialFacilities.xml.gz: diff --git a/input/v1.1/lausitz-v1.1-10pct.config.xml b/input/v1.1/lausitz-v1.1-10pct.config.xml index 52a5bbe..e8d5b20 100644 --- a/input/v1.1/lausitz-v1.1-10pct.config.xml +++ b/input/v1.1/lausitz-v1.1-10pct.config.xml @@ -26,13 +26,13 @@ + value="https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/lausitz/input/v1.1/lausitz-v1.1-network-with-pt.xml.gz"/> + value="https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/lausitz/input/v1.1/lausitz-v1.1-10pct.plans-initial.xml.gz"/> @@ -53,7 +53,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -132,12 +132,12 @@ - + - + @@ -164,7 +164,7 @@ - + @@ -212,7 +212,7 @@ - + diff --git a/src/main/java/org/matsim/run/LausitzScenario.java b/src/main/java/org/matsim/run/LausitzScenario.java index 14cc55d..f7fa06b 100644 --- a/src/main/java/org/matsim/run/LausitzScenario.java +++ b/src/main/java/org/matsim/run/LausitzScenario.java @@ -1,11 +1,11 @@ package org.matsim.run; import com.google.common.collect.Sets; -import com.google.inject.Key; -import com.google.inject.name.Names; import org.matsim.analysis.personMoney.PersonMoneyEventsAnalysisModule; +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.population.Person; import org.matsim.application.MATSimApplication; import org.matsim.application.analysis.CheckPopulation; import org.matsim.application.analysis.traffic.LinkStats; @@ -31,9 +31,8 @@ import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; +import org.matsim.core.population.PopulationUtils; import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; -import org.matsim.core.router.costcalculators.TravelDisutilityFactory; -import org.matsim.core.router.util.TravelTime; import org.matsim.core.scoring.functions.ScoringParametersForPerson; import org.matsim.run.analysis.CommuterAnalysis; import org.matsim.run.prepare.PrepareNetwork; @@ -51,6 +50,7 @@ import java.util.List; import java.net.URISyntaxException; import java.nio.file.Paths; +import java.util.Map; import java.util.Set; @CommandLine.Command(header = ":: Open Lausitz Scenario ::", version = LausitzScenario.VERSION, mixinStandardHelpOptions = true) @@ -66,8 +66,11 @@ public class LausitzScenario extends MATSimApplication { public static final String VERSION = "1.1"; - private static final String FREIGHT = "freight"; + public static final String FREIGHT = "longDistanceFreight"; private static final String AVERAGE = "average"; + public static final String HEAVY_MODE = "truck40t"; + public static final String MEDIUM_MODE = "truck18t"; + public static final String LIGHT_MODE = "truck8t"; // To decrypt hbefa input files set MATSIM_DECRYPTION_PASSWORD as environment variable. ask VSP for access. private static final String HBEFA_2020_PATH = "https://svn.vsp.tu-berlin.de/repos/public-svn/3507bb3997e5657ab9da76dbedbb13c9b5991d3e/0e73947443d68f95202b71a156b337f7f71604ae/"; @@ -182,6 +185,25 @@ protected Config prepareConfig(Config config) { @Override protected void prepareScenario(Scenario scenario) { + + for (Person person : scenario.getPopulation().getPersons().values()) { + + if (PopulationUtils.getSubpopulation(person).contains("commercialPersonTraffic") || + PopulationUtils.getSubpopulation(person).contains("goodsTraffic")) { + + Map> types = VehicleUtils.getVehicleTypes(person); + + for (Map.Entry> entry : types.entrySet()) { + if (Set.of(HEAVY_MODE, MEDIUM_MODE, LIGHT_MODE).contains(entry.getKey())) { + types.put(entry.getKey(), Id.create(entry.getKey(), VehicleType.class)); + } + } + } + + } + + + // add freight and truck as allowed modes together with car PrepareNetwork.prepareFreightNetwork(scenario.getNetwork()); @@ -210,8 +232,6 @@ public void install() { addTravelTimeBinding(TransportMode.ride).to(networkTravelTime()); addTravelDisutilityFactoryBinding(TransportMode.ride).to(carTravelDisutilityFactoryKey()); - addTravelTimeBinding(FREIGHT).to(Key.get(TravelTime.class, Names.named(TransportMode.truck))); - addTravelDisutilityFactoryBinding(FREIGHT).to(Key.get(TravelDisutilityFactory.class, Names.named(TransportMode.truck))); // we do not need to add SwissRailRaptor explicitely! this is done in core } @@ -223,7 +243,7 @@ public void install() { */ public static void prepareCommercialTrafficConfig(Config config) { - Set modes = Set.of(FREIGHT, TransportMode.truck); + Set modes = Set.of(HEAVY_MODE, MEDIUM_MODE, LIGHT_MODE); modes.forEach(mode -> { ScoringConfigGroup.ModeParams thisModeParams = new ScoringConfigGroup.ModeParams(mode); @@ -244,7 +264,6 @@ public static void prepareCommercialTrafficConfig(Config config) { config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("freight_start").setTypicalDuration(30 * 60.)); config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("freight_end").setTypicalDuration(30 * 60.)); - //TODO: add freight and remove from config or change freight subpopulation and mode for long distance freight for (String subpopulation : List.of("commercialPersonTraffic", "commercialPersonTraffic_service", "goodsTraffic")) { config.replanning().addStrategySettings( new ReplanningConfigGroup.StrategySettings() diff --git a/src/main/java/org/matsim/run/prepare/AdaptFreightTrafficToDetailedModes.java b/src/main/java/org/matsim/run/prepare/AdaptFreightTrafficToDetailedModes.java new file mode 100644 index 0000000..bf79276 --- /dev/null +++ b/src/main/java/org/matsim/run/prepare/AdaptFreightTrafficToDetailedModes.java @@ -0,0 +1,128 @@ +package org.matsim.run.prepare; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.Population; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; +import picocli.CommandLine; + +import java.nio.file.Path; +import java.util.Map; +import java.util.Set; + +import static org.matsim.run.LausitzScenario.*; + +@CommandLine.Command( + name = "adapt-freight-plans", + description = "Adapt all freight plans (including small scall commercial traffic) to new standards." +) +public class AdaptFreightTrafficToDetailedModes implements MATSimAppCommand { + + Logger log = LogManager.getLogger(AdaptFreightTrafficToDetailedModes.class); + + @CommandLine.Parameters(arity = "1", paramLabel = "INPUT", description = "Path to input population") + private Path input; + + @CommandLine.Option(names = "--output", description = "Path to output population", required = true) + private Path output; + + public static void main(String[] args) { + new AdaptFreightTrafficToDetailedModes().execute(args); + } + + @Override + public Integer call() throws Exception { + + Population population = PopulationUtils.readPopulation(input.toString()); + + for (Person person : population.getPersons().values()) { + if (PopulationUtils.getSubpopulation(person).equals("freight")) { + // rename freight subpop to longDistanceFreight + person.getAttributes().removeAttribute("subpopulation"); + person.getAttributes().putAttribute("subpopulation", FREIGHT); + +// rename each leg mode freight to longDistanceFreight + for (Plan plan : person.getPlans()) { + for (Leg leg : TripStructureUtils.getLegs(plan)) { + if (leg.getMode().equals("freight")) { + leg.setMode(FREIGHT); + } + } + } + } else if (PopulationUtils.getSubpopulation(person).equals(FREIGHT)) { + for (Plan plan : person.getPlans()) { + for (Leg leg : TripStructureUtils.getLegs(plan)) { + if (!leg.getMode().equals(FREIGHT)) { + leg.setMode(FREIGHT); + } + } + } + + } + + if (PopulationUtils.getSubpopulation(person).contains("commercialPersonTraffic") || + PopulationUtils.getSubpopulation(person).contains("goodsTraffic")) { + + Map> types = VehicleUtils.getVehicleTypes(person); + + for (Plan plan : person.getPlans()) { + for (Leg leg : TripStructureUtils.getLegs(plan)) { + if (leg.getMode().equals(TransportMode.truck)) { + String vehicleTypes = person.getAttributes().getAttribute("vehicleTypes").toString(); + if (vehicleTypes.contains("light8t")) { + leg.setMode(LIGHT_MODE); + } else if (vehicleTypes.contains("medium18t")) { + leg.setMode(MEDIUM_MODE); + } else if (vehicleTypes.contains("heavy40t")) { + leg.setMode(HEAVY_MODE); + } else { + log.error("Unknown vehicle type in: {}", vehicleTypes); + return 2; + } + } else if (leg.getMode().equals(TransportMode.car)) { +// TODO + } + } + } + + for (Map.Entry> entry : types.entrySet()) { + if (Set.of(HEAVY_MODE, MEDIUM_MODE, LIGHT_MODE).contains(entry.getKey())) { + types.put(entry.getKey(), Id.create(entry.getKey(), VehicleType.class)); + } + } + } + } + + + + + PopulationUtils.writePopulation(population, output.toString()); + + return 0; + } + + private static @NotNull Population removeSmallScaleCommercialTrafficFromPopulation(Population population) { + Population newPop = PopulationUtils.createPopulation(ConfigUtils.createConfig()); + + for (Person person : population.getPersons().values()) { + if (PopulationUtils.getSubpopulation(person).contains("commercialPersonTraffic") + || PopulationUtils.getSubpopulation(person).contains("goodsTraffic")) { +// do not add commercial or goods traffic from RE + continue; + } + newPop.addPerson(person); + } + return newPop; + } +} diff --git a/src/main/java/org/matsim/run/prepare/PrepareNetwork.java b/src/main/java/org/matsim/run/prepare/PrepareNetwork.java index 9da98b2..9b292c5 100644 --- a/src/main/java/org/matsim/run/prepare/PrepareNetwork.java +++ b/src/main/java/org/matsim/run/prepare/PrepareNetwork.java @@ -15,6 +15,8 @@ import java.util.Set; +import static org.matsim.run.LausitzScenario.*; + @CommandLine.Command( name = "network", description = "Prepare network / link attributes." @@ -23,8 +25,6 @@ public class PrepareNetwork implements MATSimAppCommand { private static final Logger log = LogManager.getLogger(PrepareNetwork.class); - private static final String FREIGHT = "freight"; - @CommandLine.Option(names = "--network", description = "Path to network file", required = true) private String networkFile; @@ -61,17 +61,19 @@ public static void prepareFreightNetwork(Network network) { if (modes.contains(TransportMode.car)) { Set newModes = Sets.newHashSet(modes); + newModes.add(HEAVY_MODE); + newModes.add(MEDIUM_MODE); + newModes.add(LIGHT_MODE); newModes.add(FREIGHT); - newModes.add(TransportMode.truck); link.setAllowedModes(newModes); linkCount++; } } - log.info("For {} links {} and {} has been added as an allowed mode.", linkCount, FREIGHT, TransportMode.truck); + log.info("For {} links {}, {}, {} and {} has been added as an allowed mode.", linkCount, HEAVY_MODE, MEDIUM_MODE, LIGHT_MODE, FREIGHT); - new MultimodalNetworkCleaner(network).run(Set.of(FREIGHT, TransportMode.truck)); + new MultimodalNetworkCleaner(network).run(Set.of(HEAVY_MODE, MEDIUM_MODE, LIGHT_MODE, FREIGHT)); } /** diff --git a/src/main/java/org/matsim/run/prepare/PreparePopulation.java b/src/main/java/org/matsim/run/prepare/PreparePopulation.java index 55a955a..f3cbec0 100644 --- a/src/main/java/org/matsim/run/prepare/PreparePopulation.java +++ b/src/main/java/org/matsim/run/prepare/PreparePopulation.java @@ -96,7 +96,8 @@ private void prepare(Person person) { } // Assign income to person (skip the freight agents) - if (person.getId().toString().startsWith("freight")) { + if (person.getId().toString().startsWith("freight") || person.getId().toString().startsWith("commercial") + || person.getId().toString().startsWith("goods")) { return; } diff --git a/src/test/java/org/matsim/run/RunIntegrationTest.java b/src/test/java/org/matsim/run/RunIntegrationTest.java index 83e0d75..3b1bd33 100644 --- a/src/test/java/org/matsim/run/RunIntegrationTest.java +++ b/src/test/java/org/matsim/run/RunIntegrationTest.java @@ -49,7 +49,7 @@ void runScenario() { assert MATSimApplication.execute(LausitzScenario.class, config, "--1pct", "--iterations", "1", - "--config:plans.inputPlansFile", "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/lausitz/input/v1.0/lausitz-v1.0-1pct.plans-initial.xml.gz", + "--config:plans.inputPlansFile", "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/lausitz/input/v1.1/lausitz-v1.1-1pct.plans-initial.xml.gz", "--output", utils.getOutputDirectory(), "--config:controller.overwriteFiles=deleteDirectoryIfExists") == 0 : "Must return non error code"; } @@ -62,7 +62,7 @@ void runScenarioIncludingDrt() { assert MATSimApplication.execute(RunLausitzDrtScenario.class, config, "--1pct", "--iterations", "1", - "--config:plans.inputPlansFile", "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/lausitz/input/v1.0/lausitz-v1.0-1pct.plans-initial.xml.gz", + "--config:plans.inputPlansFile", "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/lausitz/input/v1.1/lausitz-v1.1-1pct.plans-initial.xml.gz", "--output", utils.getOutputDirectory(), "--config:controller.overwriteFiles=deleteDirectoryIfExists") == 0 : "Must return non error code";