Skip to content

Commit

Permalink
Merge pull request #9 from matsim-scenarios/emission-noise-analysis
Browse files Browse the repository at this point in the history
Emission noise analysis
  • Loading branch information
simei94 authored Aug 22, 2024
2 parents ab3dae0 + d5834ff commit afe958e
Show file tree
Hide file tree
Showing 4 changed files with 324 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.matsim.simwrapper.Dashboard;
import org.matsim.simwrapper.DashboardProvider;
import org.matsim.simwrapper.SimWrapper;
import org.matsim.simwrapper.dashboard.EmissionsDashboard;
import org.matsim.simwrapper.dashboard.TripDashboard;

import java.util.List;
Expand All @@ -14,12 +15,18 @@
public class LausitzDashboardProvider implements DashboardProvider {
@Override
public List<Dashboard> getDashboards(Config config, SimWrapper simWrapper) {
return List.of(new TripDashboard(

TripDashboard trips = new TripDashboard(
"lausitz_mode_share.csv",
"lausitz_mode_share_per_dist.csv",
"lausitz_mode_users.csv")
.withGroupedRefData("lausitz_mode_share_per_group_dist_ref.csv", "age", "economic_status")
.withDistanceDistribution("lausitz_mode_share_distance_distribution.csv")
.withDistanceDistribution("lausitz_mode_share_distance_distribution.csv");

return List.of(trips,
new EmissionsDashboard()
// the NoiseAnalysis is not run here because it needs more RAM than the entire simulation,
// which leads to VM crashes and prevents other analysis to run. We have to run it separately (e.g. with LausitzSimWrapperRunner)
);
}
}
104 changes: 104 additions & 0 deletions src/main/java/org/matsim/dashboards/LausitzSimWrapperRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* *********************************************************************** *
* 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.dashboards;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.application.ApplicationUtils;
import org.matsim.application.MATSimAppCommand;
import org.matsim.application.options.ShpOptions;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.simwrapper.Dashboard;
import org.matsim.simwrapper.SimWrapper;
import org.matsim.simwrapper.SimWrapperConfigGroup;
import org.matsim.simwrapper.dashboard.NoiseDashboard;
import picocli.CommandLine;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.file.Path;
import java.util.List;

@CommandLine.Command(
name = "simwrapper",
description = "Run additional analysis and create SimWrapper dashboard for existing run output."
)
final class LausitzSimWrapperRunner implements MATSimAppCommand {

private static final Logger log = LogManager.getLogger(LausitzSimWrapperRunner.class);

@CommandLine.Parameters(arity = "1..*", description = "Path to run output directories for which dashboards are to be generated.")
private List<Path> inputPaths;

@CommandLine.Mixin
private final ShpOptions shp = new ShpOptions();

@CommandLine.Option(names = "--noise", defaultValue = "false", description = "create noise dashboard")
private boolean noise;


private LausitzSimWrapperRunner(){
}

@Override
public Integer call() throws Exception {

if (!noise){
throw new IllegalArgumentException("you have not configured any dashboard to be created! Please use command line parameters!");
}

for (Path runDirectory : inputPaths) {
log.info("Running on {}", runDirectory);

Path configPath = ApplicationUtils.matchInput("config.xml", runDirectory);
Config config = ConfigUtils.loadConfig(configPath.toString());
SimWrapper sw = SimWrapper.create(config);

SimWrapperConfigGroup simwrapperCfg = ConfigUtils.addOrGetModule(config, SimWrapperConfigGroup.class);
if (shp.isDefined()){
simwrapperCfg.defaultParams().shp = shp.getShapeFile();
}
//skip default dashboards
simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled;

//add dashboards according to command line parameters
// TODO: if more dashboards are to be added here, we need to check if noise==true before adding noise dashboard here
sw.addDashboard(Dashboard.customize(new NoiseDashboard()).context("noise"));


try {
sw.generate(runDirectory, true);
sw.run(runDirectory);
} catch (IOException e) {
throw new InterruptedIOException();
}
}

return 0;
}

public static void main(String[] args) {
new LausitzSimWrapperRunner().execute(args);

}

}
98 changes: 96 additions & 2 deletions src/main/java/org/matsim/run/LausitzScenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
import org.matsim.application.prepare.network.CreateNetworkFromSumo;
import org.matsim.application.prepare.population.*;
import org.matsim.application.prepare.pt.CreateTransitScheduleFromGtfs;
import org.matsim.contrib.emissions.HbefaRoadTypeMapping;
import org.matsim.contrib.emissions.HbefaVehicleCategory;
import org.matsim.contrib.emissions.OsmHbefaMapping;
import org.matsim.contrib.emissions.utils.EmissionsConfigGroup;
import org.matsim.contrib.vsp.scenario.SnzActivities;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
Expand All @@ -25,6 +29,7 @@
import org.matsim.core.config.groups.ScoringConfigGroup;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.controler.Controler;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule;
import org.matsim.core.router.costcalculators.TravelDisutilityFactory;
import org.matsim.core.router.util.TravelTime;
Expand All @@ -33,6 +38,9 @@
import org.matsim.run.prepare.PreparePopulation;
import org.matsim.simwrapper.SimWrapperConfigGroup;
import org.matsim.simwrapper.SimWrapperModule;
import org.matsim.vehicles.EngineInformation;
import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;
import picocli.CommandLine;
import playground.vsp.pt.fare.DistanceBasedPtFareParams;
import playground.vsp.pt.fare.PtFareConfigGroup;
Expand Down Expand Up @@ -60,10 +68,21 @@ public class LausitzScenario extends MATSimApplication {

public static final String VERSION = "1.1";
private static final String FREIGHT = "freight";
private static final String AVERAGE = "average";

// 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/";
private static final String HBEFA_FILE_COLD_DETAILED = HBEFA_2020_PATH + "82t7b02rc0rji2kmsahfwp933u2rfjlkhfpi2u9r20.enc";
private static final String HBEFA_FILE_WARM_DETAILED = HBEFA_2020_PATH + "944637571c833ddcf1d0dfcccb59838509f397e6.enc";
private static final String HBEFA_FILE_COLD_AVERAGE = HBEFA_2020_PATH + "r9230ru2n209r30u2fn0c9rn20n2rujkhkjhoewt84202.enc" ;
private static final String HBEFA_FILE_WARM_AVERAGE = HBEFA_2020_PATH + "7eff8f308633df1b8ac4d06d05180dd0c5fdf577.enc";

@CommandLine.Mixin
private final SampleOptions sample = new SampleOptions( 100, 25, 10, 1);

@CommandLine.Option(names = "--emissions", defaultValue = "PERFORM_EMISSIONS_ANALYSIS", description = "Define if emission analysis should be performed or not.")
private EmissionAnalysisHandling emissions;


public LausitzScenario(@Nullable Config config) {
super(config);
Expand Down Expand Up @@ -124,7 +143,7 @@ protected Config prepareConfig(Config config) {
config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLink);

prepareCommercialTrafficConfig(config);
// TODO: Config options

// set pt fare calc model to fareZoneBased = fare of vvo tarifzone 20 is paid for trips within fare zone
// every other trip: Deutschlandtarif
// for more info see FareZoneBasedPtFareHandler class in vsp contrib
Expand All @@ -138,8 +157,17 @@ protected Config prepareConfig(Config config) {
throw new RuntimeException(e);
}

// TODO: recreate counts format with car and trucks

if (emissions == EmissionAnalysisHandling.PERFORM_EMISSIONS_ANALYSIS) {
// set hbefa input files for emission analysis
EmissionsConfigGroup eConfig = ConfigUtils.addOrGetModule(config, EmissionsConfigGroup.class);
eConfig.setDetailedColdEmissionFactorsFile(HBEFA_FILE_COLD_DETAILED);
eConfig.setDetailedWarmEmissionFactorsFile(HBEFA_FILE_WARM_DETAILED);
eConfig.setAverageColdEmissionFactorsFile(HBEFA_FILE_COLD_AVERAGE);
eConfig.setAverageWarmEmissionFactorsFile(HBEFA_FILE_WARM_AVERAGE);
eConfig.setHbefaTableConsistencyCheckingLevel(EmissionsConfigGroup.HbefaTableConsistencyCheckingLevel.consistent);
eConfig.setDetailedVsAverageLookupBehavior(EmissionsConfigGroup.DetailedVsAverageLookupBehavior.tryDetailedThenTechnologyAverageThenAverageTable);
}
return config;
}

Expand All @@ -158,6 +186,22 @@ protected void prepareScenario(Scenario scenario) {
link.setAllowedModes(newModes);
}
}

if (emissions == EmissionAnalysisHandling.PERFORM_EMISSIONS_ANALYSIS) {
// do not use VspHbefaRoadTypeMapping() as it results in almost every road to mapped to "highway"!
HbefaRoadTypeMapping roadTypeMapping = OsmHbefaMapping.build();
// the type attribute in our network has the prefix "highway" for all links but pt links.
// we need to delete that because OsmHbefaMapping does not handle that.
for (Link link : scenario.getNetwork().getLinks().values()) {
//pt links can be disregarded
if (!link.getAllowedModes().contains("pt")) {
NetworkUtils.setType(link, NetworkUtils.getType(link).replaceFirst("highway.", ""));
}
}
roadTypeMapping.addHbefaMappings(scenario.getNetwork());

prepareVehicleTypesForEmissionAnalysis(scenario);
}
}

@Override
Expand Down Expand Up @@ -225,4 +269,54 @@ public static void prepareCommercialTrafficConfig(Config config) {
);
}
}

