Skip to content

Commit

Permalink
Merge branch 'master' into drtMinDetour
Browse files Browse the repository at this point in the history
  • Loading branch information
nkuehnel authored Dec 5, 2024
2 parents 8ef78dc + f9eae62 commit 54a8d6d
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 36 deletions.
2 changes: 1 addition & 1 deletion contribs/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
<dependency>
<groupId>com.github.matsim-org</groupId>
<artifactId>gtfs2matsim</artifactId>
<version>47b0802a29</version>
<version>19f1676fc6</version>
<exclusions>
<!-- Exclude unneeded dependencies and these with known CVE -->
<exclusion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@
import org.matsim.core.utils.io.IOUtils;
import org.matsim.pt.transitSchedule.api.*;
import org.matsim.pt.utils.CreatePseudoNetwork;
import org.matsim.pt.utils.CreatePseudoNetworkWithLoopLinks;
import org.matsim.pt.utils.TransitScheduleValidator;
import org.matsim.vehicles.*;
import picocli.CommandLine;

import java.io.File;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;

Expand Down Expand Up @@ -85,8 +89,8 @@ public class CreateTransitScheduleFromGtfs implements MATSimAppCommand {
@CommandLine.Option(names = "--transform-schedule", description = "Fully qualified class name to a Consumer<TransitSchedule> to be executed after the schedule was created", arity = "0..*", split = ",")
private List<Class<?>> transformSchedule;

@CommandLine.Option(names = "--merge-stops", description = "Whether stops should be merged by coordinate")
private boolean mergeStops;
@CommandLine.Option(names = "--merge-stops", description = "Whether stops should be merged by coordinate", defaultValue = "doNotMerge")
private GtfsConverter.MergeGtfsStops mergeStops;

@CommandLine.Option(names = "--prefix", description = "Prefixes to add to the gtfs ids. Required if multiple inputs are used and ids are not unique.", split = ",")
private List<String> prefixes = new ArrayList<>();
Expand All @@ -100,10 +104,29 @@ public class CreateTransitScheduleFromGtfs implements MATSimAppCommand {
@CommandLine.Option(names = "--shp-crs", description = "Overwrite coordinate system of the shape file")
private String shpCrs;

@CommandLine.Option(names = "--pseudo-network", description = "Define how the pseudo network should be created", defaultValue = "singleLinkBetweenStops")
private PseudoNetwork pseudoNetwork;


public static void main(String[] args) {
System.exit(new CommandLine(new CreateTransitScheduleFromGtfs()).execute(args));
}

private static void addHbefaMapping(VehicleType vehicleType, HbefaVehicleCategory category) {
EngineInformation carEngineInformation = vehicleType.getEngineInformation();
VehicleUtils.setHbefaVehicleCategory(carEngineInformation, String.valueOf(category));
VehicleUtils.setHbefaTechnology(carEngineInformation, "average");
VehicleUtils.setHbefaSizeClass(carEngineInformation, "average");
VehicleUtils.setHbefaEmissionsConcept(carEngineInformation, "average");
vehicleType.setNetworkMode(TransportMode.pt);
}

private static void increaseLinkFreespeedIfLower(Link link, double newFreespeed) {
if (link.getFreespeed() < newFreespeed) {
link.setFreespeed(newFreespeed);
}
}

@Override
public Integer call() throws Exception {

Expand Down Expand Up @@ -237,14 +260,19 @@ private Predicate<Stop> createFilter(int i) throws Exception {
/**
* Creates the pt scenario and network.
*/
private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network network, TransitSchedule schedule, String ptNetworkIdentifier) {
private Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network network, TransitSchedule schedule, String ptNetworkIdentifier) {
ScenarioUtils.ScenarioBuilder builder = new ScenarioUtils.ScenarioBuilder(ConfigUtils.createConfig());
builder.setNetwork(network);
builder.setTransitSchedule(schedule);
Scenario scenario = builder.build();

// add pseudo network for pt
new CreatePseudoNetwork(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
switch (pseudoNetwork) {
case singleLinkBetweenStops ->
new CreatePseudoNetwork(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
case withLoopLinks ->
new CreatePseudoNetworkWithLoopLinks(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
}

// create TransitVehicle types
// see https://svn.vsp.tu-berlin.de/repos/public-svn/publications/vspwp/2014/14-24/ for veh capacities
Expand Down Expand Up @@ -481,20 +509,15 @@ private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network
return scenario;
}

private static void addHbefaMapping(VehicleType vehicleType, HbefaVehicleCategory category) {
EngineInformation carEngineInformation = vehicleType.getEngineInformation();
VehicleUtils.setHbefaVehicleCategory(carEngineInformation, String.valueOf(category));
VehicleUtils.setHbefaTechnology(carEngineInformation, "average");
VehicleUtils.setHbefaSizeClass(carEngineInformation, "average");
VehicleUtils.setHbefaEmissionsConcept(carEngineInformation, "average");
vehicleType.setNetworkMode(TransportMode.pt);
}

private static void increaseLinkFreespeedIfLower(Link link, double newFreespeed) {
if (link.getFreespeed() < newFreespeed) {
link.setFreespeed(newFreespeed);
}
public enum PseudoNetwork {
/**
* Create links between all stops and possibly duplicate stops.
*/
singleLinkBetweenStops,
/**
* Create a pseudo network with loop links at each stop.
*/
withLoopLinks,
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

package org.matsim.pt.utils;

import com.google.common.annotations.Beta;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Link;
Expand All @@ -40,11 +39,8 @@
* is assigned to a loop link, located in a node with the same coordinates as the stop.
* The stop facility ID is used for node and link IDs.
*
* @author mrieser, davibicudo
*
* @implNote THis functionality might be merged with {@link CreatePseudoNetwork}.
* @author mrieser, davibicudo, rakow
*/
@Beta
public class CreatePseudoNetworkWithLoopLinks {

private final TransitSchedule schedule;
Expand Down Expand Up @@ -82,23 +78,29 @@ public void createNetwork() {
List<Tuple<TransitLine, TransitRoute>> toBeRemoved = new LinkedList<>();
for (TransitLine tLine : this.schedule.getTransitLines().values()) {
for (TransitRoute tRoute : tLine.getRoutes().values()) {
ArrayList<Id<Link>> routeLinks = new ArrayList<>();

if (tRoute.getStops().size() < 2) {
System.err.println("Line " + tLine.getId() + " route " + tRoute.getId() + " has less than two stops. Removing this route from schedule.");
toBeRemoved.add(new Tuple<>(tLine, tRoute));
continue;
}

List<Id<Link>> routeLinks = new ArrayList<>();
TransitRouteStop prevStop = null;

for (TransitRouteStop stop : tRoute.getStops()) {
if (prevStop != null) {
Link link = getNetworkLink(prevStop, stop);
routeLinks.add(link.getId());
}

// Add the loop links of all stops to the route
routeLinks.add(getLoopLink(stop.getStopFacility()).getId());
prevStop = stop;
}

if (!routeLinks.isEmpty()) {
NetworkRoute route = RouteUtils.createNetworkRoute(routeLinks);
tRoute.setRoute(route);
} else {
System.err.println("Line " + tLine.getId() + " route " + tRoute.getId() + " has less than two stops. Removing this route from schedule.");
toBeRemoved.add(new Tuple<>(tLine, tRoute));
}
NetworkRoute route = RouteUtils.createNetworkRoute(routeLinks);
tRoute.setRoute(route);
}
}

Expand All @@ -114,13 +116,30 @@ private void createStopNodesAndLoopLinks() {
this.nodes.put(stop, node);

Link loopLink = this.network.getFactory().createLink(Id.createLinkId (this.prefix + stop.getId()), node, node);
// Loop links needs to have a length so that the travel time is not zero
loopLink.setLength(1);
loopLink.setFreespeed(linkFreeSpeed);
loopLink.setCapacity(linkCapacity);
// Ensure enough vehicles can be placed on the loop link
loopLink.setNumberOfLanes(linkCapacity);
loopLink.setAllowedModes(transitModes);

stop.setLinkId(loopLink.getId());
this.network.addLink(loopLink);
Tuple<Node, Node> connection = new Tuple<>(node, node);
this.links.put(connection, loopLink);
}
}

/**
* Get the loop link for a stop facility.
*/
private Link getLoopLink(final TransitStopFacility stop) {
Node node = this.nodes.get(stop);
Tuple<Node, Node> connection = new Tuple<>(node, node);
return this.links.get(connection);
}

private Link getNetworkLink(final TransitRouteStop fromStop, final TransitRouteStop toStop) {
TransitStopFacility fromFacility = fromStop.getStopFacility();
TransitStopFacility toFacility = toStop.getStopFacility();
Expand All @@ -137,13 +156,15 @@ private Link createAndAddLink(Tuple<Node, Node> connection) {
Node fromNode = connection.getFirst();
Node toNode = connection.getSecond();
Link link;
link = this.network.getFactory().createLink(Id.createLinkId(this.prefix + fromNode.getId() + "-" + toNode.getId()), fromNode,
toNode);
link.setLength(CoordUtils.calcEuclideanDistance(fromNode.getCoord(), toNode.getCoord()));
link = this.network.getFactory().createLink(Id.createLinkId(fromNode.getId() + "-" + toNode.getId()),
fromNode, toNode);

double dist = CoordUtils.calcEuclideanDistance(fromNode.getCoord(), toNode.getCoord());
link.setLength(dist);
link.setFreespeed(linkFreeSpeed);
link.setCapacity(linkCapacity);
link.setNumberOfLanes(1);

this.network.addLink(link);
link.setAllowedModes(this.transitModes);
this.links.put(connection, link);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.matsim.pt.utils;

import org.junit.jupiter.api.Test;
import org.matsim.api.core.v01.Scenario;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.scenario.ScenarioUtils;

import static org.assertj.core.api.Assertions.assertThat;

class CreatePseudoNetworkWithLoopLinksTest {

@Test
void createValidSchedule() {

Scenario scenario = ScenarioUtils.loadScenario(ConfigUtils.loadConfig("test/scenarios/pt-tutorial/0.config.xml"));

CreatePseudoNetworkWithLoopLinks creator = new CreatePseudoNetworkWithLoopLinks(scenario.getTransitSchedule(), scenario.getNetwork(), "pt_");
creator.createNetwork();


TransitScheduleValidator.ValidationResult result = TransitScheduleValidator.validateAll(scenario.getTransitSchedule(), scenario.getNetwork());

assertThat(result.getWarnings()).isEmpty();
assertThat(result.getErrors()).isEmpty();
assertThat(result.isValid()).isTrue();

}
}

0 comments on commit 54a8d6d

Please sign in to comment.