From 748c4b437cbfb0a80e19264a26a0bd47f4451543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 26 Nov 2022 12:25:18 +0100 Subject: [PATCH] feat: Improve batch routing tools (#153) * Update routing * Add changelog --- CHANGELOG.md | 1 + .../routing/BatchPublicTransportRouter.java | 92 ++++++-- .../core/tools/routing/BatchRoadRouter.java | 16 ++ .../RunBatchPublicTransportRouter.java | 217 +++++++++++++++++- .../tools/routing/RunBatchRoadRouter.java | 12 +- 5 files changed, 313 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc7bdb3ad..e6c9d1ff4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ included in the (note yet determined) next version number. **Development version** +- Improve functionality of routing tools to set utilities in detail - Fix bug in EqasimTransitQSimModule: first check if EqasimConfigGroup has TransitEngineModule before removing it - Updated config option from `eqasim.tripAnalysisInterval` to `eqasim.analysisInterval` - Automatically produce analysis output for legs and public transport information diff --git a/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java index 53191a6a1..879609679 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java @@ -3,15 +3,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; import org.eqasim.core.components.headway.HeadwayCalculator; import org.eqasim.core.misc.ParallelProgress; 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.Leg; import org.matsim.core.network.NetworkUtils; @@ -24,6 +23,7 @@ import org.matsim.pt.transitSchedule.api.TransitRoute; import org.matsim.pt.transitSchedule.api.TransitSchedule; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.inject.Provider; public class BatchPublicTransportRouter { @@ -36,9 +36,11 @@ public class BatchPublicTransportRouter { private final int numberOfThreads; private final double interval; + private final Set transitModes; + public BatchPublicTransportRouter(Provider routerProvider, Provider headwayCalculatorProvider, TransitSchedule schedule, Network network, - int batchSize, int numberOfThreads, double interval) { + int batchSize, int numberOfThreads, double interval, Set transitModes) { this.routerProvider = routerProvider; this.headwayCalculatorProvider = headwayCalculatorProvider; this.batchSize = batchSize; @@ -46,6 +48,7 @@ public BatchPublicTransportRouter(Provider routerProvider, this.schedule = schedule; this.network = network; this.interval = interval; + this.transitModes = transitModes; } public Pair, Collection> run(Collection tasks) @@ -119,7 +122,6 @@ public void run() { Facility toFacility = new LinkWrapperFacility(NetworkUtils.getNearestLink(network, toCoord)); List legs = router.calcRoute(fromFacility, toFacility, task.departureTime, null); - List routeInformation = new LinkedList<>(); if (legs != null) { boolean isFirstVehicularLeg = true; @@ -137,21 +139,17 @@ public void run() { for (Leg leg : legs) { boolean isFirstLeg = currentIndex == 0; boolean isLastLeg = currentIndex == legs.size() - 1; - currentIndex++; - if (leg.getMode().equals(TransportMode.access_walk) - || (leg.getMode().equals(TransportMode.walk) && isFirstLeg)) { + if (leg.getMode().contains("walk") && isFirstLeg) { tripInformation.accessTravelTime_min += leg.getTravelTime().seconds() / 60.0; tripInformation.accessDistance_km += leg.getRoute().getDistance() * 1e-3; - } else if (leg.getMode().equals(TransportMode.egress_walk) - || (leg.getMode().equals(TransportMode.walk) && isLastLeg)) { + } else if (leg.getMode().contains("walk") && isLastLeg) { tripInformation.egressTravelTime_min += leg.getTravelTime().seconds() / 60.0; tripInformation.egressDistance_km += leg.getRoute().getDistance() * 1e-3; - } else if (leg.getMode().equals(TransportMode.transit_walk) - || (leg.getMode().equals(TransportMode.walk) && !isFirstLeg && !isLastLeg)) { + } else if (leg.getMode().contains("walk") && !isFirstLeg && !isLastLeg) { tripInformation.transferTravelTime_min += leg.getTravelTime().seconds() / 60.0; tripInformation.transferDistance_km += leg.getRoute().getDistance() * 1e-3; - } else if (leg.getMode().equals(TransportMode.pt)) { + } else if (transitModes.contains(leg.getMode())) { TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); double waitingTime = route.getBoardingTime().seconds() @@ -201,7 +199,7 @@ public void run() { LegInformation legInformation = new LegInformation(); legInformation.identifier = task.identifier; legInformation.legIndex = currentIndex; - legInformation.mode = transitMode; + legInformation.transitMode = transitMode; legInformation.lineId = transitLine.getId().toString(); legInformation.routeId = transitRoute.getId().toString(); legInformation.vehicleId = departure.getVehicleId().toString(); @@ -214,6 +212,8 @@ public void run() { } else { throw new IllegalStateException(); } + + currentIndex++; } tripInformation.inVehicleTimeTotal_min = tripInformation.inVehicleTimeRail_min @@ -262,72 +262,132 @@ private static Departure findDeparture(TransitPassengerRoute passengerRoute, Tra } static public class Task { + @JsonProperty("identifier") public String identifier; + @JsonProperty("origin_x") public double originX; + + @JsonProperty("origin_y") public double originY; + @JsonProperty("destination_x") public double destinationX; + + @JsonProperty("destination_y") public double destinationY; + @JsonProperty("departure_time") public double departureTime; } static public class TripInformation { + @JsonProperty("identifier") public String identifier; + @JsonProperty("access_travel_time_min") public double accessTravelTime_min; + + @JsonProperty("access_distance_km") public double accessDistance_km; + @JsonProperty("egress_travel_time_min") public double egressTravelTime_min; + + @JsonProperty("egress_distance_km") public double egressDistance_km; + @JsonProperty("transfer_travel_time_min") public double transferTravelTime_min; + + @JsonProperty("transfer_distance_km") public double transferDistance_km; + @JsonProperty("total_walk_travel_time_min") public double totalWalkTravelTime_min; + + @JsonProperty("total_walk_distance_km") public double totalWalkDistance_km; + @JsonProperty("in_vehicle_time_rail_min") public double inVehicleTimeRail_min; + + @JsonProperty("in_vehicle_time_subway_min") public double inVehicleTimeSubway_min; + + @JsonProperty("in_vehicle_time_bus_min") public double inVehicleTimeBus_min; + + @JsonProperty("in_vehicle_time_tram_min") public double inVehicleTimeTram_min; + + @JsonProperty("in_vehicle_time_other_min") public double inVehicleTimeOther_min; + + @JsonProperty("in_vehicle_time_total_min") public double inVehicleTimeTotal_min; + @JsonProperty("in_vehicle_distance_rail_km") public double inVehicleDistanceRail_km; + + @JsonProperty("in_vehicle_distance_subway_km") public double inVehicleDistanceSubway_km; + + @JsonProperty("in_vehicle_distance_bus_km") public double inVehicleDistanceBus_km; + + @JsonProperty("in_vehicle_distance_tram_km") public double inVehicleDistanceTram_km; + + @JsonProperty("in_vehicle_distance_other_km") public double inVehicleDistanceOther_km; + + @JsonProperty("in_vehicle_distance_total_km") public double inVehicleDistanceTotal_km; + @JsonProperty("transfers") public int numberOfTransfers; + @JsonProperty("initial_waiting_time_min") public double initialWaitingTime_min; + + @JsonProperty("transfer_waiting_time_min") public double transferWaitingTime_min; + @JsonProperty("headway_min") public double headway_min; + @JsonProperty("is_only_walk") public int isOnlyWalk; - public String route; - TripInformation(Task task) { this.identifier = task.identifier; } } static public class LegInformation { + @JsonProperty("identifier") public String identifier; + + @JsonProperty("leg_index") public int legIndex; + @JsonProperty("line_id") public String lineId; + + @JsonProperty("route_id") public String routeId; + + @JsonProperty("vehicle_id") public String vehicleId; - public String mode; + @JsonProperty("transit_mode") + public String transitMode; + + @JsonProperty("access_time") public double accessTime; + + @JsonProperty("egress_time") public double egressTime; } } diff --git a/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java index ae33b457d..6ed4f91ff 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java @@ -19,6 +19,7 @@ import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime; import org.matsim.core.utils.geometry.CoordUtils; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.inject.Provider; public class BatchRoadRouter { @@ -126,24 +127,39 @@ public void run() { } static public class Task { + @JsonProperty("identifier") public String identifier; + @JsonProperty("origin_x") public double originX; + + @JsonProperty("origin_y") public double originY; + @JsonProperty("destination_x") public double destinationX; + + @JsonProperty("destination_y") public double destinationY; + @JsonProperty("departure_time") public double departureTime; } static public class Result { + @JsonProperty("identifier") public String identifier; + @JsonProperty("access_euclidean_distance_km") public double accessEuclideanDistance_km; + + @JsonProperty("egress_euclidean_distance_km") public double egressEuclideanDistance_km; + @JsonProperty("in_vehicle_time_min") public double inVehicleTime_min; + + @JsonProperty("in_vehicle_distance_km") public double inVehicleDistance_km; Result(Task task) { diff --git a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java index 9f61cfaf3..fc39573c3 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java @@ -3,10 +3,15 @@ import java.io.File; import java.io.IOException; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; import org.apache.commons.lang3.tuple.Pair; +import org.apache.log4j.Logger; import org.eqasim.core.components.headway.HeadwayCalculator; import org.eqasim.core.components.headway.HeadwayImputerModule; import org.eqasim.core.misc.InjectorBuilder; @@ -19,10 +24,19 @@ import org.matsim.core.config.CommandLine; import org.matsim.core.config.CommandLine.ConfigurationException; import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.ConfigWriter; +import org.matsim.core.config.groups.PlanCalcScoreConfigGroup.ModeParams; +import org.matsim.core.config.groups.PlansCalcRouteConfigGroup.ModeRoutingParams; +import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.pt.router.TransitRouter; +import org.matsim.pt.transitSchedule.api.TransitLine; +import org.matsim.pt.transitSchedule.api.TransitRoute; import org.matsim.pt.transitSchedule.api.TransitSchedule; +import org.matsim.pt.transitSchedule.api.TransitScheduleReader; +import org.matsim.vehicles.MatsimVehicleReader; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; @@ -33,31 +47,218 @@ import com.google.inject.Injector; import com.google.inject.Provider; +import ch.sbb.matsim.config.SwissRailRaptorConfigGroup; + public class RunBatchPublicTransportRouter { + private final static Logger logger = Logger.getLogger(RunBatchPublicTransportRouter.class); + static public void main(String[] args) throws ConfigurationException, JsonGenerationException, JsonMappingException, IOException, InterruptedException { CommandLine cmd = new CommandLine.Builder(args) // - .requireOptions("config-path", "input-path", "output-path") // - .allowOptions("threads", "batch-size", "interval", "transfer-utility", "output-legs-path") // + .requireOptions("config-path", "input-path") // + .allowOptions("threads", "batch-size", "interval", // + "transfer-utility", "waiting-utility", // + "direct-walk-factor", "maximum-transfer-distance", // + "walk-factor", "walk-speed", // + "output-trips-path", "output-legs-path", "output-config-path") // + .allowPrefixes("travel-utility") // .build(); EqasimConfigurator configurator = new EqasimConfigurator(); Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"), configurator.getConfigGroups()); cmd.applyConfiguration(config); + // No opportunity scoring + config.planCalcScore().setPerforming_utils_hr(0.0); + + if (config.planCalcScore().getPerforming_utils_hr() != 0.0) { + logger.warn("Setting opporunity cost to zero"); + } + + if (cmd.hasOption("maximum-transfer-distance")) { + config.transitRouter().setMaxBeelineWalkConnectionDistance( + Double.parseDouble(cmd.getOptionStrict("maximum-transfer-distance"))); + logger.info("Setting maximum transfer distance to " + + config.transitRouter().getMaxBeelineWalkConnectionDistance()); + } + + // Transfer utility if (cmd.hasOption("transfer-utility")) { config.planCalcScore().setUtilityOfLineSwitch(Double.parseDouble(cmd.getOptionStrict("transfer-utility"))); + logger.info("Setting transfer utility to " + config.planCalcScore().getUtilityOfLineSwitch()); + } + + // Waiting utility + if (cmd.hasOption("waiting-utility")) { + config.planCalcScore() + .setMarginalUtlOfWaitingPt_utils_hr(Double.parseDouble(cmd.getOptionStrict("waiting-utility"))); + logger.info("Setting waiting utility to " + config.planCalcScore().getMarginalUtlOfWaitingPt_utils_hr()); + } + + // Direct walk factor + if (cmd.hasOption("direct-walk-factor")) { + config.transitRouter().setDirectWalkFactor(Double.parseDouble(cmd.getOptionStrict("direct-walk-factor"))); + logger.info("Setting direct walk factor to " + config.transitRouter().getDirectWalkFactor()); + } + + // Walking + ModeRoutingParams walkRoutingParams = config.plansCalcRoute().getModeRoutingParams().get("walk"); + + if (cmd.hasOption("walk-factor")) { + walkRoutingParams.setBeelineDistanceFactor(Double.parseDouble(cmd.getOptionStrict("walk-factor"))); + logger.info("Setting walk factor to " + walkRoutingParams.getBeelineDistanceFactor()); + } + + if (cmd.hasOption("walk-speed")) { + walkRoutingParams.setTeleportedModeSpeed(Double.parseDouble(cmd.getOptionStrict("walk-speed"))); + logger.info("Setting walk speed to " + walkRoutingParams.getTeleportedModeSpeed()); } + // Load scenario to find transit modes Scenario scenario = ScenarioUtils.createScenario(config); configurator.configureScenario(scenario); - ScenarioUtils.loadScenario(scenario); + + // We only load network, schedule and transit vehicles + new MatsimNetworkReader(scenario.getNetwork()) + .readURL(ConfigGroup.getInputFileURL(config.getContext(), config.network().getInputFile())); + new TransitScheduleReader(scenario) + .readURL(ConfigGroup.getInputFileURL(config.getContext(), config.transit().getTransitScheduleFile())); + + if (config.transit().getVehiclesFile() != null) { + new MatsimVehicleReader(scenario.getTransitVehicles()) + .readURL(ConfigGroup.getInputFileURL(config.getContext(), config.transit().getVehiclesFile())); + } + + // Collect travel utilities + Set transitModes = new HashSet<>(); + for (TransitLine transitLine : scenario.getTransitSchedule().getTransitLines().values()) { + for (TransitRoute transitRoute : transitLine.getRoutes().values()) { + transitModes.add(transitRoute.getTransportMode()); + } + } + + Map utilities = new HashMap<>(); + + for (String option : cmd.getAvailableOptions()) { + if (option.startsWith("travel-utility:")) { + String[] parts = option.split(":"); + String mode = parts[1]; + utilities.put(mode, Double.parseDouble(cmd.getOptionStrict(option))); + } + } + + if (utilities.size() > 0) { + logger.info("Updating utilities"); + + Set modeSpecificTesting = new HashSet<>(); + modeSpecificTesting.addAll(utilities.keySet()); + modeSpecificTesting.remove("walk"); + modeSpecificTesting.remove("pt"); + + SwissRailRaptorConfigGroup srrConfig = (SwissRailRaptorConfigGroup) config.getModules() + .get(SwissRailRaptorConfigGroup.GROUP); + + if (modeSpecificTesting.size() == 0) { + // Not mode specific + logger.info("Setting up mode *un*specific routing"); + srrConfig.setUseModeMappingForPassengers(false); + + for (String mode : utilities.keySet()) { + ModeParams modeParameters = config.planCalcScore().getModes().get(mode); + modeParameters.setMarginalUtilityOfTraveling(utilities.get(mode)); + logger.info(String.format("Setting travel utility for %s to %f", mode, + modeParameters.getMarginalUtilityOfTraveling())); + } + } else { + logger.info("Setting up mode *specific* routing"); + srrConfig.setUseModeMappingForPassengers(true); + + Set availableModes = new HashSet<>(); + availableModes.addAll(transitModes); + availableModes.add("other"); + availableModes.add("walk"); + + for (String mode : utilities.keySet()) { + if (!availableModes.contains(mode)) { + throw new IllegalStateException("No need to set travel utility for mode: " + mode); + } + + ModeParams modeParameters = config.planCalcScore().getModes().get(mode); + + if (modeParameters == null) { + modeParameters = new ModeParams(mode); + modeParameters.setConstant(0.0); + modeParameters.setMarginalUtilityOfDistance(0.0); + modeParameters.setMonetaryDistanceRate(0.0); + config.planCalcScore().addModeParams(modeParameters); + } + + modeParameters.setMarginalUtilityOfTraveling(utilities.get(mode)); + logger.info(String.format("Setting travel utility for %s to %f", mode, + modeParameters.getMarginalUtilityOfTraveling())); + + SwissRailRaptorConfigGroup.ModeMappingForPassengersParameterSet mapping = null; + + for (var candidate : srrConfig.getModeMappingForPassengers()) { + if (candidate.getRouteMode().equals(mode)) { + mapping = candidate; + break; + } + } + + if (mapping == null) { + srrConfig.addModeMappingForPassengers( + new SwissRailRaptorConfigGroup.ModeMappingForPassengersParameterSet(mode, mode)); + } else { + mapping.setPassengerMode(mode); + } + } + + for (String mode : availableModes) { + ModeParams modeParameters = config.planCalcScore().getModes().get(mode); + + if (modeParameters == null) { + double utility = utilities.getOrDefault("other", -1.0); + + modeParameters = new ModeParams(mode); + modeParameters.setConstant(0.0); + modeParameters.setMarginalUtilityOfDistance(0.0); + modeParameters.setMonetaryDistanceRate(0.0); + modeParameters.setMarginalUtilityOfTraveling(utility); + config.planCalcScore().addModeParams(modeParameters); + + logger.info(String.format("Creating mode with travel utility for %s as %f", mode, + modeParameters.getMarginalUtilityOfTraveling())); + + srrConfig.addModeMappingForPassengers( + new SwissRailRaptorConfigGroup.ModeMappingForPassengersParameterSet(mode, mode)); + } + } + } + } + + /*-{ + RaptorParameters raptorParameters = RaptorUtils.createParameters(config); + + Scenario scenario; + + OccupancyData occupancyData = new OccupancyData(); + RaptorStaticConfig srrStaticConfig = RaptorUtils.createStaticConfig(config); + + SwissRailRaptorData srrData = SwissRailRaptorData.create(scenario.getTransitSchedule(), + scenario.getTransitVehicles(), srrStaticConfig, scenario.getNetwork(), occupancyData); + SwissRailRaptor raptor = new SwissRailRaptor.Builder(srrData, config).build(); + + }-*/ int numberOfThreads = cmd.getOption("threads").map(Integer::parseInt) .orElse(Runtime.getRuntime().availableProcessors()); int batchSize = cmd.getOption("batch-size").map(Integer::parseInt).orElse(100); double interval = (double) cmd.getOption("interval").map(Integer::parseInt).orElse(0); + Optional outputLegsPath = cmd.getOption("output-legs-path"); + Optional outputTripsPath = cmd.getOption("output-trips-path"); + Optional outputConfigPath = cmd.getOption("output-config-path"); Injector injector = new InjectorBuilder(scenario) // .addOverridingModules(configurator.getModules()) // @@ -69,7 +270,7 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera Network network = injector.getInstance(Network.class); BatchPublicTransportRouter batchRouter = new BatchPublicTransportRouter(routerProvider, - headwayCalculatorProvider, schedule, network, batchSize, numberOfThreads, interval); + headwayCalculatorProvider, schedule, network, batchSize, numberOfThreads, interval, transitModes); CsvMapper mapper = new CsvMapper(); @@ -85,8 +286,8 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera Collection tripResults = results.getLeft(); Collection legResults = results.getRight(); - { - File outputFile = new File(cmd.getOptionStrict("output-path")); + if (outputTripsPath.isPresent()) { + File outputFile = new File(outputTripsPath.get()); CsvSchema resultSchema = mapper.typedSchemaFor(TripInformation.class).withHeader().withColumnSeparator(','); SequenceWriter writer = mapper.writerWithTypedSchemaFor(TripInformation.class).with(resultSchema) @@ -102,5 +303,9 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera .writeValues(outputFile); writer.writeAll(legResults); } + + if (outputConfigPath.isPresent()) { + new ConfigWriter(config).write(outputConfigPath.get()); + } } } diff --git a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java index 2f9f530fd..4fa8736ee 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java @@ -3,8 +3,9 @@ import java.io.File; import java.io.IOException; import java.util.Collection; -import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eqasim.core.misc.InjectorBuilder; import org.eqasim.core.simulation.EqasimConfigurator; @@ -41,7 +42,7 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera IOException, InterruptedException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("config-path", "input-path", "output-path") // - .allowOptions("threads", "batch-size") // + .allowOptions("threads", "batch-size", "modes") // .build(); EqasimConfigurator configurator = new EqasimConfigurator(); @@ -56,6 +57,11 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera .orElse(Runtime.getRuntime().availableProcessors()); int batchSize = cmd.getOption("batch-size").map(Integer::parseInt).orElse(100); + Set modes = new HashSet<>(); + for (String mode : cmd.getOption("modes").orElse("car").split(",")) { + modes.add(mode); + } + Injector injector = new InjectorBuilder(scenario) // .addOverridingModules(configurator.getModules()) // .addOverridingModule(new AbstractModule() { @@ -68,7 +74,7 @@ public void install() { @Named("car") public Network provideCarNetwork(Network network) { Network carNetwork = NetworkUtils.createNetwork(); - new TransportModeNetworkFilter(network).filter(carNetwork, Collections.singleton("car")); + new TransportModeNetworkFilter(network).filter(carNetwork, modes); new NetworkCleaner().run(carNetwork); return carNetwork; }