private static void prepareVehicleTypesForEmissionAnalysis(Scenario scenario) {
for (VehicleType type : scenario.getVehicles().getVehicleTypes().values()) {
EngineInformation engineInformation = type.getEngineInformation();

// only set engine information if none are present
if (engineInformation.getAttributes().isEmpty()) {
switch (type.getId().toString()) {
case TransportMode.car -> {
VehicleUtils.setHbefaVehicleCategory(engineInformation, HbefaVehicleCategory.PASSENGER_CAR.toString());
VehicleUtils.setHbefaTechnology(engineInformation, AVERAGE);
VehicleUtils.setHbefaSizeClass(engineInformation, AVERAGE);
VehicleUtils.setHbefaEmissionsConcept(engineInformation, AVERAGE);
}
case TransportMode.ride -> {
// ignore ride, the mode routed on network, but then teleported
VehicleUtils.setHbefaVehicleCategory(engineInformation, HbefaVehicleCategory.NON_HBEFA_VEHICLE.toString());
VehicleUtils.setHbefaTechnology(engineInformation, AVERAGE);
VehicleUtils.setHbefaSizeClass(engineInformation, AVERAGE);
VehicleUtils.setHbefaEmissionsConcept(engineInformation, AVERAGE);
}
case FREIGHT -> {
VehicleUtils.setHbefaVehicleCategory(engineInformation, HbefaVehicleCategory.HEAVY_GOODS_VEHICLE.toString());
VehicleUtils.setHbefaTechnology(engineInformation, AVERAGE);
VehicleUtils.setHbefaSizeClass(engineInformation, AVERAGE);
VehicleUtils.setHbefaEmissionsConcept(engineInformation, AVERAGE);
}
case TransportMode.bike -> {
// ignore bikes
VehicleUtils.setHbefaVehicleCategory(engineInformation, HbefaVehicleCategory.NON_HBEFA_VEHICLE.toString());
VehicleUtils.setHbefaTechnology(engineInformation, AVERAGE);
VehicleUtils.setHbefaSizeClass(engineInformation, AVERAGE);
VehicleUtils.setHbefaEmissionsConcept(engineInformation, AVERAGE);
}
default -> throw new IllegalArgumentException("does not know how to handle vehicleType " + type.getId().toString());
}
}
}

// ignore all pt veh types
scenario.getTransitVehicles()
.getVehicleTypes()
.values().forEach(type -> VehicleUtils.setHbefaVehicleCategory(type.getEngineInformation(), HbefaVehicleCategory.NON_HBEFA_VEHICLE.toString()));
}

/**
* Defines if all necessary configs for emissions analysis should be made
* and hence if emissions analysis is performed or not (will fail without configs).
*/
enum EmissionAnalysisHandling {PERFORM_EMISSIONS_ANALYSIS, DO_NOT_PERFORM_EMISSIONS_ANALYSIS}
}
Loading

0 comments on commit afe958e

Please sign in to comment.