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

Flow analysis

parent ce6e9a63
package ch.ethz.matsim.projects.astra_2018_002.analysis.flow;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.LinkEnterEvent;
import org.matsim.api.core.v01.events.handler.LinkEnterEventHandler;
import org.matsim.api.core.v01.network.Link;
import org.matsim.vehicles.Vehicle;
import org.matsim.vehicles.Vehicles;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.FlowEfficiencyCalculator;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.FlowEfficiencyConfigurator;
public class FlowListener implements LinkEnterEventHandler {
private final double startTime;
private final double interval;
private final int numberOfLinks;
private final int numberOfBins;
private final Item[][] timeItems;
private final Item[] totalItems;
private final Map<Id<Link>, Integer> linkMap = new HashMap<>();
private final List<Link> links;
private final Set<Id<Link>> linkIds;
private final FlowEfficiencyCalculator flowEfficiencyCalculator;
private final Vehicle CONVENTIONAL_VEHICLE;
private final Vehicle PRIVATE_AV;
private final Vehicle SHARED_AV;
public FlowListener(Vehicles vehicles, Collection<Link> links, double startTime, double endTime, double interval,
FlowEfficiencyCalculator flowEfficiencyCalculator) {
this.startTime = startTime;
this.interval = interval;
this.numberOfBins = (int) Math.ceil((endTime - startTime) / interval);
this.numberOfLinks = links.size();
this.links = links.stream().collect(Collectors.toList());
this.linkIds = links.stream().map(Link::getId).collect(Collectors.toSet());
for (int index = 0; index < links.size(); index++) {
linkMap.put(this.links.get(index).getId(), index);
}
this.CONVENTIONAL_VEHICLE = vehicles.getFactory().createVehicle(Id.createVehicleId("conventional"),
vehicles.getVehicleTypes().get(FlowEfficiencyConfigurator.CONVENTIONAL_VEHICLE_TYPE_ID));
this.PRIVATE_AV = vehicles.getFactory().createVehicle(Id.createVehicleId("private_av"),
vehicles.getVehicleTypes().get(FlowEfficiencyConfigurator.PRIVATE_AV_VEHICLE_TYPE_ID));
this.SHARED_AV = vehicles.getFactory().createVehicle(Id.createVehicleId("shared_av"),
vehicles.getVehicleTypes().get(FlowEfficiencyConfigurator.SHARED_AV_VEHICLE_TYPE_ID));
this.totalItems = new Item[numberOfLinks];
this.timeItems = new Item[numberOfLinks][numberOfBins];
this.flowEfficiencyCalculator = flowEfficiencyCalculator;
for (int linkIndex = 0; linkIndex < numberOfLinks; linkIndex++) {
totalItems[linkIndex] = new Item();
for (int timeIndex = 0; timeIndex < numberOfBins; timeIndex++) {
timeItems[linkIndex][timeIndex] = new Item();
}
}
}
public class Item {
public int numberOfConventionalVehicles;
public int numberOfPrivateAutomatedVehicles;
public int numberOfSharedAutomatedVehicles;
public double numberOfPCUs;
}
@Override
public void handleEvent(LinkEnterEvent event) {
if (linkIds.contains(event.getLinkId())) {
int linkIndex = linkMap.get(event.getLinkId());
Link link = links.get(linkIndex);
Vehicle vehicle = CONVENTIONAL_VEHICLE;
String plainVehicleId = event.getVehicleId().toString();
if (plainVehicleId.startsWith("av_")) {
vehicle = SHARED_AV;
} else if (plainVehicleId.startsWith("prav_")) {
vehicle = PRIVATE_AV;
}
Item totalItem = totalItems[linkIndex];
totalItem.numberOfPCUs += flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, link);
if (vehicle == CONVENTIONAL_VEHICLE) {
totalItem.numberOfConventionalVehicles++;
} else if (vehicle == SHARED_AV) {
totalItem.numberOfPrivateAutomatedVehicles++;
} else {
totalItem.numberOfSharedAutomatedVehicles++;
}
int timeIndex = (int) Math.floor((event.getTime() - startTime) / interval);
if (timeIndex > -1 && timeIndex < numberOfBins) {
Item timeItem = timeItems[linkIndex][timeIndex];
timeItem.numberOfPCUs += flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, link);
if (vehicle == CONVENTIONAL_VEHICLE) {
timeItem.numberOfConventionalVehicles++;
} else if (vehicle == SHARED_AV) {
timeItem.numberOfPrivateAutomatedVehicles++;
} else {
timeItem.numberOfSharedAutomatedVehicles++;
}
}
}
}
public int getNumberOfLinks() {
return numberOfLinks;
}
public int getNumberOfBins() {
return numberOfBins;
}
public Item getTotalItem(Id<Link> linkId) {
int linkIndex = linkMap.get(linkId);
if (linkIndex == -1) {
throw new IllegalStateException();
}
return totalItems[linkIndex];
}
public Item[] getTimeItems(Id<Link> linkId) {
int linkIndex = linkMap.get(linkId);
if (linkIndex == -1) {
throw new IllegalStateException();
}
return timeItems[linkIndex];
}
}
package ch.ethz.matsim.projects.astra_2018_002.analysis.flow;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Link;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.events.EventsUtils;
import org.matsim.core.events.MatsimEventsReader;
import org.matsim.core.network.io.MatsimNetworkReader;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.geometry.geotools.MGC;
import org.matsim.core.utils.gis.PolylineFeatureFactory;
import org.matsim.core.utils.gis.ShapeFileWriter;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Coordinate;
import ch.ethz.matsim.baseline_scenario.config.CommandLine;
import ch.ethz.matsim.baseline_scenario.config.CommandLine.ConfigurationException;
import ch.ethz.matsim.projects.astra_2018_002.analysis.flow.FlowListener.Item;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.FlowEfficiencyCalculator;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.FlowEfficiencyConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.StaticFlowEfficiencyCalculator;
public class RunFlowAnalysis {
static public void main(String[] args) throws ConfigurationException, IOException {
CommandLine cmd = new CommandLine.Builder(args) //
.requireOptions("network-path", "events-path", "output-path") //
.build();
Config config = ConfigUtils.createConfig();
Scenario scenario = ScenarioUtils.createScenario(config);
new MatsimNetworkReader(scenario.getNetwork()).readFile(cmd.getOptionStrict("network-path"));
FlowEfficiencyConfigurator.defineVehicleTypes(scenario);
FlowEfficiencyCalculator flowEfficiencyCalculator = new StaticFlowEfficiencyCalculator();
double startTime = 5.0 * 3600.0;
double endTime = 22.0 * 3600.0;
double interval = 3600.0;
List<Link> links = new LinkedList<>();
for (Link link : scenario.getNetwork().getLinks().values()) {
String osmType = (String) link.getAttributes().getAttribute("osm:way:highway");
if (osmType != null
&& (osmType.equals("primary") || osmType.equals("secondary") || osmType.equals("tertiary"))) {
links.add(link);
}
}
FlowListener flowListener = new FlowListener(scenario.getVehicles(), links, startTime, endTime, interval,
flowEfficiencyCalculator);
EventsManager eventsManager = EventsUtils.createEventsManager();
eventsManager.addHandler(flowListener);
new MatsimEventsReader(eventsManager).readFile(cmd.getOptionStrict("events-path"));
CoordinateReferenceSystem crs = MGC.getCRS("EPSG:2056");
int morningPeakIndex = 8 - 5;
int eveningPeakIndex = 17 - 5;
Collection<SimpleFeature> features = new ArrayList<>(links.size());
PolylineFeatureFactory featureFactory = new PolylineFeatureFactory.Builder() //
.setCrs(crs) //
.setName("links") //
.addAttribute("link_id", String.class) //
.addAttribute("day_cv", Integer.class) //
.addAttribute("day_prav", Integer.class) //
.addAttribute("day_sav", Integer.class) //
.addAttribute("day_pcu", Double.class) //
.addAttribute("am_cv", Integer.class) //
.addAttribute("am_prav", Integer.class) //
.addAttribute("am_sav", Integer.class) //
.addAttribute("am_pcu", Double.class) //
.addAttribute("pm_cv", Integer.class) //
.addAttribute("pm_prav", Integer.class) //
.addAttribute("pm_sav", Integer.class) //
.addAttribute("pm_pcu", Double.class) //
.addAttribute("capacity", Double.class) //
.addAttribute("freespeed", Double.class) //
.addAttribute("lanes", Double.class) //
.addAttribute("osm_type", String.class) //
.create();
for (Link link : links) {
Item totalItem = flowListener.getTotalItem(link.getId());
Item morningItem = flowListener.getTimeItems(link.getId())[morningPeakIndex];
Item eveningItem = flowListener.getTimeItems(link.getId())[eveningPeakIndex];
Coordinate fromCoord = new Coordinate(link.getFromNode().getCoord().getX(),
link.getFromNode().getCoord().getY());
Coordinate toCoord = new Coordinate(link.getToNode().getCoord().getX(), link.getToNode().getCoord().getY());
String osmType = (String) link.getAttributes().getAttribute("osm:way:highway");
if (osmType == null) {
osmType = "unknown";
}
SimpleFeature feature = featureFactory.createPolyline(new Coordinate[] { fromCoord, toCoord },
new Object[] { link.getId().toString(), //
totalItem.numberOfConventionalVehicles, totalItem.numberOfPrivateAutomatedVehicles,
totalItem.numberOfSharedAutomatedVehicles, totalItem.numberOfPCUs, //
morningItem.numberOfConventionalVehicles, morningItem.numberOfPrivateAutomatedVehicles,
morningItem.numberOfSharedAutomatedVehicles, morningItem.numberOfPCUs, //
eveningItem.numberOfConventionalVehicles, eveningItem.numberOfPrivateAutomatedVehicles,
eveningItem.numberOfSharedAutomatedVehicles, eveningItem.numberOfPCUs, //
link.getCapacity(), link.getFreespeed(), link.getNumberOfLanes(), osmType //
}, null);
features.add(feature);
List<String> row = new LinkedList<>();
row.add(link.getId().toString());
row.add(String.valueOf(totalItem.numberOfConventionalVehicles));
row.add(String.valueOf(totalItem.numberOfPrivateAutomatedVehicles));
row.add(String.valueOf(totalItem.numberOfSharedAutomatedVehicles));
row.add(String.valueOf(totalItem.numberOfPCUs));
}
ShapeFileWriter.writeGeometries(features, cmd.getOptionStrict("output-path"));
}
}
......@@ -8,6 +8,10 @@ import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;
public class FlowEfficiencyConfigurator {
static final public Id<VehicleType> CONVENTIONAL_VEHICLE_TYPE_ID = Id.create("car", VehicleType.class);
static final public Id<VehicleType> PRIVATE_AV_VEHICLE_TYPE_ID = Id.create("private_av", VehicleType.class);
static final public Id<VehicleType> SHARED_AV_VEHICLE_TYPE_ID = Id.create("shared_av", VehicleType.class);
static public void configure(Config config) {
// Load vehicles by vehicle type
config.qsim().setVehiclesSource(VehiclesSource.modeVehicleTypesFromVehiclesData);
......@@ -26,15 +30,15 @@ public class FlowEfficiencyConfigurator {
static public void defineVehicleTypes(Scenario scenario) {
VehicleType carVehicleType = VehicleUtils.getFactory() //
.createVehicleType(Id.create("car", VehicleType.class));
.createVehicleType(CONVENTIONAL_VEHICLE_TYPE_ID);
scenario.getVehicles().addVehicleType(carVehicleType);
VehicleType privateAvVehicleType = VehicleUtils.getFactory() //
.createVehicleType(Id.create("private_av", VehicleType.class));
.createVehicleType(PRIVATE_AV_VEHICLE_TYPE_ID);
scenario.getVehicles().addVehicleType(privateAvVehicleType);
VehicleType sharedAvVehicleType = VehicleUtils.getFactory() //
.createVehicleType(Id.create("shared_av", VehicleType.class));
.createVehicleType(SHARED_AV_VEHICLE_TYPE_ID);
scenario.getVehicles().addVehicleType(sharedAvVehicleType);
}
}
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