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) { 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..d20d7693ef7 --- /dev/null +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/OsmRailwayReader.java @@ -0,0 +1,109 @@ +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.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +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 { + + private static final double FALLBACK_MAX_SPEED = 100.; + + 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); + + setAttributes(link, tags); + setAllowedModes(link, tags); + setSpeed(link, tags); + + outfacingCallback.accept(link, tags, direction); + } + + 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)); + } else { + link.getAttributes().putAttribute(OsmTags.MAXSPEED, FALLBACK_MAX_SPEED); + } + + 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 + Collection createLinks(WaySegment segment) { + Collection links = super.createLinks(segment); + return links; + } + + 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(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); + } + + @Override + OsmRailwayReader createInstance() { + OsmNetworkParser parser = new OsmNetworkParser(coordinateTransformation, linkProperties, includeLinkAtCoordWithHierarchy, Executors.newWorkStealingPool(), OsmTags.RAILWAY); + 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..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 @@ -42,4 +42,20 @@ 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"; + 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/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/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)); - - } -}