Commit 24535592 authored by Sebastian Hörl's avatar Sebastian Hörl
Browse files

Merge branch 'network_assignment' into 'master'

Custom restrictions for AVs depending on year

See merge request !15
parents 3dc7b0bf 38a24cad
package ch.ethz.matsim.projects.astra_2018_002;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Link;
import org.matsim.core.config.Config;
import org.matsim.core.config.groups.ControlerConfigGroup.RoutingAlgorithmType;
public class ASTRAConfigurator {
static public void adjustNetwork(Scenario scenario, int year) {
for (Link link : scenario.getNetwork().getLinks().values()) {
Set<String> allowedModes = new HashSet<>(link.getAllowedModes());
if (allowedModes.contains("car")) {
allowedModes.addAll(Arrays.asList("av", "prav3", "prav4", "prav5", "car_passenger"));
}
link.setAllowedModes(allowedModes);
}
}
static public void configure(Config config) {
config.controler().setRoutingAlgorithmType(RoutingAlgorithmType.FastAStarLandmarks);
}
......
......@@ -14,6 +14,7 @@ import ch.ethz.matsim.baseline_scenario.transit.routing.DefaultEnrichedTransitRo
import ch.ethz.matsim.baseline_scenario.transit.routing.DefaultEnrichedTransitRouteFactory;
import ch.ethz.matsim.discrete_mode_choice.modules.DiscreteModeChoiceModule;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.FlowEfficiencyConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.link_assignment.LinkAssignmentConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.SwissDiscreteModeChoiceModule;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.SwissModeChoiceConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.SwissUtilityParameters.UtilitySet;
......@@ -55,7 +56,7 @@ public class RunASTRA2018002 {
// Adjust scenario
SwissModeChoiceConfigurator.copyHousholdAttributes(scenario);
FlowEfficiencyConfigurator.defineVehicleTypes(scenario, year);
ASTRAConfigurator.adjustNetwork(scenario, year);
LinkAssignmentConfigurator.configureNetwork(config, scenario, year);
PrivateAVConfigurator.assignPrivateAVs(scenario, year);
// Set up controller
......
package ch.ethz.matsim.projects.astra_2018_002.link_assignment;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.network.NetworkWriter;
import org.matsim.api.core.v01.population.Person;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.network.algorithms.NetworkCleaner;
import org.matsim.core.network.algorithms.TransportModeNetworkFilter;
import org.matsim.core.network.io.MatsimNetworkReader;
import org.matsim.core.router.DijkstraFactory;
import org.matsim.core.router.util.LeastCostPathCalculator;
import org.matsim.core.router.util.LeastCostPathCalculator.Path;
import org.matsim.core.router.util.TravelDisutility;
import org.matsim.core.router.util.TravelTime;
import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime;
import org.matsim.core.utils.collections.QuadTree;
import org.matsim.vehicles.Vehicle;
import org.opengis.feature.simple.SimpleFeature;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
public class AVLinkAssignment {
private final GeometryFactory geometryFactory = new GeometryFactory();
private final Network network;
private final Collection<Link> allowedLinks = new HashSet<>();
private final QuadTree<Link> index;
private final List<Coord> centroids = new LinkedList<>();
public AVLinkAssignment(Network network) {
this.network = NetworkUtils.createNetwork();
new TransportModeNetworkFilter(network).filter(this.network, Collections.singleton("car"));
new NetworkCleaner().run(this.network);
double[] dimensions = NetworkUtils.getBoundingBox(network.getNodes().values());
this.index = new QuadTree<>(dimensions[0], dimensions[1], dimensions[2], dimensions[3]);
}
public void allowLink(Link link) {
if (!allowedLinks.contains(link)) {
index.put(link.getCoord().getX(), link.getCoord().getY(), link);
}
allowedLinks.add(link);
}
public void allowOsmType(String osmType) {
for (Link link : network.getLinks().values()) {
String linkOsmType = (String) link.getAttributes().getAttribute("osm:way:highway");
if (linkOsmType != null && linkOsmType.equals(osmType)) {
allowLink(link);
}
}
}
public void allowAll() {
for (Link link : network.getLinks().values()) {
allowLink(link);
}
}
public void allowIf(Function<Link, Boolean> filter) {
for (Link link : network.getLinks().values()) {
if (filter.apply(link)) {
allowLink(link);
}
}
}
public void allowArea(URL url) {
try {
DataStore dataStore = DataStoreFinder.getDataStore(Collections.singletonMap("url", url));
SimpleFeatureSource featureSource = dataStore.getFeatureSource(dataStore.getTypeNames()[0]);
SimpleFeatureCollection featureCollection = featureSource.getFeatures();
SimpleFeatureIterator featureIterator = featureCollection.features();
while (featureIterator.hasNext()) {
SimpleFeature feature = featureIterator.next();
Geometry geometry = (Geometry) feature.getDefaultGeometry();
if (geometry instanceof MultiPolygon) {
for (Link link : network.getLinks().values()) {
Coord linkCoord = link.getCoord();
Coordinate linkCoordinate = new Coordinate(linkCoord.getX(), linkCoord.getY());
Point linkPoint = geometryFactory.createPoint(linkCoordinate);
if (geometry.contains(linkPoint)) {
allowLink(link);
}
}
} else {
throw new IllegalStateException("Expected a shape file with polygons.");
}
centroids.add(new Coord(geometry.getCentroid().getX(), geometry.getCentroid().getY()));
}
featureIterator.close();
dataStore.dispose();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Collection<Id<Link>> getLinkIds() {
TravelTime travelTime = new FreeSpeedTravelTime();
TravelDisutility travelDisutility = new TravelDisutility() {
@Override
public double getLinkTravelDisutility(Link link, double time, Person person, Vehicle vehicle) {
return allowedLinks.contains(link) ? 1.0 : 1000.0;
}
@Override
public double getLinkMinimumTravelDisutility(Link link) {
return 1.0;
}
};
Set<Link> result = new HashSet<>();
result.addAll(allowedLinks);
// Make sure there is a connection between all centroids
LeastCostPathCalculator router = new DijkstraFactory().createPathCalculator(this.network, travelDisutility,
travelTime);
if (centroids.size() > 0) {
for (Coord a : centroids) {
for (Coord b : centroids) {
Link linkA = index.getClosest(a.getX(), a.getY());
Link linkB = index.getClosest(b.getX(), b.getY());
Path path = router.calcLeastCostPath(linkA.getToNode(), linkB.getFromNode(), 0.0, null, null);
for (Link link : path.links) {
result.add(link);
}
}
}
}
// Make sure there is a connection from every link to some reference link
Link referenceLink = allowedLinks.iterator().next();
for (Link link : new ArrayList<>(allowedLinks)) {
boolean hasAllowedUpstream = false;
boolean hasAllowedDownstream = false;
for (Link inLink : link.getFromNode().getInLinks().values()) {
if (inLink != link && allowedLinks.contains(inLink)) {
hasAllowedUpstream = true;
break;
}
}
for (Link inLink : link.getToNode().getOutLinks().values()) {
if (inLink != link && allowedLinks.contains(inLink)) {
hasAllowedDownstream = true;
break;
}
}
if (!hasAllowedUpstream || !hasAllowedDownstream) {
Path path1 = router.calcLeastCostPath(link.getToNode(), referenceLink.getFromNode(), 0.0, null, null);
Path path2 = router.calcLeastCostPath(referenceLink.getToNode(), link.getFromNode(), 0.0, null, null);
for (Link pathLink : path1.links) {
result.add(pathLink);
}
for (Link pathLink : path2.links) {
result.add(pathLink);
}
}
}
// Add tags
for (Link link : result) {
Set<String> allowedModes = new HashSet<>(link.getAllowedModes());
allowedModes.add("___newmode___");
link.setAllowedModes(allowedModes);
}
Network newNetwork = NetworkUtils.createNetwork();
new TransportModeNetworkFilter(network).filter(newNetwork, Collections.singleton("___newmode___"));
new NetworkCleaner().run(newNetwork);
Set<Id<Link>> remainingIds = new HashSet<>();
for (Link link : newNetwork.getLinks().values()) {
if (link.getAllowedModes().contains("___newmode___")) {
remainingIds.add(link.getId());
}
}
for (Link link : result) {
Set<String> allowedModes = new HashSet<>(link.getAllowedModes());
allowedModes.remove("___newmode___");
link.setAllowedModes(allowedModes);
}
return remainingIds;
}
public void apply(Network network, String mode) {
for (Id<Link> linkId : getLinkIds()) {
Link link = network.getLinks().get(linkId);
Set<String> allowedModes = new HashSet<>(link.getAllowedModes());
allowedModes.add(mode);
link.setAllowedModes(allowedModes);
}
}
static public void main(String[] args) throws MalformedURLException {
Network network = NetworkUtils.createNetwork();
new MatsimNetworkReader(network).readFile(args[0]);
AVLinkAssignment assignment = new AVLinkAssignment(network);
assignment.allowOsmType("motorway");
assignment.allowArea(new File("allowed.shp").toURI().toURL());
assignment.apply(network, "av");
new NetworkWriter(network).write("assigned_network.xml.gz");
}
}
package ch.ethz.matsim.projects.astra_2018_002.link_assignment;
import java.net.URL;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Link;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigGroup;
import ch.ethz.matsim.projects.astra_2018_002.private_av.PrivateAVConfigGroup;
public class LinkAssignmentConfigurator {
static public void configureNetwork(Config config, Scenario scenario, int year) {
PrivateAVConfigGroup pravConfig = (PrivateAVConfigGroup) config.getModules()
.get(PrivateAVConfigGroup.GROUP_NAME);
AVLinkAssignment assignment = new AVLinkAssignment(scenario.getNetwork());
if (year >= 2030) {
if (pravConfig.getCityShapefile() == null) {
throw new IllegalStateException("No city shape file is given for years >= 2030 !");
}
URL citiesURL = ConfigGroup.getInputFileURL(config.getContext(), pravConfig.getCityShapefile());
assignment.allowArea(citiesURL);
assignment.allowOsmType("motorway");
assignment.allowOsmType("motorway_link");
assignment.allowOsmType("trunk");
assignment.allowOsmType("trunk_link");
}
if (year >= 2040) {
assignment.allowOsmType("primary");
assignment.allowOsmType("primary_link");
assignment.allowIf(link -> link.getFreespeed() <= 13.8);
}
if (year >= 2050) {
assignment.allowAll();
}
// Add prav4, prav5, and av (shared) for the criteria set above
assignment.apply(scenario.getNetwork(), "prav4");
assignment.apply(scenario.getNetwork(), "prav5");
assignment.apply(scenario.getNetwork(), "av");
// Add prav3, car_passenger and truck to every link
for (Link link : scenario.getNetwork().getLinks().values()) {
if (link.getAllowedModes().contains("car")) {
Set<String> allowedModes = new HashSet<>(link.getAllowedModes());
allowedModes.addAll(Arrays.asList("prav3", "car_passenger", "truck"));
link.setAllowedModes(allowedModes);
}
}
}
}
package ch.ethz.matsim.projects.astra_2018_002.mode_choice;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
......@@ -20,6 +21,12 @@ public class SwissModeAvailability extends CarModeAvailability {
@Override
public Collection<String> getAvailableModes(Person person, List<DiscreteModeChoiceTrip> trips) {
Boolean isFreight = (Boolean) person.getAttributes().getAttribute("isFreight");
if (isFreight != null && isFreight) {
return Collections.singleton("truck");
}
boolean bikeAvailability = !"FOR_NONE".equals((String) person.getAttributes().getAttribute("bikeAvailability"));
Set<String> modes = new HashSet<>();
......
......@@ -35,13 +35,13 @@ public class SwissModeChoiceConfigurator {
dmcConfig.setTripEstimator(SwissDiscreteModeChoiceModule.SWISS_ESTIMATOR_NAME);
dmcConfig.setTourEstimator(EstimatorModule.CUMULATIVE);
dmcConfig.setCachedModes(Arrays.asList("car", "bike", "pt", "walk", "car_passenger"));
dmcConfig.setCachedModes(Arrays.asList("car", "bike", "pt", "walk", "car_passenger", "truck"));
dmcConfig.setTourFinder(SwissDiscreteModeChoiceModule.SWISS_TOUR_FINDER_NAME);
dmcConfig.getActivityTourFinderConfigGroup().setActivityType("home");
dmcConfig.setModeAvailability(SwissDiscreteModeChoiceModule.SWISS_MODE_AVAILABILITY_NAME);
dmcConfig.getCarModeAvailabilityConfig().setAvailableModes(Arrays.asList("car", "bike", "pt", "walk"));
dmcConfig.getCarModeAvailabilityConfig().setAvailableModes(Arrays.asList("car", "bike", "pt", "walk", "truck"));
dmcConfig.setTourConstraints(
Arrays.asList(ConstraintModule.VEHICLE_CONTINUITY, ConstraintModule.FROM_TRIP_BASED));
......
......@@ -121,6 +121,7 @@ public abstract class BaseUtilityEstimator extends AbstractTripRouterEstimator {
case TransportMode.car:
return estimateCarTrip(personVariables, trip, routedTrip) + outsideOffset;
case "car_passenger":
case "truck":
return 0.0;
case TransportMode.pt:
return estimatePtTrip(personVariables, trip, routedTrip) + outsideOffset;
......
......@@ -8,8 +8,11 @@ public class PrivateAVConfigGroup extends ReflectiveConfigGroup {
private final static String USE_PRIVATE_AVS = "usePrivateAVs";
private final static String ASSIGN_PRIVATE_AVS = "assignPrivateAVs";
private final static String CITY_SHAPEFILE = "cityShapefile";
private boolean usePrivateAVs = false;
private boolean assignPrivateAVs = false;
private String cityShapefile = null;
public PrivateAVConfigGroup() {
super(GROUP_NAME);
......@@ -34,4 +37,14 @@ public class PrivateAVConfigGroup extends ReflectiveConfigGroup {
public void setAssignPrivateAVs(boolean assignPrivateAVs) {
this.assignPrivateAVs = assignPrivateAVs;
}
@StringGetter(CITY_SHAPEFILE)
public String getCityShapefile() {
return cityShapefile;
}
@StringSetter(CITY_SHAPEFILE)
public void setCityShapefile(String cityShapefile) {
this.cityShapefile = cityShapefile;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment