From c49d991c8b2decd2e8aaff16ee0ab2f0bede05bc Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Mon, 25 Mar 2024 12:20:02 +0100 Subject: [PATCH 01/10] simplify activities in kelheim test and remove SnzActivities class --- .../integration/RailsimIntegrationTest.java | 27 +++++- .../railsim/integration/SnzActivities.java | 91 ------------------- 2 files changed, 25 insertions(+), 93 deletions(-) delete mode 100644 contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/SnzActivities.java 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 b139bfd423b..7adbb41fc31 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 @@ -30,9 +30,14 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.api.experimental.events.VehicleArrivesAtFacilityEvent; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.scenario.ScenarioUtils; @@ -51,6 +56,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Consumer; @@ -367,8 +373,25 @@ void testScenarioKelheim() { type.setMaximumVelocity(30); type.setLength(100); } - - SnzActivities.addScoringParams(config); + + // simplify the activity types, e.g. home_3600 -> home + Set activityTypes = new HashSet<>(); + for (Person person : scenario.getPopulation().getPersons().values()) { + for (Plan plan : person.getPlans()) { + for (PlanElement pE : plan.getPlanElements()) { + if(pE instanceof Activity) { + Activity act = (Activity) pE; + String baseType = act.getType().split("_")[0]; + act.setType(baseType); + activityTypes.add(baseType); + } + } + } + } + + for (String type : activityTypes) { + config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams(type).setTypicalDuration(1234.)); + } Controler controler = new Controler(scenario); controler.addOverridingModule(new RailsimModule()); diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/SnzActivities.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/SnzActivities.java deleted file mode 100644 index ac3a039f5a5..00000000000 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/SnzActivities.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Avoid dependency on vsp contrib, copy from: - * https://github.com/matsim-org/matsim-libs/blob/b2305e5e0f744b357486c8bbab253bb7c38aaad4/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scenario/SnzActivities.java - */ -package ch.sbb.matsim.contrib.railsim.integration; - -import org.matsim.core.config.Config; -import org.matsim.core.config.groups.ScoringConfigGroup; - -/** - * Defines available activities and open- and closing times in Snz scenarios at vsp. - */ -public enum SnzActivities { - - home, - other, - visit, - accomp_children, - accomp_other, - - educ_kiga(7, 17), - educ_primary(7, 16), - educ_secondary(7, 17), - educ_tertiary(7, 22), - educ_higher(7, 19), - educ_other(7, 22), - - work(6, 20), - business(8, 20), - errands(8, 20), - - leisure(9, 27), - restaurant(8, 27), - shop_daily(8, 20), - shop_other(8, 20); - - /** - * Start time of an activity in hours, can be -1 if not defined. - */ - private final double start; - - /** - * End time of an activity in hours, can be -1 if not defined. - */ - private final double end; - - SnzActivities(double start, double end) { - this.start = start; - this.end = end; - } - - SnzActivities() { - this.start = -1; - this.end = -1; - } - - - /** - * Apply start and end time to params. - */ - public ScoringConfigGroup.ActivityParams apply(ScoringConfigGroup.ActivityParams params) { - if (start >= 0) - params = params.setOpeningTime(start * 3600.); - if (end >= 0) - params = params.setClosingTime(end * 3600.); - - return params; - } - - /** - * Add activity params for the scenario config. - */ - public static void addScoringParams(Config config) { - - for (SnzActivities value : SnzActivities.values()) { - for (long ii = 600; ii <= 97200; ii += 600) { - config.scoring().addActivityParams(value.apply(new ScoringConfigGroup.ActivityParams(value.name() + "_" + ii).setTypicalDuration(ii))); - } - } - - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("car interaction").setTypicalDuration(60)); - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("ride interaction").setTypicalDuration(60)); - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("bike interaction").setTypicalDuration(60)); - - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("other").setTypicalDuration(600 * 3)); - - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("freight_start").setTypicalDuration(60 * 15)); - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("freight_end").setTypicalDuration(60 * 15)); - - } -} From 3630417490a32482230ca7314eb21a552c208356 Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Mon, 25 Mar 2024 17:35:10 +0100 Subject: [PATCH 02/10] adding a railway osm reader, similar to the existing highway approach --- .../osm/networkReader/OsmRailwayParser.java | 143 ++++++++++++++++++ .../osm/networkReader/OsmRailwayReader.java | 66 ++++++++ .../contrib/osm/networkReader/OsmTags.java | 10 ++ contribs/railsim/pom.xml | 7 + .../contrib/railsim/RunRailsimExample.java | 12 +- .../prepare/RunRailOsmNetworkReader.java | 43 ++++++ 6 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java create mode 100644 contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java create mode 100644 contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java new file mode 100644 index 00000000000..3e9c9053b55 --- /dev/null +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java @@ -0,0 +1,143 @@ +package org.matsim.contrib.osm.networkReader; + +import de.topobyte.osm4j.core.model.iface.OsmNode; +import de.topobyte.osm4j.core.model.iface.OsmWay; +import de.topobyte.osm4j.core.model.util.OsmModelUtil; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Coord; +import org.matsim.core.utils.geometry.CoordinateTransformation; + +import java.nio.file.Path; +import java.text.NumberFormat; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.function.BiPredicate; +import java.util.stream.Collectors; + +class OsmRailwayParser extends OsmNetworkParser { + + private static final Logger log = LogManager.getLogger(OsmRailwayParser.class); + private static final NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.UK); + + private final CoordinateTransformation transformation; + private final Map linkProperties; + private final BiPredicate linkFilter; + final ExecutorService executor; + Map ways; + Map nodes; + Map> nodeReferences; + + OsmRailwayParser(CoordinateTransformation transformation, Map linkProperties, BiPredicate linkFilter, ExecutorService executor) { + super(transformation, linkProperties, linkFilter, executor); + + this.transformation = transformation; + this.linkProperties = linkProperties; + this.linkFilter = linkFilter; + this.executor = executor; + } + + public Map getWays() { + return ways; + } + + public Map getNodes() { + return nodes; + } + + void parse(Path inputFile) { + + // make sure we have empty collections + ways = new ConcurrentHashMap<>(); + nodes = new ConcurrentHashMap<>(); + nodeReferences = new ConcurrentHashMap<>(); + + new PbfParser.Builder() + .setWaysHandler(this::handleWay) + .setExecutor(executor) + .build() + .parse(inputFile); + + log.info("Finished reading ways"); + log.info("Starting to read nodes"); + + new PbfParser.Builder() + .setNodeHandler(this::handleNode) + .setExecutor(executor) + .build() + .parse(inputFile); + + log.info("finished reading nodes"); + } + + void handleNode(OsmNode osmNode) { + + if (nodeReferences.containsKey(osmNode.getId())) { + + List waysThatReferenceNode = nodeReferences.get(osmNode.getId()); + Coord transformedCoord = transformation.transform(new Coord(osmNode.getLongitude(), osmNode.getLatitude())); + + // 'testWhetherReferencingLinksAreInFilter' may be expensive because it might include a test whether the + // supplied coordinate is within a shape. Therefore we want to test as few cases as possible. Two cases are tested anyway: + // 1. if more than one way references this node, this node is an intersection and a possible end node for a + // matsim link. + // 2. if this node is either the start- or end node of a referencing way which makes it a candidate for a node + // in a matsim link as well + // + // if a way has both ends outside the filter and no intersections within the filter it will not be included + // in the final network. I think this is unlikely in real world scenarios, so I think we can live with this + // to achieve faster execution + List filteredReferencingLinks; + if (waysThatReferenceNode.size() > 1 || isEndNodeOfReferencingLink(osmNode, waysThatReferenceNode.get(0))) + filteredReferencingLinks = testWhetherReferencingLinksAreInFilter(transformedCoord, waysThatReferenceNode); + else + filteredReferencingLinks = Collections.emptyList(); + + ProcessedOsmNode result = new ProcessedOsmNode(osmNode.getId(), filteredReferencingLinks, transformedCoord); + this.nodes.put(result.getId(), result); + + if (nodes.size() % 100000 == 0) { + log.info("Added " + numberFormat.format(nodes.size()) + " nodes"); + } + } + } + + void handleWay(OsmWay osmWay) { + + Map tags = OsmModelUtil.getTagsAsMap(osmWay); + + if (isStreetOfInterest(tags)) { + LinkProperties linkProperty = linkProperties.get(tags.get(OsmTags.RAILWAY)); + ProcessedOsmWay processedWay = ProcessedOsmWay.create(osmWay, tags, linkProperty); + ways.put(osmWay.getId(), processedWay); + + // keep track of which node is referenced by which way + for (int i = 0; i < osmWay.getNumberOfNodes(); i++) { + + long nodeId = osmWay.getNodeId(i); + nodeReferences.computeIfAbsent(nodeId, id -> Collections.synchronizedList(new ArrayList<>())) + .add(processedWay); + } + + if (ways.size() % 10000 == 0) { + log.info("Added " + numberFormat.format(ways.size()) + " ways"); + } + } + } + + private boolean isStreetOfInterest(Map tags) { + return tags.containsKey(OsmTags.RAILWAY) && linkProperties.containsKey(tags.get(OsmTags.RAILWAY)); + } + + private boolean isEndNodeOfReferencingLink(OsmNode node, ProcessedOsmWay processedOsmWay) { + return processedOsmWay.getEndNodeId() == node.getId() || processedOsmWay.getStartNode() == node.getId(); + } + + private List testWhetherReferencingLinksAreInFilter(Coord coord, List waysThatReferenceNode) { + + return waysThatReferenceNode.stream() + .filter(way -> linkFilter.test(coord, way.getLinkProperties().hierarchyLevel)) + .collect(Collectors.toList()); + } +} diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java new file mode 100644 index 00000000000..faed409019c --- /dev/null +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java @@ -0,0 +1,66 @@ +package org.matsim.contrib.osm.networkReader; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.network.NetworkUtils; + +public final class OsmRailwayReader extends SupersonicOsmNetworkReader { + + public OsmRailwayReader(OsmNetworkParser parser, + Predicate preserveNodeWithId, + BiPredicate includeLinkAtCoordWithHierarchy, + AfterLinkCreated afterLinkCreated, double freeSpeedFactor, double adjustCapacityLength, boolean storeOriginalGeometry) { + + super(parser, preserveNodeWithId, includeLinkAtCoordWithHierarchy, (link, tags, direction) -> handleLink(link, tags, direction, afterLinkCreated), freeSpeedFactor, adjustCapacityLength, storeOriginalGeometry); + } + + private static void handleLink(Link link, Map tags, SupersonicOsmNetworkReader.Direction direction, AfterLinkCreated outfacingCallback) { + + String railwayType = tags.get(OsmTags.RAILWAY); + link.getAttributes().putAttribute("osm_way_type", "railway"); + link.getAttributes().putAttribute(NetworkUtils.TYPE, railwayType); + + for (String tag : tags.keySet()) { + link.getAttributes().putAttribute(tag, tags.get(tag)); + } + + setAllowedModes(link, tags); + + outfacingCallback.accept(link, tags, direction); + } + + private static void setAllowedModes(Link link, Map tags) { + if (tags.containsKey(OsmTags.SERVICE) && tags.get(OsmTags.SERVICE).equals("yard")) { + Set allowedModes = new HashSet<>(); + link.setAllowedModes(allowedModes); + } else { + // everything else should be allowed for rail + Set allowedModes = new HashSet<>(); + allowedModes.add("rail"); + link.setAllowedModes(allowedModes); + } + } + + @Override + Collection createLinks(WaySegment segment) { + Collection links = super.createLinks(segment); + return links; + } + + public static class Builder extends AbstractBuilder { + + @Override + OsmRailwayReader createInstance() { + OsmRailwayParser parser = new OsmRailwayParser(coordinateTransformation, linkProperties, includeLinkAtCoordWithHierarchy, Executors.newWorkStealingPool()); + return new OsmRailwayReader(parser, preserveNodeWithId, includeLinkAtCoordWithHierarchy, afterLinkCreated, freeSpeedFactor, adjustCapacityLength, storeOriginalGeometry); + } + } +} diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java index 4d18e1c6d22..22cba7f7c83 100644 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java @@ -42,4 +42,14 @@ public class OsmTags { public static final String CROSSING = "crossing"; public static final String TYPE = "type"; public static final String RESTRICTION = "restriction"; + + public static final String RAILWAY = "railway"; + public static final String RAIL = "rail"; + public static final String NARROW_GAUGE = "narrow_gauge"; + public static final String TRAM = "tram"; + public static final String FUNICULAR = "funicular"; + public static final String SUBWAY = "subway"; + public static final String LIGHT_RAIL = "light_rail"; + public static final String MONORAIL = "monorail"; + public static final String USAGE = "usage"; } diff --git a/contribs/railsim/pom.xml b/contribs/railsim/pom.xml index b6172ab206c..5398dba3ae7 100644 --- a/contribs/railsim/pom.xml +++ b/contribs/railsim/pom.xml @@ -28,6 +28,13 @@ mockito-core test + + + org.matsim.contrib + osm + 16.0-SNAPSHOT + compile + diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/RunRailsimExample.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/RunRailsimExample.java index e4f69dbb5b7..5b5343ed8f6 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/RunRailsimExample.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/RunRailsimExample.java @@ -19,7 +19,6 @@ package ch.sbb.matsim.contrib.railsim; -import ch.sbb.matsim.contrib.railsim.qsimengine.RailsimQSimModule; import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -27,6 +26,8 @@ import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.scenario.ScenarioUtils; +import ch.sbb.matsim.contrib.railsim.qsimengine.RailsimQSimModule; + /** * Example script that shows how to use railsim included in this contrib. */ @@ -37,12 +38,13 @@ private RunRailsimExample() { public static void main(String[] args) { - if (args.length == 0) { - System.err.println("Path to config is required as first argument."); - System.exit(2); + String configFilename; + if (args.length != 0) { + configFilename = args[0]; + } else { + configFilename = "test/input/ch/sbb/matsim/contrib/railsim/integration/microOlten/config.xml"; } - String configFilename = args[0]; Config config = ConfigUtils.loadConfig(configFilename); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java new file mode 100644 index 00000000000..841e535f50a --- /dev/null +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java @@ -0,0 +1,43 @@ +package ch.sbb.matsim.contrib.railsim.prepare; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.NetworkWriter; +import org.matsim.contrib.osm.networkReader.LinkProperties; +import org.matsim.contrib.osm.networkReader.OsmRailwayReader; +import org.matsim.contrib.osm.networkReader.OsmTags; +import org.matsim.core.network.algorithms.NetworkCleaner; +import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; + +public class RunRailOsmNetworkReader { + + private static final String inputFile = "path/to/file.osm.pbf"; + private static final String outputFile = "path/to/network.xml.gz"; + + private static final CoordinateTransformation coordinateTransformation = TransformationFactory.getCoordinateTransformation(TransformationFactory.WGS84, "EPSG:2056"); + + public static void main(String[] args) { + + ConcurrentMap linkProperties = new ConcurrentHashMap<>(); + linkProperties.put(OsmTags.RAIL, new LinkProperties(1, 1, 30., 1000., false)); + linkProperties.put(OsmTags.NARROW_GAUGE, new LinkProperties(2, 1, 30., 1000., false)); + linkProperties.put(OsmTags.LIGHT_RAIL, new LinkProperties(3, 1, 30., 1000., false)); + linkProperties.put(OsmTags.SUBWAY, new LinkProperties(4, 1, 30., 1000., false)); + linkProperties.put(OsmTags.MONORAIL, new LinkProperties(5, 1, 30., 1000., false)); + + Network network = new OsmRailwayReader.Builder() + .setCoordinateTransformation(coordinateTransformation) + .setLinkProperties(linkProperties) + .setPreserveNodeWithId(id -> true) // this filter keeps the detailed geometries + .build() + .read(inputFile); + + network.getAttributes().putAttribute("data_origin", "OSM"); + + new NetworkCleaner().run(network); + new NetworkWriter(network).write(outputFile); + } +} From 6a6b49f36f3fc63feec064afeacf4aa3b3fe332f Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Tue, 26 Mar 2024 11:13:23 +0100 Subject: [PATCH 03/10] improved setting of attributes --- .../osm/networkReader/OsmRailwayReader.java | 65 +++++++++++++++---- .../contrib/osm/networkReader/OsmTags.java | 6 ++ .../prepare/RunRailOsmNetworkReader.java | 26 +++----- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java index faed409019c..a2d6ffbf0e9 100644 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java @@ -4,6 +4,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executors; import java.util.function.BiPredicate; import java.util.function.Predicate; @@ -28,25 +30,49 @@ private static void handleLink(Link link, Map tags, SupersonicOs link.getAttributes().putAttribute("osm_way_type", "railway"); link.getAttributes().putAttribute(NetworkUtils.TYPE, railwayType); - for (String tag : tags.keySet()) { - link.getAttributes().putAttribute(tag, tags.get(tag)); - } - + setAttributes(link, tags); setAllowedModes(link, tags); + setSpeed(link, tags); outfacingCallback.accept(link, tags, direction); } - private static void setAllowedModes(Link link, Map tags) { - if (tags.containsKey(OsmTags.SERVICE) && tags.get(OsmTags.SERVICE).equals("yard")) { - Set allowedModes = new HashSet<>(); - link.setAllowedModes(allowedModes); - } else { - // everything else should be allowed for rail - Set allowedModes = new HashSet<>(); - allowedModes.add("rail"); - link.setAllowedModes(allowedModes); + private static void setSpeed(Link link, Map tags) { + + } + + private static void setAttributes(Link link, Map tags) { + + if (tags.containsKey(OsmTags.USAGE)) { + link.getAttributes().putAttribute(OsmTags.USAGE, tags.get(OsmTags.USAGE)); + } + + if (tags.containsKey(OsmTags.GAUGE)) { + link.getAttributes().putAttribute(OsmTags.GAUGE, tags.get(OsmTags.GAUGE)); } + + if (tags.containsKey(OsmTags.ELECTRIFIED)) { + link.getAttributes().putAttribute(OsmTags.ELECTRIFIED, tags.get(OsmTags.ELECTRIFIED)); + } + + if (tags.containsKey(OsmTags.MAXSPEED)) { + link.getAttributes().putAttribute(OsmTags.MAXSPEED, tags.get(OsmTags.MAXSPEED)); + } + + if (tags.containsKey(OsmTags.ETCS)) { + link.getAttributes().putAttribute(OsmTags.ETCS, tags.get(OsmTags.ETCS)); + } + + if (tags.containsKey(OsmTags.OPERATOR)) { + link.getAttributes().putAttribute(OsmTags.OPERATOR, tags.get(OsmTags.OPERATOR)); + } + + } + + private static void setAllowedModes(Link link, Map tags) { + Set allowedModes = new HashSet<>(); + allowedModes.add(tags.get(OsmTags.RAILWAY)); + link.setAllowedModes(allowedModes); } @Override @@ -57,6 +83,19 @@ Collection createLinks(WaySegment segment) { public static class Builder extends AbstractBuilder { + public Builder() { + ConcurrentMap linkProperties = new ConcurrentHashMap<>(); + linkProperties.put(OsmTags.RAIL, new LinkProperties(1, 1, 30., 1000., false)); + linkProperties.put(OsmTags.NARROW_GAUGE, new LinkProperties(2, 1, 30., 1000., false)); + linkProperties.put(OsmTags.LIGHT_RAIL, new LinkProperties(3, 1, 30., 1000., false)); + linkProperties.put(OsmTags.MONORAIL, new LinkProperties(4, 1, 30., 1000., false)); + linkProperties.put(OsmTags.FUNICULAR, new LinkProperties(5, 1, 30., 1000., false)); + linkProperties.put(OsmTags.SUBWAY, new LinkProperties(6, 1, 30., 1000., false)); + linkProperties.put(OsmTags.TRAM, new LinkProperties(7, 1, 30., 1000., false)); + + setLinkProperties(linkProperties); + } + @Override OsmRailwayReader createInstance() { OsmRailwayParser parser = new OsmRailwayParser(coordinateTransformation, linkProperties, includeLinkAtCoordWithHierarchy, Executors.newWorkStealingPool()); diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java index 22cba7f7c83..0c5dc5d6cb2 100644 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmTags.java @@ -52,4 +52,10 @@ public class OsmTags { public static final String LIGHT_RAIL = "light_rail"; public static final String MONORAIL = "monorail"; public static final String USAGE = "usage"; + public static final String GAUGE = "gauge"; + public static final String ELECTRIFIED = "electrified"; + public static final String ETCS = "etcs"; + public static final String OPERATOR = "operator"; + + } diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java index 841e535f50a..f483d5c5185 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java @@ -1,43 +1,35 @@ package ch.sbb.matsim.contrib.railsim.prepare; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.network.NetworkWriter; -import org.matsim.contrib.osm.networkReader.LinkProperties; import org.matsim.contrib.osm.networkReader.OsmRailwayReader; -import org.matsim.contrib.osm.networkReader.OsmTags; import org.matsim.core.network.algorithms.NetworkCleaner; import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.transformations.TransformationFactory; public class RunRailOsmNetworkReader { - private static final String inputFile = "path/to/file.osm.pbf"; - private static final String outputFile = "path/to/network.xml.gz"; + private static final String baseDirectory = "path/to/directory/"; + + private static final String inputFile = baseDirectory + "switzerland-latest.osm.pbf"; + private static final String outputFile1 = baseDirectory + "switzerland_network.xml.gz"; + private static final String outputFile2 = baseDirectory + "switzerland_network_cleaned.xml.gz"; private static final CoordinateTransformation coordinateTransformation = TransformationFactory.getCoordinateTransformation(TransformationFactory.WGS84, "EPSG:2056"); public static void main(String[] args) { - - ConcurrentMap linkProperties = new ConcurrentHashMap<>(); - linkProperties.put(OsmTags.RAIL, new LinkProperties(1, 1, 30., 1000., false)); - linkProperties.put(OsmTags.NARROW_GAUGE, new LinkProperties(2, 1, 30., 1000., false)); - linkProperties.put(OsmTags.LIGHT_RAIL, new LinkProperties(3, 1, 30., 1000., false)); - linkProperties.put(OsmTags.SUBWAY, new LinkProperties(4, 1, 30., 1000., false)); - linkProperties.put(OsmTags.MONORAIL, new LinkProperties(5, 1, 30., 1000., false)); Network network = new OsmRailwayReader.Builder() .setCoordinateTransformation(coordinateTransformation) - .setLinkProperties(linkProperties) - .setPreserveNodeWithId(id -> true) // this filter keeps the detailed geometries + .setPreserveNodeWithId(id -> true) // this filter keeps the detailed geometries, only required for cosmetic reasons .build() .read(inputFile); network.getAttributes().putAttribute("data_origin", "OSM"); + new NetworkWriter(network).write(outputFile1); + new NetworkCleaner().run(network); - new NetworkWriter(network).write(outputFile); + new NetworkWriter(network).write(outputFile2); } } From 1d2dc59747e768af5e7d667f9045b487e8b1d4b3 Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Tue, 26 Mar 2024 11:43:28 +0100 Subject: [PATCH 04/10] add an alternative constructor which allows for other way types, e.g. railway --- .../osm/networkReader/OsmNetworkParser.java | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmNetworkParser.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmNetworkParser.java index 168f57ace1a..4f4e9f72fe2 100644 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmNetworkParser.java +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmNetworkParser.java @@ -28,12 +28,39 @@ class OsmNetworkParser { Map ways; Map nodes; Map> nodeReferences; - + private final String wayType; + + /** + * The default constructor for roads (OSM highway tag) + * + * @param transformation + * @param linkProperties + * @param linkFilter + * @param executor + */ OsmNetworkParser(CoordinateTransformation transformation, Map linkProperties, BiPredicate linkFilter, ExecutorService executor) { this.transformation = transformation; this.linkProperties = linkProperties; this.linkFilter = linkFilter; this.executor = executor; + this.wayType = OsmTags.HIGHWAY; + } + + /** + * A more flexible constructor which allows to pass a different way type, e.g. railway + * + * @param transformation + * @param linkProperties + * @param linkFilter + * @param executor + * @param wayType + */ + OsmNetworkParser(CoordinateTransformation transformation, Map linkProperties, BiPredicate linkFilter, ExecutorService executor, String wayType) { + this.transformation = transformation; + this.linkProperties = linkProperties; + this.linkFilter = linkFilter; + this.executor = executor; + this.wayType = wayType; } public Map getWays() { @@ -106,7 +133,7 @@ void handleWay(OsmWay osmWay) { Map tags = OsmModelUtil.getTagsAsMap(osmWay); if (isStreetOfInterest(tags)) { - LinkProperties linkProperty = linkProperties.get(tags.get(OsmTags.HIGHWAY)); + LinkProperties linkProperty = linkProperties.get(tags.get(wayType)); ProcessedOsmWay processedWay = ProcessedOsmWay.create(osmWay, tags, linkProperty); ways.put(osmWay.getId(), processedWay); @@ -125,7 +152,7 @@ void handleWay(OsmWay osmWay) { } private boolean isStreetOfInterest(Map tags) { - return tags.containsKey(OsmTags.HIGHWAY) && linkProperties.containsKey(tags.get(OsmTags.HIGHWAY)); + return tags.containsKey(wayType) && linkProperties.containsKey(tags.get(wayType)); } private boolean isEndNodeOfReferencingLink(OsmNode node, ProcessedOsmWay processedOsmWay) { From b74fdd29650ae5b349909ee477196b52b4b3a6a0 Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Tue, 26 Mar 2024 11:45:08 +0100 Subject: [PATCH 05/10] use more generic osm network parser --- .../org/matsim/contrib/osm/networkReader/OsmRailwayReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java index a2d6ffbf0e9..be35630e2a5 100644 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java @@ -98,7 +98,7 @@ public Builder() { @Override OsmRailwayReader createInstance() { - OsmRailwayParser parser = new OsmRailwayParser(coordinateTransformation, linkProperties, includeLinkAtCoordWithHierarchy, Executors.newWorkStealingPool()); + OsmNetworkParser parser = new OsmNetworkParser(coordinateTransformation, linkProperties, includeLinkAtCoordWithHierarchy, Executors.newWorkStealingPool(), OsmTags.RAILWAY); return new OsmRailwayReader(parser, preserveNodeWithId, includeLinkAtCoordWithHierarchy, afterLinkCreated, freeSpeedFactor, adjustCapacityLength, storeOriginalGeometry); } } From cfff352ec7534eb53228c7423e47a4eec016b7d4 Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Tue, 26 Mar 2024 11:45:27 +0100 Subject: [PATCH 06/10] remove first copy paste approach --- .../osm/networkReader/OsmRailwayParser.java | 143 ------------------ 1 file changed, 143 deletions(-) delete mode 100644 contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java deleted file mode 100644 index 3e9c9053b55..00000000000 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayParser.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.matsim.contrib.osm.networkReader; - -import de.topobyte.osm4j.core.model.iface.OsmNode; -import de.topobyte.osm4j.core.model.iface.OsmWay; -import de.topobyte.osm4j.core.model.util.OsmModelUtil; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.matsim.api.core.v01.Coord; -import org.matsim.core.utils.geometry.CoordinateTransformation; - -import java.nio.file.Path; -import java.text.NumberFormat; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.function.BiPredicate; -import java.util.stream.Collectors; - -class OsmRailwayParser extends OsmNetworkParser { - - private static final Logger log = LogManager.getLogger(OsmRailwayParser.class); - private static final NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.UK); - - private final CoordinateTransformation transformation; - private final Map linkProperties; - private final BiPredicate linkFilter; - final ExecutorService executor; - Map ways; - Map nodes; - Map> nodeReferences; - - OsmRailwayParser(CoordinateTransformation transformation, Map linkProperties, BiPredicate linkFilter, ExecutorService executor) { - super(transformation, linkProperties, linkFilter, executor); - - this.transformation = transformation; - this.linkProperties = linkProperties; - this.linkFilter = linkFilter; - this.executor = executor; - } - - public Map getWays() { - return ways; - } - - public Map getNodes() { - return nodes; - } - - void parse(Path inputFile) { - - // make sure we have empty collections - ways = new ConcurrentHashMap<>(); - nodes = new ConcurrentHashMap<>(); - nodeReferences = new ConcurrentHashMap<>(); - - new PbfParser.Builder() - .setWaysHandler(this::handleWay) - .setExecutor(executor) - .build() - .parse(inputFile); - - log.info("Finished reading ways"); - log.info("Starting to read nodes"); - - new PbfParser.Builder() - .setNodeHandler(this::handleNode) - .setExecutor(executor) - .build() - .parse(inputFile); - - log.info("finished reading nodes"); - } - - void handleNode(OsmNode osmNode) { - - if (nodeReferences.containsKey(osmNode.getId())) { - - List waysThatReferenceNode = nodeReferences.get(osmNode.getId()); - Coord transformedCoord = transformation.transform(new Coord(osmNode.getLongitude(), osmNode.getLatitude())); - - // 'testWhetherReferencingLinksAreInFilter' may be expensive because it might include a test whether the - // supplied coordinate is within a shape. Therefore we want to test as few cases as possible. Two cases are tested anyway: - // 1. if more than one way references this node, this node is an intersection and a possible end node for a - // matsim link. - // 2. if this node is either the start- or end node of a referencing way which makes it a candidate for a node - // in a matsim link as well - // - // if a way has both ends outside the filter and no intersections within the filter it will not be included - // in the final network. I think this is unlikely in real world scenarios, so I think we can live with this - // to achieve faster execution - List filteredReferencingLinks; - if (waysThatReferenceNode.size() > 1 || isEndNodeOfReferencingLink(osmNode, waysThatReferenceNode.get(0))) - filteredReferencingLinks = testWhetherReferencingLinksAreInFilter(transformedCoord, waysThatReferenceNode); - else - filteredReferencingLinks = Collections.emptyList(); - - ProcessedOsmNode result = new ProcessedOsmNode(osmNode.getId(), filteredReferencingLinks, transformedCoord); - this.nodes.put(result.getId(), result); - - if (nodes.size() % 100000 == 0) { - log.info("Added " + numberFormat.format(nodes.size()) + " nodes"); - } - } - } - - void handleWay(OsmWay osmWay) { - - Map tags = OsmModelUtil.getTagsAsMap(osmWay); - - if (isStreetOfInterest(tags)) { - LinkProperties linkProperty = linkProperties.get(tags.get(OsmTags.RAILWAY)); - ProcessedOsmWay processedWay = ProcessedOsmWay.create(osmWay, tags, linkProperty); - ways.put(osmWay.getId(), processedWay); - - // keep track of which node is referenced by which way - for (int i = 0; i < osmWay.getNumberOfNodes(); i++) { - - long nodeId = osmWay.getNodeId(i); - nodeReferences.computeIfAbsent(nodeId, id -> Collections.synchronizedList(new ArrayList<>())) - .add(processedWay); - } - - if (ways.size() % 10000 == 0) { - log.info("Added " + numberFormat.format(ways.size()) + " ways"); - } - } - } - - private boolean isStreetOfInterest(Map tags) { - return tags.containsKey(OsmTags.RAILWAY) && linkProperties.containsKey(tags.get(OsmTags.RAILWAY)); - } - - private boolean isEndNodeOfReferencingLink(OsmNode node, ProcessedOsmWay processedOsmWay) { - return processedOsmWay.getEndNodeId() == node.getId() || processedOsmWay.getStartNode() == node.getId(); - } - - private List testWhetherReferencingLinksAreInFilter(Coord coord, List waysThatReferenceNode) { - - return waysThatReferenceNode.stream() - .filter(way -> linkFilter.test(coord, way.getLinkProperties().hierarchyLevel)) - .collect(Collectors.toList()); - } -} From 49e34dac71e340b55e5f6e2cdb4466242f438cf7 Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Tue, 26 Mar 2024 12:56:42 +0100 Subject: [PATCH 07/10] adjust the railway defaults --- .../osm/networkReader/OsmRailwayReader.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java index be35630e2a5..d20d7693ef7 100644 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java @@ -15,6 +15,8 @@ import org.matsim.core.network.NetworkUtils; public final class OsmRailwayReader extends SupersonicOsmNetworkReader { + + private static final double FALLBACK_MAX_SPEED = 100.; public OsmRailwayReader(OsmNetworkParser parser, Predicate preserveNodeWithId, @@ -57,6 +59,8 @@ private static void setAttributes(Link link, Map tags) { if (tags.containsKey(OsmTags.MAXSPEED)) { link.getAttributes().putAttribute(OsmTags.MAXSPEED, tags.get(OsmTags.MAXSPEED)); + } else { + link.getAttributes().putAttribute(OsmTags.MAXSPEED, FALLBACK_MAX_SPEED); } if (tags.containsKey(OsmTags.ETCS)) { @@ -86,12 +90,12 @@ public static class Builder extends AbstractBuilder { public Builder() { ConcurrentMap linkProperties = new ConcurrentHashMap<>(); linkProperties.put(OsmTags.RAIL, new LinkProperties(1, 1, 30., 1000., false)); - linkProperties.put(OsmTags.NARROW_GAUGE, new LinkProperties(2, 1, 30., 1000., false)); - linkProperties.put(OsmTags.LIGHT_RAIL, new LinkProperties(3, 1, 30., 1000., false)); - linkProperties.put(OsmTags.MONORAIL, new LinkProperties(4, 1, 30., 1000., false)); - linkProperties.put(OsmTags.FUNICULAR, new LinkProperties(5, 1, 30., 1000., false)); - linkProperties.put(OsmTags.SUBWAY, new LinkProperties(6, 1, 30., 1000., false)); - linkProperties.put(OsmTags.TRAM, new LinkProperties(7, 1, 30., 1000., false)); + linkProperties.put(OsmTags.NARROW_GAUGE, new LinkProperties(1, 1, 30., 1000., false)); + linkProperties.put(OsmTags.LIGHT_RAIL, new LinkProperties(1, 1, 30., 1000., false)); + linkProperties.put(OsmTags.MONORAIL, new LinkProperties(1, 1, 30., 1000., false)); + linkProperties.put(OsmTags.FUNICULAR, new LinkProperties(1, 1, 30., 1000., false)); + linkProperties.put(OsmTags.SUBWAY, new LinkProperties(1, 1, 30., 1000., false)); + linkProperties.put(OsmTags.TRAM, new LinkProperties(1, 1, 30., 1000., false)); setLinkProperties(linkProperties); } From c1df036411acab2e83f5eb8dab005c3ea0ec5633 Mon Sep 17 00:00:00 2001 From: ikaddoura Date: Tue, 9 Apr 2024 11:20:51 +0200 Subject: [PATCH 08/10] remove dependency to osm contrib --- contribs/railsim/pom.xml | 7 ---- .../prepare/RunRailOsmNetworkReader.java | 35 ------------------- 2 files changed, 42 deletions(-) delete mode 100644 contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java diff --git a/contribs/railsim/pom.xml b/contribs/railsim/pom.xml index 5398dba3ae7..b6172ab206c 100644 --- a/contribs/railsim/pom.xml +++ b/contribs/railsim/pom.xml @@ -28,13 +28,6 @@ mockito-core test - - - org.matsim.contrib - osm - 16.0-SNAPSHOT - compile - diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java deleted file mode 100644 index f483d5c5185..00000000000 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/prepare/RunRailOsmNetworkReader.java +++ /dev/null @@ -1,35 +0,0 @@ -package ch.sbb.matsim.contrib.railsim.prepare; - -import org.matsim.api.core.v01.network.Network; -import org.matsim.api.core.v01.network.NetworkWriter; -import org.matsim.contrib.osm.networkReader.OsmRailwayReader; -import org.matsim.core.network.algorithms.NetworkCleaner; -import org.matsim.core.utils.geometry.CoordinateTransformation; -import org.matsim.core.utils.geometry.transformations.TransformationFactory; - -public class RunRailOsmNetworkReader { - - private static final String baseDirectory = "path/to/directory/"; - - private static final String inputFile = baseDirectory + "switzerland-latest.osm.pbf"; - private static final String outputFile1 = baseDirectory + "switzerland_network.xml.gz"; - private static final String outputFile2 = baseDirectory + "switzerland_network_cleaned.xml.gz"; - - private static final CoordinateTransformation coordinateTransformation = TransformationFactory.getCoordinateTransformation(TransformationFactory.WGS84, "EPSG:2056"); - - public static void main(String[] args) { - - Network network = new OsmRailwayReader.Builder() - .setCoordinateTransformation(coordinateTransformation) - .setPreserveNodeWithId(id -> true) // this filter keeps the detailed geometries, only required for cosmetic reasons - .build() - .read(inputFile); - - network.getAttributes().putAttribute("data_origin", "OSM"); - - new NetworkWriter(network).write(outputFile1); - - new NetworkCleaner().run(network); - new NetworkWriter(network).write(outputFile2); - } -} From 9d45f37cef8a8eff2ab8e48e744ff386677bfb8c Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Mon, 22 Apr 2024 08:25:34 +0200 Subject: [PATCH 09/10] mostly comments; some refactoring --- .../RunOneTaxiWithPrebookingExampleIT.java | 16 +-- .../mobsim/qsim/PreplanningEngineTest.java | 77 ++++++++++++ .../drtAndPt/PtAlongALine2Test.java | 9 +- .../mobsim/qsim/ActivityEngineWithWakeup.java | 5 +- .../core/mobsim/qsim/PreplanningEngine.java | 116 +++++++++++------- .../core/mobsim/qsim/PreplanningUtils.java | 15 +++ .../components/QSimComponentsConfigGroup.java | 9 ++ 7 files changed, 191 insertions(+), 56 deletions(-) create mode 100644 contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java create mode 100644 matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningUtils.java diff --git a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/examples/onetaxi/RunOneTaxiWithPrebookingExampleIT.java b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/examples/onetaxi/RunOneTaxiWithPrebookingExampleIT.java index b6661027c45..a5d8baff1cf 100644 --- a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/examples/onetaxi/RunOneTaxiWithPrebookingExampleIT.java +++ b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/examples/onetaxi/RunOneTaxiWithPrebookingExampleIT.java @@ -47,16 +47,14 @@ import org.matsim.contrib.dvrp.run.DvrpModule; import org.matsim.contrib.dvrp.run.DvrpQSimComponents; import org.matsim.api.core.v01.events.HasPersonId; +import org.matsim.contrib.otfvis.OTFVisLiveModule; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.events.handler.BasicEventHandler; -import org.matsim.core.mobsim.qsim.AbstractQSimModule; -import org.matsim.core.mobsim.qsim.ActivityEngineModule; -import org.matsim.core.mobsim.qsim.ActivityEngineWithWakeup; -import org.matsim.core.mobsim.qsim.PreplanningEngine; +import org.matsim.core.mobsim.qsim.*; import org.matsim.core.mobsim.qsim.components.QSimComponentsConfigGroup; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.io.IOUtils; @@ -96,9 +94,7 @@ void testRun() { Scenario scenario = ScenarioUtils.loadScenario(config); for (Person person : scenario.getPopulation().getPersons().values()) { - person.getSelectedPlan() - .getAttributes() - .putAttribute(PreplanningEngine.PREBOOKING_OFFSET_ATTRIBUTE_NAME, 900.); + PreplanningUtils.setPrebookingOffset_s( person.getSelectedPlan(), 900. ); } //PopulationUtils.writePopulation(scenario.getPopulation(), utils.getOutputDirectory() + "/../pop.xml"); @@ -158,6 +154,12 @@ public void install() { } }); + if ("true".equals(System.getProperty("runOTFVis"))) { + // This will start otfvis + controler.addOverridingModule(new OTFVisLiveModule() ); + // !! does not work together with parameterized tests :-( !! + } + // run simulation controler.run(); diff --git a/contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java b/contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java new file mode 100644 index 00000000000..74536deae58 --- /dev/null +++ b/contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java @@ -0,0 +1,77 @@ +package org.matsim.core.mobsim.qsim; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.otfvis.OTFVisLiveModule; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.Controler; +import org.matsim.core.mobsim.qsim.components.QSimComponentsConfigGroup; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.testcases.MatsimTestUtils; + +import javax.inject.Singleton; + +class PreplanningEngineTest{ + // Cannot use otfvis if in core matsim. --> In vsp contrib for time being. kai, apr'24 + private static final Logger log = LogManager.getLogger(PreplanningEngineTest.class ); + + @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); + + @Test public void test() { + // I am interested here in testing this NOT with DRT but with other modes. kai, apr'24 + // In the somewhat longer run, should work together with fleetpy (of TUM). kai, apr'24 + + Config config = ConfigUtils.loadConfig( IOUtils.extendUrl( ExamplesUtils.getTestScenarioURL( "equil" ), "config.xml" ) ); + + config.controller().setOutputDirectory( utils.getOutputDirectory() ); + config.controller().setLastIteration( 0 ); + + QSimComponentsConfigGroup componentsConfig = ConfigUtils.addOrGetModule( config, QSimComponentsConfigGroup.class ); + + componentsConfig.removeActiveComponent( ActivityEngineModule.COMPONENT_NAME ); + componentsConfig.addActiveComponent( ActivityEngineWithWakeup.COMPONENT_NAME ); + + componentsConfig.addActiveComponent( PreplanningEngineQSimModule.COMPONENT_NAME ); + + Scenario scenario = ScenarioUtils.loadScenario( config ); + for( Person person : scenario.getPopulation().getPersons().values() ){ + PreplanningUtils.setPrebookingOffset_s( person.getSelectedPlan(), 900. ); + } + + Controler controler = new Controler( scenario ); + + controler.addOverridingQSimModule( new AbstractQSimModule(){ + @Override protected void configureQSim(){ + bind(PreplanningEngine.class).asEagerSingleton(); + addQSimComponentBinding(PreplanningEngineQSimModule.COMPONENT_NAME).to(PreplanningEngine.class).in( Singleton.class ); + // Does the following: + // * on prepare sim: register all departure handlers that implement the TripInfo.Provider interface + // * + + // the above just installs the functionality; it also needs to be requested (from config). + + // needs to go along with ActivityEngineWithWakeup. complains if not bound. + // yy is, however, ok if bound but not activated. --?? --> should end up in same module! + + addQSimComponentBinding( ActivityEngineWithWakeup.COMPONENT_NAME ).to( ActivityEngineWithWakeup.class ).in( Singleton.class ); + + } + } ); + + if ("true".equals(System.getProperty("runOTFVis"))) { + // This will start otfvis if property is set + controler.addOverridingModule(new OTFVisLiveModule() ); + // !! does not work together with parameterized tests :-( !! + } + + controler.run(); + } + +} diff --git a/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java b/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java index 7d884443580..3a1e217d4f4 100644 --- a/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java +++ b/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java @@ -45,10 +45,7 @@ import org.matsim.core.controler.Controler; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.listener.IterationEndsListener; -import org.matsim.core.mobsim.qsim.AbstractQSimModule; -import org.matsim.core.mobsim.qsim.ActivityEngineModule; -import org.matsim.core.mobsim.qsim.ActivityEngineWithWakeup; -import org.matsim.core.mobsim.qsim.PreplanningEngine; +import org.matsim.core.mobsim.qsim.*; import org.matsim.core.mobsim.qsim.components.QSimComponentsConfigGroup; import org.matsim.core.router.AnalysisMainModeIdentifier; import org.matsim.core.router.TripStructureUtils; @@ -321,9 +318,7 @@ void testPtAlongALineWithRaptorAndDrtServiceArea() { } if (drtMode == DrtMode.withPrebooking) { for (Person person : scenario.getPopulation().getPersons().values()) { - person.getSelectedPlan() - .getAttributes() - .putAttribute(PreplanningEngine.PREBOOKING_OFFSET_ATTRIBUTE_NAME, 7200.); + PreplanningUtils.setPrebookingOffset_s( person.getSelectedPlan(), 7200. ); } } diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/ActivityEngineWithWakeup.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/ActivityEngineWithWakeup.java index b23b695b9d4..64d9e9a3319 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/ActivityEngineWithWakeup.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/ActivityEngineWithWakeup.java @@ -26,6 +26,8 @@ import jakarta.inject.Inject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.population.Activity; @@ -37,7 +39,7 @@ public final class ActivityEngineWithWakeup implements ActivityEngine { public static final String COMPONENT_NAME = "ActivityEngineWithWakeup"; - + private static final Logger log = LogManager.getLogger(ActivityEngineWithWakeup.class ); private final EventsManager eventsManager; private final PreplanningEngine preplanningEngine; private final ActivityEngine delegate; @@ -55,6 +57,7 @@ public final class ActivityEngineWithWakeup implements ActivityEngine { @Override public void onPrepareSim() { + log.warn( "running onPrepareSim"); delegate.onPrepareSim(); } diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningEngine.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningEngine.java index 0f34e2d4a5b..5232b826ccf 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningEngine.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningEngine.java @@ -72,11 +72,12 @@ import com.google.inject.Inject; public final class PreplanningEngine implements MobsimEngine { - // Could implement this as a generalized version of the bdi-abm implementation: can send notifications to agent, and agent can react. Similar to the drive-to action. - // Notifications and corresponding handlers could then be registered. On the other hand, it is easy to add an engine such as this one; how much does it help to have another - // layer of infrastructure? Am currently leaning towards the second argument. kai, mar'19 + // Could implement this as a generalized version of the bdi-abm implementation: can send notifications to agent, and agent can react. Similar + // to the drive-to action. Notifications and corresponding handlers could then be registered. - public static final String PREBOOKING_OFFSET_ATTRIBUTE_NAME = "prebookingOffset_s"; + // On the other hand, it is easy to add an engine such as this one; how much does it help to have another layer of infrastructure? + + // Am currently leaning towards the second argument. kai, mar'19 private static final Logger log = LogManager.getLogger(PreplanningEngine.class); @@ -93,9 +94,11 @@ public final class PreplanningEngine implements MobsimEngine { private final Map> tripInfoUpdatesMap = new TreeMap<>(comparing(Identifiable::getId )); // yyyy not sure about possible race conditions here! kai, feb'19 // yyyyyy can't have non-sorted maps here because we will get non-deterministic results. kai, mar'19 + // (haven't these two points be fixed by using the "comparing"? kai, apr'24) private final Map tripInfoRequestMap = new TreeMap<>(comparing(Identifiable::getId )); // yyyyyy can't have non-sorted maps here because we will get non-deterministic results. kai, mar'19 + // (hasn't this point be fixed by using the "comparing"? kai, apr'24) private EditPlans editPlans; @@ -113,6 +116,7 @@ public final class PreplanningEngine implements MobsimEngine { } @Override public void onPrepareSim() { + log.warn( "running onPrepareSim"); for (DepartureHandler departureHandler : internalInterface.getDepartureHandlers()) { if (departureHandler instanceof TripInfo.Provider) { String mode = ((TripInfo.Provider)departureHandler).getMode(); @@ -136,7 +140,8 @@ public final class PreplanningEngine implements MobsimEngine { // (I have inlined the below methods since I find this for the time being easier to read. Can be extracted again at some later point in time . // kai, jan'20) - // process all (initial) requests: + // the following goes through all requests (generated by the agent wakups), send them to the trip info providers, and decide based on + // the returned information: for (Map.Entry entry : tripInfoRequestMap.entrySet()) { final MobsimAgent mobsimAgent = entry.getKey(); final TripInfo.Request request = entry.getValue(); @@ -149,11 +154,14 @@ public final class PreplanningEngine implements MobsimEngine { // TODO add info for mode that is in agent plan, if not returned by trip info provider // not sure if that is needed. kai, jan'20 + // the following method decides, and + // * puts it then into the tripInfoUpdatesMap (processed below); or + // * if the agent needs to wait for confirmation, the confirming method (currently only in PassengerEngineWithPrebooking) puts it into tripInfoUpdatesMap. decide( mobsimAgent, allTripInfos ); } tripInfoRequestMap.clear(); - // process all updates: + // process the tripInfoUpdatesMap (see above): for (Map.Entry> entry : tripInfoUpdatesMap.entrySet()) { MobsimAgent agent = entry.getKey(); @@ -163,6 +171,14 @@ public final class PreplanningEngine implements MobsimEngine { TripInfo actualTripInfo = tripInfo.get(); updateAgentPlan(agent, actualTripInfo); } else { + // this can e.g. happen if the booking failed. At first glance, I am not too happy about this. I think that if a + // provider is not able to process the trip, it should not return a TripInfo offer. At second glance, it may happen + // that no provider returns a TripInfo offer. Now evidently, this could be avoided by always allowing for a fallback + // mode, e.g. walk and/or pt. On the other hand, since the functionality is already here, we can as well try to keep + // it. However, need to make sure that it eventually gets resolved. Also see the questions below. + + // in principle, one could always give the pt TripOption. However, this would be fairly expensive to compute. + TripInfo.Request request = null; //TODO get it from where ??? from TripInfo??? //TODO agent should adapt trip info request given that the previous one got rejected?? @@ -175,8 +191,10 @@ public final class PreplanningEngine implements MobsimEngine { // (I have inlined the above methods since I find this for the time being easier to read. Can be extracted again at some later point in time . kai, jan'20) } - public synchronized final void notifyChangedTripInformation(MobsimAgent agent, Optional tripInfoUpdate) { + public synchronized void notifyChangedTripInformation( MobsimAgent agent, Optional tripInfoUpdate ) { // yyyy My IDE complains about "Optional" in method signatures. kai, jan'20 + // It looks like it needs to be possible to return an "empty" tripInfoUpdate in order to notify that the "decided" (= selected) trip + // option did not work out. Or, alternatively, none of the providers returned an answer at all. tripInfoUpdatesMap.put(agent, tripInfoUpdate); } @@ -195,7 +213,7 @@ private void decide(MobsimAgent agent, List allTripInfos) { } // to get started, we assume that we are only getting one drt option back. - // TODO: make complete + // yyyy TODO: evidently, this needs to be changed to mode choice between available modes. kai, apr'24 TripInfo tripInfo = allTripInfos.iterator().next(); if (tripInfo instanceof TripInfoWithRequiredBooking) { @@ -220,9 +238,15 @@ private void decide(MobsimAgent agent, List allTripInfos) { editPlans.rescheduleActivityEnd(agent); + // (if the trip requires booking, the booking confirmation comes later, so we need to delay the call to + // notifyChangedTripInformation until we have confirmation. The "notifyChangedTripInfo" is actually called from within dvrp (PassengerEngineWithPrebooking). ) } else { - notifyChangedTripInformation(agent, Optional.of(tripInfo));//no booking here + // if we do not have to wait for the booking confirmation, we can immediately compute and insert the trip. This is (once + // more) done by first collecting it into a container, and process the container later. To achieve thread safety, inserting + // it into the container is a "synchronized" method: + notifyChangedTripInformation(agent, Optional.of(tripInfo)); } + log.warn("---"); } @@ -232,12 +256,10 @@ List generateWakeups( MobsimAgent agent, do return Collections.emptyList(); } - - Double prebookingOffset_s = (Double)((PlanAgent)agent).getCurrentPlan().getAttributes().getAttribute(PREBOOKING_OFFSET_ATTRIBUTE_NAME); - // yyyy prebooking info needs to be in plan since it will not survive in the leg. :-( kai, jan'20 + final Double prebookingOffset_s = PreplanningUtils.getPrebookingOffset_s( ((PlanAgent) agent).getCurrentPlan() ); if (prebookingOffset_s == null) { - log.warn("The " + PREBOOKING_OFFSET_ATTRIBUTE_NAME + " is not set in the agent. No wakeup for prebooking will be generated."); + log.warn("The " + "prebookingOffset_s" + " is not set in the agent. No wakeup for prebooking will be generated." ); return Collections.emptyList(); } @@ -246,12 +268,16 @@ List generateWakeups( MobsimAgent agent, do for (String mode : new String[] { TransportMode.drt, TransportMode.taxi } ) { // (only do the following for drt and taxi yyyy which means it may fail for, say, "drt2". kai, apr'23) + // (not doing this for, say, pt, is fine, though. we could still have pt as fallback mode for drt/taxi.) + for (Leg drtLeg : EditPlans.findLegsWithModeInFuture(agent, mode )) { // (find the corresponding legs) final double prebookingTime = drtLeg.getDepartureTime().seconds() - prebookingOffset_s; if (prebookingTime < agent.getActivityEndTime()) { - // yyyy and here one sees that having this in the activity engine is not very practical + // (yyyy and here one sees that having this in the activity engine is not very practical) + + // ### the following inserts the preplanLeg (--> preplanTrip??), to be executed at wakeup: ### log.info("generating wakeup entry"); wakeups.add(new ActivityEngineWithWakeup.AgentEntry(agent, prebookingTime, (agent1, then) -> preplanLeg(agent1, then, drtLeg )) ); } @@ -299,6 +325,12 @@ private void preplanLeg( MobsimAgent agent, double now, Leg leg ) { //first simulate ActivityEngineWithWakeup and then PreplanningEngine --> decision process //in the same time step this.notifyTripInfoNeeded(agent, request); + + // (this enters the request into tripInfoRequestMap ... would be easier to read this if it was inlined ... but the method needs to be + // threadsafe and this is easier to achieve with a separate method. kai, apr'24) + + // (the tripInfoRequestMap will be processed in every time step. Not sure if we can enforce that this happens after processing the + // wakeups, so it may happen in the following time step (--???). This would contradict the comment above the method call. kai, apr'24 ) } private void updateAgentPlan(MobsimAgent agent, TripInfo tripInfo) { @@ -327,33 +359,47 @@ private void updateAgentPlan(MobsimAgent agent, TripInfo tripInfo) { } Gbl.assertNotNull(inputTrip); - List result = new ArrayList<>(); - inputTrip.getOriginActivity().setEndTime(tripInfo.getExpectedBoardingTime() - 900); // yyyy means for time being we always depart 15min before pickup. kai, mar'19 WithinDayAgentUtils.resetCaches(agent); log.warn("agentId=" + agent.getId() + " | newActEndTime=" + inputTrip.getOriginActivity() - .getEndTime() - .seconds()); + .getEndTime() + .seconds()); + + final List result = createDrtTripInclAccessEgress( tripInfo, inputTrip ); + + TripRouter.insertTrip(plan, inputTrip.getOriginActivity(), result, inputTrip.getDestinationActivity()); + + editPlans.rescheduleActivityEnd(agent); + // I don't think that this can ever do damage. + + log.warn("new plan for agentId=" + agent.getId()); + for (PlanElement planElement : plan.getPlanElements()) { + log.warn(planElement.toString()); + } + log.warn("---"); + + } + private List createDrtTripInclAccessEgress( TripInfo tripInfo, TripStructureUtils.Trip inputTrip ){ + // code below currently has taxi hardcoded but this is not necessary IMO. kai, apr'24 - // result.add( inputTrip.getOriginActivity() ) ; - // --- + List result = new ArrayList<>(); PopulationFactory pf = population.getFactory(); { - Facility fromFacility = FacilitiesUtils.toFacility(inputTrip.getOriginActivity(), facilities); + Facility fromFacility = FacilitiesUtils.toFacility( inputTrip.getOriginActivity(), facilities ); Facility toFacility = tripInfo.getPickupLocation(); double departureTime = tripInfo.getExpectedBoardingTime() - 900.; // always depart 15min before pickup List planElements = tripRouter.calcRoute(TransportMode.walk, fromFacility, - toFacility, departureTime, null, inputTrip.getTripAttributes()); + toFacility, departureTime, null, inputTrip.getTripAttributes() ); // not sure if this works for walk, but it should ... result.addAll(planElements); } { Activity act = pf.createActivityFromLinkId(createStageActivityType(TransportMode.taxi), - tripInfo.getPickupLocation().getLinkId()); + tripInfo.getPickupLocation().getLinkId() ); act.setMaximumDuration(0.); result.add(act); } @@ -362,45 +408,33 @@ private void updateAgentPlan(MobsimAgent agent, TripInfo tripInfo) { result.add(leg); Route route = pf.getRouteFactories() .createRoute(GenericRouteImpl.class, tripInfo.getPickupLocation().getLinkId(), - tripInfo.getDropoffLocation().getLinkId()); + tripInfo.getDropoffLocation().getLinkId() ); leg.setRoute(route); } { Activity act = pf.createActivityFromLinkId(createStageActivityType(TransportMode.taxi), - tripInfo.getDropoffLocation().getLinkId()); + tripInfo.getDropoffLocation().getLinkId() ); act.setMaximumDuration(0.); result.add(act); } { Facility fromFacility = tripInfo.getDropoffLocation(); - Facility toFacility = FacilitiesUtils.toFacility(inputTrip.getDestinationActivity(), facilities); + Facility toFacility = FacilitiesUtils.toFacility( inputTrip.getDestinationActivity(), facilities ); double expectedTravelTime; try { expectedTravelTime = tripInfo.getExpectedTravelTime(); } catch (Exception ee) { - expectedTravelTime = 15. - * 60; // using 15min as quick fix since dvrp refuses to provide this. kai, mar'19 + expectedTravelTime = 15. * 60; // using 15min as quick fix since dvrp refuses to provide this. kai, mar'19 } double departureTime = tripInfo.getExpectedBoardingTime() + expectedTravelTime; List planElements = tripRouter.calcRoute(TransportMode.walk, fromFacility, - toFacility, departureTime, null, inputTrip.getOriginActivity().getAttributes()); + toFacility, departureTime, null, inputTrip.getOriginActivity().getAttributes() ); result.addAll(planElements); } // result.add( inputTrip.getDestinationActivity() ) ; - - TripRouter.insertTrip(plan, inputTrip.getOriginActivity(), result, inputTrip.getDestinationActivity()); - - editPlans.rescheduleActivityEnd(agent); - // I don't think that this can ever do damage. - - log.warn("new plan for agentId=" + agent.getId()); - for (PlanElement planElement : plan.getPlanElements()) { - log.warn(planElement.toString()); - } - log.warn("---"); - + return result; } static String toString(TripInfo info) { diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningUtils.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningUtils.java new file mode 100644 index 00000000000..bfc117ca153 --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/PreplanningUtils.java @@ -0,0 +1,15 @@ +package org.matsim.core.mobsim.qsim; + +import org.matsim.api.core.v01.population.Plan; + +public class PreplanningUtils{ + private PreplanningUtils() {} // do not instantiate + public static Double getPrebookingOffset_s( Plan plan ){ + // yyyy prebooking info needs to be in plan since it will not survive in the leg. :-( kai, jan'20 + return (Double) plan.getAttributes().getAttribute( "prebookingOffset_s" ); + } + public static void setPrebookingOffset_s( Plan plan, double offset ){ + plan.getAttributes().putAttribute( "prebookingOffset_s", offset ); + // yyyy prebooking info needs to be in plan since it will not survive in the leg. :-( kai, jan'20 + } +} diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/components/QSimComponentsConfigGroup.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/components/QSimComponentsConfigGroup.java index 8878ebe4118..c21058da8b3 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/components/QSimComponentsConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/components/QSimComponentsConfigGroup.java @@ -80,6 +80,15 @@ public void addActiveComponent( String component ) { // (doing this the indirect way because of the Set vs List discussion above. kai, apr'23 } + public void removeActiveComponent( String component ) { + // I need this so often that I am finally adding it here. kai, apr'24 + + List components = getActiveComponents(); + components.remove( component ); + setActiveComponents( components ); + // (doing this the indirect way because of the Set vs List discussion above. kai, apr'24 + } + @StringGetter(ACTIVE_COMPONENTS) public String getActiveComponentsAsString() { return String.join(", ", activeComponents); From 8a219568299e6c456c209a3339feb42ec134fbd7 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Mon, 22 Apr 2024 14:01:01 +0200 Subject: [PATCH 10/10] I added a testcase but did not finish it. It currently fails. Thus disabling it. --- .../java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java b/contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java index 74536deae58..b7ac20ef8bb 100644 --- a/contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java +++ b/contribs/vsp/src/test/java/org/matsim/core/mobsim/qsim/PreplanningEngineTest.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Scenario; @@ -24,6 +25,7 @@ class PreplanningEngineTest{ @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); + @Disabled @Test public void test() { // I am interested here in testing this NOT with DRT but with other modes. kai, apr'24 // In the somewhat longer run, should work together with fleetpy (of TUM). kai, apr'24