From 6282d86a8d4cb0873311b97e79dd322d56abdc42 Mon Sep 17 00:00:00 2001 From: sime94 Date: Mon, 16 Dec 2024 16:20:36 +0100 Subject: [PATCH] move computeSurfaceFactor to BicycleParamsDefaultImpl and add test for the method --- ...BicycleLinkSpeedCalculatorDefaultImpl.java | 66 ++----------------- .../matsim/contrib/bicycle/BicycleParams.java | 2 + .../bicycle/BicycleParamsDefaultImpl.java | 62 +++++++++++++++++ .../bicycle/BicycleParamsDefaultImplTest.java | 24 +++++++ 4 files changed, 93 insertions(+), 61 deletions(-) diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java index f6e5104fa86..a96073b1ad3 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java @@ -1,5 +1,6 @@ package org.matsim.contrib.bicycle; +import com.google.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.network.Link; @@ -9,13 +10,13 @@ import org.matsim.core.mobsim.qsim.qnetsimengine.QVehicle; import org.matsim.vehicles.Vehicle; -import jakarta.inject.Inject; import org.matsim.vehicles.VehicleType; import java.util.Objects; public final class BicycleLinkSpeedCalculatorDefaultImpl implements BicycleLinkSpeedCalculator { private static final Logger log = LogManager.getLogger(BicycleLinkSpeedCalculatorDefaultImpl.class ); + @Inject private BicycleParams params; @Inject private BicycleConfigGroup bicycleConfigGroup; @Inject private QSimConfigGroup qSimConfigGroup; @Inject private Config config; @@ -47,7 +48,7 @@ public double getMaximumVelocityForLink(Link link, Vehicle vehicle) { // prior to matsim 12.0 routers would not pass a vehicle. This is why we have a fallback for a default value from the config double maxBicycleSpeed = vehicle == null ? bicycleConfigGroup.getMaxBicycleSpeedForRouting() : vehicle.getType().getMaximumVelocity(); double bicycleInfrastructureFactor = computeInfrastructureFactor(link); - double surfaceFactor = computeSurfaceFactor(link); + double surfaceFactor = params.computeSurfaceFactor(link); double gradientFactor = computeGradientFactor(link); double speed = maxBicycleSpeed * bicycleInfrastructureFactor * surfaceFactor * gradientFactor; return Math.min(speed, link.getFreespeed()); @@ -79,69 +80,12 @@ private double computeGradientFactor(Link link) { return factor; } - // TODO combine this with comfort - private double computeSurfaceFactor(Link link) { - if (hasNotAttribute(link, BicycleUtils.WAY_TYPE) - || BicycleUtils.CYCLEWAY.equals(link.getAttributes().getAttribute(BicycleUtils.WAY_TYPE)) - || hasNotAttribute(link, BicycleUtils.SURFACE) - ) { - return 1.0; - } - - //so, the link is NOT a cycleway, and has a surface attribute - String surface = (String) link.getAttributes().getAttribute(BicycleUtils.SURFACE); - switch (Objects.requireNonNull(surface)) { - case "paved": - case "asphalt": - return 1.0; - - case "cobblestone (bad)": - case "grass": - return 0.4; - - case "cobblestone;flattened": - case "cobblestone:flattened": - case "sett": - case "earth": - return 0.6; - - case "concrete": - case "asphalt;paving_stones:35": - case "compacted": - return 0.9; - - case "concrete:lanes": - case "concrete_plates": - case "concrete:plates": - case "paving_stones:3": - return 0.8; - - case "paving_stones": - case "paving_stones:35": - case "paving_stones:30": - case "compressed": - case "bricks": - case "stone": - case "pebblestone": - case "fine_gravel": - case "gravel": - case "ground": - return 0.7; - - case "sand": - return 0.2; - - default: - return 0.5; - } - } - private double computeInfrastructureFactor(Link link) { var speedFactor = link.getAttributes().getAttribute(BicycleUtils.BICYCLE_INFRASTRUCTURE_SPEED_FACTOR); return speedFactor == null ? 1.0 : Double.parseDouble(speedFactor.toString()); } - private boolean hasNotAttribute(Link link, String attributeName) { + static boolean hasNotAttribute(Link link, String attributeName) { return link.getAttributes().getAttribute(attributeName) == null; } @@ -155,7 +99,7 @@ private boolean isBike(QVehicle qVehicle) { final VehicleType vehicleType = qVehicle.getVehicle().getType(); // the below consistentcy check is to broad; need a version that is more narrow ... - + // if ( qSimConfigGroup.getVehiclesSource()== QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData ) { // if ( !vehicleType.getId().toString().equals( vehicleType.getNetworkMode() ) ) { // throw new RuntimeException( "You are using mode vehicles but the network mode of the vehicle type is wrong: vehType.id=" + vehicleType.getId() diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParams.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParams.java index 130a5f9101c..18888865d93 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParams.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParams.java @@ -8,4 +8,6 @@ public interface BicycleParams { double getInfrastructureFactor(String type, String cyclewaytype); double getGradient(Link link); + + double computeSurfaceFactor(Link link); } diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImpl.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImpl.java index 5c2724713c1..de302798425 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImpl.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImpl.java @@ -2,6 +2,10 @@ import org.matsim.api.core.v01.network.Link; +import java.util.Objects; + +import static org.matsim.contrib.bicycle.BicycleLinkSpeedCalculatorDefaultImpl.hasNotAttribute; + public class BicycleParamsDefaultImpl implements BicycleParams { // TODO Combine this with speeds? @@ -60,6 +64,64 @@ public double getInfrastructureFactor( String type, String cyclewaytype ) { } } + // TODO combine this with comfort + @Override + public double computeSurfaceFactor(Link link) { + if (hasNotAttribute(link, BicycleUtils.WAY_TYPE) + || BicycleUtils.CYCLEWAY.equals(link.getAttributes().getAttribute(BicycleUtils.WAY_TYPE)) + || hasNotAttribute(link, BicycleUtils.SURFACE) + ) { + return 1.0; + } + + //so, the link is NOT a cycleway, and has a surface attribute + String surface = (String) link.getAttributes().getAttribute(BicycleUtils.SURFACE); + switch (Objects.requireNonNull(surface)) { + case "paved": + case "asphalt": + return 1.0; + + case "cobblestone (bad)": + case "grass": + return 0.4; + + case "cobblestone;flattened": + case "cobblestone:flattened": + case "sett": + case "earth": + return 0.6; + + case "concrete": + case "asphalt;paving_stones:35": + case "compacted": + return 0.9; + + case "concrete:lanes": + case "concrete_plates": + case "concrete:plates": + case "paving_stones:3": + return 0.8; + + case "paving_stones": + case "paving_stones:35": + case "paving_stones:30": + case "compressed": + case "bricks": + case "stone": + case "pebblestone": + case "fine_gravel": + case "gravel": + case "ground": + return 0.7; + + case "sand": + return 0.2; + + default: + return 0.5; + } + } + @Override public double getGradient(Link link) { diff --git a/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImplTest.java b/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImplTest.java index e8cbfccf9bd..e48d4752737 100644 --- a/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImplTest.java +++ b/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/BicycleParamsDefaultImplTest.java @@ -127,6 +127,30 @@ void testInfrastructureFactors() { } } + @Test + void testComputeSurfaceFactor() { + List> surfaces = List.of(ObjectDoublePair.of("paved", 1.0), ObjectDoublePair.of("asphalt", 1.0), + ObjectDoublePair.of("concrete:lanes", .8), ObjectDoublePair.of("concrete_plates", .8), ObjectDoublePair.of("concrete:plates", .8), + ObjectDoublePair.of("fine_gravel", .7), ObjectDoublePair.of("paving_stones", .7), ObjectDoublePair.of("paving_stones:35", .7), + ObjectDoublePair.of("paving_stones:30", .7), ObjectDoublePair.of("compacted", .9), + ObjectDoublePair.of("asphalt;paving_stones:35", .9), ObjectDoublePair.of("bricks", .7), ObjectDoublePair.of("gravel", .7), + ObjectDoublePair.of("ground", .7), ObjectDoublePair.of("sett", .6), ObjectDoublePair.of("cobblestone;flattened", .6), + ObjectDoublePair.of("cobblestone:flattened", .6), ObjectDoublePair.of("stone", .7), + ObjectDoublePair.of("grass", .4), ObjectDoublePair.of("compressed", .7), ObjectDoublePair.of("paving_stones:3", .8), + ObjectDoublePair.of("cobblestone (bad)", .4), ObjectDoublePair.of("earth", .6), ObjectDoublePair.of("pebblestone", .7), + ObjectDoublePair.of("sand", .2), ObjectDoublePair.of("concrete", .9), + ObjectDoublePair.of(null, 1.), ObjectDoublePair.of("test:default", .5)); + + Link link = createLink(new Coord(0, 0), new Coord(100, 0)); + link.getAttributes().putAttribute(BicycleUtils.WAY_TYPE, "type"); + + for (ObjectDoublePair pair : surfaces) { + link.getAttributes().putAttribute(OsmTags.SURFACE, pair.left()); + assertEquals(pair.rightDouble(), params.computeSurfaceFactor(link), 0.00001); + } + + } + private static Link createLink(Coord from, Coord to) { Network net = NetworkUtils.createNetwork();