From 9c92c4b6b07bf3b596d63574a100348036b10c6d Mon Sep 17 00:00:00 2001 From: rakow <rakow@users.noreply.github.com> Date: Tue, 28 May 2024 11:17:57 +0200 Subject: [PATCH 1/2] MATSim Application: Improve network params estimators (#3292) * adding todos for network param improvements * more flexible reference models * prepare capacity models, use the new predictor interface * handle nan values * Added hbs.py to calculate sapacity * implemented capacities from HBS * change parentheses * update calculation * update comments * also create features from link attributes * adding features useful for intersections * update features * handle non existing links * catch errors in sample network * round capacity * also round freespeed factor * use correct lane attribute * warn if number of lanes does not match * add more standard features * don't classify secondary roads as residential * use capacity bounds as in the old model * refactored, option to only decease existing values * fix calcCurvature bug * remove TODO * added curvature to hbs.py (only the structure, not the calculation) * calculate geh value for traffic counts * add capacities based on cuvature for landstrassen, add cuvature calculation --------- Co-authored-by: frievoe97 <friedrich.voelkers@me.com> --- .../traffic/CountComparisonAnalysis.java | 18 +- .../matsim/application/prepare/Predictor.java | 1 + .../prepare/network/SampleNetwork.java | 15 +- .../network/params/ApplyNetworkParams.java | 178 +++++++++---- .../network/params/EvalFreespeedParams.java | 11 +- .../network/params/FeatureRegressor.java | 24 +- .../network/params/FreespeedOptServer.java | 2 +- .../prepare/network/params/NetworkModel.java | 14 +- .../network/params/NetworkParamsOpt.java | 64 ++++- .../params/hbs/HBSMotorwayCapacity.java | 44 ++++ .../network/params/hbs/HBSNetworkParams.java | 31 +++ .../network/params/hbs/HBSRoadCapacity.java | 144 +++++++++++ .../params/ref/DecisionTreeParams.java | 2 +- .../params/ref/GermanyNetworkParams.java | 4 +- .../src/main/python/capacity/hbs.py | 234 ++++++++++++++++++ .../params/ApplyNetworkParamsTest.java | 1 - .../network/params/HBSNetworkParamsTest.java | 44 ++++ .../sumo/SumoNetworkFeatureExtractor.java | 104 +++++++- .../sumo/SumoNetworkFeatureExtractorTest.java | 81 ++++++ 19 files changed, 929 insertions(+), 87 deletions(-) create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSMotorwayCapacity.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSNetworkParams.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSRoadCapacity.java create mode 100644 contribs/application/src/main/python/capacity/hbs.py create mode 100644 contribs/application/src/test/java/org/matsim/application/prepare/network/params/HBSNetworkParamsTest.java create mode 100644 contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractorTest.java diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/CountComparisonAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/CountComparisonAnalysis.java index adc9a86f435..e0c02a41831 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/CountComparisonAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/CountComparisonAnalysis.java @@ -76,6 +76,16 @@ private static int[] sum(int[] a, int[] b) { return counts; } + /** + * Calculate the geh value for simulated and reference count + */ + private static double geh(double simulated, double observed) { + final double diff = simulated - observed; + final double sum = simulated + observed; + + return Math.sqrt(2 * diff * diff / sum); + } + @Override public Integer call() throws Exception { @@ -114,14 +124,16 @@ private Table writeOutput(Counts<Link> counts, Network network, VolumesAnalyzer StringColumn.create("road_type"), IntColumn.create("hour"), DoubleColumn.create("observed_traffic_volume"), - DoubleColumn.create("simulated_traffic_volume") + DoubleColumn.create("simulated_traffic_volume"), + DoubleColumn.create("geh") ); Table dailyTrafficVolume = Table.create(StringColumn.create("link_id"), StringColumn.create("name"), StringColumn.create("road_type"), DoubleColumn.create("observed_traffic_volume"), - DoubleColumn.create("simulated_traffic_volume") + DoubleColumn.create("simulated_traffic_volume"), + DoubleColumn.create("geh") ); for (Map.Entry<Id<Link>, MeasurementLocation<Link>> entry : counts.getMeasureLocations().entrySet()) { @@ -170,6 +182,7 @@ private Table writeOutput(Counts<Link> counts, Network network, VolumesAnalyzer row.setInt("hour", hour); row.setDouble("observed_traffic_volume", observedTrafficVolumeAtHour); row.setDouble("simulated_traffic_volume", simulatedTrafficVolumeAtHour); + row.setDouble("geh", geh(simulatedTrafficVolumeAtHour, observedTrafficVolumeAtHour)); } } else { // Get the daily values @@ -183,6 +196,7 @@ private Table writeOutput(Counts<Link> counts, Network network, VolumesAnalyzer row.setString("road_type", type); row.setDouble("observed_traffic_volume", observedTrafficVolumeByDay); row.setDouble("simulated_traffic_volume", simulatedTrafficVolumeByDay); + row.setDouble("geh", geh(simulatedTrafficVolumeByDay, observedTrafficVolumeByDay)); } DoubleColumn relError = dailyTrafficVolume.doubleColumn("simulated_traffic_volume") diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/Predictor.java b/contribs/application/src/main/java/org/matsim/application/prepare/Predictor.java index 460d1a41abe..473048a99ed 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/Predictor.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/Predictor.java @@ -11,6 +11,7 @@ public interface Predictor { /** * Predict value from given features. + * @return predicted value, maybe NaN if no prediction is possible. */ double predict(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories); diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java index 82a7a278e32..242667bec49 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java @@ -144,6 +144,10 @@ public Integer call() throws Exception { List<? extends Node> list = e.getValue(); + // for now only consider traffic lights + if (!e.getKey().equals("traffic_light")) + continue; + log.info("Sampling {} out of {} intersections for type {}", sample, list.size(), e.getKey()); for (int i = 0; i < sample && !list.isEmpty(); i++) { @@ -193,7 +197,7 @@ public Integer call() throws Exception { RandomizedTravelTime tt = new RandomizedTravelTime(rnd); - LeastCostPathCalculator router = createRandomizedRouter(network, tt); + LeastCostPathCalculator router = createRandomizedRouter(cityNetwork, tt); sampleCityRoutes(cityNetwork, router, tt, rnd); @@ -223,9 +227,16 @@ private void sampleCityRoutes(Network network, LeastCostPathCalculator router, R Link to = NetworkUtils.getNearestLink(network, dest); + // Links could be on the very edge so that nodes are outside the network + if (to == null || !network.getNodes().containsKey(link.getFromNode().getId()) || + !network.getNodes().containsKey(to.getToNode().getId())) { + i--; + continue; + } + LeastCostPathCalculator.Path path = router.calcLeastCostPath(link.getFromNode(), to.getToNode(), 0, null, null); - if (path.nodes.size() < 2) { + if (path == null || path.nodes.size() < 2) { i--; continue; } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java index deef01dfe5e..048e2fa81b7 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; -import it.unimi.dsi.fastutil.objects.Object2DoubleMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -14,12 +13,16 @@ import org.matsim.application.MATSimAppCommand; import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; +import org.matsim.application.prepare.Predictor; import org.matsim.application.prepare.network.params.NetworkParamsOpt.Feature; import org.matsim.core.network.NetworkUtils; import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; import java.io.BufferedReader; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; import java.util.Map; import java.util.Set; @@ -40,6 +43,7 @@ public class ApplyNetworkParams implements MATSimAppCommand { @CommandLine.Mixin private final OutputOptions output = OutputOptions.ofCommand(ApplyNetworkParams.class); + @CommandLine.Parameters(arity = "1..*", description = "Type of parameters to apply. Available: ${COMPLETION-CANDIDATES}") private Set<NetworkAttribute> params; @@ -52,6 +56,19 @@ public class ApplyNetworkParams implements MATSimAppCommand { @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower,upper bound)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) private double[] speedFactorBounds; + @CommandLine.Option(names = "--capacity-bounds", split = ",", defaultValue = "0.4,0.6,0.8", + description = "Minimum relative capacity against theoretical max (traffic light,right before left, priority)") + private List<Double> capacityBounds; + + @CommandLine.Option(names = "--road-types", split = ",", description = "Road types to apply changes to") + private Set<String> roadTypes; + + @CommandLine.Option(names = "--junction-types", split = ",", description = "Junction types to apply changes to") + private Set<String> junctionTypes; + + @CommandLine.Option(names = "--decrease-only", description = "Only set values if the are lower than the current value", defaultValue = "false") + private boolean decrease; + private NetworkModel model; private NetworkParams paramsOpt; @@ -62,14 +79,14 @@ public static void main(String[] args) { } /** - * Theoretical capacity. + * Theoretical capacity assuming fixed car length and headway. This should usually not be exceeded. */ - private static double capacityEstimate(double v) { + public static double capacityEstimate(double v) { // headway double tT = 1.2; - // car length + // car length + buffer double lL = 7.0; double Qc = v / (v * tT + lL); @@ -94,13 +111,19 @@ public Integer call() throws Exception { } } - Map<Id<Link>, Feature> features = NetworkParamsOpt.readFeatures(input.getPath("features.csv"), network.getLinks().size()); + Map<Id<Link>, Feature> features = NetworkParamsOpt.readFeatures(input.getPath("features.csv"), network.getLinks()); for (Link link : network.getLinks().values()) { Feature ft = features.get(link.getId()); + if (roadTypes != null && !roadTypes.isEmpty() && !roadTypes.contains(ft.highwayType())) + continue; + + if (junctionTypes != null && !junctionTypes.isEmpty() && !junctionTypes.contains(ft.junctionType())) + continue; + try { - applyChanges(link, ft.junctionType(), ft.features()); + applyChanges(link, ft); } catch (IllegalArgumentException e) { warn++; log.warn("Error processing link {}", link.getId(), e); @@ -117,67 +140,126 @@ public Integer call() throws Exception { /** * Apply speed and capacity models and apply changes. */ - private void applyChanges(Link link, String junctionType, Object2DoubleMap<String> features) { - - String type = NetworkUtils.getHighwayType(link); + private void applyChanges(Link link, Feature ft) { boolean modified = false; if (params.contains(NetworkAttribute.capacity)) { + modified = applyCapacity(link, ft); + } + + if (params.contains(NetworkAttribute.freespeed)) { + modified |= applyFreeSpeed(link, ft); + } - FeatureRegressor capacity = model.capacity(junctionType); + if (modified) + warn++; + } - double perLane = capacity.predict(features); + private boolean applyCapacity(Link link, Feature ft) { - double cap = capacityEstimate(features.getDouble("speed")); + Predictor capacity = model.capacity(ft.junctionType(), ft.highwayType()); + // No operation performed if not supported + if (capacity == null) { + return false; + } - // Minimum thresholds - double threshold = switch (junctionType) { - // traffic light can reduce capacity at least to 50% (with equal green split) - case "traffic_light" -> 0.4; - case "right_before_left" -> 0.6; - // Motorways are kept at their max theoretical capacity - case "priority" -> type.startsWith("motorway") ? 1 : 0.8; - default -> 0; - }; + double perLane = capacity.predict(ft.features(), ft.categories()); + if (Double.isNaN(perLane)) { + return true; + } - if (perLane < cap * threshold) { - log.warn("Increasing capacity per lane on {} ({}, {}) from {} to {}", link.getId(), type, junctionType, perLane, cap * threshold); - perLane = cap * threshold; - modified = true; - } + double cap = capacityEstimate(ft.features().getDouble("speed")); - link.setCapacity(link.getNumberOfLanes() * perLane); + if (capacityBounds.isEmpty()) + capacityBounds.add(0.0); + + // Fill up to 3 elements if not provided + if (capacityBounds.size() < 3) { + capacityBounds.add(capacityBounds.get(0)); + capacityBounds.add(capacityBounds.get(1)); } + // Minimum thresholds + double threshold = switch (ft.junctionType()) { + case "traffic_light" -> capacityBounds.get(0); + case "right_before_left" -> capacityBounds.get(1); + case "priority" -> capacityBounds.get(2); + default -> 0; + }; - if (params.contains(NetworkAttribute.freespeed)) { + boolean modified = false; - double speedFactor = 1.0; - FeatureRegressor speedModel = model.speedFactor(junctionType); + if (perLane < cap * threshold) { + log.warn("Increasing capacity per lane on {} ({}, {}) from {} to {}", + link.getId(), ft.highwayType(), ft.junctionType(), perLane, cap * threshold); + perLane = cap * threshold; + modified = true; + } - speedFactor = paramsOpt != null ? - speedModel.predict(features, paramsOpt.getParams(junctionType)) : - speedModel.predict(features); + if (perLane > cap) { + log.warn("Reducing capacity per lane on {} ({}, {}) from {} to {}", + link.getId(), ft.highwayType(), ft.junctionType(), perLane, cap); + perLane = cap; + modified = true; + } - if (speedFactor > speedFactorBounds[1]) { - log.warn("Reducing speed factor on {} from {} to {}", link.getId(), speedFactor, speedFactorBounds[1]); - speedFactor = speedFactorBounds[1]; - modified = true; - } + if (ft.features().getOrDefault("num_lanes", link.getNumberOfLanes()) != link.getNumberOfLanes()) + log.warn("Number of lanes for link {} does not match the feature file", link.getId()); - // Threshold for very low speed factors - if (speedFactor < speedFactorBounds[0]) { - log.warn("Increasing speed factor on {} from {} to {}", link, speedFactor, speedFactorBounds[0]); - speedFactor = speedFactorBounds[0]; - modified = true; - } + int totalCap = BigDecimal.valueOf(link.getNumberOfLanes() * perLane).setScale(0, RoundingMode.HALF_UP).intValue(); + + if (decrease && totalCap > link.getCapacity()) + return false; + + link.setCapacity(totalCap); + + return modified; + } + + private boolean applyFreeSpeed(Link link, Feature ft) { - link.setFreespeed((double) link.getAttributes().getAttribute("allowed_speed") * speedFactor); - link.getAttributes().putAttribute("speed_factor", speedFactor); + Predictor speedModel = model.speedFactor(ft.junctionType(), ft.highwayType()); + + // No operation performed if not supported + if (speedModel == null) { + return false; } - if (modified) - warn++; + double speedFactor = paramsOpt != null ? + speedModel.predict(ft.features(), ft.categories(), paramsOpt.getParams(ft.junctionType())) : + speedModel.predict(ft.features(), ft.categories()); + + if (Double.isNaN(speedFactor)) { + return false; + } + + boolean modified = false; + + if (speedFactor > speedFactorBounds[1]) { + log.warn("Reducing speed factor on {} from {} to {}", link.getId(), speedFactor, speedFactorBounds[1]); + speedFactor = speedFactorBounds[1]; + modified = true; + } + + // Threshold for very low speed factors + if (speedFactor < speedFactorBounds[0]) { + log.warn("Increasing speed factor on {} from {} to {}", link, speedFactor, speedFactorBounds[0]); + speedFactor = speedFactorBounds[0]; + modified = true; + } + + double freeSpeed = (double) link.getAttributes().getAttribute("allowed_speed") * speedFactor; + + freeSpeed = BigDecimal.valueOf(freeSpeed).setScale(3, RoundingMode.HALF_EVEN).doubleValue(); + + if (decrease && freeSpeed > link.getFreespeed()) + return false; + + link.setFreespeed(freeSpeed); + link.getAttributes().putAttribute("speed_factor", freeSpeed); + + return modified; } + } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java index 014d2615549..cd2ba4e016a 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java @@ -18,6 +18,7 @@ import org.matsim.application.analysis.traffic.traveltime.SampleValidationRoutes; import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; +import org.matsim.application.prepare.Predictor; import org.matsim.contrib.osm.networkReader.LinkProperties; import org.matsim.core.network.NetworkUtils; import picocli.CommandLine; @@ -104,7 +105,7 @@ static Result applyAndEvaluateParams( continue; } - FeatureRegressor speedModel = model.speedFactor(ft.junctionType()); + Predictor speedModel = model.speedFactor(ft.junctionType(), ft.highwayType()); if (speedModel == null) { link.setFreespeed(allowedSpeed); @@ -115,15 +116,15 @@ static Result applyAndEvaluateParams( if (request.hasParams()) { double[] p = request.getParams(ft.junctionType()); - speedFactor = speedModel.predict(ft.features(), p); + speedFactor = speedModel.predict(ft.features(), ft.categories(), p); } else - speedFactor = speedModel.predict(ft.features()); + speedFactor = speedModel.predict(ft.features(), ft.categories()); // apply lower and upper bound speedFactor = Math.max(speedFactorBounds[0], speedFactor); speedFactor = Math.min(speedFactorBounds[1], speedFactor); - attributes.put(link.getId(), speedModel.getData(ft.features())); + attributes.put(link.getId(), speedModel.getData(ft.features(), ft.categories())); link.setFreespeed(allowedSpeed * speedFactor); link.getAttributes().putAttribute("speed_factor", speedFactor); @@ -151,7 +152,7 @@ public Integer call() throws Exception { mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); validationSet = readValidation(validationFiles, refHours); - features = readFeatures(input.getPath("features.csv"), network.getLinks().size()); + features = readFeatures(input.getPath("features.csv"), network.getLinks()); CSVPrinter csv; Path out = output.getPath("eval.csv"); diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java index 051135e89b6..cade7eb1693 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java @@ -1,11 +1,15 @@ package org.matsim.application.prepare.network.params; import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import org.matsim.application.prepare.Predictor; /** * Predictor interface for regression. + * @deprecated Use {@link Predictor} instead. */ -public interface FeatureRegressor { +@Deprecated +public interface FeatureRegressor extends Predictor { /** @@ -28,4 +32,22 @@ default double[] getData(Object2DoubleMap<String> ft) { throw new UnsupportedOperationException("Not implemented"); } + default double predict(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories) { + return predict(features); + } + + /** + * Predict values with adjusted model params. + */ + default double predict(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories, double[] params) { + return predict(features, params); + } + + /** + * Return data that is used for internal prediction function (normalization already applied). + */ + default double[] getData(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories) { + return getData(features); + } + } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java index 387824839f4..fef19850305 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java @@ -102,7 +102,7 @@ public Integer call() throws Exception { } validationSet = NetworkParamsOpt.readValidation(validationFiles, refHours); - features = NetworkParamsOpt.readFeatures(input.getPath("features.csv"), network.getLinks().size()); + features = NetworkParamsOpt.readFeatures(input.getPath("features.csv"), network.getLinks()); log.info("Initial score:"); applyAndEvaluateParams(null, "init"); diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java index f98bb9bd41e..f88c4183c58 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java @@ -1,22 +1,24 @@ package org.matsim.application.prepare.network.params; +import org.matsim.application.prepare.Predictor; + /** * A model for estimating network parameters. */ public interface NetworkModel { /** - * Flow Capacity (per lane) + * Flow Capacity (per lane). */ - default FeatureRegressor capacity(String junctionType) { - return null; + default Predictor capacity(String junctionType, String highwayType) { + throw new UnsupportedOperationException("Capacity model not implemented for class: " + getClass().getName()); } /** - * Speed factor (relative to free flow speed). + * Speed factor (relative to allowed speed). */ - default FeatureRegressor speedFactor(String junctionType) { - return null; + default Predictor speedFactor(String junctionType, String highwayType) { + throw new UnsupportedOperationException("Speed factor model not implemented for class: " + getClass().getName()); } } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java index 2c69e7c6498..e9185fc7a0f 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java @@ -4,6 +4,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2DoubleMap; import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVPrinter; @@ -15,6 +17,7 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.network.Node; import org.matsim.application.analysis.traffic.traveltime.SampleValidationRoutes; +import org.matsim.core.network.NetworkUtils; import org.matsim.core.router.DijkstraFactory; import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility; import org.matsim.core.router.util.LeastCostPathCalculator; @@ -55,9 +58,14 @@ static NetworkModel load(Class<? extends NetworkModel> modelClazz) { /** * Read network edge features from csv. */ - static Map<Id<Link>, Feature> readFeatures(String input, int expectedLinks) throws IOException { + static Map<Id<Link>, Feature> readFeatures(String input, Map<Id<Link>, ? extends Link> links) throws IOException { - Map<Id<Link>, Feature> features = new IdMap<>(Link.class, expectedLinks); + Map<Id<Link>, Feature> features = new IdMap<>(Link.class, links.size()); + + // Create features from link attributes + for (Link link : links.values()) { + features.put(link.getId(), createDefaultFeature(link)); + } try (CSVParser reader = new CSVParser(IOUtils.getBufferedReader(input), CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).build())) { @@ -67,27 +75,65 @@ static Map<Id<Link>, Feature> readFeatures(String input, int expectedLinks) thro for (CSVRecord row : reader) { Id<Link> id = Id.createLinkId(row.get("linkId")); - - Object2DoubleOpenHashMap<String> ft = new Object2DoubleOpenHashMap<>(); - ft.defaultReturnValue(Double.NaN); + Link link = links.get(id); + Feature ft = features.computeIfAbsent(id, (k) -> createDefaultFeature(link)); for (String column : header) { String v = row.get(column); try { - ft.put(column, Double.parseDouble(v)); + ft.features.put(column, Double.parseDouble(v)); } catch (NumberFormatException e) { // every not equal to True will be false - ft.put(column, Boolean.parseBoolean(v) ? 1 : 0); + ft.features.put(column, Boolean.parseBoolean(v) ? 1 : 0); + ft.categories.put(column, v); } } - features.put(id, new Feature(row.get("junction_type"), ft)); + String highwayType = header.contains(NetworkUtils.TYPE) ? row.get(NetworkUtils.TYPE) : + (link != null ? NetworkUtils.getHighwayType(link) : null); + + features.put(id, new Feature(row.get("junction_type").intern(), highwayType, ft.features, ft.categories)); } } return features; } + /** + * Create default feature based on link attributes. + */ + private static Feature createDefaultFeature(Link link) { + Object2DoubleOpenHashMap<String> ft = new Object2DoubleOpenHashMap<>(); + ft.defaultReturnValue(Double.NaN); + Object2ObjectMap<String, String> categories = new Object2ObjectOpenHashMap<>(); + + // Link might not be present in the network + if (link == null) + return new Feature("", "", ft, categories); + + String highwayType = NetworkUtils.getHighwayType(link); + categories.put("highway_type", highwayType); + ft.put("speed", NetworkUtils.getAllowedSpeed(link)); + ft.put("num_lanes", link.getNumberOfLanes()); + ft.put("length", link.getLength()); + ft.put("capacity", link.getCapacity()); + ft.put("freespeed", link.getFreespeed()); + + for (Map.Entry<String, Object> e : link.getAttributes().getAsMap().entrySet()) { + String key = e.getKey(); + Object value = e.getValue(); + if (value instanceof Number) { + ft.put(key, ((Number) value).doubleValue()); + } else if (value instanceof Boolean) { + ft.put(key, (Boolean) value ? 1 : 0); + } else { + categories.put(key, value.toString()); + } + } + + return new Feature("", highwayType, ft, categories); + } + /** * Read validation files and calc target speed. */ @@ -170,7 +216,7 @@ static Result evaluate(Network network, Object2DoubleMap<SampleValidationRoutes. return new Result(rmse.getMean(), mse.getMean(), data); } - record Feature(String junctionType, Object2DoubleMap<String> features) { + record Feature(String junctionType, String highwayType, Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories) { } record Result(double rmse, double mae, Map<String, List<Data>> data) { diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSMotorwayCapacity.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSMotorwayCapacity.java new file mode 100644 index 00000000000..4a8bb92e219 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSMotorwayCapacity.java @@ -0,0 +1,44 @@ +package org.matsim.application.prepare.network.params.hbs; + +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import org.matsim.application.prepare.Predictor; + +/** + * Capacity for motorways. + */ +public class HBSMotorwayCapacity implements Predictor { + @Override + public double predict(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories) { + + // speed in km/h + int speed = (int) Math.round(features.getDouble("speed") * 3.6); + int lanes = (int) features.getOrDefault("num_lanes", 1); + + // Capacity for 1 lane motorways is not defined in HBS + double capacity = 2000; + if (lanes == 2) { + if (speed >= 130) + capacity = 3700.0; + else if (speed >= 120) + capacity = 3800; + else + capacity = 3750; + } else if (lanes == 3) { + if (speed >= 130) + capacity = 5300; + else if (speed >= 120) + capacity = 5400; + else + capacity = 5350; + } else if (lanes >= 4) { + if (speed >= 130) + capacity = 7300; + else + capacity = 7400; + } + + // Return capacity per lane + return capacity / lanes; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSNetworkParams.java new file mode 100644 index 00000000000..faff8379a3c --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSNetworkParams.java @@ -0,0 +1,31 @@ +package org.matsim.application.prepare.network.params.hbs; + +import org.matsim.application.prepare.Predictor; +import org.matsim.application.prepare.network.params.NetworkModel; + +/** + * Capacity params calculated according to + * "Handbuch für die Bemessung von Straßenverkehrsanlagen“ (HBS) + */ +public class HBSNetworkParams implements NetworkModel { + + private static final Predictor MOTORWAY = new HBSMotorwayCapacity(); + private static final Predictor ROAD = new HBSRoadCapacity(); + + @Override + public Predictor capacity(String junctionType, String highwayType) { + + // Traffic lights are not considered + if (junctionType.equals("traffic_light")) { + return null; + } + + if (highwayType.startsWith("motorway")) { + return MOTORWAY; + } + + // All lower category roads + return ROAD; + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSRoadCapacity.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSRoadCapacity.java new file mode 100644 index 00000000000..3e07362db8f --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/hbs/HBSRoadCapacity.java @@ -0,0 +1,144 @@ +package org.matsim.application.prepare.network.params.hbs; + +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import org.matsim.application.prepare.Predictor; + +/** + * Capacity for general roads, that are not motorways or residential roads. + */ +public class HBSRoadCapacity implements Predictor { + /** + * Capacity on "Landstraße", often osm secondary. These numbers are taken from the HBS (see contribs/application/src/main/python/capacity/hbs.py) + */ + private static double capacityLandStr(int lanes, int curvature) { + + + if (lanes == 1) { + if (curvature == 1) return 1369.532383465354; + + if (curvature == 2) return 1117.1498589355958; + + if (curvature == 3) return 1048.5840399296935; + + if (curvature == 4) return 956.0314100959505; + } + + if (lanes == 2) return 1956.6719999999998; + + + // Own assumption of increasing capacity with more lanes + // This is not covered by the HBS and is a very rare case + return (1956.6719999999998 * 1.3) / lanes; + } + + /** + * Bundesstraße with at least 70km/h, often osm primary or trunk + */ + private static double capacityBundesStr(int lanes) { + + if (lanes == 1) + return 2033.868926820213; + + if (lanes == 2) + return 3902.4390243902435 / 2; + + return (3902.4390243902435 * 1.3) / lanes; + } + + /** + * Capacity on a side road merging into a main road at a junction. + * + * @param qP the vehicle volume of the main road + */ + private static double capacityMerging(double qP) { + + // See HBS page 5-20, eq. S5-12 table S5-5 + + // mean Folgezeitlücken of the different combinations + double tf = 3.5; + + // mean Grenzzeitlücke + double tg = 6.36; + + + return Math.exp((-qP / 3600) * (tg - tf / 2)) * 3600 / tf; + } + + private static int curvatureCategory(double length, double curvature) { + + // for too short segment, curvature is not relevant + if (length < 50 || curvature == 0) + return 1; + + double sumChanges = curvature * (length / 1000); + + // Scale length of segment to at least 300m, because the manual recommends at least a certain segment length + double ku = sumChanges / Math.max(0.3, length / 1000); + + if (ku > 150) + return 4; + if (ku > 100) + return 3; + if (ku > 50) + return 2; + return 1; + + } + + /** + * Capacity of a side road of type merging into a main road. + * + * @param roadType type of the target road + * @param mainType type of the higher priority road + */ + private static double capacityMerging(String roadType, String mainType) { + + if (mainType.equals("trunk") || mainType.equals("primary") || roadType.contains("residential")) + // ~600 veh/h + return capacityMerging(600); + + // ~800 veh/h + return capacityMerging(400); + } + + @Override + public double predict(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories) { + + // Speed in km/h + int speed = (int) Math.round(features.getDouble("speed") * 3.6); + int lanes = (int) features.getOrDefault("num_lanes", 1); + int curvature = curvatureCategory(features.getDouble("length"), features.getOrDefault("curvature", 0)); + String type = categories.get("highway_type"); + + // Primary and trunk roads are often Bundesstraßen, + // but only if they have a speed limit of 70 or more, this calculation is valid + // From OSM alone it is not possible to distinguish anbaufreie Hauptverkehrsstraßen and Landstraße clearly + if (speed >= 90 || ((type.contains("primary") || type.contains("trunk")) && speed >= 70)) { + return capacityBundesStr(lanes); + } else if (speed >= 70) { + return capacityLandStr(lanes, curvature); + } + + String merging = categories.get("is_merging_into"); + + // Only merging with a single lane road is considered + if (!merging.isEmpty() && lanes == 1) { + return capacityMerging(type, merging); + } + + // Capacity for city roads + if (speed >= 40 || lanes >= 2 || features.getDouble("is_secondary_or_higher") == 1) { + return switch (lanes) { + case 1 -> 1139.0625; + case 2 -> 2263.438914027149 / 2; + // Own assumption, rare edge-case + default -> 2263.438914027149 * 1.3 / lanes; + }; + } + + // Remaining are residential which are assumed to have high urbanisation + return 800.0 / lanes; + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java index 4bb84fa6577..7dab8d49135 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java @@ -18,7 +18,7 @@ public final class DecisionTreeParams implements NetworkModel { private static final FeatureRegressor INSTANCE = new Model(); @Override - public FeatureRegressor speedFactor(String junctionType) { + public FeatureRegressor speedFactor(String junctionType, String highwayType) { return INSTANCE; } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java index ffe7250b2f4..80541a82a7e 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java @@ -9,7 +9,7 @@ */ public final class GermanyNetworkParams implements NetworkModel { @Override - public FeatureRegressor capacity(String junctionType) { + public FeatureRegressor capacity(String junctionType, String highwayType) { return switch (junctionType) { case "traffic_light" -> GermanyNetworkParams_capacity_traffic_light.INSTANCE; case "right_before_left" -> GermanyNetworkParams_capacity_right_before_left.INSTANCE; @@ -19,7 +19,7 @@ public FeatureRegressor capacity(String junctionType) { } @Override - public FeatureRegressor speedFactor(String junctionType) { + public FeatureRegressor speedFactor(String junctionType, String highwayType) { return switch (junctionType) { case "traffic_light" -> GermanyNetworkParams_speedRelative_traffic_light.INSTANCE; case "right_before_left" -> GermanyNetworkParams_speedRelative_right_before_left.INSTANCE; diff --git a/contribs/application/src/main/python/capacity/hbs.py b/contribs/application/src/main/python/capacity/hbs.py new file mode 100644 index 00000000000..aad41f1a45e --- /dev/null +++ b/contribs/application/src/main/python/capacity/hbs.py @@ -0,0 +1,234 @@ +import math +import matplotlib.pyplot as plt +import plotly.graph_objects as go + + +def capacity_estimate(v): + # headway + tT = 1.2 + # car length + lL = 7.0 + Qc = v / (v * tT + lL) + return 3600 * Qc + + +def merge(qp=400): + tf = 3.5 + tg = 6.36 + return math.exp((-qp / 3600) * (tg - tf / 2)) * 3600 / tf + + +class Street: + def __init__(self, osm_type, lanes, speed, curvature): + self.osm_type = osm_type + self.lanes = lanes + self.speed = speed + self.curvature = curvature + + +def calc_capacity_stadtstrasse(street): + # Source: HSB S3 + k = 0 + a = 54 + b = 0.850 + + if street.lanes == 1: + f = 1.0 + # Assume middle-high "Erschließungsintensität" + if street.speed == 30: + k = 45 + a = 38 + b = 0.715 + elif street.speed == 50: + k = 45 + a = 54 + b = 0.850 + elif street.speed == 70: + k = 40 + a = 89 + b = 0.846 + + return (-1.0 * b * math.pow(k, 3 / 2) * math.sqrt(4 * a * f + b * b * k) + 2 * a * f * k + b * b * k * k) / ( + 2 * f * f) + elif street.lanes == 2: + f = 0.7 + if street.speed == 50: + k = 45 + a = -0.009 + b = 55.58 + elif street.speed == 70: + f = 0.5 + k = 40 + a = -0.008 + b = 80 + + return (b * k) / (f - a * k) + + +def calc_capacity_landstrasse(street): + # Source: HSB table L3-4 + if street.lanes == 1: + k = 20 + + a = 0 + b = 0 + + # Table L3-4 + if street.curvature == 1: + a = 98.73 + b = 0.8175 + elif street.curvature == 2: + a = 83.88 + b = 0.8384 + elif street.curvature == 3: + a = 74.41 + b = 0.6788 + elif street.curvature == 4: + a = 68.02 + b = 0.6539 + else: + raise ValueError(f"Unknown curvature {street.curvature}") + + return 0.5 * (-b * math.pow(k, 3 / 2) * math.sqrt(4 * a + b * b * k) + 2 * a * k + b * b * k * k) + if street.lanes == 2: + k = 48 + a = 55.5 + b = -0.614 + + # Divide by 2 because the formula is for both directions + return k * (2 * a + b * k) / 2 + + +def calc_capacity_autobahn(street): + # Source: HSB A3 + anzahl_fahrstreifen = 1 + if street.lanes <= 2: + if street.speed >= 130: + return 3700 / anzahl_fahrstreifen + elif street.speed == 120: + return 3800 / anzahl_fahrstreifen + elif street.speed <= 120: + return 3750 / anzahl_fahrstreifen + elif street.lanes == 3: + if street.speed >= 130: + return 5300 / anzahl_fahrstreifen + elif street.speed == 120: + return 5400 / anzahl_fahrstreifen + elif street.speed <= 120: + return 5350 / anzahl_fahrstreifen + else: + if street.speed >= 130: + return 7300 / anzahl_fahrstreifen + elif street.speed == 120: + return 7400 / anzahl_fahrstreifen + elif street.speed <= 120: + return 7400 / anzahl_fahrstreifen + + +osm_types = { + 'residential': 'Stadtstraßen', + 'unclassified': 'Landstraßen', + 'motorway': 'Autobahnen' +} + +speeds = [30, 50, 70, 80, 90, 100, 120, 130] +curvatures = [1, 2, 3, 4] + +capacities = {} +streets = [] + +for osm_type, street_type in osm_types.items(): + capacities[osm_type] = {} + for lanes in range(1, 5): + capacities[osm_type][lanes] = {} + for curvature in curvatures: + capacities[osm_type][lanes][curvature] = {} + for speed in speeds: + if (osm_type == 'residential' and speed > 70) or (osm_type == 'residential' and speed < 30) or ( + osm_type == 'residential' and lanes > 2): + continue + if (osm_type == 'unclassified' and speed > 100) or (osm_type == 'unclassified' and speed <= 50) or ( + osm_type == 'unclassified' and lanes > 2): + continue + if (osm_type == 'motorway' and lanes == 1) or (osm_type == 'motorway' and speed < 80): + continue + street = Street(osm_type, lanes, speed, curvature) + streets.append(street) + capacities[osm_type][lanes][curvature][speed] = 0 + +for street in streets: + capacity = 0 + if street.osm_type == 'residential': + capacity = calc_capacity_stadtstrasse(street) + elif street.osm_type == 'motorway': + capacity = calc_capacity_autobahn(street) + else: + capacity = calc_capacity_landstrasse(street) + capacities[street.osm_type][street.lanes][street.curvature][street.speed] = capacity + +for street_type, lanes_capacity in capacities.items(): + for lanes, speeds_capacity in lanes_capacity.items(): + print(f"{osm_types[street_type]}, Fahrstreifen: {lanes}:") + for curvature, capacity in speeds_capacity.items(): + for speed, capacity in capacity.items(): + print(f"Geschwindigkeit {speed} km/h: Kurvigkeit {curvature} Verkehrskapazität {capacity} ") + +plt.figure(figsize=(14, 10)) +for street_type, lanes_capacity in capacities.items(): + for lanes, speeds_capacity in lanes_capacity.items(): + for curvature, capacity in speeds_capacity.items(): + plt.plot(list(capacity.keys()), list(capacity.values()), + label=f"{osm_types[street_type]}, Fahrstreifen: {lanes} Kurvigkeit: {curvature}") + +# plt.figure(figsize=(14, 10)) +# for street_type, lanes_capacity in capacities.items(): +# for lanes, speeds_capacity in lanes_capacity.items(): +# for speed, curvatures_capacity in speeds_capacity.items(): +# for curvature, capacity in curvatures_capacity.items(): +# plt.plot(speed, capacity, +# label=f"{osm_types[street_type]}, Fahrstreifen: {lanes}, Kurvigkeit: {curvature}") + +speeds_compare = [] +capacity_compare = [] +for v in range(30, 130, 10): + speeds_compare.append(v) + capacity_compare.append(capacity_estimate(v)) +plt.plot(speeds_compare, capacity_compare, label="Referenz") + +plt.xlabel('Geschwindigkeit (km/h)') +plt.ylabel('Verkehrskapazität') +plt.title('Verkehrskapazität nach Straßentyp, Fahrstreifen und Geschwindigkeit') +plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.2), fancybox=True, ncol=4) +plt.subplots_adjust(bottom=0.3) +plt.show() + +# fig = go.Figure() +# +# for street_type, lanes_capacity in capacities.items(): +# for lanes, speeds_capacity in lanes_capacity.items(): +# fig.add_trace(go.Scatter(x=list(speeds_capacity.keys()), y=list(speeds_capacity.values()), +# mode='lines', +# name=f"{osm_types[street_type]}, Fahrstreifen: {lanes}")) +# +# speeds_compare = [] +# capacity_compare = [] +# for v in range(50, 140, 10): +# speeds_compare.append(v) +# capacity_compare.append(capacity_estimate(v)) +# fig.add_trace(go.Scatter(x=speeds_compare, y=capacity_compare, mode='lines', showlegend=True, name="REFERENZ")) +# +# for qp in (0, 200, 400, 600): +# kontenpunkt_y = [] +# kontenpunkt_y.append(merge(qp)) +# kontenpunkt_y.append(merge(qp)) +# fig.add_trace(go.Scatter(x=(30, 50), y=kontenpunkt_y, mode='lines', showlegend=True, name="Knotenpunkt %d" % qp)) +# +# fig.update_layout( +# title='Verkehrskapazität nach Straßentyp, Fahrstreifen und Geschwindigkeit', +# xaxis_title='Geschwindigkeit (km/h)', +# yaxis_title='Verkehrskapazität', +# legend=dict(x=0.5, y=-0.2, orientation='h'), +# margin=dict(b=100) +# ) +# +# fig.show() diff --git a/contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java b/contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java index b25737d6c40..e9f723d6db8 100644 --- a/contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java +++ b/contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java @@ -40,6 +40,5 @@ void apply() throws Exception { ); assertThat(output.resolve("network-opt.xml")).exists(); - } } diff --git a/contribs/application/src/test/java/org/matsim/application/prepare/network/params/HBSNetworkParamsTest.java b/contribs/application/src/test/java/org/matsim/application/prepare/network/params/HBSNetworkParamsTest.java new file mode 100644 index 00000000000..ab6172db208 --- /dev/null +++ b/contribs/application/src/test/java/org/matsim/application/prepare/network/params/HBSNetworkParamsTest.java @@ -0,0 +1,44 @@ +package org.matsim.application.prepare.network.params; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.contrib.sumo.SumoNetworkConverter; +import org.matsim.testcases.MatsimTestUtils; + +import java.nio.file.Path; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class HBSNetworkParamsTest { + + @RegisterExtension + MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + void apply() throws Exception { + + Path networkPath = Path.of(utils.getPackageInputDirectory()).resolve("osm.net.xml"); + + Path output = Path.of(utils.getOutputDirectory()); + + SumoNetworkConverter converter = SumoNetworkConverter.newInstance(List.of(networkPath), + output.resolve("network.xml"), + "EPSG:4326", "EPSG:4326"); + + converter.call(); + + assertThat(output.resolve("network.xml")).exists(); + assertThat(output.resolve("network-ft.csv")).exists(); + + new ApplyNetworkParams().execute( + "capacity", + "--network", output.resolve("network.xml").toString(), + "--input-features", output.resolve("network-ft.csv").toString(), + "--output", output.resolve("network-hbs.xml").toString(), + "--model", "org.matsim.application.prepare.network.params.hbs.HBSNetworkParams" + ); + + assertThat(output.resolve("network-hbs.xml")).exists(); + } +} diff --git a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java index 7bf1154bf2d..ee8c9a45b87 100644 --- a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java +++ b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java @@ -1,5 +1,7 @@ package org.matsim.contrib.sumo; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.apache.commons.csv.CSVPrinter; import org.matsim.contrib.osm.networkReader.LinkProperties; @@ -28,7 +30,7 @@ class SumoNetworkFeatureExtractor { incomingEdges = new HashMap<>(); for (SumoNetworkHandler.Edge edge : this.handler.edges.values()) { - incomingEdges.computeIfAbsent(edge.to, (k) -> new ArrayList<>()) + incomingEdges.computeIfAbsent(edge.to, k -> new ArrayList<>()) .add(edge); } } @@ -77,6 +79,60 @@ private static Set<Character> directionSet(SumoNetworkHandler.Connection c) { return set; } + /** + * Calculate the curvature of an edge. One gon is 1/400 of a full circle. + * The formula is: KU = (Sum of the curvature of the subsegments) / (Length of the edge) + * + * @return curvature in gon/km + */ + static double calcCurvature(SumoNetworkHandler.Edge edge) { + double totalGon = 0; + List<double[]> coordinates = edge.shape; + + for (int i = 2; i < coordinates.size(); i++) { + double[] pointA = coordinates.get(i - 2); + double[] pointB = coordinates.get(i - 1); + double[] pointC = coordinates.get(i); + + double[] vectorAB = {pointB[0] - pointA[0], pointB[1] - pointA[1]}; + double[] vectorBC = {pointC[0] - pointB[0], pointC[1] - pointB[1]}; + + double dotProduct = calcDotProduct(vectorAB, vectorBC); + double magnitudeAB = calcMagnitude(vectorAB); + double magnitudeBC = calcMagnitude(vectorBC); + + double cosine = dotProduct / (magnitudeAB * magnitudeBC); + double angleRadians = Math.acos(cosine); + double angleDegrees = Math.toDegrees(angleRadians); + + totalGon += Math.abs((angleDegrees / 360) * 400); + } + + return totalGon / (edge.getLength() / 1000); + } + + /** + * Calculate the dot product of two vectors. + * + * @param vec1 vector 1 + * @param vec2 vector 2 + * @return dot product + */ + private static double calcDotProduct(double[] vec1, double[] vec2) { + return vec1[0] * vec2[0] + vec1[1] * vec2[1]; + } + + /** + * Calculate the magnitude of a vector. + * + * @param vec vector + * @return magnitude + */ + private static double calcMagnitude(double[] vec) { + return Math.sqrt(vec[0] * vec[0] + vec[1] * vec[1]); + } + + /** * Get priority. Higher is more important. */ @@ -86,9 +142,12 @@ private int getPrio(SumoNetworkHandler.Edge edge) { public List<String> getHeader() { return List.of("linkId", "highway_type", "speed", "length", "num_lanes", "change_num_lanes", "change_speed", "num_to_links", "num_conns", - "num_response", "num_foes", "dir_multiple_s", "dir_l", "dir_r", "dir_s", "dir_exclusive", + "num_response", "num_foes", "dir_multiple_s", "dir_l", "dir_r", "dir_s", "dir_exclusive", "curvature", "junction_type", "junction_inc_lanes", "priority_higher", "priority_equal", "priority_lower", - "is_secondary_or_higher", "is_primary_or_higher", "is_motorway", "is_link"); + "is_secondary_or_higher", "is_primary_or_higher", "is_motorway", + "is_link", "has_merging_link", "is_merging_into", + "num_left", "num_right", "num_straight" + ); } public void print(CSVPrinter out) { @@ -106,7 +165,7 @@ public void print(CSVPrinter out, String linkId, SumoNetworkHandler.Edge edge) t String highwayType = getHighwayType(edge.type); SumoNetworkHandler.Junction junction = handler.junctions.get(edge.to); - List<SumoNetworkHandler.Connection> connections = handler.connections.computeIfAbsent(edge.id, (k) -> new ArrayList<>()); + List<SumoNetworkHandler.Connection> connections = handler.connections.computeIfAbsent(edge.id, k -> new ArrayList<>()); Set<SumoNetworkHandler.Edge> toEdges = connections.stream() .filter(c -> !c.dir.equals("t")) @@ -129,12 +188,18 @@ public void print(CSVPrinter out, String linkId, SumoNetworkHandler.Edge edge) t Set<Character> dirs = new HashSet<>(); boolean multipleDirS = false; boolean exclusiveDirs = true; + + // Number of connections per direction + Object2IntMap<Character> numConnections = new Object2IntOpenHashMap<>(); + for (SumoNetworkHandler.Connection c : connections) { Set<Character> d = directionSet(c); if (dirs.contains('s') && d.contains('s')) multipleDirS = true; + d.forEach(dir -> numConnections.mergeInt(dir, 1, Integer::sum)); + Set<Character> intersection = new HashSet<>(dirs); // use the copy constructor intersection.retainAll(d); if (!intersection.isEmpty()) @@ -152,12 +217,27 @@ public void print(CSVPrinter out, String linkId, SumoNetworkHandler.Edge edge) t .mapToInt(e -> e.lanes.size()) .sum(); - boolean geq_secondary = switch (highwayType) { + boolean merging = incomingEdges.get(junction.id).stream() + .anyMatch(e -> e.type.contains("link")); + + OptionalInt highestPrio = incomingEdges.get(junction.id).stream() + .mapToInt(this::getPrio).max(); + + // Find category of the highest merging lane + String mergingHighest = ""; + if (highestPrio.isPresent() && highestPrio.getAsInt() > getPrio(edge)) { + Optional<Map.Entry<String, LinkProperties>> m = osm.entrySet().stream().filter(e -> e.getValue().getHierarchyLevel() == -highestPrio.getAsInt()) + .findFirst(); + if (m.isPresent()) + mergingHighest = m.get().getKey(); + } + + boolean geqSecondary = switch (highwayType) { case "secondary", "primary", "trunk", "motorway" -> true; default -> false; }; - boolean geq_primary = switch (highwayType) { + boolean geqPrimary = switch (highwayType) { case "primary", "trunk", "motorway" -> true; default -> false; }; @@ -170,7 +250,7 @@ public void print(CSVPrinter out, String linkId, SumoNetworkHandler.Edge edge) t out.print(Math.max(-3, Math.min(3, maxLanes - edge.lanes.size()))); out.print(maxSpeed - edge.lanes.get(0).speed); out.print(toEdges.size()); - out.print(Math.min(6, handler.connections.get(edge.id).size())); + out.print(Math.min(6, connections.size())); out.print(Math.min(12, aggr.response().cardinality())); out.print(Math.min(12, aggr.foes().cardinality())); out.print(bool(multipleDirS)); @@ -178,15 +258,21 @@ public void print(CSVPrinter out, String linkId, SumoNetworkHandler.Edge edge) t out.print(bool(dirs.contains('r'))); out.print(bool(dirs.contains('s'))); out.print(bool(exclusiveDirs)); + out.print(calcCurvature(edge)); out.print(junction.type); out.print(Math.min(12, incomingLanes)); out.print(bool("higher".equals(prio))); out.print(bool("equal".equals(prio))); out.print(bool("lower".equals(prio))); - out.print(bool(geq_secondary)); - out.print(bool(geq_primary)); + out.print(bool(geqSecondary)); + out.print(bool(geqPrimary)); out.print(bool("motorway".equals(highwayType))); out.print(bool(highwayType.contains("link"))); + out.print(bool(merging)); + out.print(mergingHighest); + out.print(numConnections.getInt('l')); + out.print(numConnections.getInt('r')); + out.print(numConnections.getInt('s')); out.println(); } diff --git a/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractorTest.java b/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractorTest.java new file mode 100644 index 00000000000..e8b41e359da --- /dev/null +++ b/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractorTest.java @@ -0,0 +1,81 @@ +package org.matsim.contrib.sumo; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class SumoNetworkFeatureExtractorTest { + + @Test + void twoCoordsBackAndForth() { + String[] coords = {"0,0", "0,100", "0,0"}; + int lentgh = 200; + + SumoNetworkHandler.Edge edge = new SumoNetworkHandler.Edge("1", "2", "3", "highway", 0, "name", coords); + edge.lanes.add(new SumoNetworkHandler.Lane("1", 0, lentgh, 50 / 3.6, null, null)); + + double ku = SumoNetworkFeatureExtractor.calcCurvature(edge); + + // Length: 0.2 km + // Gon: 200 + // Curvature: 200 / 0.2 = 1000 + + Assertions.assertEquals(1000, ku, 0.000001); + + System.out.println(ku); + } + + + @Test + void nintyDegreeCorner() { + + String[] coords = {"0,0", "0,100", "100,100"}; + int lentgh = 200; + + SumoNetworkHandler.Edge edge = new SumoNetworkHandler.Edge("1", "2", "3", "highway", 0, "name", coords); + edge.lanes.add(new SumoNetworkHandler.Lane("1", 0, lentgh, 50 / 3.6, null, null)); + + double ku = SumoNetworkFeatureExtractor.calcCurvature(edge); + + // Length: 0.2 km + // Gon: 100 + // Curvature: 100 / 0.2 = 500 + + Assertions.assertEquals(500, ku, 0.000001); + } + + @Test + void twoCorners() { + + String[] coords = {"0,0", "0,100", "100,100", "100,200"}; + int lentgh = 300; + + SumoNetworkHandler.Edge edge = new SumoNetworkHandler.Edge("1", "2", "3", "highway", 0, "name", coords); + edge.lanes.add(new SumoNetworkHandler.Lane("1", 0, lentgh, 50 / 3.6, null, null)); + + double ku = SumoNetworkFeatureExtractor.calcCurvature(edge); + + // Length: 0.3 km + // Gon: 100 + 100 = 200 + // Curvature: 200 / 0.3 = 666.6666666666666 + + Assertions.assertEquals((200 / 0.3), ku, 0.000001); + } + + @Test + void rectangle() { + + String[] coords = {"0,0", "0,100", "100,100", "100,0", "0,0"}; + int lentgh = 400; + + SumoNetworkHandler.Edge edge = new SumoNetworkHandler.Edge("1", "2", "3", "highway", 0, "name", coords); + edge.lanes.add(new SumoNetworkHandler.Lane("1", 0, lentgh, 50 / 3.6, null, null)); + + double ku = SumoNetworkFeatureExtractor.calcCurvature(edge); + + // Length: 0.4 km + // Gon: 100 + 100 + 100 = 300 + // Curvature: 300 / 0.4 = 666.6666666666666 + + Assertions.assertEquals((300 / 0.4), ku, 0.000001); + } +} From f4e4a6f1590f09b7ae989b6d19551dbbd60d5084 Mon Sep 17 00:00:00 2001 From: NicDul <71266428+NicDul@users.noreply.github.com> Date: Tue, 28 May 2024 11:30:46 +0200 Subject: [PATCH 2/2] Added a test scenario for a construction site between Morges and Renens on the line Lausanne - Geneva (#3283) Co-authored-by: u238053 <nicolas.dulex@sbb.ch> Co-authored-by: rakow <rakow@users.noreply.github.com> --- .../integration/RailsimIntegrationTest.java | 11 +- .../config.xml | 39 ++ .../trainNetwork.xml | 319 +++++++++ .../transitSchedule.xml | 605 ++++++++++++++++++ .../transitVehicles.xml | 191 ++++++ 5 files changed, 1162 insertions(+), 3 deletions(-) create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/config.xml create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/trainNetwork.xml create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitSchedule.xml create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitVehicles.xml diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java index 7adbb41fc31..4bf88ef4c05 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java @@ -373,9 +373,9 @@ void testScenarioKelheim() { type.setMaximumVelocity(30); type.setLength(100); } - + // simplify the activity types, e.g. home_3600 -> home - Set<String> activityTypes = new HashSet<>(); + Set<String> activityTypes = new HashSet<>(); for (Person person : scenario.getPopulation().getPersons().values()) { for (Plan plan : person.getPlans()) { for (PlanElement pE : plan.getPlanElements()) { @@ -388,7 +388,7 @@ void testScenarioKelheim() { } } } - + for (String type : activityTypes) { config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams(type).setTypicalDuration(1234.)); } @@ -405,6 +405,11 @@ void testScenarioMicroMesoCombination() { EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "scenarioMicroMesoCombination")); } + @Test + void testScenarioMicroMesoConstructionSiteLsGe() { + EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "scenarioMicroMesoConstructionSiteLsGe")); + } + private EventsCollector runSimulation(File scenarioDir) { return runSimulation(scenarioDir, null); } diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/config.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/config.xml new file mode 100644 index 00000000000..da3761b5c4e --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/config.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" ?> +<!DOCTYPE config SYSTEM "http://www.matsim.org/files/dtd/config_v2.dtd"> +<config> + + <module name="global"> + <param name="randomSeed" value="4711"/> + <param name="coordinateSystem" value="Atlantis"/> + </module> + + <module name="controler"> + <param name="runId" value="test"/> + <param name="firstIteration" value="0"/> + </module> + + <module name="qsim"> + <!-- "start/endTime" of MobSim (00:00:00 == take earliest activity time/ run as long as active vehicles exist) --> + <param name="startTime" value="00:00:00"/> + <param name="endTime" value="24:00:00"/> + + <param name="snapshotperiod" value="00:00:00"/> <!-- 00:00:00 means NO snapshot writing --> + <param name="mainMode" value="car"/> + + <!-- time in seconds. Time after which the frontmost vehicle on a link is called `stuck' if it does not move. --> + <param name="stuckTime" value="999999."/> + </module> + + <module name="transit"> + <param name="routingAlgorithmType" value="SwissRailRaptor"/> + <param name="transitScheduleFile" value="transitSchedule.xml"/> + <param name="useTransit" value="true"/> + <param name="usingTransitInMobsim" value="true"/> + <param name="vehiclesFile" value="transitVehicles.xml"/> + </module> + + <module name="network"> + <param name="inputNetworkFile" value="trainNetwork.xml"/> + </module> + +</config> diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/trainNetwork.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/trainNetwork.xml new file mode 100644 index 00000000000..731eca24217 --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/trainNetwork.xml @@ -0,0 +1,319 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE network SYSTEM "http://www.matsim.org/files/dtd/network_v2.dtd"> +<network name="test network"> + + <!-- ====================================================================== --> + + <!-- Network Lausanne - Genève, the whole line is mesoscopic except the portion between MOR and REN, where it is divided into two microscopic links. + All the stations are 400m long + The following convention applies to all stations : (Node : Station1) - (Stop : Station) - (Node : Station2) + /<=1=>\ + GE1 <=7=> GE2 <=3=> COP1 <=3=> COP2 <=2=> NY1 <=3=> NY2 <=2=> GLA1 <=2=> GLA2 <=2=> ROL1 <=2=> ROL2 <=2=> ALL1 <=3=> ALL2 <=2=> MOR1 <=4=> MOR2 REN1 <=5=> REN2 <=4=> LS1 <=7=> LS2 + \<=1=>/ + + --> + + <!-- ====================================================================== --> + + <nodes> + <node id="GE1" x="-60660" y="0"></node> + <node id="GE2" x="-60260" y="0"></node> + <node id="COP1" x="-47200" y="0"></node> + <node id="COP2" x="-46800" y="0"></node> + <node id="NY1" x="-38730" y="0"></node> + <node id="NY2" x="-38330" y="0"></node> + <node id="GLA1" x="-33990" y="0"></node> + <node id="GLA2" x="-33590" y="0"></node> + <node id="ROL1" x="-26860" y="0"></node> + <node id="ROL2" x="-26460" y="0"></node> + <node id="ALL1" x="-21680" y="0"></node> + <node id="ALL2" x="-21280" y="0"></node> + <node id="MOR1" x="-12700" y="0"></node> + <node id="MOR2" x="-12300" y="0"></node> + <node id="REN1" x="-4710" y="0"></node> + <node id="REN2" x="-4310" y="0"></node> + <node id="LS1" x="0" y="0"></node> + <node id="LS2" x="400" y="0"></node> + </nodes> + + <!-- ====================================================================== --> + + <links capperiod="01:00:00" effectivecellsize="7.5" effectivelanewidth="3.75"> + <link id="GE1-GE2" from="GE1" to="GE2" length="400" freespeed="32" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GE1GE2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">7</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="GE2-GE1" from="GE2" to="GE1" length="400" freespeed="32" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GE1GE2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">7</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="GE2-COP1" from="GE2" to="COP1" length="13060" freespeed="32" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GE2COP1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="COP1-GE2" from="COP1" to="GE2" length="13060" freespeed="32" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GE2COP1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="COP1-COP2" from="COP1" to="COP2" length="400" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">COP1COP2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="COP2-COP1" from="COP2" to="COP1" length="400" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">COP1COP2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + + <link id="COP2-NY1" from="COP2" to="NY1" length="8070" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">COP2NY1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="NY1-COP2" from="NY1" to="COP2" length="8070" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">COP2NY1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="NY1-NY2" from="NY1" to="NY2" length="400" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">NY1NY2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="NY2-NY1" from="NY2" to="NY1" length="400" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">NY1NY2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="NY2-GLA1" from="NY2" to="GLA1" length="4340" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">NY2GLA1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="GLA1-NY2" from="GLA1" to="NY2" length="4340" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">NY2GLA1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="GLA1-GLA2" from="GLA1" to="GLA2" length="400" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GLA1GLA2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="GLA2-GLA1" from="GLA2" to="GLA1" length="400" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GLA1GLA2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="GLA2-ROL1" from="GLA2" to="ROL1" length="6730" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GLA2ROL1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="ROL1-GLA2" from="ROL1" to="GLA2" length="6730" freespeed="38" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">GLA2ROL1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + + <link id="ROL1-ROL2" from="ROL1" to="ROL2" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ROL1ROL2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="ROL2-ROL1" from="ROL2" to="ROL1" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ROL1ROL2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="ROL2-ALL1" from="ROL2" to="ALL1" length="4780" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ROL2ALL1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="ALL1-ROL2" from="ALL1" to="ROL2" length="4780" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ROL2ALL1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="ALL1-ALL2" from="ALL1" to="ALL2" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ALL1ALL2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="ALL2-ALL1" from="ALL2" to="ALL1" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ALL1ALL2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">3</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="ALL2-MOR1" from="ALL2" to="MOR1" length="8580" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ALL2MOR1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="MOR1-ALL2" from="MOR1" to="ALL2" length="8580" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">ALL2MOR1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="MOR1-MOR2" from="MOR1" to="MOR2" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">MOR1MOR2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">4</attribute> + <attribute name="railsimEntry" class="java.lang.Boolean">true</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="MOR2-MOR1" from="MOR2" to="MOR1" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">MOR1MOR2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">4</attribute> + <attribute name="railsimExit" class="java.lang.Boolean">true</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="MOR2_REN1-1" from="MOR2" to="REN1" length="7590" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">MOR2REN1-1</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="REN1-MOR2-1" from="REN1" to="MOR2" length="7590" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">MOR2REN1-1</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="MOR2_REN1-2" from="MOR2" to="REN1" length="7590" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">MOR2REN1-2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="REN1-MOR2-2" from="REN1" to="MOR2" length="7590" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">MOR2REN1-2</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + + <link id="REN1-REN2" from="REN1" to="REN2" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">REN1REN2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">5</attribute> + <attribute name="railsimExit" class="java.lang.Boolean">true</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="REN2-REN1" from="REN2" to="REN1" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">REN1REN2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">5</attribute> + <attribute name="railsimEntry" class="java.lang.Boolean">true</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="REN2-LS1" from="REN2" to="LS1" length="4310" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">REN2LS1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">4</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="LS1-REN2" from="LS1" to="REN2" length="4310" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">REN2LS1</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">4</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + <link id="LS1-LS2" from="LS1" to="LS2" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">LS1LS2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">7</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + <link id="LS2-LS1" from="LS2" to="LS1" length="400" freespeed="29" capacity="3600.0" permlanes="1.0" oneway="1" modes="rail"> + <attributes> + <attribute name="railsimResourceId" class="java.lang.String">LS1LS2</attribute> + <attribute name="railsimTrainCapacity" class="java.lang.Integer">7</attribute> + <attribute name="railsimResourceType" class="java.lang.String">fixedBlock</attribute> + </attributes> + </link> + + + </links> + + <!-- ====================================================================== --> + +</network> diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitSchedule.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitSchedule.xml new file mode 100644 index 00000000000..19b28847fff --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitSchedule.xml @@ -0,0 +1,605 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE transitSchedule SYSTEM "http://www.matsim.org/files/dtd/transitSchedule_v2.dtd"> + +<transitSchedule> + + <!-- ====================================================================== --> + + <!-- The schedule is taken from : https://network.sbb.ch/en/ + Naming convention : Line-DepartureViaArrival-departure + + In order to model a construction site between Morges and Renens, a new stop is created in the middle of the link, and a construction train stops there during the planned time, thus reducing the capacity of the link. + + --> + + <!-- ====================================================================== --> + + <transitStops> + <stopFacility id="LS" x="0" y="0" linkRefId="LS1-LS2" stopAreaId="LS"> + </stopFacility> + <stopFacility id="REN" x="-4510" y="0" linkRefId="REN1-REN2" stopAreaId="REN"> + </stopFacility> + <stopFacility id="MOR" x="-12500" y="0" linkRefId="MOR1-MOR2" stopAreaId="MOR"> + </stopFacility> + <stopFacility id="ALL" x="-21480" y="0" linkRefId="ALL1-ALL2" stopAreaId="ALL"> + </stopFacility> + <stopFacility id="ROL" x="-26660" y="0" linkRefId="ROL1-ROL2" stopAreaId="ROL"> + </stopFacility> + <stopFacility id="GLA" x="-33790" y="0" linkRefId="GLA1-GLA2" stopAreaId="GLA"> + </stopFacility> + <stopFacility id="NY" x="-38530" y="0" linkRefId="NY1-NY2" stopAreaId="NY"> + </stopFacility> + <stopFacility id="COP" x="-47000" y="0" linkRefId="COP1-COP2" stopAreaId="COP"> + </stopFacility> + <stopFacility id="GE" x="-60260" y="0" linkRefId="GE1-GE2" stopAreaId="GE"> + </stopFacility> + <stopFacility id="LS1" x="0" y="0" linkRefId="LS2-LS1" stopAreaId="LS"> + </stopFacility> + <stopFacility id="REN1" x="-4510" y="0" linkRefId="REN2-REN1" stopAreaId="REN"> + </stopFacility> + <stopFacility id="MOR1" x="-12500" y="0" linkRefId="MOR2-MOR1" stopAreaId="MOR"> + </stopFacility> + <stopFacility id="ALL1" x="-21480" y="0" linkRefId="ALL2-ALL1" stopAreaId="ALL"> + </stopFacility> + <stopFacility id="ROL1" x="-26660" y="0" linkRefId="ROL2-ROL1" stopAreaId="ROL"> + </stopFacility> + <stopFacility id="GLA1" x="-33790" y="0" linkRefId="GLA2-GLA1" stopAreaId="GLA"> + </stopFacility> + <stopFacility id="NY1" x="-38530" y="0" linkRefId="NY2-NY1" stopAreaId="NY"> + </stopFacility> + <stopFacility id="COP1" x="-47000" y="0" linkRefId="COP2-COP1" stopAreaId="COP"> + </stopFacility> + <stopFacility id="GE1" x="-60260" y="0" linkRefId="GE2-GE1" stopAreaId="GE"> + </stopFacility> + + + <stopFacility id="Construction_Site_MOR_REN" x="-10000" y="0" linkRefId="MOR2_REN1-1" stopAreaId="BAU"> + </stopFacility> + <stopFacility id="Construction_Site_MOR_REN2" x="-10000" y="0" linkRefId="MOR2_REN1-2" stopAreaId="BAU"> + </stopFacility> + + </transitStops> + + <transitLine id="RE33"> + <transitRoute id="RE33-ANNGELS"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="GE" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="COP" arrivalOffset="00:12:00" departureOffset="00:13:00" awaitDeparture="true"/> + <stop refId="NY" arrivalOffset="00:18:00" departureOffset="00:19:00" awaitDeparture="true"/> + <stop refId="GLA" arrivalOffset="00:22:00" departureOffset="00:23:00" awaitDeparture="true"/> + <stop refId="ROL" arrivalOffset="00:27:00" departureOffset="00:28:00" awaitDeparture="true"/> + <stop refId="ALL" arrivalOffset="00:31:00" departureOffset="00:32:00" awaitDeparture="true"/> + <stop refId="MOR" arrivalOffset="00:37:00" departureOffset="00:38:00" awaitDeparture="true"/> + <stop refId="REN" arrivalOffset="00:44:00" departureOffset="00:45:00" awaitDeparture="true"/> + <stop refId="LS" arrivalOffset="00:51:00" departureOffset="00:54:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="GE1-GE2"/> + <link refId="GE2-COP1"/> + <link refId="COP1-COP2"/> + <link refId="COP2-NY1"/> + <link refId="NY1-NY2"/> + <link refId="NY2-GLA1"/> + <link refId="GLA1-GLA2"/> + <link refId="GLA2-ROL1"/> + <link refId="ROL1-ROL2"/> + <link refId="ROL2-ALL1"/> + <link refId="ALL1-ALL2"/> + <link refId="ALL2-MOR1"/> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + <link refId="REN2-LS1"/> + <link refId="LS1-LS2"/> + </route> + <departures> + <departure id="RE33-ANNGELS-8" departureTime="08:47:00" vehicleRefId="RE33-ANNGELS-8"/> + <departure id="RE33-ANNGELS-9" departureTime="09:47:00" vehicleRefId="RE33-ANNGELS-9"/> + <departure id="RE33-ANNGELS-10" departureTime="10:47:00" vehicleRefId="RE33-ANNGELS-10"/> + <departure id="RE33-ANNGELS-11" departureTime="11:47:00" vehicleRefId="RE33-ANNGELS-11"/> + <departure id="RE33-ANNGELS-12" departureTime="12:47:00" vehicleRefId="RE33-ANNGELS-12"/> + </departures> + </transitRoute> + <transitRoute id="RE33-ANNGESM"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="GE" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="COP" arrivalOffset="00:12:00" departureOffset="00:13:00" awaitDeparture="true"/> + <stop refId="NY" arrivalOffset="00:18:00" departureOffset="00:19:00" awaitDeparture="true"/> + <stop refId="GLA" arrivalOffset="00:22:00" departureOffset="00:23:00" awaitDeparture="true"/> + <stop refId="ROL" arrivalOffset="00:27:00" departureOffset="00:28:00" awaitDeparture="true"/> + <stop refId="ALL" arrivalOffset="00:31:00" departureOffset="00:32:00" awaitDeparture="true"/> + <stop refId="MOR" arrivalOffset="00:37:00" departureOffset="00:38:00" awaitDeparture="true"/> + <stop refId="REN" arrivalOffset="00:44:00" departureOffset="00:45:00" awaitDeparture="true"/> + <stop refId="LS" arrivalOffset="00:51:00" departureOffset="00:54:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="GE1-GE2"/> + <link refId="GE2-COP1"/> + <link refId="COP1-COP2"/> + <link refId="COP2-NY1"/> + <link refId="NY1-NY2"/> + <link refId="NY2-GLA1"/> + <link refId="GLA1-GLA2"/> + <link refId="GLA2-ROL1"/> + <link refId="ROL1-ROL2"/> + <link refId="ROL2-ALL1"/> + <link refId="ALL1-ALL2"/> + <link refId="ALL2-MOR1"/> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + <link refId="REN2-LS1"/> + <link refId="LS1-LS2"/> + </route> + <departures> + <departure id="RE33-ANNGESM-8" departureTime="08:17:00" vehicleRefId="RE33-ANNGESM-8"/> + <departure id="RE33-ANNGESM-9" departureTime="09:17:00" vehicleRefId="RE33-ANNGESM-9"/> + <departure id="RE33-ANNGESM-10" departureTime="10:17:00" vehicleRefId="RE33-ANNGESM-10"/> + <departure id="RE33-ANNGESM-11" departureTime="11:17:00" vehicleRefId="RE33-ANNGESM-11"/> + <departure id="RE33-ANNGESM-12" departureTime="12:17:00" vehicleRefId="RE33-ANNGESM-12"/> + </departures> + </transitRoute> + + <transitRoute id="RE33-VVGEANN"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="LS1" arrivalOffset="00:00:00" departureOffset="00:02:00" awaitDeparture="true"/> + <stop refId="REN1" arrivalOffset="00:08:00" departureOffset="00:08:00" awaitDeparture="true"/> + <stop refId="MOR1" arrivalOffset="00:15:00" departureOffset="00:16:00" awaitDeparture="true"/> + <stop refId="ALL1" arrivalOffset="00:21:00" departureOffset="00:22:00" awaitDeparture="true"/> + <stop refId="ROL1" arrivalOffset="00:25:00" departureOffset="00:26:00" awaitDeparture="true"/> + <stop refId="GLA1" arrivalOffset="00:31:00" departureOffset="00:32:00" awaitDeparture="true"/> + <stop refId="NY1" arrivalOffset="00:35:00" departureOffset="00:36:00" awaitDeparture="true"/> + <stop refId="COP1" arrivalOffset="00:41:00" departureOffset="00:42:00" awaitDeparture="true"/> + <stop refId="GE1" arrivalOffset="00:51:00" departureOffset="00:52:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="LS2-LS1"/> + <link refId="LS1-REN2"/> + <link refId="REN2-REN1"/> + <link refId="REN1-MOR2-2"/> + <link refId="MOR2-MOR1"/> + <link refId="MOR1-ALL2"/> + <link refId="ALL2-ALL1"/> + <link refId="ALL1-ROL2"/> + <link refId="ROL2-ROL1"/> + <link refId="ROL1-GLA2"/> + <link refId="GLA2-GLA1"/> + <link refId="GLA1-NY2"/> + <link refId="NY2-NY1"/> + <link refId="NY1-COP2"/> + <link refId="COP2-COP1"/> + <link refId="COP1-GE2"/> + <link refId="GE2-GE1"/> + </route> + <departures> + <departure id="RE33-VVGEANN-8" departureTime="08:19:00" vehicleRefId="RE33-VVGEANN-8"/> + <departure id="RE33-VVGEANN-9" departureTime="09:19:00" vehicleRefId="RE33-VVGEANN-9"/> + <departure id="RE33-VVGEANN-10" departureTime="10:19:00" vehicleRefId="RE33-VVGEANN-10"/> + <departure id="RE33-VVGEANN-11" departureTime="11:19:00" vehicleRefId="RE33-VVGEANN-11"/> + <departure id="RE33-VVGEANN-12" departureTime="12:19:00" vehicleRefId="RE33-VVGEANN-12"/> + </departures> + </transitRoute> + + <transitRoute id="RE33-SMGEANN"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="LS1" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="REN1" arrivalOffset="00:09:00" departureOffset="00:09:00" awaitDeparture="true"/> + <stop refId="MOR1" arrivalOffset="00:16:00" departureOffset="00:17:00" awaitDeparture="true"/> + <stop refId="ALL1" arrivalOffset="00:22:00" departureOffset="00:23:00" awaitDeparture="true"/> + <stop refId="ROL1" arrivalOffset="00:26:00" departureOffset="00:27:00" awaitDeparture="true"/> + <stop refId="GLA1" arrivalOffset="00:32:00" departureOffset="00:33:00" awaitDeparture="true"/> + <stop refId="NY1" arrivalOffset="00:36:00" departureOffset="00:37:00" awaitDeparture="true"/> + <stop refId="COP1" arrivalOffset="00:42:00" departureOffset="00:43:00" awaitDeparture="true"/> + <stop refId="GE1" arrivalOffset="00:52:00" departureOffset="00:54:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="LS2-LS1"/> + <link refId="LS1-REN2"/> + <link refId="REN2-REN1"/> + <link refId="REN1-MOR2-2"/> + <link refId="MOR2-MOR1"/> + <link refId="MOR1-ALL2"/> + <link refId="ALL2-ALL1"/> + <link refId="ALL1-ROL2"/> + <link refId="ROL2-ROL1"/> + <link refId="ROL1-GLA2"/> + <link refId="GLA2-GLA1"/> + <link refId="GLA1-NY2"/> + <link refId="NY2-NY1"/> + <link refId="NY1-COP2"/> + <link refId="COP2-COP1"/> + <link refId="COP1-GE2"/> + <link refId="GE2-GE1"/> + </route> + <departures> + <departure id="RE33-SMGEANN-8" departureTime="08:48:00" vehicleRefId="RE33-SMGEANN-8"/> + <departure id="RE33-SMGEANN-9" departureTime="09:48:00" vehicleRefId="RE33-SMGEANN-9"/> + <departure id="RE33-SMGEANN-10" departureTime="10:48:00" vehicleRefId="RE33-SMGEANN-10"/> + <departure id="RE33-SMGEANN-11" departureTime="11:48:00" vehicleRefId="RE33-SMGEANN-11"/> + <departure id="RE33-SMGEANN-12" departureTime="12:48:00" vehicleRefId="RE33-SMGEANN-12"/> + </departures> + </transitRoute> + + </transitLine> + + <transitLine id="IR90"> + <transitRoute id="IR90-GEAPGEBR1"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="GE" arrivalOffset="00:00:00" departureOffset="00:02:00" awaitDeparture="true"/> + <stop refId="LS" arrivalOffset="00:39:00" departureOffset="00:42:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="GE1-GE2"/> + <link refId="GE2-COP1"/> + <link refId="COP1-COP2"/> + <link refId="COP2-NY1"/> + <link refId="NY1-NY2"/> + <link refId="NY2-GLA1"/> + <link refId="GLA1-GLA2"/> + <link refId="GLA2-ROL1"/> + <link refId="ROL1-ROL2"/> + <link refId="ROL2-ALL1"/> + <link refId="ALL1-ALL2"/> + <link refId="ALL2-MOR1"/> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + <link refId="REN2-LS1"/> + <link refId="LS1-LS2"/> + </route> + <departures> + <departure id="IR90-GEAPGEBR1-8" departureTime="08:08:00" vehicleRefId="IR90-GEAPGEBR1-8"/> + <departure id="IR90-GEAPGEBR1-9" departureTime="09:08:00" vehicleRefId="IR90-GEAPGEBR1-9"/> + <departure id="IR90-GEAPGEBR1-10" departureTime="10:08:00" vehicleRefId="IR90-GEAPGEBR1-10"/> + <departure id="IR90-GEAPGEBR1-11" departureTime="11:08:00" vehicleRefId="IR90-GEAPGEBR1-11"/> + <departure id="IR90-GEAPGEBR1-12" departureTime="12:08:00" vehicleRefId="IR90-GEAPGEBR1-12"/> + </departures> + </transitRoute> + <transitRoute id="IR90-GEAPGEBR2"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="GE" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="NY" arrivalOffset="00:17:00" departureOffset="00:17:00" awaitDeparture="true"/> + <stop refId="MOR" arrivalOffset="00:34:00" departureOffset="00:34:00" awaitDeparture="true"/> + <stop refId="LS" arrivalOffset="00:45:00" departureOffset="00:55:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="GE1-GE2"/> + <link refId="GE2-COP1"/> + <link refId="COP1-COP2"/> + <link refId="COP2-NY1"/> + <link refId="NY1-NY2"/> + <link refId="NY2-GLA1"/> + <link refId="GLA1-GLA2"/> + <link refId="GLA2-ROL1"/> + <link refId="ROL1-ROL2"/> + <link refId="ROL2-ALL1"/> + <link refId="ALL1-ALL2"/> + <link refId="ALL2-MOR1"/> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + <link refId="REN2-LS1"/> + <link refId="LS1-LS2"/> + </route> + <departures> + <departure id="IR90-GEAPGEBR2-8" departureTime="08:26:00" vehicleRefId="IR90-GEAPGEBR2-8"/> + <departure id="IR90-GEAPGEBR2-9" departureTime="09:26:00" vehicleRefId="IR90-GEAPGEBR2-9"/> + <departure id="IR90-GEAPGEBR2-10" departureTime="10:26:00" vehicleRefId="IR90-GEAPGEBR2-10"/> + <departure id="IR90-GEAPGEBR2-11" departureTime="11:26:00" vehicleRefId="IR90-GEAPGEBR2-11"/> + <departure id="IR90-GEAPGEBR2-12" departureTime="12:26:00" vehicleRefId="IR90-GEAPGEBR2-12"/> + </departures> + </transitRoute> + + <transitRoute id="IR90-BRGEGEAP1"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="LS1" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="GE1" arrivalOffset="00:40:00" departureOffset="00:42:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="LS2-LS1"/> + <link refId="LS1-REN2"/> + <link refId="REN2-REN1"/> + <link refId="REN1-MOR2-2"/> + <link refId="MOR2-MOR1"/> + <link refId="MOR1-ALL2"/> + <link refId="ALL2-ALL1"/> + <link refId="ALL1-ROL2"/> + <link refId="ROL2-ROL1"/> + <link refId="ROL1-GLA2"/> + <link refId="GLA2-GLA1"/> + <link refId="GLA1-NY2"/> + <link refId="NY2-NY1"/> + <link refId="NY1-COP2"/> + <link refId="COP2-COP1"/> + <link refId="COP1-GE2"/> + <link refId="GE2-GE1"/> + </route> + <departures> + <departure id="IR90-BRGEGEAP1-8" departureTime="08:10:00" vehicleRefId="IR90-BRGEGEAP1-8"/> + <departure id="IR90-BRGEGEAP1-9" departureTime="09:10:00" vehicleRefId="IR90-BRGEGEAP1-9"/> + <departure id="IR90-BRGEGEAP1-10" departureTime="10:10:00" vehicleRefId="IR90-BRGEGEAP1-10"/> + <departure id="IR90-BRGEGEAP1-11" departureTime="11:10:00" vehicleRefId="IR90-BRGEGEAP1-11"/> + <departure id="IR90-BRGEGEAP1-12" departureTime="12:10:00" vehicleRefId="IR90-BRGEGEAP1-12"/> + </departures> + </transitRoute> + <transitRoute id="IR90-BRGEGEAP2"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="LS1" arrivalOffset="00:00:00" departureOffset="00:09:00" awaitDeparture="true"/> + <stop refId="MOR1" arrivalOffset="00:20:00" departureOffset="00:20:00" awaitDeparture="true"/> + <stop refId="NY1" arrivalOffset="00:36:00" departureOffset="00:37:00" awaitDeparture="true"/> + <stop refId="GE1" arrivalOffset="00:52:00" departureOffset="00:55:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="LS2-LS1"/> + <link refId="LS1-REN2"/> + <link refId="REN2-REN1"/> + <link refId="REN1-MOR2-2"/> + <link refId="MOR2-MOR1"/> + <link refId="MOR1-ALL2"/> + <link refId="ALL2-ALL1"/> + <link refId="ALL1-ROL2"/> + <link refId="ROL2-ROL1"/> + <link refId="ROL1-GLA2"/> + <link refId="GLA2-GLA1"/> + <link refId="GLA1-NY2"/> + <link refId="NY2-NY1"/> + <link refId="NY1-COP2"/> + <link refId="COP2-COP1"/> + <link refId="COP1-GE2"/> + <link refId="GE2-GE1"/> + </route> + <departures> + <departure id="IR90-BRGEGEAP2-8" departureTime="08:39:00" vehicleRefId="IR90-BRGEGEAP2-8"/> + <departure id="IR90-BRGEGEAP2-9" departureTime="09:39:00" vehicleRefId="IR90-BRGEGEAP2-9"/> + <departure id="IR90-BRGEGEAP2-10" departureTime="10:39:00" vehicleRefId="IR90-BRGEGEAP2-10"/> + <departure id="IR90-BRGEGEAP2-11" departureTime="11:39:00" vehicleRefId="IR90-BRGEGEAP2-11"/> + <departure id="IR90-BRGEGEAP2-12" departureTime="12:39:00" vehicleRefId="IR90-BRGEGEAP2-12"/> + </departures> + </transitRoute> + + </transitLine> + + <transitLine id="IR15"> + <transitRoute id="IR15-GEAPGELZ"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="GE" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="NY" arrivalOffset="00:17:00" departureOffset="00:17:00" awaitDeparture="true"/> + <stop refId="MOR" arrivalOffset="00:34:00" departureOffset="00:34:00" awaitDeparture="true"/> + <stop refId="LS" arrivalOffset="00:45:00" departureOffset="00:48:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="GE1-GE2"/> + <link refId="GE2-COP1"/> + <link refId="COP1-COP2"/> + <link refId="COP2-NY1"/> + <link refId="NY1-NY2"/> + <link refId="NY2-GLA1"/> + <link refId="GLA1-GLA2"/> + <link refId="GLA2-ROL1"/> + <link refId="ROL1-ROL2"/> + <link refId="ROL2-ALL1"/> + <link refId="ALL1-ALL2"/> + <link refId="ALL2-MOR1"/> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + <link refId="REN2-LS1"/> + <link refId="LS1-LS2"/> + </route> + <departures> + <departure id="IR15-GEAPGELZ-8" departureTime="08:56:00" vehicleRefId="IR15-GEAPGELZ-8"/> + <departure id="IR15-GEAPGELZ-9" departureTime="09:56:00" vehicleRefId="IR15-GEAPGELZ-9"/> + <departure id="IR15-GEAPGELZ-10" departureTime="10:56:00" vehicleRefId="IR15-GEAPGELZ-10"/> + <departure id="IR15-GEAPGELZ-11" departureTime="11:56:00" vehicleRefId="IR15-GEAPGELZ-11"/> + <departure id="IR15-GEAPGELZ-12" departureTime="12:56:00" vehicleRefId="IR15-GEAPGELZ-12"/> + </departures> + </transitRoute> + + <transitRoute id="IR15-LZGEGEAP"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="LS1" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="MOR1" arrivalOffset="00:13:00" departureOffset="00:13:00" awaitDeparture="true"/> + <stop refId="NY1" arrivalOffset="00:29:00" departureOffset="00:30:00" awaitDeparture="true"/> + <stop refId="GE1" arrivalOffset="00:45:00" departureOffset="00:48:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="LS2-LS1"/> + <link refId="LS1-REN2"/> + <link refId="REN2-REN1"/> + <link refId="REN1-MOR2-2"/> + <link refId="MOR2-MOR1"/> + <link refId="MOR1-ALL2"/> + <link refId="ALL2-ALL1"/> + <link refId="ALL1-ROL2"/> + <link refId="ROL2-ROL1"/> + <link refId="ROL1-GLA2"/> + <link refId="GLA2-GLA1"/> + <link refId="GLA1-NY2"/> + <link refId="NY2-NY1"/> + <link refId="NY1-COP2"/> + <link refId="COP2-COP1"/> + <link refId="COP1-GE2"/> + <link refId="GE2-GE1"/> + </route> + <departures> + <departure id="IR15-LZGEGEAP-8" departureTime="08:16:00" vehicleRefId="IR15-LZGEGEAP-8"/> + <departure id="IR15-LZGEGEAP-9" departureTime="09:16:00" vehicleRefId="IR15-LZGEGEAP-9"/> + <departure id="IR15-LZGEGEAP-10" departureTime="10:16:00" vehicleRefId="IR15-LZGEGEAP-10"/> + <departure id="IR15-LZGEGEAP-11" departureTime="11:16:00" vehicleRefId="IR15-LZGEGEAP-11"/> + <departure id="IR15-LZGEGEAP-12" departureTime="12:16:00" vehicleRefId="IR15-LZGEGEAP-12"/> + </departures> + </transitRoute> + + </transitLine> + + <transitLine id="IC1"> + <transitRoute id="IC1-GEAPZUESG"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="GE" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="LS" arrivalOffset="00:38:00" departureOffset="00:40:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="GE1-GE2"/> + <link refId="GE2-COP1"/> + <link refId="COP1-COP2"/> + <link refId="COP2-NY1"/> + <link refId="NY1-NY2"/> + <link refId="NY2-GLA1"/> + <link refId="GLA1-GLA2"/> + <link refId="GLA2-ROL1"/> + <link refId="ROL1-ROL2"/> + <link refId="ROL2-ALL1"/> + <link refId="ALL1-ALL2"/> + <link refId="ALL2-MOR1"/> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + <link refId="REN2-LS1"/> + <link refId="LS1-LS2"/> + </route> + <departures> + <departure id="IC1-GEAPZUESG-8" departureTime="08:39:00" vehicleRefId="IC1-GEAPZUESG-8"/> + <departure id="IC1-GEAPZUESG-9" departureTime="09:39:00" vehicleRefId="IC1-GEAPZUESG-9"/> + <departure id="IC1-GEAPZUESG-10" departureTime="10:39:00" vehicleRefId="IC1-GEAPZUESG-10"/> + <departure id="IC1-GEAPZUESG-11" departureTime="11:39:00" vehicleRefId="IC1-GEAPZUESG-11"/> + <departure id="IC1-GEAPZUESG-12" departureTime="12:39:00" vehicleRefId="IC1-GEAPZUESG-12"/> + </departures> + </transitRoute> + + <transitRoute id="IC1-SGZUEGEAP"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="LS1" arrivalOffset="00:00:00" departureOffset="00:02:00" awaitDeparture="true"/> + <stop refId="GE1" arrivalOffset="00:37:00" departureOffset="00:39:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="LS2-LS1"/> + <link refId="LS1-REN2"/> + <link refId="REN2-REN1"/> + <link refId="REN1-MOR2-2"/> + <link refId="MOR2-MOR1"/> + <link refId="MOR1-ALL2"/> + <link refId="ALL2-ALL1"/> + <link refId="ALL1-ROL2"/> + <link refId="ROL2-ROL1"/> + <link refId="ROL1-GLA2"/> + <link refId="GLA2-GLA1"/> + <link refId="GLA1-NY2"/> + <link refId="NY2-NY1"/> + <link refId="NY1-COP2"/> + <link refId="COP2-COP1"/> + <link refId="COP1-GE2"/> + <link refId="GE2-GE1"/> + </route> + <departures> + <departure id="IC1-SGZUEGEAP-8" departureTime="08:41:00" vehicleRefId="IC1-SGZUEGEAP-8"/> + <departure id="IC1-SGZUEGEAP-9" departureTime="09:41:00" vehicleRefId="IC1-SGZUEGEAP-9"/> + <departure id="IC1-SGZUEGEAP-10" departureTime="10:41:00" vehicleRefId="IC1-SGZUEGEAP-10"/> + <departure id="IC1-SGZUEGEAP-11" departureTime="11:41:00" vehicleRefId="IC1-SGZUEGEAP-11"/> + <departure id="IC1-SGZUEGEAP-12" departureTime="12:41:00" vehicleRefId="IC1-SGZUEGEAP-12"/> + </departures> + </transitRoute> + + + </transitLine> + + <transitLine id="IC5"> + <transitRoute id="IC5-GEAPZUERS"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="GE" arrivalOffset="00:00:00" departureOffset="00:03:00" awaitDeparture="true"/> + <stop refId="MOR" arrivalOffset="00:29:00" departureOffset="00:30:00" awaitDeparture="true"/> + <stop refId="REN" arrivalOffset="00:37:00" awaitDeparture="false"/> + </routeProfile> + <route> + <link refId="GE1-GE2"/> + <link refId="GE2-COP1"/> + <link refId="COP1-COP2"/> + <link refId="COP2-NY1"/> + <link refId="NY1-NY2"/> + <link refId="NY2-GLA1"/> + <link refId="GLA1-GLA2"/> + <link refId="GLA2-ROL1"/> + <link refId="ROL1-ROL2"/> + <link refId="ROL2-ALL1"/> + <link refId="ALL1-ALL2"/> + <link refId="ALL2-MOR1"/> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + </route> + <departures> + <departure id="IC5-GEAPZUERS-8" departureTime="08:12:00" vehicleRefId="IC5-GEAPZUERS-8"/> + <departure id="IC5-GEAPZUERS-9" departureTime="09:12:00" vehicleRefId="IC5-GEAPZUERS-9"/> + <departure id="IC5-GEAPZUERS-10" departureTime="10:12:00" vehicleRefId="IC5-GEAPZUERS-10"/> + <departure id="IC5-GEAPZUERS-11" departureTime="11:12:00" vehicleRefId="IC5-GEAPZUERS-11"/> + <departure id="IC5-GEAPZUERS-12" departureTime="12:12:00" vehicleRefId="IC5-GEAPZUERS-12"/> + </departures> + </transitRoute> + + <transitRoute id="IC5-RSZUEGEAP"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="REN1" arrivalOffset="00:00:00" departureOffset="00:00:00" awaitDeparture="true"/> + <stop refId="MOR1" arrivalOffset="00:07:00" departureOffset="00:09:00" awaitDeparture="true"/> + <stop refId="GE1" arrivalOffset="00:38:00" departureOffset="00:40:00" awaitDeparture="true"/> + </routeProfile> + <route> + <link refId="REN2-REN1"/> + <link refId="REN1-MOR2-2"/> + <link refId="MOR2-MOR1"/> + <link refId="MOR1-ALL2"/> + <link refId="ALL2-ALL1"/> + <link refId="ALL1-ROL2"/> + <link refId="ROL2-ROL1"/> + <link refId="ROL1-GLA2"/> + <link refId="GLA2-GLA1"/> + <link refId="GLA1-NY2"/> + <link refId="NY2-NY1"/> + <link refId="NY1-COP2"/> + <link refId="COP2-COP1"/> + <link refId="COP1-GE2"/> + <link refId="GE2-GE1"/> + </route> + <departures> + <departure id="IC5-RSZUEGEAP-8" departureTime="08:09:00" vehicleRefId="IC5-RSZUEGEAP-8"/> + <departure id="IC5-RSZUEGEAP-9" departureTime="09:09:00" vehicleRefId="IC5-RSZUEGEAP-9"/> + <departure id="IC5-RSZUEGEAP-10" departureTime="10:09:00" vehicleRefId="IC5-RSZUEGEAP-10"/> + <departure id="IC5-RSZUEGEAP-11" departureTime="11:09:00" vehicleRefId="IC5-RSZUEGEAP-11"/> + <departure id="IC5-RSZUEGEAP-12" departureTime="12:09:00" vehicleRefId="IC5-RSZUEGEAP-12"/> + </departures> + </transitRoute> + + <transitRoute id="Construction_REN_LS"> + <transportMode>rail</transportMode> + <routeProfile> + <stop refId="MOR" arrivalOffset="00:00:00" departureOffset="00:00:00" awaitDeparture="false"/> + <stop refId="Construction_Site_MOR_REN" arrivalOffset="00:00:00" departureOffset="01:00:00" awaitDeparture="true"/> + <stop refId="REN" arrivalOffset="01:00:00" departureOffset="01:00:00" awaitDeparture="false"/> + </routeProfile> + <route> + <link refId="MOR1-MOR2"/> + <link refId="MOR2_REN1-1"/> + <link refId="REN1-REN2"/> + </route> + <departures> + <departure id="Construction_MOR_REN_10" departureTime="10:00:00" vehicleRefId="Construction_Train1"/> + </departures> + </transitRoute> + + + </transitLine> + + +</transitSchedule> diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitVehicles.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitVehicles.xml new file mode 100644 index 00000000000..7439829e879 --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/scenarioMicroMesoConstructionSiteLsGe/transitVehicles.xml @@ -0,0 +1,191 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<vehicleDefinitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.matsim.org/files/dtd" xsi:schemaLocation="http://www.matsim.org/files/dtd http://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd"> + + + <!-- ====================================================================== --> + + <!-- Four types of vehicles are used for the different traffc types : Regional (RV160), InterRegio (FV200IR), InterCity (FV200IC), Construction (Construction_Train) + --> + + <!-- ====================================================================== --> + + + <vehicleType id="RV160"> + <attributes> + <attribute name="accessTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="doorOperationMode" class="org.matsim.vehicles.VehicleType$DoorOperationMode">serial</attribute> + <attribute name="egressTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="railsimAcceleration" class="java.lang.Double">1</attribute> + <attribute name="railsimDeceleration" class="java.lang.Double">1</attribute> + </attributes> + <capacity seats="200" standingRoomInPersons="0"> + + </capacity> + <length meter="150"/> + <width meter="2.85"/> + <maximumVelocity meterPerSecond="44"/> + <costInformation> + + </costInformation> + <passengerCarEquivalents pce="1.0"/> + <networkMode networkMode="rail"/> + <flowEfficiencyFactor factor="1.0"/> + </vehicleType> + + <vehicleType id="FV200IR"> + <attributes> + <attribute name="accessTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="doorOperationMode" class="org.matsim.vehicles.VehicleType$DoorOperationMode">serial</attribute> + <attribute name="egressTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="railsimAcceleration" class="java.lang.Double">0.8</attribute> + <attribute name="railsimDeceleration" class="java.lang.Double">0.8</attribute> + </attributes> + <capacity seats="400" standingRoomInPersons="0"> + + </capacity> + <length meter="200"/> + <width meter="2.85"/> + <maximumVelocity meterPerSecond="55"/> + <costInformation> + + </costInformation> + <passengerCarEquivalents pce="1.0"/> + <networkMode networkMode="rail"/> + <flowEfficiencyFactor factor="1.0"/> + </vehicleType> + + <vehicleType id="FV200IC"> + <attributes> + <attribute name="accessTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="doorOperationMode" class="org.matsim.vehicles.VehicleType$DoorOperationMode">serial</attribute> + <attribute name="egressTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="railsimAcceleration" class="java.lang.Double">0.8</attribute> + <attribute name="railsimDeceleration" class="java.lang.Double">0.8</attribute> + </attributes> + <capacity seats="400" standingRoomInPersons="0"> + + </capacity> + <length meter="200"/> + <width meter="2.85"/> + <maximumVelocity meterPerSecond="55"/> + <costInformation> + + </costInformation> + <passengerCarEquivalents pce="1.0"/> + <networkMode networkMode="rail"/> + <flowEfficiencyFactor factor="1.0"/> + </vehicleType> + + <vehicleType id="Construction_Train"> + <attributes> + <attribute name="accessTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="doorOperationMode" class="org.matsim.vehicles.VehicleType$DoorOperationMode">serial</attribute> + <attribute name="egressTimeInSecondsPerPerson" class="java.lang.Double">5.0</attribute> + <attribute name="railsimAcceleration" class="java.lang.Double">0.8</attribute> + <attribute name="railsimDeceleration" class="java.lang.Double">0.8</attribute> + </attributes> + <capacity seats="1" standingRoomInPersons="0"> + + </capacity> + <length meter="200"/> + <width meter="2.85"/> + <maximumVelocity meterPerSecond="55"/> + <costInformation> + + </costInformation> + <passengerCarEquivalents pce="1.0"/> + <networkMode networkMode="rail"/> + <flowEfficiencyFactor factor="1.0"/> + </vehicleType> + + + <vehicle id="RE33-ANNGELS-8" type="RV160"/> + <vehicle id="RE33-ANNGELS-9" type="RV160"/> + <vehicle id="RE33-ANNGELS-10" type="RV160"/> + <vehicle id="RE33-ANNGELS-11" type="RV160"/> + <vehicle id="RE33-ANNGELS-12" type="RV160"/> + + <vehicle id="RE33-ANNGESM-8" type="RV160"/> + <vehicle id="RE33-ANNGESM-9" type="RV160"/> + <vehicle id="RE33-ANNGESM-10" type="RV160"/> + <vehicle id="RE33-ANNGESM-11" type="RV160"/> + <vehicle id="RE33-ANNGESM-12" type="RV160"/> + + <vehicle id="RE33-VVGEANN-8" type="RV160"/> + <vehicle id="RE33-VVGEANN-9" type="RV160"/> + <vehicle id="RE33-VVGEANN-10" type="RV160"/> + <vehicle id="RE33-VVGEANN-11" type="RV160"/> + <vehicle id="RE33-VVGEANN-12" type="RV160"/> + + <vehicle id="RE33-SMGEANN-8" type="RV160"/> + <vehicle id="RE33-SMGEANN-9" type="RV160"/> + <vehicle id="RE33-SMGEANN-10" type="RV160"/> + <vehicle id="RE33-SMGEANN-11" type="RV160"/> + <vehicle id="RE33-SMGEANN-12" type="RV160"/> + + <vehicle id="IR90-GEAPGEBR1-8" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR1-9" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR1-10" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR1-11" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR1-12" type="FV200IR"/> + + <vehicle id="IR90-GEAPGEBR2-8" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR2-9" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR2-10" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR2-11" type="FV200IR"/> + <vehicle id="IR90-GEAPGEBR2-12" type="FV200IR"/> + + <vehicle id="IR90-BRGEGEAP1-8" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP1-9" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP1-10" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP1-11" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP1-12" type="FV200IR"/> + + <vehicle id="IR90-BRGEGEAP2-8" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP2-9" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP2-10" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP2-11" type="FV200IR"/> + <vehicle id="IR90-BRGEGEAP2-12" type="FV200IR"/> + + <vehicle id="IR15-GEAPGELZ-8" type="FV200IR"/> + <vehicle id="IR15-GEAPGELZ-9" type="FV200IR"/> + <vehicle id="IR15-GEAPGELZ-10" type="FV200IR"/> + <vehicle id="IR15-GEAPGELZ-11" type="FV200IR"/> + <vehicle id="IR15-GEAPGELZ-12" type="FV200IR"/> + + <vehicle id="IR15-LZGEGEAP-8" type="FV200IR"/> + <vehicle id="IR15-LZGEGEAP-9" type="FV200IR"/> + <vehicle id="IR15-LZGEGEAP-10" type="FV200IR"/> + <vehicle id="IR15-LZGEGEAP-11" type="FV200IR"/> + <vehicle id="IR15-LZGEGEAP-12" type="FV200IR"/> + + <vehicle id="IC1-GEAPZUESG-8" type="FV200IC"/> + <vehicle id="IC1-GEAPZUESG-9" type="FV200IC"/> + <vehicle id="IC1-GEAPZUESG-10" type="FV200IC"/> + <vehicle id="IC1-GEAPZUESG-11" type="FV200IC"/> + <vehicle id="IC1-GEAPZUESG-12" type="FV200IC"/> + + <vehicle id="IC1-SGZUEGEAP-8" type="FV200IC"/> + <vehicle id="IC1-SGZUEGEAP-9" type="FV200IC"/> + <vehicle id="IC1-SGZUEGEAP-10" type="FV200IC"/> + <vehicle id="IC1-SGZUEGEAP-11" type="FV200IC"/> + <vehicle id="IC1-SGZUEGEAP-12" type="FV200IC"/> + + <vehicle id="IC5-GEAPZUERS-8" type="FV200IC"/> + <vehicle id="IC5-GEAPZUERS-9" type="FV200IC"/> + <vehicle id="IC5-GEAPZUERS-10" type="FV200IC"/> + <vehicle id="IC5-GEAPZUERS-11" type="FV200IC"/> + <vehicle id="IC5-GEAPZUERS-12" type="FV200IC"/> + + <vehicle id="IC5-RSZUEGEAP-8" type="FV200IC"/> + <vehicle id="IC5-RSZUEGEAP-9" type="FV200IC"/> + <vehicle id="IC5-RSZUEGEAP-10" type="FV200IC"/> + <vehicle id="IC5-RSZUEGEAP-11" type="FV200IC"/> + <vehicle id="IC5-RSZUEGEAP-12" type="FV200IC"/> + + + <vehicle id="Construction_Train1" type="Construction_Train"/> + + +</vehicleDefinitions>