From 66f6fab8a2d9ff6a4d9326f9cee9de707033553f Mon Sep 17 00:00:00 2001 From: GregorRyb Date: Wed, 12 Jun 2024 21:46:09 +0200 Subject: [PATCH 01/15] add test for bike speed and score --- .../org/matsim/run/TestBicycleRouting.java | 143 ++++++++++++++++-- 1 file changed, 131 insertions(+), 12 deletions(-) diff --git a/src/test/java/org/matsim/run/TestBicycleRouting.java b/src/test/java/org/matsim/run/TestBicycleRouting.java index 2bdb704..3f4e10d 100644 --- a/src/test/java/org/matsim/run/TestBicycleRouting.java +++ b/src/test/java/org/matsim/run/TestBicycleRouting.java @@ -9,29 +9,40 @@ import org.locationtech.jts.geom.prep.PreparedGeometry; import org.locationtech.jts.geom.prep.PreparedGeometryFactory; import org.matsim.api.core.v01.*; +import org.matsim.api.core.v01.events.PersonScoreEvent; +import org.matsim.api.core.v01.events.handler.PersonScoreEventHandler; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; import org.matsim.application.MATSimApplication; import org.matsim.contrib.bicycle.BicycleConfigGroup; +import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PersonUtils; import org.matsim.core.population.io.PopulationReader; import org.matsim.core.population.routes.NetworkRoute; +import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.trafficmonitoring.TravelTimeCalculator; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.VehicleType; import picocli.CommandLine; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.Set; @Disabled public class TestBicycleRouting { private static final Id personId = Id.createPersonId("test-person"); - private static final String inputNetworkFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/metropole-ruhr/metropole-ruhr-v1.0/input/metropole-ruhr-v1.4.network_resolutionHigh-with-pt.xml.gz"; + private static final String inputNetworkFile = "/Users/gregorr/Documents/work/respos/public-svn/matsim/scenarios/countries/de/metropole-ruhr/metropole-ruhr-v2.0/input/metropole-ruhr-v2.0.network_resolutionHigh-with-pt.xml.gz"; @RegisterExtension public MatsimTestUtils testUtils = new MatsimTestUtils(); @@ -40,18 +51,18 @@ public void testElevationRouting() { var outputDir = testUtils.getOutputDirectory(); - MATSimApplication.execute(TestApplication.class, "--output=" + outputDir + "withElevation", "--useElevation=true", "--download-input", "--1pct", "--config:network.inputNetworkFile=" + inputNetworkFile); - MATSimApplication.execute(TestApplication.class, "--output=" + outputDir + "withoutElevation", "--useElevation=false", "--download-input", "--1pct", "--config:network.inputNetworkFile=" + inputNetworkFile); + MATSimApplication.execute(TestApplication.class, "--output=" + outputDir + "withElevation", "--useElevation=true", "--1pct", "--config:network.inputNetworkFile=" + inputNetworkFile); + MATSimApplication.execute(TestApplication.class, "--output=" + outputDir + "withoutElevation", "--useElevation=false", "--1pct", "--config:network.inputNetworkFile=" + inputNetworkFile); - // load output of both runs - var scenarioWithElevation = ScenarioUtils.createScenario(ConfigUtils.createConfig()); - new PopulationReader(scenarioWithElevation).readFile(outputDir + "withElevation/" + TestApplication.RUN_ID + ".output_plans.xml.gz"); + // load output of both runs + var scenarioWithElevation = ScenarioUtils.createScenario(ConfigUtils.createConfig()); + new PopulationReader(scenarioWithElevation).readFile(outputDir + "withElevation/" + TestApplication.RUN_ID + ".output_plans.xml.gz"); var scenarioWithoutElevation = ScenarioUtils.createScenario(ConfigUtils.createConfig()); new PopulationReader(scenarioWithoutElevation).readFile(outputDir + "withoutElevation/" + TestApplication.RUN_ID + ".output_plans.xml.gz"); // somehow compare the two routes - var personWithElevation = scenarioWithElevation.getPopulation().getPersons().get(personId); + var personWithElevation = scenarioWithElevation.getPopulation().getPersons().get(personId); var personWithoutElevation = scenarioWithoutElevation.getPopulation().getPersons().get(personId); Assertions.assertTrue(personWithElevation.getSelectedPlan().getScore() < personWithoutElevation.getSelectedPlan().getScore()); @@ -59,9 +70,73 @@ public void testElevationRouting() { var bikeRouteWithElevation = getBikeRoute(personWithElevation); var bikeRouteWithoutElevation = getBikeRoute(personWithoutElevation); - Assertions.assertNotEquals(bikeRouteWithElevation.toString(), bikeRouteWithoutElevation.toString()); + Network networkWithoutElevation = NetworkUtils.readNetwork(outputDir + "withoutElevation/" + TestApplication.RUN_ID + ".output_network.xml.gz"); + Network networkWithElevation = NetworkUtils.readNetwork(outputDir + "withoutElevation/" + TestApplication.RUN_ID + ".output_network.xml.gz"); + + TravelTime travelTimeCalculatorNoElevation = getBikeTravelTime(outputDir + "withoutElevation/" + TestApplication.RUN_ID + ".output_events.xml.gz", networkWithoutElevation); + TravelTime travelTimeCalculatorWithElevation = getBikeTravelTime(outputDir + "withElevation/" + TestApplication.RUN_ID + ".output_events.xml.gz", networkWithElevation); + + double bikeScoringEventsNoElevation = getScoreEvents(outputDir + "withoutElevation/" + TestApplication.RUN_ID + ".output_events.xml.gz"); + double bikeScoringEventsWithElevation = getScoreEvents(outputDir + "withElevation/" + TestApplication.RUN_ID + ".output_events.xml.gz"); + + + double speedOnLinkNoElevation = travelTimeCalculatorNoElevation.getLinkTravelTime(networkWithoutElevation.getLinks().get(Id.createLinkId("2368352800005r")), + 10.0, personWithoutElevation, null); + + double speedOnLinkNoElevation2 = travelTimeCalculatorNoElevation.getLinkTravelTime(networkWithoutElevation.getLinks().get(Id.createLinkId( "9404091330015r")), + 0.0, scenarioWithoutElevation.getPopulation().getPersons().get("test-person"), null); + + double speedOnLinkWithElevation = travelTimeCalculatorWithElevation.getLinkTravelTime(networkWithElevation.getLinks().get(Id.createLinkId( "2368352800005r")), + 10.0, scenarioWithoutElevation.getPopulation().getPersons().get("test-person"), null); + + double speedOnLinkWithElevation2 = travelTimeCalculatorWithElevation.getLinkTravelTime(networkWithElevation.getLinks().get(Id.createLinkId( "9404091330015r")), + 0.0, scenarioWithoutElevation.getPopulation().getPersons().get("test-person"), null); + + Assertions.assertNotEquals(bikeRouteWithElevation.toString(), bikeRouteWithoutElevation.toString()); + Assertions.assertNotEquals(speedOnLinkNoElevation, speedOnLinkWithElevation); + + // equal as the second nodes z coord is below the first node + Assertions.assertEquals(speedOnLinkNoElevation2, speedOnLinkWithElevation2); + Assertions.assertTrue(speedOnLinkNoElevation > speedOnLinkNoElevation2); + Assertions.assertTrue(speedOnLinkNoElevation > speedOnLinkWithElevation); + + + Assertions.assertTrue(bikeScoringEventsWithElevation<0.0); + Assertions.assertTrue(bikeScoringEventsNoElevation==0.0); + Assertions.assertTrue(bikeScoringEventsNoElevation > bikeScoringEventsWithElevation); + } + private static TravelTime getBikeTravelTime(String eventsPath, Network network) { + + + TravelTimeCalculator.Builder builder = new TravelTimeCalculator.Builder(network); + builder.setAnalyzedModes(Set.of("bike")); + TravelTimeCalculator tt = builder.build(); + EventsManager eventsManager = EventsUtils.createEventsManager(); + eventsManager.addHandler(tt); + EventsUtils.readEvents(eventsManager, eventsPath); + eventsManager.finishProcessing(); + return tt.getLinkTravelTimes(); + } + + private static double getScoreEvents (String eventsPath) { + ScoringEventHandler scoringEventHandler= new ScoringEventHandler(); + EventsManager eventsManager = EventsUtils.createEventsManager(); + eventsManager.addHandler(scoringEventHandler); + EventsUtils.readEvents(eventsManager, eventsPath); + eventsManager.finishProcessing(); + + double sumScoreEvents = 0.0; + for(PersonScoreEvent scoringEvent: scoringEventHandler.getPersonsScoreEvents()) { + scoringEvent.getAmount(); + sumScoreEvents = sumScoreEvents + scoringEvent.getAmount(); + } + + return sumScoreEvents; + + } + private static NetworkRoute getBikeRoute(Person person) { return person.getSelectedPlan().getPlanElements().stream() .filter(element -> element instanceof Leg) @@ -76,7 +151,6 @@ public static class TestApplication extends MetropoleRuhrScenario { @CommandLine.Option(names = "--useElevation", description = "Overwrite output folder defined by the application") protected boolean isUseElevation; - private static final String RUN_ID = "TestApplication"; @Override @@ -130,7 +204,7 @@ public void prepareScenario(Scenario scenario) { var nodeIdsToRemove = scenario.getNetwork().getNodes().values().parallelStream() .filter(node -> !bbox.covers(MGC.coord2Point(node.getCoord()))) .map(Identifiable::getId) - .collect(Collectors.toList()); + .toList(); for (var id : nodeIdsToRemove) { scenario.getNetwork().removeNode(id); @@ -145,10 +219,30 @@ public void prepareScenario(Scenario scenario) { node.setCoord(coord); }); } + + if (isUseElevation) { + scenario.getNetwork().getNodes().values().parallelStream() + .forEach(node -> { + // copy coord and always add a z component + var coord = new Coord(node.getCoord().getX(), node.getCoord().getY(), node.getCoord().getZ() + MatsimRandom.getRandom().nextDouble() *100); + node.setCoord(coord); + }); + } + // this is necessary to get the test to work, the default networkMode of the bicycle vehicle type was set to "car" scenario.getVehicles().getVehicleTypes().get(Id.create("bike", VehicleType.class)).setNetworkMode("bike"); } - } + + public void prepareControler(Controler controler) { + super.prepareControler(controler); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addEventHandlerBinding().toInstance(new ScoringEventHandler()); + } + }); + } + } /* Create a bounding box around the links. Take the links as corners of the box and then add a 2km padding around it. @@ -167,4 +261,29 @@ private static PreparedGeometry createBoundingBox(Network network) { }); return new PreparedGeometryFactory().create(geometry); } + + private static class ScoringEventHandler implements PersonScoreEventHandler { + + + ArrayList personsScoreEvents = new ArrayList<>(); + + private ArrayList getPersonsScoreEvents() { + return personsScoreEvents; + } + + + @Override + public void handleEvent(PersonScoreEvent personScoreEvent) { + if (personScoreEvent.getKind().equals("bicycleAdditionalLinkScore")) { + personsScoreEvents.add(personScoreEvent); + } + } + + + + @Override + public void reset(int iteration) { + PersonScoreEventHandler.super.reset(iteration); + } + } } From bf07b269ab23680881bf52239438fda8410b5e62 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:40:33 +0200 Subject: [PATCH 02/15] Update vehicle selector with prob and add test --- .../commercial/CommercialVehicleSelector.java | 4 +- .../DefaultCommercialVehicleSelector.java | 93 +++++++++++++++++-- .../FTLFreightAgentGeneratorRuhr.java | 2 +- ...ltCommercialServiceTimeCalculatorTest.java | 67 +++++++++++++ 4 files changed, 155 insertions(+), 11 deletions(-) create mode 100644 src/test/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculatorTest.java diff --git a/src/main/java/org/matsim/prepare/commercial/CommercialVehicleSelector.java b/src/main/java/org/matsim/prepare/commercial/CommercialVehicleSelector.java index a7e0470..f822d1e 100644 --- a/src/main/java/org/matsim/prepare/commercial/CommercialVehicleSelector.java +++ b/src/main/java/org/matsim/prepare/commercial/CommercialVehicleSelector.java @@ -5,7 +5,9 @@ import java.util.List; public interface CommercialVehicleSelector { - List getPossibleVehicleTypes(Person freightDemandDataRelation, String string); + String getVehicleTypeForPlan(Person freightDemandDataRelation, String carrierId); + + List getPossibleVehicleTypes(Person freightDemandDataRelation, String carrierId); String getModeForFTLTrip(Person freightDemandDataRelation); } diff --git a/src/main/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelector.java b/src/main/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelector.java index 1877d76..8e3b413 100644 --- a/src/main/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelector.java +++ b/src/main/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelector.java @@ -1,27 +1,99 @@ package org.matsim.prepare.commercial; +import org.apache.commons.math3.distribution.EnumeratedDistribution; +import org.apache.commons.math3.random.MersenneTwister; +import org.apache.commons.math3.random.RandomGenerator; +import org.apache.commons.math3.util.Pair; import org.matsim.api.core.v01.population.Person; +import java.util.ArrayList; import java.util.List; public class DefaultCommercialVehicleSelector implements CommercialVehicleSelector { - // TODO perhaps vehicleTypes to constructor to get relevant data - @Override - public List getPossibleVehicleTypes(Person freightDemandDataRelation, String carrierId) { + private final RandomGenerator rnd = new MersenneTwister(4711); + EnumeratedDistribution vehicleDistributionFTL; + EnumeratedDistribution vehicleDistributionWaste; + EnumeratedDistribution vehicleDistributionParcel; + EnumeratedDistribution vehicleDistributionParcel_truck; + EnumeratedDistribution vehicleDistributionRest; + + public DefaultCommercialVehicleSelector() { + createVehicleTypeDistribution(); + } + + /** + * Creates the vehicle type distribution for the different transport types. + */ + private void createVehicleTypeDistribution() { + List> vehicleSelectionProbabilityDistributionFTL = new ArrayList<>(); + vehicleSelectionProbabilityDistributionFTL.add(new Pair<>(new VehicleSelection("heavy40t"), 1.0)); + vehicleDistributionFTL = new EnumeratedDistribution<>(rnd, vehicleSelectionProbabilityDistributionFTL); + + List> vehicleSelectionProbabilityDistributionWaste = new ArrayList<>(); + vehicleSelectionProbabilityDistributionWaste.add(new Pair<>(new VehicleSelection("waste_collection_diesel"), 1.0)); + vehicleDistributionWaste = new EnumeratedDistribution<>(rnd, vehicleSelectionProbabilityDistributionWaste); + + List> vehicleSelectionProbabilityDistributionParcel = new ArrayList<>(); + vehicleSelectionProbabilityDistributionParcel.add(new Pair<>(new VehicleSelection("mercedes313_parcel"), 1.0)); + vehicleDistributionParcel = new EnumeratedDistribution<>(rnd, vehicleSelectionProbabilityDistributionParcel); + + List> vehicleSelectionProbabilityDistributionParcel_truck = new ArrayList<>(); + vehicleSelectionProbabilityDistributionParcel_truck.add(new Pair<>(new VehicleSelection("medium18t_parcel"), 1.0)); + vehicleDistributionParcel_truck = new EnumeratedDistribution<>(rnd, vehicleSelectionProbabilityDistributionParcel_truck); + + List> vehicleSelectionProbabilityDistributionRest = new ArrayList<>(); + vehicleSelectionProbabilityDistributionRest.add(new Pair<>(new VehicleSelection("medium18t"), 1.0)); + vehicleDistributionRest = new EnumeratedDistribution<>(rnd, vehicleSelectionProbabilityDistributionRest); + } + + /** + * Gets the possible vehicle type for the given freight demand data relation. + * + * @param freightDemandDataRelation the freight demand data relation + * @param carrierId the carrier id + * @return the possible vehicle type + */ + @Override + public String getVehicleTypeForPlan(Person freightDemandDataRelation, String carrierId) { if (CommercialTrafficUtils.getTransportType(freightDemandDataRelation).equals("FTL")) - return List.of("heavy40t"); + return vehicleDistributionFTL.sample().vehicleType; else if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 140) // waste collection - return List.of("waste_collection_diesel"); + return vehicleDistributionWaste.sample().vehicleType; if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 150) // parcel delivery if (carrierId.contains("_truck18t")) - return List.of("medium18t_parcel"); + return vehicleDistributionParcel_truck.sample().vehicleType; else - return List.of("mercedes313_parcel"); - return List.of("medium18t"); + return vehicleDistributionParcel.sample().vehicleType; + return vehicleDistributionRest.sample().vehicleType; } - @Override + /** + * Gets the possible vehicle types for the given carrier. + * + * @param freightDemandDataRelation the freight demand data relation + * @param carrierId the carrier id + * @return the possible vehicle types for this carrier + */ + @Override + public List getPossibleVehicleTypes(Person freightDemandDataRelation, String carrierId) { + List allVehicleTypes = new ArrayList<>(); + if (CommercialTrafficUtils.getTransportType(freightDemandDataRelation).equals("FTL")) + allVehicleTypes.addAll(vehicleDistributionFTL.getPmf().stream().map(Pair::getFirst).map(VehicleSelection::vehicleType).toList()); + else if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 140) // waste collection + allVehicleTypes.addAll(vehicleDistributionWaste.getPmf().stream().map(Pair::getFirst).map(VehicleSelection::vehicleType).toList()); + else if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 150) // parcel delivery + if (carrierId.contains("_truck18t")) + allVehicleTypes.addAll( + vehicleDistributionParcel_truck.getPmf().stream().map(Pair::getFirst).map(VehicleSelection::vehicleType).toList()); + else + allVehicleTypes.addAll(vehicleDistributionParcel.getPmf().stream().map(Pair::getFirst).map(VehicleSelection::vehicleType).toList()); + else allVehicleTypes.addAll(vehicleDistributionRest.getPmf().stream().map(Pair::getFirst).map(VehicleSelection::vehicleType).toList()); + + return allVehicleTypes; + } + + @Override public String getModeForFTLTrip(Person freightDemandDataRelation) { // the current assumption is that all FTL trips are done by 40 tones trucks if (CommercialTrafficUtils.getTransportType(freightDemandDataRelation).equals("FTL") || CommercialTrafficUtils.getTransportType(freightDemandDataRelation).equals( @@ -29,4 +101,7 @@ public String getModeForFTLTrip(Person freightDemandDataRelation) { return "truck40t"; return null; } + + private record VehicleSelection(String vehicleType) {} + } diff --git a/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java b/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java index e579fde..fca5c39 100644 --- a/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java +++ b/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java @@ -54,7 +54,7 @@ private void createFreightFTLAgentWithPlan(Person freightDemandDataRelation, Lis double destinationX = CommercialTrafficUtils.getDestinationX(freightDemandDataRelation); double destinationY = CommercialTrafficUtils.getDestinationY(freightDemandDataRelation); String FTL_mode = commercialVehicleSelector.getModeForFTLTrip(freightDemandDataRelation); - String vehicleType = commercialVehicleSelector.getPossibleVehicleTypes(freightDemandDataRelation, null).getFirst(); + String vehicleType = commercialVehicleSelector.getVehicleTypeForPlan(freightDemandDataRelation, null); for (int i = 0; i < numOfTrips; i++) { Person person = populationFactory.createPerson(Id.createPersonId("freight_" + tripRelationId + "_" + i + "_" + transportType)); double departureTime = departureTimeCalculator.calculateDepartureTime(freightDemandDataRelation); diff --git a/src/test/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculatorTest.java b/src/test/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculatorTest.java new file mode 100644 index 0000000..c189ecd --- /dev/null +++ b/src/test/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculatorTest.java @@ -0,0 +1,67 @@ +package org.matsim.prepare.commercial; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.population.PopulationUtils; + +import static org.junit.jupiter.api.Assertions.*; + +class DefaultCommercialServiceTimeCalculatorTest { + + private DefaultCommercialServiceTimeCalculator calculator; + private Person freightDemandDataRelationParcel; + private Person freightDemandDataRelationWaste; + + @BeforeEach + void setUp() { + calculator = new DefaultCommercialServiceTimeCalculator(); + freightDemandDataRelationParcel = createFreightDemandDataRelation(150); + freightDemandDataRelationWaste = createFreightDemandDataRelation(140); + } + + private Person createFreightDemandDataRelation(int goodsType) { + Person freightDemandDataRelation = PopulationUtils.getFactory().createPerson(Id.createPersonId("exampleFreightDemandDataRelation")); + freightDemandDataRelation.getAttributes().putAttribute("goods_type", goodsType); + return freightDemandDataRelation; + } + + @Test + void testCalculateDeliveryTime_ParcelDelivery_LargeDemand() { + int deliveryTime = calculator.calculateDeliveryTime(freightDemandDataRelationParcel, 150); + assertEquals(1800, deliveryTime); // 30 minutes + } + + @Test + void testCalculateDeliveryTime_ParcelDelivery_SmallDemand() { + int deliveryTime = calculator.calculateDeliveryTime(freightDemandDataRelationParcel, 50); + assertEquals(9000, deliveryTime); // 50 parcels * 180 seconds + } + + @Test + void testCalculateDeliveryTime_WasteCollection() { + int deliveryTime = calculator.calculateDeliveryTime(freightDemandDataRelationWaste, 22000); + assertEquals(5400, deliveryTime); // (22000 / 11000) * 45 * 60 seconds + } + + @Test + void testCalculateDeliveryTime_Default() { + Person personOther = createFreightDemandDataRelation(100); + int deliveryTime = calculator.calculateDeliveryTime(personOther, 100); + assertEquals(1800, deliveryTime); // 30 minutes default + } + + @Test + void testCalculatePickupTime_WasteCollection() { + int pickupTime = calculator.calculatePickupTime(freightDemandDataRelationWaste, 220); + assertEquals(82, pickupTime); // 41 seconds per bin * 2 bins + } + + @Test + void testCalculatePickupTime_Default() { + Person personOther = createFreightDemandDataRelation(100); + int pickupTime = calculator.calculatePickupTime(personOther, 100); + assertEquals(0, pickupTime); // default case, no time needed + } +} From b2cc374b75a1c5ccf5c61af9f184de4fca0de9de Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:42:07 +0200 Subject: [PATCH 03/15] add tests --- .../CommercialTrafficUtilsTest.java | 103 ++++++++++++++++++ .../commercial/RvrTripRelationTest.java | 58 ++++++++++ 2 files changed, 161 insertions(+) create mode 100644 src/test/java/org/matsim/prepare/commercial/CommercialTrafficUtilsTest.java create mode 100644 src/test/java/org/matsim/prepare/commercial/RvrTripRelationTest.java diff --git a/src/test/java/org/matsim/prepare/commercial/CommercialTrafficUtilsTest.java b/src/test/java/org/matsim/prepare/commercial/CommercialTrafficUtilsTest.java new file mode 100644 index 0000000..baf5e51 --- /dev/null +++ b/src/test/java/org/matsim/prepare/commercial/CommercialTrafficUtilsTest.java @@ -0,0 +1,103 @@ +package org.matsim.prepare.commercial; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.population.PopulationUtils; + +import static org.junit.jupiter.api.Assertions.*; + +class CommercialTrafficUtilsTest { + + private Person person; + private RvrTripRelation rvrTripRelation; + + @BeforeEach + void setUp() { + person = PopulationUtils.getFactory().createPerson(Id.createPersonId("person")); + } + + @Test + void testWriteCommonAttributesForNonParcel() { + rvrTripRelation = new RvrTripRelation.Builder() + .goodsType("100") // Non-parcel goods type + .originCell("originCell") + .destinationCell("destinationCell") + .originLocationId("originLocationId") + .destinationLocationId("destinationLocationId") + .tonsPerYear(500) + .transportType("LTL") + .originX(1.0) + .originY(2.0) + .destinationX(3.0) + .destinationY(4.0) + .build(); + + CommercialTrafficUtils.writeCommonAttributes(person, rvrTripRelation, "tripRelationId"); + + assertEquals("tripRelationId", person.getAttributes().getAttribute("trip_relation_index")); + assertEquals("originCell", person.getAttributes().getAttribute("origin_cell")); + assertEquals("destinationCell", person.getAttributes().getAttribute("destination_cell")); + assertEquals("originLocationId", person.getAttributes().getAttribute("origin_locationId")); + assertEquals("destinationLocationId", person.getAttributes().getAttribute("destination_locationId")); + assertEquals(500.0, person.getAttributes().getAttribute("tons_per_year")); + assertEquals("LTL", person.getAttributes().getAttribute("transportType")); + assertEquals(1.0, person.getAttributes().getAttribute("origin_x")); + assertEquals(2.0, person.getAttributes().getAttribute("origin_y")); + assertEquals(3.0, person.getAttributes().getAttribute("destination_x")); + assertEquals(4.0, person.getAttributes().getAttribute("destination_y")); + } + + @Test + void testWriteCommonAttributesForParcel() { + rvrTripRelation = new RvrTripRelation.Builder() + .goodsType("150") // Parcel goods type + .parcelOperator("operator") + .parcelHubId("hubId") + .parcelsPerYear(1000) + .build(); + + CommercialTrafficUtils.writeCommonAttributes(person, rvrTripRelation, "tripRelationId"); + + assertEquals("tripRelationId", person.getAttributes().getAttribute("trip_relation_index")); + assertEquals("operator", person.getAttributes().getAttribute("parcelOperator")); + assertEquals("hubId", person.getAttributes().getAttribute("parcelHubId")); + assertEquals(1000.0, person.getAttributes().getAttribute("parcelsPerYear")); + } + + @Test + void testGetters() { + person.getAttributes().putAttribute("transportType", "LTL"); + person.getAttributes().putAttribute("trip_relation_index", "tripRelationId"); + person.getAttributes().putAttribute("origin_cell", "originCell"); + person.getAttributes().putAttribute("destination_cell", "destinationCell"); + person.getAttributes().putAttribute("origin_x", 1.0); + person.getAttributes().putAttribute("origin_y", 2.0); + person.getAttributes().putAttribute("destination_x", 3.0); + person.getAttributes().putAttribute("destination_y", 4.0); + person.getAttributes().putAttribute("goods_type", "100"); + person.getAttributes().putAttribute("tons_per_year", 500.0); + person.getAttributes().putAttribute("origin_locationId", "originLocationId"); + person.getAttributes().putAttribute("destination_locationId", "destinationLocationId"); + person.getAttributes().putAttribute("parcelOperator", "operator"); + person.getAttributes().putAttribute("parcelsPerYear", 1000.0); + person.getAttributes().putAttribute("parcelHubId", "hubId"); + + assertEquals("LTL", CommercialTrafficUtils.getTransportType(person)); + assertEquals("tripRelationId", CommercialTrafficUtils.getTripRelationIndex(person)); + assertEquals("originCell", CommercialTrafficUtils.getOriginCell(person)); + assertEquals("destinationCell", CommercialTrafficUtils.getDestinationCell(person)); + assertEquals(1.0, CommercialTrafficUtils.getOriginX(person)); + assertEquals(2.0, CommercialTrafficUtils.getOriginY(person)); + assertEquals(3.0, CommercialTrafficUtils.getDestinationX(person)); + assertEquals(4.0, CommercialTrafficUtils.getDestinationY(person)); + assertEquals(100, CommercialTrafficUtils.getGoodsType(person)); + assertEquals(500.0, CommercialTrafficUtils.getTonsPerYear(person)); + assertEquals("originLocationId", CommercialTrafficUtils.getOriginLocationId(person)); + assertEquals("destinationLocationId", CommercialTrafficUtils.getDestinationLocationId(person)); + assertEquals("operator", CommercialTrafficUtils.getParcelOperator(person)); + assertEquals(1000, CommercialTrafficUtils.getParcelsPerYear(person)); + assertEquals("hubId", CommercialTrafficUtils.getParcelHubId(person)); + } +} diff --git a/src/test/java/org/matsim/prepare/commercial/RvrTripRelationTest.java b/src/test/java/org/matsim/prepare/commercial/RvrTripRelationTest.java new file mode 100644 index 0000000..c06ffb6 --- /dev/null +++ b/src/test/java/org/matsim/prepare/commercial/RvrTripRelationTest.java @@ -0,0 +1,58 @@ +package org.matsim.prepare.commercial; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class RvrTripRelationTest { + + @Test + void testBuilderAndGetters() { + RvrTripRelation rvrTripRelation = new RvrTripRelation.Builder() + .originCell("originCell") + .originLocationId("originLocationId") + .destinationCell("destinationCell") + .destinationLocationId("destinationLocationId") + .transportType("LTL") + .goodsType("100") + .tonsPerYear(500) + .originX(1.0) + .originY(2.0) + .destinationX(3.0) + .destinationY(4.0) + .parcelsPerYear(1000) + .parcelOperator("operator") + .parcelHubId("hubId") + .build(); + + assertEquals("originCell", rvrTripRelation.getOriginCell()); + assertEquals("originLocationId", rvrTripRelation.getOriginLocationId()); + assertEquals("destinationCell", rvrTripRelation.getDestinationCell()); + assertEquals("destinationLocationId", rvrTripRelation.getDestinationLocationId()); + assertEquals("LTL", rvrTripRelation.getTransportType()); + assertEquals("100", rvrTripRelation.getGoodsType()); + assertEquals(500.0, rvrTripRelation.getTonsPerYear()); + assertEquals(1.0, rvrTripRelation.getOriginX()); + assertEquals(2.0, rvrTripRelation.getOriginY()); + assertEquals(3.0, rvrTripRelation.getDestinationX()); + assertEquals(4.0, rvrTripRelation.getDestinationY()); + assertEquals(1000.0, rvrTripRelation.getParcelsPerYear()); + assertEquals("operator", rvrTripRelation.getParcelOperator()); + assertEquals("hubId", rvrTripRelation.getParcelHubId()); + } + + @Test + void testParcelAttributes() { + RvrTripRelation rvrTripRelation = new RvrTripRelation.Builder() + .goodsType("150") // Parcel goods type + .parcelOperator("operator") + .parcelHubId("hubId") + .parcelsPerYear(1000) + .build(); + + assertEquals("150", rvrTripRelation.getGoodsType()); + assertEquals("operator", rvrTripRelation.getParcelOperator()); + assertEquals("hubId", rvrTripRelation.getParcelHubId()); + assertEquals(1000.0, rvrTripRelation.getParcelsPerYear()); + } +} From 9fba545ad6dbccbe2a31fc2655cb4476ffc31cb6 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:43:37 +0200 Subject: [PATCH 04/15] add java doc --- .../DefaultDemandPerDayCalculator.java | 47 ++++++++++++------- .../DefaultDepartureTimeCalculator.java | 6 +++ .../FTLFreightAgentGeneratorRuhr.java | 25 ++++++++-- .../prepare/commercial/RvrTripRelation.java | 4 +- 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java b/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java index 99770a7..f323a70 100644 --- a/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java +++ b/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java @@ -8,6 +8,11 @@ import java.util.*; +/** + * Calculates the demand per day for a given freight demand data relation. + * + * @Author Ricardo Ewert + */ public class DefaultDemandPerDayCalculator implements DemandPerDayCalculator { private final Random rnd = new Random(1234L); private final int workingDays; @@ -24,6 +29,12 @@ public DefaultDemandPerDayCalculator(int workingDays, double sample) { this.zonesWithWasteCollectionsOnThisDay = new HashMap<>(); } + /** + * Calculate the kilograms per day. + * + * @param tonsPerYear the tons per year + * @return the kilograms per day + */ @Override public int calculateKilogramsPerDay(double tonsPerYear) { double kilogramsPerDay = this.sample * tonsPerYear * 1000 / ((double) this.workingDays); @@ -31,13 +42,14 @@ public int calculateKilogramsPerDay(double tonsPerYear) { return (int) kilogramsPerDay; } - /** - * Calculate the waste demand per day. + + /** + * Calculate the waste demand per day. * The assumption is that waste is collected once a week and is collected in 20% of the zones on each day. - * - * @param freightDemandDataRelation the freight demand data relation - * @return the waste demand per day - */ + * + * @param freightDemandDataRelation the freight demand data relation + * @return the waste demand per day + */ @Override public int calculateWasteDemandPerDay(Person freightDemandDataRelation) { String destination = CommercialTrafficUtils.getDestinationLocationId(freightDemandDataRelation); @@ -63,21 +75,25 @@ public int calculateWasteDemandPerDay(Person freightDemandDataRelation) { return 0; } - /** - * @param parcelsPerYear the number of parcels per year. This demand calculation contains no sampling. This results in a 100% demand. - * @return the number of parcels per day - */ + /** + * Calculate the number of parcels per day. + * + * @param parcelsPerYear the number of parcels per year. This demand calculation contains no sampling. This results in a 100% demand. + * @return the number of parcels per day + */ @Override public int calculateParcelsPerDay(int parcelsPerYear) { int deliveryDaysPerWeek = 5; return (int) Math.floor((double) parcelsPerYear / (52 * deliveryDaysPerWeek)); } - /** - * @param existingCarrier the carrier - * @param demand the demand in kilograms - * @return the number of jobs - */ + /** + * Calculate the number of jobs for a given demand and carrier. + * + * @param existingCarrier the carrier + * @param demand the demand in kilograms + * @return the number of jobs + */ @Override public int calculateNumberOfJobsForDemand(Carrier existingCarrier, int demand) { double largestVehicleCapacity = 0; @@ -92,5 +108,4 @@ public int calculateNumberOfJobsForDemand(Carrier existingCarrier, int demand) { } return 1; } - } diff --git a/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java b/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java index c64a6f6..bf6d720 100644 --- a/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java +++ b/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java @@ -4,6 +4,12 @@ import java.util.Random; +/** + * Default implementation of the {@link DepartureTimeCalculator}. + * Calculates the departure time of a tour for a given freight demand data relation. + * + * @Author Ricardo Ewert + */ public class DefaultDepartureTimeCalculator implements DepartureTimeCalculator { private final Random rnd = new Random(1111); diff --git a/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java b/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java index fca5c39..7cd3616 100644 --- a/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java +++ b/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java @@ -15,17 +15,32 @@ import java.util.List; import java.util.Map; +/** + * Generates freight agents for full truck load (FTL) trips in the Ruhr area. + * + * @Author Ricardo Ewert + */ public class FTLFreightAgentGeneratorRuhr { private final DepartureTimeCalculator departureTimeCalculator; private final org.matsim.application.prepare.freight.tripGeneration.FreightAgentGenerator.NumOfTripsCalculator numOfTripsCalculator; private final PopulationFactory populationFactory; private final CommercialVehicleSelector commercialVehicleSelector; - public FTLFreightAgentGeneratorRuhr(double averageLoad, int workingDays, double sample) { - this.departureTimeCalculator = new DefaultDepartureTimeCalculator(); - this.numOfTripsCalculator = new DefaultNumberOfTripsCalculator(averageLoad, workingDays, sample); - this.commercialVehicleSelector = new DefaultCommercialVehicleSelector(); - this.populationFactory = PopulationUtils.getFactory(); + /** + * FTLLightFreightAgentGeneratorRuhr constructor to + * + * @param averageLoad the average load of a truck in tons + * @param workingDays the number of working days per year + * @param sample the scaling factor of the freight traffic (0, 1) + * @param departureTimeCalculator the departure time calculator, if null, a default implementation is used + * @param numOfTripsCalculator the number of trips calculator, if null, a default implementation is used + * @param commercialVehicleSelector the commercial vehicle selector, if null, a default implementation is used + */ + public FTLFreightAgentGeneratorRuhr(double averageLoad, int workingDays, double sample, DepartureTimeCalculator departureTimeCalculator, FreightAgentGenerator.NumOfTripsCalculator numOfTripsCalculator, CommercialVehicleSelector commercialVehicleSelector) { + this.departureTimeCalculator = Objects.requireNonNullElseGet(departureTimeCalculator, DefaultDepartureTimeCalculator::new); + this.numOfTripsCalculator = Objects.requireNonNullElseGet(numOfTripsCalculator, () -> new DefaultNumberOfTripsCalculator(averageLoad, workingDays, sample)); + this.commercialVehicleSelector = Objects.requireNonNullElseGet(commercialVehicleSelector, DefaultCommercialVehicleSelector::new); + this.populationFactory = PopulationUtils.getFactory(); } public List generateFreightFTLAgents(Person freightDemandDataRelation, int maxKilometerForReturnJourney) { diff --git a/src/main/java/org/matsim/prepare/commercial/RvrTripRelation.java b/src/main/java/org/matsim/prepare/commercial/RvrTripRelation.java index b8f318b..53bb820 100644 --- a/src/main/java/org/matsim/prepare/commercial/RvrTripRelation.java +++ b/src/main/java/org/matsim/prepare/commercial/RvrTripRelation.java @@ -17,7 +17,9 @@ import java.util.List; /** - * //TODO: Add description + * Represents a relation between two locations for a commercial trip. + * + * @Author Ricardo Ewert */ public class RvrTripRelation { public static final String column_originCellId = "quell_vz_nr"; From ca58b4a878fd70f17e0ab946bf95dea070c9c38e Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:45:03 +0200 Subject: [PATCH 05/15] update demandPerDayCalculator and add test --- .../DefaultDemandPerDayCalculator.java | 3 +- .../DefaultDemandPerDayCalculatorTest.java | 72 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src/test/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculatorTest.java diff --git a/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java b/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java index f323a70..b6f5c1a 100644 --- a/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java +++ b/src/main/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculator.java @@ -66,8 +66,7 @@ public int calculateWasteDemandPerDay(Person freightDemandDataRelation) { //if zone has a waste collection on this day, calculate the demand if (zonesWithWasteCollectionsOnThisDay.get(destination).contains(originCell)){ int numberOfCollectionsPerWeek = 1; - double shareOfPersonalWaste = 0.15; //TODO the current matrix has a wrong demand, because the tons per year are inclusive commercial/construction waste -> the share of personal waste is 0.15 - double tonsPerYear = CommercialTrafficUtils.getTonsPerYear(freightDemandDataRelation) * shareOfPersonalWaste; + double tonsPerYear = CommercialTrafficUtils.getTonsPerYear(freightDemandDataRelation); double kilogramsPerDay = tonsPerYear * 1000 / (52 * numberOfCollectionsPerWeek); kilogramsPerDay = Math.floor(kilogramsPerDay + this.rnd.nextDouble()); return (int) kilogramsPerDay; diff --git a/src/test/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculatorTest.java b/src/test/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculatorTest.java new file mode 100644 index 0000000..c9c052c --- /dev/null +++ b/src/test/java/org/matsim/prepare/commercial/DefaultDemandPerDayCalculatorTest.java @@ -0,0 +1,72 @@ +package org.matsim.prepare.commercial; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.population.PopulationUtils; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierCapabilities; +import org.matsim.freight.carriers.CarrierVehicle; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +import static org.junit.jupiter.api.Assertions.*; + +class DefaultDemandPerDayCalculatorTest { + + private DefaultDemandPerDayCalculator calculator; + private Person freightDemandDataRelation; + private Carrier carrier; + + @BeforeEach + void setUp() { + calculator = new DefaultDemandPerDayCalculator(250, 1.0); + + freightDemandDataRelation = createFreightDemandDataRelation(); + + carrier = CarriersUtils.createCarrier(Id.create("carrier", Carrier.class)); + CarrierVehicle vehicle = CarrierVehicle.Builder.newInstance(Id.create("vehicle", Vehicle.class), + Id.createLinkId("link"), createVehicleType()).build(); + CarrierCapabilities capabilities = CarrierCapabilities.Builder.newInstance().addVehicle(vehicle).build(); + carrier.setCarrierCapabilities(capabilities); + } + + private Person createFreightDemandDataRelation() { + Person freightDemandDataRelation = PopulationUtils.getFactory().createPerson(Id.createPersonId("exampleFreightDemandDataRelation")); + freightDemandDataRelation.getAttributes().putAttribute("origin_cell", "origin1"); + freightDemandDataRelation.getAttributes().putAttribute("destination_locationId", "destination1"); + freightDemandDataRelation.getAttributes().putAttribute("tons_per_year", 5.0); + return freightDemandDataRelation; + } + + private VehicleType createVehicleType() { + VehicleType vehicleType = VehicleUtils.getFactory().createVehicleType(Id.create("vehicleType", VehicleType.class)); + vehicleType.getCapacity().setOther(5000); + return vehicleType; + } + + @Test + void testCalculateKilogramsPerDay() { + assertEquals(4000, calculator.calculateKilogramsPerDay(1000.0)); + } + + @Test + void testCalculateWasteDemandPerDay() { + int demandPerDay = calculator.calculateWasteDemandPerDay(freightDemandDataRelation); + assertEquals(96, demandPerDay); // Depending on the random value, the actual value may vary + } + + @Test + void testCalculateParcelsPerDay() { + assertEquals(38, calculator.calculateParcelsPerDay(10000)); + } + + @Test + void testCalculateNumberOfJobsForDemand() { + assertEquals(1, calculator.calculateNumberOfJobsForDemand(carrier, 4000)); + assertEquals(2, calculator.calculateNumberOfJobsForDemand(carrier, 6000)); + } +} From e9a93de770ae01704541878de50ab566e451a204 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:45:39 +0200 Subject: [PATCH 06/15] add test --- .../DefaultCommercialVehicleSelectorTest.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/test/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelectorTest.java diff --git a/src/test/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelectorTest.java b/src/test/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelectorTest.java new file mode 100644 index 0000000..2f4b781 --- /dev/null +++ b/src/test/java/org/matsim/prepare/commercial/DefaultCommercialVehicleSelectorTest.java @@ -0,0 +1,79 @@ +package org.matsim.prepare.commercial; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.population.PopulationUtils; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class DefaultCommercialVehicleSelectorTest { + + private DefaultCommercialVehicleSelector selector; + private Person freightDemandDataRelationFTL; + private Person freightDemandDataRelationWaste; + private Person freightDemandDataRelationParcel; + private Person freightDemandDataRelationParcelTruck18t; + private Person freightDemandDataRelationRest; + + @BeforeEach + void setUp() { + selector = new DefaultCommercialVehicleSelector(); + + freightDemandDataRelationFTL = createFreightDemandDataRelation("FTL", 100); + freightDemandDataRelationWaste = createFreightDemandDataRelation("other", 140); + freightDemandDataRelationParcel = createFreightDemandDataRelation("other", 150); + freightDemandDataRelationParcelTruck18t = createFreightDemandDataRelation("other", 150); + freightDemandDataRelationRest = createFreightDemandDataRelation("other", 120); + } + + private Person createFreightDemandDataRelation(String transportType, int goodsType) { + + Person freightDemandDataRelation = PopulationUtils.getFactory().createPerson(Id.createPersonId("exampleFreightDemandDataRelation")); + freightDemandDataRelation.getAttributes().putAttribute("goods_type", goodsType); + freightDemandDataRelation.getAttributes().putAttribute("transportType", transportType); + return freightDemandDataRelation; + } + + @Test + void testGetVehicleTypeForPlan() { + assertEquals("heavy40t", selector.getVehicleTypeForPlan(freightDemandDataRelationFTL, "")); + assertEquals("waste_collection_diesel", selector.getVehicleTypeForPlan(freightDemandDataRelationWaste, "")); + assertEquals("mercedes313_parcel", selector.getVehicleTypeForPlan(freightDemandDataRelationParcel, "")); + assertEquals("medium18t_parcel", selector.getVehicleTypeForPlan(freightDemandDataRelationParcelTruck18t, "parcel_truck18t")); + assertEquals("medium18t", selector.getVehicleTypeForPlan(freightDemandDataRelationRest, "")); + } + + @Test + void testGetPossibleVehicleTypes() { + List vehicleTypesFTL = selector.getPossibleVehicleTypes(freightDemandDataRelationFTL, ""); + assertEquals(1, vehicleTypesFTL.size()); + assertTrue(vehicleTypesFTL.contains("heavy40t")); + + List vehicleTypesWaste = selector.getPossibleVehicleTypes(freightDemandDataRelationWaste, ""); + assertEquals(1, vehicleTypesWaste.size()); + assertTrue(vehicleTypesWaste.contains("waste_collection_diesel")); + + List vehicleTypesParcel = selector.getPossibleVehicleTypes(freightDemandDataRelationParcel, ""); + assertEquals(1, vehicleTypesParcel.size()); + assertTrue(vehicleTypesParcel.contains("mercedes313_parcel")); + + List vehicleTypesParcelTruck18t = selector.getPossibleVehicleTypes(freightDemandDataRelationParcelTruck18t, "_truck18t"); + assertEquals(1, vehicleTypesParcelTruck18t.size()); + assertTrue(vehicleTypesParcelTruck18t.contains("medium18t_parcel")); + + List vehicleTypesRest = selector.getPossibleVehicleTypes(freightDemandDataRelationRest, ""); + assertEquals(1, vehicleTypesRest.size()); + assertTrue(vehicleTypesRest.contains("medium18t")); + } + + @Test + void testGetModeForFTLTrip() { + assertEquals("truck40t", selector.getModeForFTLTrip(freightDemandDataRelationFTL)); + assertNull(selector.getModeForFTLTrip(freightDemandDataRelationWaste)); + assertNull(selector.getModeForFTLTrip(freightDemandDataRelationParcel)); + } +} From 16bb9d133b7f2ca81d56a072dd9c5e94620aaa59 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:45:51 +0200 Subject: [PATCH 07/15] add comments --- ...efaultCommercialServiceTimeCalculator.java | 74 +++++++++++-------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculator.java b/src/main/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculator.java index 1ef7fe7..494df07 100644 --- a/src/main/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculator.java +++ b/src/main/java/org/matsim/prepare/commercial/DefaultCommercialServiceTimeCalculator.java @@ -2,38 +2,48 @@ import org.matsim.api.core.v01.population.Person; +/** + * Default implementation of the {@link CommercialServiceTimeCalculator}. + * Calculates the service time of a job at a tour for a given freight demand data relation. + * + * @Author Ricardo Ewert + */ public class DefaultCommercialServiceTimeCalculator implements CommercialServiceTimeCalculator { - /** - * @param freightDemandDataRelation this relation data - * @param demand demand of teh good - * @return time in seconds - */ - @Override - public int calculateDeliveryTime(Person freightDemandDataRelation, int demand) { - if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 150) { // parcel delivery - // assumption: for large amount of parcels a fast delivery is possible (B2B), 30min is an assumption - if (demand > 100) - return (int) (0.5 * 3600); //TODO - int timePerParcel = 180; - return (demand * timePerParcel); - } - if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 140) // waste collection - return (int) ((double) demand / 11000 * 45 * 60); // assuming that the delivery time is 45 minutes (lunch break) and the vehicle is full when driving to the dump; - return (int) (0.5 * 3600); //TODO - } - /** - * @param freightDemandDataRelation this relation data - * @return time in seconds - */ - @Override - public int calculatePickupTime(Person freightDemandDataRelation, int demand) { - if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 140) { // waste collection - double maxLoadPerBinInKilogramm = 110; //bin with 1100l and density 100kg/m^3 - int timePerBin = 41; - return timePerBin * (int) Math.ceil(demand / maxLoadPerBinInKilogramm); - } - // assuming that the vehicle is already loaded and the driver only has to drive to the customer - return 0; - } + /** + * Calculates the delivery time of a shipment for a given freight demand data relation. + * + * @param freightDemandDataRelation this relation data + * @param demand demand of teh good + * @return time in seconds + */ + @Override + public int calculateDeliveryTime(Person freightDemandDataRelation, int demand) { + if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 150) { // parcel delivery + // assumption: for large amount of parcels a fast delivery is possible (B2B), 30min is an assumption + if (demand > 100) return (int) (0.5 * 3600); //TODO perhaps find better assumption + int timePerParcel = 180; + return (demand * timePerParcel); + } + if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 140) // waste collection + return (int) ((double) demand / 11000 * 45 * 60); // assuming that the delivery time is 45 minutes (lunch break) and the vehicle is full when driving to the dump; + return (int) (0.5 * 3600); //TODO perhaps find better assumption + } + + /** + * Calculates the pickup time of a shipment for a given freight demand data relation. + * + * @param freightDemandDataRelation this relation data + * @return time in seconds + */ + @Override + public int calculatePickupTime(Person freightDemandDataRelation, int demand) { + if (CommercialTrafficUtils.getGoodsType(freightDemandDataRelation) == 140) { // waste collection + double maxLoadPerBinInKilogramm = 110; //bin with 1100l and density 100kg/m^3 + int timePerBin = 41; + return timePerBin * (int) Math.ceil(demand / maxLoadPerBinInKilogramm); + } + // assuming that the vehicle is already loaded and the driver only has to drive to the customer + return 0; + } } From 6a70b253949dbccdcb19ada0cd85b7f02edb625b Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:46:00 +0200 Subject: [PATCH 08/15] change todo --- .../prepare/commercial/DefaultDepartureTimeCalculator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java b/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java index bf6d720..92254c2 100644 --- a/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java +++ b/src/main/java/org/matsim/prepare/commercial/DefaultDepartureTimeCalculator.java @@ -29,7 +29,7 @@ else if (CommercialTrafficUtils.getParcelOperator(freightDemandDataRelation).equ return rnd.nextInt(8 * 3600, 12 * 3600); else if (CommercialTrafficUtils.getParcelOperator(freightDemandDataRelation).equals("gls")) return rnd.nextInt(8 * 3600, 10 * 3600); - return rnd.nextInt(6 * 3600, 12 * 3600); // TODO add assumptions for other goods types + return rnd.nextInt(6 * 3600, 12 * 3600); // possibility to add assumptions for other goods types } } From 92b2419b9c1f5a99c7ac5b0c19a3476f2c2192cd Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:47:08 +0200 Subject: [PATCH 09/15] update FTL generator --- .../commercial/FTLFreightAgentGeneratorRuhr.java | 11 ++++++----- .../commercial/GenerateFTLFreightPlansRuhr.java | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java b/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java index 7cd3616..1c00ad3 100644 --- a/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java +++ b/src/main/java/org/matsim/prepare/commercial/FTLFreightAgentGeneratorRuhr.java @@ -6,6 +6,7 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.application.prepare.freight.tripGeneration.DefaultNumberOfTripsCalculator; +import org.matsim.application.prepare.freight.tripGeneration.FreightAgentGenerator; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.vehicles.VehicleType; @@ -14,6 +15,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; /** * Generates freight agents for full truck load (FTL) trips in the Ruhr area. @@ -21,10 +23,10 @@ * @Author Ricardo Ewert */ public class FTLFreightAgentGeneratorRuhr { - private final DepartureTimeCalculator departureTimeCalculator; - private final org.matsim.application.prepare.freight.tripGeneration.FreightAgentGenerator.NumOfTripsCalculator numOfTripsCalculator; - private final PopulationFactory populationFactory; - private final CommercialVehicleSelector commercialVehicleSelector; + private final DepartureTimeCalculator departureTimeCalculator; + private final org.matsim.application.prepare.freight.tripGeneration.FreightAgentGenerator.NumOfTripsCalculator numOfTripsCalculator; + private final PopulationFactory populationFactory; + private final CommercialVehicleSelector commercialVehicleSelector; /** * FTLLightFreightAgentGeneratorRuhr constructor to @@ -48,7 +50,6 @@ public List generateFreightFTLAgents(Person freightDemandDataRelation, i createFreightFTLAgentWithPlan(freightDemandDataRelation, createdFreightAgentsForThisRelation, maxKilometerForReturnJourney); return createdFreightAgentsForThisRelation; - } /** diff --git a/src/main/java/org/matsim/prepare/commercial/GenerateFTLFreightPlansRuhr.java b/src/main/java/org/matsim/prepare/commercial/GenerateFTLFreightPlansRuhr.java index 67cc9bc..6eb70fc 100644 --- a/src/main/java/org/matsim/prepare/commercial/GenerateFTLFreightPlansRuhr.java +++ b/src/main/java/org/matsim/prepare/commercial/GenerateFTLFreightPlansRuhr.java @@ -47,7 +47,7 @@ public class GenerateFTLFreightPlansRuhr implements MATSimAppCommand { public Integer call() throws Exception { log.info("preparing freight agent generator for FTL trips..."); - FTLFreightAgentGeneratorRuhr freightAgentGeneratorFTL = new FTLFreightAgentGeneratorRuhr(averageTruckLoad, workingDays, sample); + FTLFreightAgentGeneratorRuhr freightAgentGeneratorFTL = new FTLFreightAgentGeneratorRuhr(averageTruckLoad, workingDays, sample, null, null, null); log.info("Freight agent generator for FTL trips successfully created!"); log.info("Reading freight data..."); From 043cd1e4e31f21b3f971507d7d3eeb73db19849b Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:47:34 +0200 Subject: [PATCH 10/15] update LTL generator --- .../GenerateLTLFreightPlansRuhr.java | 2 +- .../LTLFreightAgentGeneratorRuhr.java | 33 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/matsim/prepare/commercial/GenerateLTLFreightPlansRuhr.java b/src/main/java/org/matsim/prepare/commercial/GenerateLTLFreightPlansRuhr.java index 3a2d7be..28ea29f 100644 --- a/src/main/java/org/matsim/prepare/commercial/GenerateLTLFreightPlansRuhr.java +++ b/src/main/java/org/matsim/prepare/commercial/GenerateLTLFreightPlansRuhr.java @@ -64,7 +64,7 @@ public class GenerateLTLFreightPlansRuhr implements MATSimAppCommand { public Integer call() throws Exception { log.info("preparing freight agent generator for FTL trips..."); - LTLFreightAgentGeneratorRuhr freightAgentGeneratorLTL = new LTLFreightAgentGeneratorRuhr(workingDays, sample); + LTLFreightAgentGeneratorRuhr freightAgentGeneratorLTL = new LTLFreightAgentGeneratorRuhr(workingDays, sample, null, null, null, null); log.info("Freight agent generator for FTL trips successfully created!"); diff --git a/src/main/java/org/matsim/prepare/commercial/LTLFreightAgentGeneratorRuhr.java b/src/main/java/org/matsim/prepare/commercial/LTLFreightAgentGeneratorRuhr.java index 04d587f..6757a20 100644 --- a/src/main/java/org/matsim/prepare/commercial/LTLFreightAgentGeneratorRuhr.java +++ b/src/main/java/org/matsim/prepare/commercial/LTLFreightAgentGeneratorRuhr.java @@ -14,10 +14,7 @@ import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -27,19 +24,21 @@ * @author Ricardo Ewert */ public class LTLFreightAgentGeneratorRuhr { - private static DepartureTimeCalculator departureTimeCalculator; - private static DemandPerDayCalculator demandPerDayCalculator; - private static CommercialVehicleSelector commercialVehicleSelector; - private static CommercialServiceTimeCalculator commercialServiceTimeCalculator; + private final DepartureTimeCalculator departureTimeCalculator; + private final DemandPerDayCalculator demandPerDayCalculator; + private final CommercialVehicleSelector commercialVehicleSelector; + private final CommercialServiceTimeCalculator commercialServiceTimeCalculator; private static double sample; - public LTLFreightAgentGeneratorRuhr(int workingDays, double sample) { - departureTimeCalculator = new DefaultDepartureTimeCalculator(); - demandPerDayCalculator = new DefaultDemandPerDayCalculator(workingDays, sample); - commercialVehicleSelector = new DefaultCommercialVehicleSelector(); - commercialServiceTimeCalculator = new DefaultCommercialServiceTimeCalculator(); - this.sample = sample; - } + public LTLFreightAgentGeneratorRuhr(int workingDays, double sample, DepartureTimeCalculator departureTimeCalculator, + DemandPerDayCalculator demandPerDayCalculator, CommercialVehicleSelector commercialVehicleSelector, + CommercialServiceTimeCalculator commercialServiceTimeCalculator) { + this.departureTimeCalculator = Objects.requireNonNullElseGet(departureTimeCalculator, DefaultDepartureTimeCalculator::new); + this.commercialVehicleSelector = Objects.requireNonNullElseGet(commercialVehicleSelector, DefaultCommercialVehicleSelector::new); + this.commercialServiceTimeCalculator = Objects.requireNonNullElseGet(commercialServiceTimeCalculator, DefaultCommercialServiceTimeCalculator::new); + this.demandPerDayCalculator = Objects.requireNonNullElseGet(demandPerDayCalculator, () -> new DefaultDemandPerDayCalculator(workingDays, sample)); + this.sample = sample; + } /** * Creates the CarrierVehicle for a carrier. @@ -48,7 +47,7 @@ public LTLFreightAgentGeneratorRuhr(int workingDays, double sample) { * @param newCarrier carrier * @param nearestLinkOrigin link of the depot */ - private static void createFreightVehicles(Scenario scenario, Carrier newCarrier, Id nearestLinkOrigin, Person freightDemandDataRelation) { + private void createFreightVehicles(Scenario scenario, Carrier newCarrier, Id nearestLinkOrigin, Person freightDemandDataRelation) { CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); @@ -232,7 +231,7 @@ else if (Math.abs(parcelDeliveryRoundingError.get()) >= 1.) { * * @return Creates a carrier id based on the freight demand data. */ - private static Id createCarrierId(Person freightDemandDataRelation) { + private Id createCarrierId(Person freightDemandDataRelation) { int goodsType = CommercialTrafficUtils.getGoodsType(freightDemandDataRelation); From fd511b146c6ce0e42ebc95c7df3a0daf4b1fc119 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 26 Jun 2024 13:48:43 +0200 Subject: [PATCH 11/15] change input --- .../org/matsim/prepare/commercial/GenerateFreightDataRuhr.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/matsim/prepare/commercial/GenerateFreightDataRuhr.java b/src/main/java/org/matsim/prepare/commercial/GenerateFreightDataRuhr.java index 66d6e83..da1d45a 100644 --- a/src/main/java/org/matsim/prepare/commercial/GenerateFreightDataRuhr.java +++ b/src/main/java/org/matsim/prepare/commercial/GenerateFreightDataRuhr.java @@ -53,7 +53,7 @@ public class GenerateFreightDataRuhr implements MATSimAppCommand { private static final Logger log = LogManager.getLogger(GenerateFreightDataRuhr.class); @CommandLine.Option(names = "--data", description = "Path to buw data", - defaultValue = "../shared-svn/projects/rvr-metropole-ruhr/data/commercialTraffic/buw/matrix_gesamt_V2.csv") + defaultValue = "../shared-svn/projects/rvr-metropole-ruhr/data/commercialTraffic/buw/matrix_gesamt_V3.csv") private Path dataFolderPath; @CommandLine.Option(names = "--KEPdata", description = "Path to buw KEP data", From 56b378f5e2923f544909e90efbcf27b9b91e306e Mon Sep 17 00:00:00 2001 From: GregorRyb Date: Wed, 26 Jun 2024 17:00:00 +0200 Subject: [PATCH 12/15] add ride scoring --- .../org/matsim/run/MetropoleRuhrScenario.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/matsim/run/MetropoleRuhrScenario.java b/src/main/java/org/matsim/run/MetropoleRuhrScenario.java index 64cb5ea..30e8cd2 100644 --- a/src/main/java/org/matsim/run/MetropoleRuhrScenario.java +++ b/src/main/java/org/matsim/run/MetropoleRuhrScenario.java @@ -25,6 +25,7 @@ import com.google.inject.Singleton; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.locationtech.jts.util.Assert; import org.matsim.analysis.ModeChoiceCoverageControlerListener; import org.matsim.analysis.TripMatrix; import org.matsim.analysis.personMoney.PersonMoneyEventsAnalysisModule; @@ -270,13 +271,21 @@ protected Config prepareConfig(Config config) { // alpha can be calibrated double alpha = 2.0; //gamma must stay one - double gamma = 1.0; + double gamma = 0.0; double monetaryDistanceRateRide = config.scoring().getOrCreateModeParams(TransportMode.car).getMonetaryDistanceRate() * alpha; - double marginalUtilityOfTravelingRide = (alpha + gamma) * -(config.scoring().getPerforming_utils_hr()) + config.scoring().getOrCreateModeParams(TransportMode.car).getMarginalUtilityOfTraveling() * (1.0 + alpha) ; + + double marginalUtilityOfTravllingRide = config.scoring().getOrCreateModeParams(TransportMode.car).getMarginalUtilityOfTraveling(); //marginal disutility of passenger + marginalUtilityOfTravllingRide += alpha * (-config.scoring().getPerforming_utils_hr() + config.scoring().getOrCreateModeParams(TransportMode.car).getMarginalUtilityOfTraveling()); // Zeitverbrauch des Fahrers + //marginalUtilityOfTravllingRide += gamma * -config.scoring().getPerforming_utils_hr(); //we prefer not using this term + + double tmp = (alpha + gamma) * -(config.scoring().getPerforming_utils_hr()) + config.scoring().getOrCreateModeParams(TransportMode.car).getMarginalUtilityOfTraveling() * (1.0 + alpha) ; + + Assert.isTrue(tmp==marginalUtilityOfTravllingRide); + double marginalUtilityOfDistanceRide = (alpha + 1.0) * config.scoring().getOrCreateModeParams(TransportMode.car).getMarginalUtilityOfDistance(); config.scoring().getOrCreateModeParams(TransportMode.ride).setMonetaryDistanceRate(monetaryDistanceRateRide); config.scoring().getOrCreateModeParams(TransportMode.ride).setMarginalUtilityOfDistance(marginalUtilityOfDistanceRide); - config.scoring().getOrCreateModeParams(TransportMode.ride).setMarginalUtilityOfTraveling(marginalUtilityOfTravelingRide); + config.scoring().getOrCreateModeParams(TransportMode.ride).setMarginalUtilityOfTraveling(marginalUtilityOfTravllingRide); prepareCommercialTrafficConfig(config); From 849dbb7686f5d9431574cc1986cdcf4e3b243bfe Mon Sep 17 00:00:00 2001 From: GregorRyb Date: Wed, 26 Jun 2024 17:02:56 +0200 Subject: [PATCH 13/15] use interface instead of implementation --- src/test/java/org/matsim/run/TestBicycleRouting.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/matsim/run/TestBicycleRouting.java b/src/test/java/org/matsim/run/TestBicycleRouting.java index 3f4e10d..a67a1e3 100644 --- a/src/test/java/org/matsim/run/TestBicycleRouting.java +++ b/src/test/java/org/matsim/run/TestBicycleRouting.java @@ -36,6 +36,7 @@ import picocli.CommandLine; import java.util.ArrayList; +import java.util.List; import java.util.Set; @Disabled @@ -265,9 +266,9 @@ private static PreparedGeometry createBoundingBox(Network network) { private static class ScoringEventHandler implements PersonScoreEventHandler { - ArrayList personsScoreEvents = new ArrayList<>(); + List personsScoreEvents = new ArrayList<>(); - private ArrayList getPersonsScoreEvents() { + private List getPersonsScoreEvents() { return personsScoreEvents; } From 85e2d2f729c918752f568d6f1a08dd28f7bf9f65 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 26 Jun 2024 17:26:31 +0200 Subject: [PATCH 14/15] adapt config --- .../input/metropole-ruhr-v2.0-3pct.config.xml | 20 ++++---- .../prepare/ConvertLinkIdsToCoords.java | 49 +++++++++++++++++++ .../matsim/prepare/DeleteRoutesFromPlans.java | 4 +- 3 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/matsim/prepare/ConvertLinkIdsToCoords.java diff --git a/scenarios/metropole-ruhr-v2.0/input/metropole-ruhr-v2.0-3pct.config.xml b/scenarios/metropole-ruhr-v2.0/input/metropole-ruhr-v2.0-3pct.config.xml index 6628ca4..a86ba21 100644 --- a/scenarios/metropole-ruhr-v2.0/input/metropole-ruhr-v2.0-3pct.config.xml +++ b/scenarios/metropole-ruhr-v2.0/input/metropole-ruhr-v2.0-3pct.config.xml @@ -137,24 +137,24 @@ - - + + - - + + - + - - - - - + + + + + diff --git a/src/main/java/org/matsim/prepare/ConvertLinkIdsToCoords.java b/src/main/java/org/matsim/prepare/ConvertLinkIdsToCoords.java new file mode 100644 index 0000000..1244733 --- /dev/null +++ b/src/main/java/org/matsim/prepare/ConvertLinkIdsToCoords.java @@ -0,0 +1,49 @@ +package org.matsim.prepare; + +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.population.PopulationUtils; +import picocli.CommandLine; + +@CommandLine.Command(name = "convert-link-ids-to-coords") +public class ConvertLinkIdsToCoords implements MATSimAppCommand { + + @CommandLine.Option(names = "--input-network", description = "Path to input network", required = true) + private String inputNetwork; + + @CommandLine.Option(names = "--input-plans", description = "Path to input plans", required = true) + private String inputPlans; + + @CommandLine.Option(names = "--output", description = "Path to output network", required = true) + private String output; + + @Override + public Integer call() throws Exception { + var pop = PopulationUtils.readPopulation(inputPlans); + var net = NetworkUtils.readNetwork(inputNetwork); + + pop.getPersons().values().stream() + .flatMap(p -> p.getPlans().stream()) + .flatMap(p -> p.getPlanElements().stream()) + .filter(e -> e instanceof Activity) + .forEach(e -> { + var act = (Activity) e; + if(act.getLinkId() == null) return; + + var link = net.getLinks().get(act.getLinkId()); + if(link == null) throw new RuntimeException("Link not found: " + act.getLinkId()); + act.setCoord(link.getCoord()); + act.setLinkId(null); + }); + + PopulationUtils.writePopulation(pop, output); + + return 0; + } + + public static void main(String[] args) { + new ConvertLinkIdsToCoords().execute(args); + } +} diff --git a/src/main/java/org/matsim/prepare/DeleteRoutesFromPlans.java b/src/main/java/org/matsim/prepare/DeleteRoutesFromPlans.java index 810cba5..5b06ab7 100644 --- a/src/main/java/org/matsim/prepare/DeleteRoutesFromPlans.java +++ b/src/main/java/org/matsim/prepare/DeleteRoutesFromPlans.java @@ -8,8 +8,8 @@ public class DeleteRoutesFromPlans { public static void main(String[] args) throws Exception { String[] argsForRemoveRoutesFromPlans = new String[]{ - "--plans=../../shared-svn/projects/matsim-metropole-ruhr/metropole-ruhr-v1.0/input/metropole-ruhr-v1.4-3pct.plans.xml.gz", - "--output=../../shared-svn/projects/matsim-metropole-ruhr/metropole-ruhr-v1.0/input/metropole-ruhr-v1.4-3pct.plans-withoutRoutes.xml.gz", + "--plans=../../../public-svn/matsim/scenarios/countries/de/metropole-ruhr/metropole-ruhr-v2.0/input/metropole-ruhr-v2.0-3pct.plans-commercial.xml.gz", + "--output=../../../public-svn/matsim/scenarios/countries/de/metropole-ruhr/metropole-ruhr-v2.0/input/no-routes/metropole-ruhr-v2.0-3pct.plans-commercial.xml.gz", "--remove-routes=true", "--remove-unselected-plans=true", "--remove-activity-location=true" From 7a7a3d5900e8ff73983dee73ac7a7275cc697aa3 Mon Sep 17 00:00:00 2001 From: GregorRyb Date: Wed, 26 Jun 2024 18:28:36 +0200 Subject: [PATCH 15/15] disable test until public svn is working again --- src/test/java/org/matsim/run/TestBicycleRouting.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/matsim/run/TestBicycleRouting.java b/src/test/java/org/matsim/run/TestBicycleRouting.java index a67a1e3..45ca3a0 100644 --- a/src/test/java/org/matsim/run/TestBicycleRouting.java +++ b/src/test/java/org/matsim/run/TestBicycleRouting.java @@ -47,7 +47,7 @@ public class TestBicycleRouting { @RegisterExtension public MatsimTestUtils testUtils = new MatsimTestUtils(); - @Test + @Test @Disabled public void testElevationRouting() { var outputDir = testUtils.getOutputDirectory();