Repository: graphhopper/graphhopper
Pull request #2702 (2022-11-29 12:13:57)

Use explicit ignore list for highway values
So far we used `VehicleTagParser#getAccess` to determine whether an OSM way shall be accepted when parsing the OSM file. With this PR all highways will be accepted except those listed in a global list of ignored values ~~there will be only one global list of accepted highway values~~. It is still up to the vehicle tag parsers (and in the near future only up to the access tag parsers) whether a given way is used for the route calculations. Putting a highway value into the global list is therefore mostly a performance optimization. So far this happened automatically by only using certain vehicles. For example if we used only profiles with the car profile footways were rejected automatically. With the new global list this needs to be done manually, but at the same time the mechanism becomes more powerful and easier to understand IMO.

See more comments inline.

Related: https://github.com/graphhopper/graphhopper/issues/2463#issuecomment-1174205767 


easbar: I did not take a look at the failing tests yet, but will fix them of course once there is agreement for this PR @karussell 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89fabca0f..24165f834 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,17 @@
 ### 7.0 [not yet released]
 
+- there is a new, required 'import.osm.ignored_highways' configuration option that must be used to not increase the graph size and decrease performance for motorized-only routing compared to previous versions, #2702
+- new osm_way_id encoded value, #2701
 - the parameters vehicle, weighting, edge_based and turn_costs are no longer supported, use the profile parameter instead
 - removed motorroad to road_class conversion, #2329
 - removed YAML support for custom models on the server-side. Only allow JSON with // comments.
 - Bike2WeightTagParser was removed. Use the bike vehicle with a custom model, see custom_models/bike2.json
-- Car4WDTagParser was removed. Use the roads vehicle with a custom model, see custom_models/car4wd.json
 - CurvatureWeighting was removed. Use a custom model with 'curvature' instead, see custom_models/curvature.json (#2665)
 - internal keys for EdgeKVStorage changed to contain the street_ prefix like the path details too. Similarly, the extra_info in the instructions of the API response, see #2661
 
 ### 6.0 [13 Sep 2022]
 
+- Car4WDTagParser was removed. Use the roads vehicle with a custom model, see custom_models/car4wd.json see #2651
 - When using a DecimalEncodedValue with useMaximumAsInfinity=true and a single bit of space make sure you always use 
   Double.POSITIVE_INFINITY to set the value, see #2646
 - renamed DouglasPeucker to RamerDouglasPeucker
diff --git a/config-example.yml b/config-example.yml
index 8e3b7eff4..98dad1b8c 100644
--- a/config-example.yml
+++ b/config-example.yml
@@ -40,6 +40,7 @@ graphhopper:
   #   u_turn_costs: 60
 
   # - name: bike
+      # to use the bike vehicle make sure to not ignore cycleways etc., see import.osm.ignored_highways below
   #   vehicle: bike
   #   weighting: custom
   #   # the custom model in bike2.json is defined to avoid hills
@@ -80,8 +81,8 @@ graphhopper:
 
   # Add additional information to every edge. Used for path details (#1548) and custom models (docs/core/custom-models.md)
   # Default values are: road_class,road_class_link,road_environment,max_speed,road_access
-  # More are: surface,smoothness,max_width,max_height,max_weight,hgv,max_axle_load,max_length,hazmat,hazmat_tunnel,hazmat_water,toll,track_type,
-  #           mtb_rating, hike_rating,horse_rating,lanes
+  # More are: surface,smoothness,max_width,max_height,max_weight,hgv,max_axle_load,max_length,hazmat,hazmat_tunnel,hazmat_water,
+  #           lanes,osm_way_id,toll,track_type,mtb_rating,hike_rating,horse_rating
   # graph.encoded_values: surface,toll,track_type
 
   #### Speed, hybrid and flexible mode ####
@@ -168,6 +169,14 @@ graphhopper:
 
   #### Storage ####
 
+  # Excludes certain types of highways during the OSM import to speed up the process and reduce the size of the graph.
+  # A typical application is excluding 'footway','cycleway','path' and maybe 'pedestrian' and 'track' highways for
+  # motorized vehicles. This leads to a smaller and less dense graph, because there are fewer ways (obviously),
+  # but also because there are fewer crossings between highways (=junctions).
+  # Another typical example is excluding 'motorway', 'trunk' and maybe 'primary' highways for bicycle or pedestrian routing.
+  import.osm.ignored_highways: footway,cycleway,path,pedestrian,steps # typically useful for motorized-only routing
+  # import.osm.ignored_highways: motorway,trunk # typically useful for non-motorized routing
+
   # configure the memory access, use RAM_STORE for well equipped servers (default and recommended)
   graph.dataaccess.default_type: RAM_STORE
 
diff --git a/core/src/main/java/com/graphhopper/GraphHopper.java b/core/src/main/java/com/graphhopper/GraphHopper.java
index 2b7f010a8..4d7216f76 100644
--- a/core/src/main/java/com/graphhopper/GraphHopper.java
+++ b/core/src/main/java/com/graphhopper/GraphHopper.java
@@ -568,6 +568,18 @@ public class GraphHopper {
         lmPreparationHandler.init(ghConfig);
 
         // osm import
+        // We do a few checks for import.osm.ignored_highways to prevent configuration errors when migrating from an older
+        // GH version.
+        if (!ghConfig.has("import.osm.ignored_highways"))
+            throw new IllegalArgumentException("Missing 'import.osm.ignored_highways'. Not using this parameter can decrease performance, see config-example.yml for more details");
+        String ignoredHighwaysString = ghConfig.getString("import.osm.ignored_highways", "");
+        if ((ignoredHighwaysString.contains("footway") || ignoredHighwaysString.contains("path")) && ghConfig.getProfiles().stream().map(Profile::getName).anyMatch(p -> p.contains("foot") || p.contains("hike") || p.contains("wheelchair")))
+            throw new IllegalArgumentException("You should not use import.osm.ignored_highways=footway or =path in conjunction with pedestrian profiles. This is probably an error in your configuration.");
+        if ((ignoredHighwaysString.contains("cycleway") || ignoredHighwaysString.contains("path")) && ghConfig.getProfiles().stream().map(Profile::getName).anyMatch(p -> p.contains("mtb") || p.contains("bike")))
+            throw new IllegalArgumentException("You should not use import.osm.ignored_highways=cycleway or =path in conjunction with bicycle profiles. This is probably an error in your configuration");
+
+        osmReaderConfig.setIgnoredHighways(Arrays.stream(ghConfig.getString("import.osm.ignored_highways", String.join(",", osmReaderConfig.getIgnoredHighways()))
+                .split(",")).map(String::trim).collect(Collectors.toList()));
         osmReaderConfig.setParseWayNames(ghConfig.getBool("datareader.instructions", osmReaderConfig.isParseWayNames()));
         osmReaderConfig.setPreferredLanguage(ghConfig.getString("datareader.preferred_language", osmReaderConfig.getPreferredLanguage()));
         osmReaderConfig.setMaxWayPointDistance(ghConfig.getDouble(Routing.INIT_WAY_POINT_MAX_DISTANCE, osmReaderConfig.getMaxWayPointDistance()));
@@ -598,7 +610,7 @@ public class GraphHopper {
         return this;
     }
 
-    private void buildEncodingManagerAndOSMParsers(String flagEncodersStr, String encodedValuesStr, String dateRangeParserString, boolean withUrbanDensity, Collection<Profile> profiles) {
+    private void buildEncodingManagerAndOSMParsers(List<String> ignoredHighways, String flagEncodersStr, String encodedValuesStr, String dateRangeParserString, boolean withUrbanDensity, Collection<Profile> profiles) {
         Map<String, String> flagEncodersMap = new LinkedHashMap<>();
         for (String encoderStr : flagEncodersStr.split(",")) {
             String name = encoderStr.split("\\|")[0].trim();
@@ -632,6 +644,8 @@ public class GraphHopper {
         encodingManager = emBuilder.build();
 
         osmParsers = new OSMParsers();
+        ignoredHighways.forEach(osmParsers::addIgnoredHighway);
+
         for (String s : encodedValueStrings) {
             TagParser tagParser = tagParserFactory.create(encodingManager, s);
             if (tagParser != null)
@@ -652,8 +666,12 @@ public class GraphHopper {
             osmParsers.addWayTagParser(new OSMMaxSpeedParser(encodingManager.getDecimalEncodedValue(MaxSpeed.KEY)));
         if (!encodedValueStrings.contains(RoadAccess.KEY))
             osmParsers.addWayTagParser(new OSMRoadAccessParser(encodingManager.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class), OSMRoadAccessParser.toOSMRestrictions(TransportationMode.CAR)));
-        if (encodingManager.hasEncodedValue(AverageSlope.KEY) && encodingManager.hasEncodedValue(MaxSlope.KEY))
-            osmParsers.addWayTagParser(new SlopeCalculator(encodingManager.getDecimalEncodedValue(MaxSlope.KEY), encodingManager.getDecimalEncodedValue(AverageSlope.KEY)));
+        if (encodingManager.hasEncodedValue(AverageSlope.KEY) || encodingManager.hasEncodedValue(MaxSlope.KEY)) {
+            if (!encodingManager.hasEncodedValue(AverageSlope.KEY) || !encodingManager.hasEncodedValue(MaxSlope.KEY))
+                throw new IllegalArgumentException("Enable both, average_slope and max_slope");
+            osmParsers.addWayTagParser(new SlopeCalculator(encodingManager.getDecimalEncodedValue(MaxSlope.KEY),
+                    encodingManager.getDecimalEncodedValue(AverageSlope.KEY)));
+        }
         if (encodingManager.hasEncodedValue(Curvature.KEY))
             osmParsers.addWayTagParser(new CurvatureCalculator(encodingManager.getDecimalEncodedValue(Curvature.KEY)));
 
@@ -789,7 +807,7 @@ public class GraphHopper {
         GHDirectory directory = new GHDirectory(ghLocation, dataAccessDefaultType);
         directory.configure(dataAccessConfig);
         boolean withUrbanDensity = urbanDensityCalculationThreads > 0;
-        buildEncodingManagerAndOSMParsers(vehiclesString, encodedValuesString, dateRangeParserString, withUrbanDensity, profilesByName.values());
+        buildEncodingManagerAndOSMParsers(osmReaderConfig.getIgnoredHighways(), vehiclesString, encodedValuesString, dateRangeParserString, withUrbanDensity, profilesByName.values());
         baseGraph = new BaseGraph.Builder(getEncodingManager())
                 .setDir(directory)
                 .set3D(hasElevation())
diff --git a/core/src/main/java/com/graphhopper/reader/osm/OSMReader.java b/core/src/main/java/com/graphhopper/reader/osm/OSMReader.java
index c7676adbc..8b12d6016 100644
--- a/core/src/main/java/com/graphhopper/reader/osm/OSMReader.java
+++ b/core/src/main/java/com/graphhopper/reader/osm/OSMReader.java
@@ -348,9 +348,6 @@ public class OSMReader {
         IntsRef relationFlags = getRelFlagsMap(way.getId());
         IntsRef edgeFlags = encodingManager.createEdgeFlags();
         edgeFlags = osmParsers.handleWayTags(edgeFlags, way, relationFlags);
-        if (edgeFlags.isEmpty())
-            return;
-
         EdgeIteratorState edge = baseGraph.edge(fromIndex, toIndex).setDistance(distance).setFlags(edgeFlags);
         List<EdgeKVStorage.KeyValue> list = way.getTag("key_values", Collections.emptyList());
         if (!list.isEmpty())
diff --git a/core/src/main/java/com/graphhopper/reader/osm/WaySegmentParser.java b/core/src/main/java/com/graphhopper/reader/osm/WaySegmentParser.java
index 0e4df3552..c6c2319d4 100644
--- a/core/src/main/java/com/graphhopper/reader/osm/WaySegmentParser.java
+++ b/core/src/main/java/com/graphhopper/reader/osm/WaySegmentParser.java
@@ -137,9 +137,9 @@ public class WaySegmentParser {
     private class Pass1Handler implements ReaderElementHandler {
         private boolean handledWays;
         private boolean handledRelations;
-        private long wayCounter = 1;
+        private long wayCounter = 0;
         private long acceptedWays = 0;
-        private long relationsCounter = -1;
+        private long relationsCounter = 0;
 
         @Override
         public void handleWay(ReaderWay way) {
@@ -198,10 +198,10 @@ public class WaySegmentParser {
         private boolean handledNodes;
         private boolean handledWays;
         private boolean handledRelations;
-        private long nodeCounter = -1;
+        private long nodeCounter = 0;
         private long acceptedNodes = 0;
         private long ignoredSplitNodes = 0;
-        private long wayCounter = -1;
+        private long wayCounter = 0;
 
         @Override
         public void handleNode(ReaderNode node) {
diff --git a/core/src/main/java/com/graphhopper/routing/OSMReaderConfig.java b/core/src/main/java/com/graphhopper/routing/OSMReaderConfig.java
index 1f196c9b0..2265c41c4 100644
--- a/core/src/main/java/com/graphhopper/routing/OSMReaderConfig.java
+++ b/core/src/main/java/com/graphhopper/routing/OSMReaderConfig.java
@@ -18,7 +18,11 @@
 
 package com.graphhopper.routing;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class OSMReaderConfig {
+    private List<String> ignoredHighways = new ArrayList<>();
     private boolean parseWayNames = true;
     private String preferredLanguage = "";
     private double maxWayPointDistance = 1;
@@ -28,6 +32,24 @@ public class OSMReaderConfig {
     private double longEdgeSamplingDistance = Double.MAX_VALUE;
     private int workerThreads = 2;
 
+    public List<String> getIgnoredHighways() {
+        return ignoredHighways;
+    }
+
+    /**
+     * Sets the values of the highway tag that shall be ignored when we read the OSM file. This can be used to speed up
+     * the import and reduce the size of the resulting routing graph. For example if one is only interested in routing
+     * for motorized vehicles the routing graph size can be reduced by excluding footways, cycleways, paths and/or
+     * tracks. This can be quite significant depending on your area. Not only are there fewer ways to be processed, but
+     * there are also fewer junctions, which means fewer nodes and edges. Another reason to exclude footways etc. for
+     * motorized vehicle routing could be preventing undesired u-turns (#1858). Similarly, one could exclude motorway,
+     * trunk or even primary highways for bicycle or pedestrian routing.
+     */
+    public OSMReaderConfig setIgnoredHighways(List<String> ignoredHighways) {
+        this.ignoredHighways = ignoredHighways;
+        return this;
+    }
+
     public String getPreferredLanguage() {
         return preferredLanguage;
     }
diff --git a/core/src/main/java/com/graphhopper/routing/ev/DefaultEncodedValueFactory.java b/core/src/main/java/com/graphhopper/routing/ev/DefaultEncodedValueFactory.java
index b977d8e9e..18fbff778 100644
--- a/core/src/main/java/com/graphhopper/routing/ev/DefaultEncodedValueFactory.java
+++ b/core/src/main/java/com/graphhopper/routing/ev/DefaultEncodedValueFactory.java
@@ -74,6 +74,8 @@ public class DefaultEncodedValueFactory implements EncodedValueFactory {
             enc = new EnumEncodedValue<>(HazmatWater.KEY, HazmatWater.class);
         } else if (Lanes.KEY.equals(name)) {
             enc = Lanes.create();
+        } else if (OSMWayID.KEY.equals(name)) {
+            enc = OSMWayID.create();
         } else if (MtbRating.KEY.equals(name)) {
             enc = MtbRating.create();
         } else if (HikeRating.KEY.equals(name)) {
diff --git a/core/src/main/java/com/graphhopper/routing/ev/OSMWayID.java b/core/src/main/java/com/graphhopper/routing/ev/OSMWayID.java
new file mode 100644
index 000000000..3d7038312
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/ev/OSMWayID.java
@@ -0,0 +1,27 @@
+/*
+ *  Licensed to GraphHopper GmbH under one or more contributor
+ *  license agreements. See the NOTICE file distributed with this work for
+ *  additional information regarding copyright ownership.
+ *
+ *  GraphHopper GmbH licenses this file to you under the Apache License,
+ *  Version 2.0 (the "License"); you may not use this file except in
+ *  compliance with the License. You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.graphhopper.routing.ev;
+
+public class OSMWayID {
+    public static final String KEY = "osm_way_id";
+
+    public static IntEncodedValue create() {
+        return new IntEncodedValueImpl(KEY, 31, false);
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/routing/util/Bike2WeightTagParser.java b/core/src/main/java/com/graphhopper/routing/util/Bike2WeightTagParser.java
deleted file mode 100644
index 25266d540..000000000
--- a/core/src/main/java/com/graphhopper/routing/util/Bike2WeightTagParser.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *  Licensed to GraphHopper GmbH under one or more contributor
- *  license agreements. See the NOTICE file distributed with this work for
- *  additional information regarding copyright ownership.
- *
- *  GraphHopper GmbH licenses this file to you under the Apache License,
- *  Version 2.0 (the "License"); you may not use this file except in
- *  compliance with the License. You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package com.graphhopper.routing.util;
-
-import com.graphhopper.reader.ReaderWay;
-import com.graphhopper.routing.ev.*;
-import com.graphhopper.storage.IntsRef;
-import com.graphhopper.util.PMap;
-import com.graphhopper.util.PointList;
-
-import static com.graphhopper.util.Helper.keepIn;
-
-/**
- * Stores two speed values into an edge to support avoiding too much incline
- *
- * @author Peter Karich
- */
-public class Bike2WeightTagParser extends BikeTagParser {
-
-    public Bike2WeightTagParser(EncodedValueLookup lookup, PMap properties) {
-        this(
-                lookup.getBooleanEncodedValue(VehicleAccess.key(properties.getString("name", "bike2"))),
-                lookup.getDecimalEncodedValue(VehicleSpeed.key(properties.getString("name", "bike2"))),
-                lookup.getDecimalEncodedValue(VehiclePriority.key(properties.getString("name", "bike2"))),
-                lookup.getEnumEncodedValue(BikeNetwork.KEY, RouteNetwork.class),
-                lookup.getBooleanEncodedValue(Roundabout.KEY),
-                lookup.getEnumEncodedValue(Smoothness.KEY, Smoothness.class),
-                lookup.hasEncodedValue(TurnCost.key(properties.getString("name", "bike2"))) ? lookup.getDecimalEncodedValue(TurnCost.key(properties.getString("name", "bike2"))) : null,
-                properties
-        );
-    }
-
-    public Bike2WeightTagParser(BooleanEncodedValue accessEnc, DecimalEncodedValue speedEnc,
-                                DecimalEncodedValue priorityEnc, EnumEncodedValue<RouteNetwork> bikeRouteEnc,
-                                BooleanEncodedValue roundaboutEnc,
-                                EnumEncodedValue<Smoothness> smoothnessEnc, DecimalEncodedValue turnCostEnc, PMap properties) {
-        super(accessEnc, speedEnc, priorityEnc, bikeRouteEnc, smoothnessEnc, properties.getString("name", "bike2"),
-                roundaboutEnc, turnCostEnc);
-        blockPrivate(properties.getBool("block_private", true));
-        blockFords(properties.getBool("block_fords", false));
-    }
-
-    @Override
-    public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way) {
-        edgeFlags = super.handleWayTags(edgeFlags, way);
-        return applyWayTags(way, edgeFlags);
-    }
-
-    public IntsRef applyWayTags(ReaderWay way, IntsRef intsRef) {
-        PointList pl = way.getTag("point_list", null);
-        if (pl == null)
-            throw new IllegalArgumentException("The artificial point_list tag is missing");
-        if (!pl.is3D())
-            throw new IllegalStateException(getName() + " requires elevation data to improve speed calculation based on it. Please enable it in config via e.g. graph.elevation.provider: srtm");
-
-        if (way.hasTag("tunnel", "yes") || way.hasTag("bridge", "yes") || way.hasTag("highway", "steps"))
-            // do not change speed
-            // note: although tunnel can have a difference in elevation it is very unlikely that the elevation data is correct for a tunnel
-            return intsRef;
-
-        // Decrease the speed for ele increase (incline), and decrease the speed for ele decrease (decline). The speed-decrease
-        // has to be bigger (compared to the speed-increase) for the same elevation difference to simulate losing energy and avoiding hills.
-        // For the reverse speed this has to be the opposite but again keeping in mind that up+down difference.
-        double incEleSum = 0, incDist2DSum = 0, decEleSum = 0, decDist2DSum = 0;
-        // double prevLat = pl.getLat(0), prevLon = pl.getLon(0);
-        double prevEle = pl.getEle(0);
-        if (!way.hasTag("edge_distance"))
-            throw new IllegalArgumentException("The artificial edge_distance tag is missing");
-        double fullDist2D = way.getTag("edge_distance", 0d);
-
-        // for short edges an incline makes no sense and for 0 distances could lead to NaN values for speed, see #432
-        if (fullDist2D < 2)
-            return intsRef;
-
-        double eleDelta = pl.getEle(pl.size() - 1) - prevEle;
-        if (eleDelta > 0.1) {
-            incEleSum = eleDelta;
-            incDist2DSum = fullDist2D;
-        } else if (eleDelta < -0.1) {
-            decEleSum = -eleDelta;
-            decDist2DSum = fullDist2D;
-        }
-
-        // Calculate slop via tan(asin(height/distance)) but for rather smallish angles where we can assume tan a=a and sin a=a.
-        // Then calculate a factor which decreases or increases the speed.
-        // Do this via a simple quadratic equation where y(0)=1 and y(0.3)=1/4 for incline and y(0.3)=2 for decline
-        double fwdIncline = incDist2DSum > 1 ? incEleSum / incDist2DSum : 0;
-        double fwdDecline = decDist2DSum > 1 ? decEleSum / decDist2DSum : 0;
-        double restDist2D = fullDist2D - incDist2DSum - decDist2DSum;
-        double maxSpeed = getHighwaySpeed("cycleway");
-        if (accessEnc.getBool(false, intsRef)) {
-            // use weighted mean so that longer incline influences speed more than shorter
-            double speed = avgSpeedEnc.getDecimal(false, intsRef);
-            double fwdFaster = 1 + 2 * keepIn(fwdDecline, 0, 0.2);
-            fwdFaster = fwdFaster * fwdFaster;
-            double fwdSlower = 1 - 5 * keepIn(fwdIncline, 0, 0.2);
-            fwdSlower = fwdSlower * fwdSlower;
-            speed = speed * (fwdSlower * incDist2DSum + fwdFaster * decDist2DSum + 1 * restDist2D) / fullDist2D;
-            setSpeed(false, intsRef, keepIn(speed, MIN_SPEED, maxSpeed));
-        }
-
-        if (accessEnc.getBool(true, intsRef)) {
-            double speedReverse = avgSpeedEnc.getDecimal(true, intsRef);
-            double bwFaster = 1 + 2 * keepIn(fwdIncline, 0, 0.2);
-            bwFaster = bwFaster * bwFaster;
-            double bwSlower = 1 - 5 * keepIn(fwdDecline, 0, 0.2);
-            bwSlower = bwSlower * bwSlower;
-            speedReverse = speedReverse * (bwFaster * incDist2DSum + bwSlower * decDist2DSum + 1 * restDist2D) / fullDist2D;
-            setSpeed(true, intsRef, keepIn(speedReverse, MIN_SPEED, maxSpeed));
-        }
-        return intsRef;
-    }
-
-}
diff --git a/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleEncodedValuesFactory.java b/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleEncodedValuesFactory.java
index c1a9cd0f2..7c0cb5e22 100644
--- a/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleEncodedValuesFactory.java
+++ b/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleEncodedValuesFactory.java
@@ -39,8 +39,8 @@ public class DefaultVehicleEncodedValuesFactory implements VehicleEncodedValuesF
         if (name.equals(BIKE))
             return VehicleEncodedValues.bike(configuration);
 
-        if (name.equals(BIKE2))
-            return VehicleEncodedValues.bike2(configuration);
+        if (name.equals("bike2"))
+            throw new IllegalArgumentException("Instead of bike2 use the bike vehicle and a custom model, see custom_models/bike2.json and #1234");
 
         if (name.equals(RACINGBIKE))
             return VehicleEncodedValues.racingbike(configuration);
diff --git a/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleTagParserFactory.java b/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleTagParserFactory.java
index a7109eedf..ba49f7026 100644
--- a/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleTagParserFactory.java
+++ b/core/src/main/java/com/graphhopper/routing/util/DefaultVehicleTagParserFactory.java
@@ -31,8 +31,6 @@ public class DefaultVehicleTagParserFactory implements VehicleTagParserFactory {
             return new CarTagParser(lookup, configuration);
         if (name.equals(BIKE))
             return new BikeTagParser(lookup, configuration);
-        if (name.equals(BIKE2))
-            return new Bike2WeightTagParser(lookup, configuration);
         if (name.equals(RACINGBIKE))
             return new RacingBikeTagParser(lookup, configuration);
         if (name.equals(MOUNTAINBIKE))
diff --git a/core/src/main/java/com/graphhopper/routing/util/OSMParsers.java b/core/src/main/java/com/graphhopper/routing/util/OSMParsers.java
index 82895b65a..4c3242681 100644
--- a/core/src/main/java/com/graphhopper/routing/util/OSMParsers.java
+++ b/core/src/main/java/com/graphhopper/routing/util/OSMParsers.java
@@ -31,6 +31,7 @@ import java.util.List;
 import java.util.function.Function;
 
 public class OSMParsers {
+    private final List<String> ignoredHighways;
     private final List<TagParser> wayTagParsers;
     private final List<VehicleTagParser> vehicleTagParsers;
     private final List<RelationTagParser> relationTagParsers;
@@ -38,17 +39,23 @@ public class OSMParsers {
     private final EncodedValue.InitializerConfig relConfig = new EncodedValue.InitializerConfig();
 
     public OSMParsers() {
-        this(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
+        this(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
     }
 
-    public OSMParsers(List<TagParser> wayTagParsers, List<VehicleTagParser> vehicleTagParsers,
+    public OSMParsers(List<String> ignoredHighways, List<TagParser> wayTagParsers, List<VehicleTagParser> vehicleTagParsers,
                       List<RelationTagParser> relationTagParsers, List<RestrictionTagParser> restrictionTagParsers) {
+        this.ignoredHighways = ignoredHighways;
         this.wayTagParsers = wayTagParsers;
         this.vehicleTagParsers = vehicleTagParsers;
         this.relationTagParsers = relationTagParsers;
         this.restrictionTagParsers = restrictionTagParsers;
     }
 
+    public OSMParsers addIgnoredHighway(String highway) {
+        ignoredHighways.add(highway);
+        return this;
+    }
+
     public OSMParsers addWayTagParser(TagParser tagParser) {
         wayTagParsers.add(tagParser);
         return this;
@@ -73,7 +80,14 @@ public class OSMParsers {
     }
 
     public boolean acceptWay(ReaderWay way) {
-        return vehicleTagParsers.stream().anyMatch(v -> !v.getAccess(way).equals(WayAccess.CAN_SKIP));
+        String highway = way.getTag("highway");
+        if (highway != null)
+            return !ignoredHighways.contains(highway);
+        else
+            // we accept all the ways with a 'route' tag and no 'highway' tag, because these are needed for e.g.
+            // route=ferry and there aren't many others:
+            // https://github.com/graphhopper/graphhopper/pull/2702/files#r1038093050
+            return way.getTag("route") != null;
     }
 
     public IntsRef handleRelationTags(ReaderRelation relation, IntsRef relFlags) {
@@ -100,6 +114,10 @@ public class OSMParsers {
         return new IntsRef(2);
     }
 
+    public List<String> getIgnoredHighways() {
+        return ignoredHighways;
+    }
+
     public List<VehicleTagParser> getVehicleTagParsers() {
         return vehicleTagParsers;
     }
diff --git a/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValues.java b/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValues.java
index 2dcf0c216..10441078c 100644
--- a/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValues.java
+++ b/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValues.java
@@ -27,7 +27,7 @@ import java.util.List;
 import static com.graphhopper.routing.util.VehicleEncodedValuesFactory.*;
 
 public class VehicleEncodedValues {
-    public static final List<String> OUTDOOR_VEHICLES = Arrays.asList(BIKE, BIKE2, RACINGBIKE, MOUNTAINBIKE, FOOT, HIKE, WHEELCHAIR);
+    public static final List<String> OUTDOOR_VEHICLES = Arrays.asList(BIKE, RACINGBIKE, MOUNTAINBIKE, FOOT, HIKE, WHEELCHAIR);
 
     private final String name;
     private final BooleanEncodedValue accessEnc;
@@ -74,15 +74,6 @@ public class VehicleEncodedValues {
         return new VehicleEncodedValues(name, accessEnc, speedEnc, priorityEnc, turnCostEnc);
     }
 
-    public static VehicleEncodedValues bike2(PMap properties) {
-        if (properties.has("speed_two_directions"))
-            throw new IllegalArgumentException("bike2 always uses two directions");
-        return bike(new PMap(properties)
-                .putObject("name", properties.getString("name", "bike2"))
-                .putObject("speed_two_directions", true)
-        );
-    }
-
     public static VehicleEncodedValues racingbike(PMap properties) {
         return bike(new PMap(properties).putObject("name", properties.getString("name", "racingbike")));
     }
diff --git a/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValuesFactory.java b/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValuesFactory.java
index 263644e69..85780abd8 100644
--- a/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValuesFactory.java
+++ b/core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValuesFactory.java
@@ -26,7 +26,6 @@ public interface VehicleEncodedValuesFactory {
     String ROADS = "roads";
     String CAR = "car";
     String BIKE = "bike";
-    String BIKE2 = "bike2";
     String RACINGBIKE = "racingbike";
     String MOUNTAINBIKE = "mtb";
     String FOOT = "foot";
diff --git a/core/src/main/java/com/graphhopper/routing/util/WheelchairTagParser.java b/core/src/main/java/com/graphhopper/routing/util/WheelchairTagParser.java
index d832519e7..99c7deb27 100644
--- a/core/src/main/java/com/graphhopper/routing/util/WheelchairTagParser.java
+++ b/core/src/main/java/com/graphhopper/routing/util/WheelchairTagParser.java
@@ -198,7 +198,7 @@ public class WheelchairTagParser extends FootTagParser {
         if (Double.isInfinite(fullDist2D))
             throw new IllegalStateException("Infinite distance should not happen due to #435. way ID=" + way.getId());
 
-        // skip elevation data adjustment for too short segments, TODO improve the elevation data handling and/or use the same mechanism as in bike2
+        // skip elevation data adjustment for too short segments, TODO improve the elevation data handling and/or use the same mechanism as we used to do in bike2
         if (fullDist2D < 20 || !pl.is3D())
             return edgeFlags;
 
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java b/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java
index df8e7f09e..7366601aa 100644
--- a/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java
@@ -69,6 +69,8 @@ public class DefaultTagParserFactory implements TagParserFactory {
             return new OSMHazmatWaterParser(lookup.getEnumEncodedValue(HazmatWater.KEY, HazmatWater.class));
         else if (name.equals(Lanes.KEY))
             return new OSMLanesParser(lookup.getIntEncodedValue(Lanes.KEY));
+        else if (name.equals(OSMWayID.KEY))
+            return new OSMWayIDParser(lookup.getIntEncodedValue(OSMWayID.KEY));
         else if (name.equals(MtbRating.KEY))
             return new OSMMtbRatingParser(lookup.getIntEncodedValue(MtbRating.KEY));
         else if (name.equals(HikeRating.KEY))
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMWayIDParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMWayIDParser.java
new file mode 100644
index 000000000..fea650446
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMWayIDParser.java
@@ -0,0 +1,42 @@
+/*
+ *  Licensed to GraphHopper GmbH under one or more contributor
+ *  license agreements. See the NOTICE file distributed with this work for
+ *  additional information regarding copyright ownership.
+ *
+ *  GraphHopper GmbH licenses this file to you under the Apache License,
+ *  Version 2.0 (the "License"); you may not use this file except in
+ *  compliance with the License. You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.graphhopper.routing.util.parsers;
+
+import com.graphhopper.reader.ReaderWay;
+import com.graphhopper.routing.ev.IntEncodedValue;
+import com.graphhopper.storage.IntsRef;
+
+public class OSMWayIDParser implements TagParser {
+    private final IntEncodedValue osmWayIdEnc;
+
+    public OSMWayIDParser(IntEncodedValue osmWayIdEnc) {
+        this.osmWayIdEnc = osmWayIdEnc;
+    }
+
+    @Override
+    public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, IntsRef relationFlags) {
+        if (way.getId() > osmWayIdEnc.getMaxStorableInt())
+            throw new IllegalArgumentException("Cannot store OSM way ID: " + way.getId() + " as it is too large (> "
+                    + osmWayIdEnc.getMaxStorableInt() + "). You can disable " + osmWayIdEnc.getName() + " if you do not " +
+                    "need to store the OSM way IDs");
+        int wayId = Math.toIntExact(way.getId());
+        osmWayIdEnc.setInt(false, edgeFlags, wayId);
+        return edgeFlags;
+    }
+}
diff --git a/web/src/test/resources/com/graphhopper/application/resources/bike2.json b/custom_models/bike2.json
similarity index 100%
rename from web/src/test/resources/com/graphhopper/application/resources/bike2.json
rename to custom_models/bike2.json
diff --git a/web/src/test/resources/com/graphhopper/application/resources/car4wd.json b/custom_models/car4wd.json
similarity index 100%
rename from web/src/test/resources/com/graphhopper/application/resources/car4wd.json
rename to custom_models/car4wd.json
diff --git a/web/src/test/resources/com/graphhopper/application/resources/curvature.json b/custom_models/curvature.json
similarity index 100%
rename from web/src/test/resources/com/graphhopper/application/resources/curvature.json
rename to custom_models/curvature.json
diff --git a/docs/core/profiles.md b/docs/core/profiles.md
index c25ba199b..2f2c119e6 100644
--- a/docs/core/profiles.md
+++ b/docs/core/profiles.md
@@ -35,7 +35,6 @@ The vehicle field must correspond to one of GraphHopper's built-in vehicle types
 - wheelchair
 - bike
 - racingbike
-- bike2
 - mtb
 - car
 - motorcycle
diff --git a/example/src/main/java/com/graphhopper/example/RoutingExample.java b/example/src/main/java/com/graphhopper/example/RoutingExample.java
index 2eb0d6d54..6cbde4385 100644
--- a/example/src/main/java/com/graphhopper/example/RoutingExample.java
+++ b/example/src/main/java/com/graphhopper/example/RoutingExample.java
@@ -105,14 +105,14 @@ public class RoutingExample {
 
         // calculate alternative routes between two points (supported with and without CH)
         req = new GHRequest().setProfile("car").
-                addPoint(new GHPoint(42.502904, 1.514714)).addPoint(new GHPoint(42.511953, 1.535914)).
+                addPoint(new GHPoint(42.502904, 1.514714)).addPoint(new GHPoint(42.508774, 1.537094)).
                 setAlgorithm(Parameters.Algorithms.ALT_ROUTE);
         req.getHints().putObject(Parameters.Algorithms.AltRoute.MAX_PATHS, 3);
         res = hopper.route(req);
         if (res.hasErrors())
             throw new RuntimeException(res.getErrors().toString());
         assert res.getAll().size() == 2;
-        assert Helper.round(res.getBest().getDistance(), -2) == 2300;
+        assert Helper.round(res.getBest().getDistance(), -2) == 2200;
     }
 
     /**


Test patch:
diff --git a/core/src/test/java/com/graphhopper/GraphHopperTest.java b/core/src/test/java/com/graphhopper/GraphHopperTest.java
index a0cb41f8b..b6a0ae808 100644
--- a/core/src/test/java/com/graphhopper/GraphHopperTest.java
+++ b/core/src/test/java/com/graphhopper/GraphHopperTest.java
@@ -98,12 +98,12 @@ public class GraphHopperTest {
 
     @ParameterizedTest
     @CsvSource({
-            DIJKSTRA + ",false,511",
-            ASTAR + ",false,256",
-            DIJKSTRA_BI + ",false,228",
-            ASTAR_BI + ",false,142",
-            ASTAR_BI + ",true,41",
-            DIJKSTRA_BI + ",true,48"
+            DIJKSTRA + ",false,708",
+            ASTAR + ",false,363",
+            DIJKSTRA_BI + ",false,346",
+            ASTAR_BI + ",false,192",
+            ASTAR_BI + ",true,42",
+            DIJKSTRA_BI + ",true,47"
     })
     public void testMonacoDifferentAlgorithms(String algo, boolean withCH, int expectedVisitedNodes) {
         final String vehicle = "car";
@@ -150,7 +150,7 @@ public class GraphHopperTest {
                 setAlgorithm(ASTAR).setProfile(profile));
 
         // identify the number of counts to compare with CH foot route
-        assertEquals(706, rsp.getHints().getLong("visited_nodes.sum", 0));
+        assertEquals(712, rsp.getHints().getLong("visited_nodes.sum", 0));
 
         ResponsePath res = rsp.getBest();
         assertEquals(3437.1, res.getDistance(), .1);
@@ -644,9 +644,13 @@ public class GraphHopperTest {
 
         req.putHint(Routing.BLOCK_AREA, "49.984434,11.505212,49.985394,11.506333");
         rsp = hopper.route(req);
-        assertEquals(11.508, rsp.getBest().getWaypoints().getLon(0), 0.001);
+        // we do not snap to Grüngraben (within the blocked area), but onto Lohweg and then we need to go to Hauptstraße
+        // and turn left onto Waldhüttenstraße. Note that if we exclude footway we get an entirely different path, because
+        // the start point snaps all the way to the East onto the end of Bergstraße (because Lohweg gets no longer split
+        // into several edges...)
+        assertEquals(11.506, rsp.getBest().getWaypoints().getLon(0), 0.001);
         assertFalse(rsp.hasErrors(), rsp.getErrors().toString());
-        assertEquals(1185, rsp.getBest().getDistance(), 10);
+        assertEquals(510, rsp.getBest().getDistance(), 10);
 
         // first point is contained in block_area => error
         req = new GHRequest(49.979, 11.516, 49.986107, 11.507202).
@@ -1600,17 +1604,17 @@ public class GraphHopperTest {
         hopper.importOrLoad();
 
         // flex
-        testCrossQueryAssert(profile1, hopper, 528.3, 138, true);
-        testCrossQueryAssert(profile2, hopper, 635.8, 138, true);
-        testCrossQueryAssert(profile3, hopper, 815.2, 140, true);
+        testCrossQueryAssert(profile1, hopper, 528.3, 196, true);
+        testCrossQueryAssert(profile2, hopper, 635.8, 198, true);
+        testCrossQueryAssert(profile3, hopper, 815.2, 198, true);
 
         // LM (should be the same as flex, but with less visited nodes!)
-        testCrossQueryAssert(profile1, hopper, 528.3, 74, false);
-        testCrossQueryAssert(profile2, hopper, 635.8, 124, false);
-        // this is actually interesting: the number of visited nodes *increases* once again (while it strictly decreases
-        // with rising distance factor for flex): cross-querying 'works', but performs *worse*, because the landmarks
-        // were not customized for the weighting in use. Creating a separate LM preparation for profile3 yields 74
-        testCrossQueryAssert(profile3, hopper, 815.2, 162, false);
+        testCrossQueryAssert(profile1, hopper, 528.3, 108, false);
+        testCrossQueryAssert(profile2, hopper, 635.8, 162, false);
+        // this is actually interesting: the number of visited nodes increases: cross-querying 'works',
+        // but can even perform *worse*, because the landmarks were not customized for the weighting in use.
+        // Creating a separate LM preparation for profile3 yields 108 (not shown)
+        testCrossQueryAssert(profile3, hopper, 815.2, 236, false);
     }
 
     private void testCrossQueryAssert(String profile, GraphHopper hopper, double expectedWeight, int expectedVisitedNodes, boolean disableLM) {
@@ -2198,13 +2202,13 @@ public class GraphHopperTest {
         GHRequest req = new GHRequest(p, q);
         req.setProfile("my_profile");
         // we force the start/target directions such that there are u-turns right after we start and right before
-        // we reach the target
+        // we reach the target. at the start location we do a u-turn at the crossing with the *steps* ('ghost junction')
         req.setCurbsides(Arrays.asList("right", "right"));
         GHResponse res = h.route(req);
         assertFalse(res.hasErrors(), "routing should not fail");
-        assertEquals(266.8, res.getBest().getRouteWeight(), 0.1);
-        assertEquals(2116, res.getBest().getDistance(), 1);
-        assertEquals(266800, res.getBest().getTime(), 1000);
+        assertEquals(242.9, res.getBest().getRouteWeight(), 0.1);
+        assertEquals(1917, res.getBest().getDistance(), 1);
+        assertEquals(243000, res.getBest().getTime(), 1000);
     }
 
     @Test
@@ -2671,7 +2675,7 @@ public class GraphHopperTest {
                     .setProfiles(new Profile("car").setVehicle("car").setWeighting("fastest"))
                     .setGraphHopperLocation(GH_LOCATION);
             hopper.load();
-            assertEquals(1942, hopper.getBaseGraph().getNodes());
+            assertEquals(2961, hopper.getBaseGraph().getNodes());
         }
     }
 
diff --git a/core/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java b/core/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
index c9366300a..a214b041a 100644
--- a/core/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
+++ b/core/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
@@ -182,7 +182,7 @@ public class GraphHopperOSMTest {
             }
         });
 
-        assertEquals(57, indexNodeList.size());
+        assertEquals(148, indexNodeList.size());
         for (int nodeId : indexNodeList) {
             if (!bbox.contains(na.getLat(nodeId), na.getLon(nodeId)))
                 fail("bbox " + bbox + " should contain " + nodeId);
@@ -462,6 +462,7 @@ public class GraphHopperOSMTest {
                                 putObject("datareader.file", testOsm3).
                                 putObject("datareader.dataaccess", "RAM").
                                 putObject("graph.vehicles", "foot,car").
+                                putObject("import.osm.ignored_highways", "").
                                 setProfiles(Arrays.asList(
                                         new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                                         new Profile("car").setVehicle("car").setWeighting("fastest")
@@ -477,6 +478,7 @@ public class GraphHopperOSMTest {
                                 putObject("datareader.file", testOsm3).
                                 putObject("datareader.dataaccess", "RAM").
                                 putObject("graph.vehicles", "foot").
+                                putObject("import.osm.ignored_highways", "").
                                 setProfiles(Collections.singletonList(
                                         new Profile("foot").setVehicle("foot").setWeighting("fastest")
                                 ))).
@@ -490,6 +492,7 @@ public class GraphHopperOSMTest {
                         putObject("datareader.file", testOsm3).
                         putObject("datareader.dataaccess", "RAM").
                         putObject("graph.vehicles", "car,foot").
+                        putObject("import.osm.ignored_highways", "").
                         setProfiles(Arrays.asList(
                                 new Profile("car").setVehicle("car").setWeighting("fastest"),
                                 new Profile("foot").setVehicle("foot").setWeighting("fastest")
@@ -506,6 +509,7 @@ public class GraphHopperOSMTest {
                                 putObject("datareader.dataaccess", "RAM").
                                 putObject("graph.encoded_values", "road_class").
                                 putObject("graph.vehicles", "foot,car").
+                                putObject("import.osm.ignored_highways", "").
                                 setProfiles(Arrays.asList(
                                         new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                                         new Profile("car").setVehicle("car").setWeighting("fastest")
@@ -525,6 +529,7 @@ public class GraphHopperOSMTest {
                                 putObject("datareader.file", testOsm3).
                                 putObject("datareader.dataaccess", "RAM").
                                 putObject("graph.vehicles", "foot,car").
+                                putObject("import.osm.ignored_highways", "").
                                 setProfiles(Arrays.asList(
                                         new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                                         new Profile("car").setVehicle("car").setWeighting("fastest")
@@ -545,6 +550,7 @@ public class GraphHopperOSMTest {
                                 putObject("graph.location", ghLoc).
                                 putObject("graph.encoded_values", "road_environment,road_class").
                                 putObject("graph.vehicles", "foot,car").
+                                putObject("import.osm.ignored_highways", "").
                                 setProfiles(Arrays.asList(
                                         new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                                         new Profile("car").setVehicle("car").setWeighting("fastest")
@@ -635,6 +641,8 @@ public class GraphHopperOSMTest {
                 setProfiles(new Profile(profile).setVehicle(vehicle).setWeighting(weighting)).
                 setGraphHopperLocation(ghLoc).
                 setOSMFile(testOsm3);
+        // exclude motorways which aren't accessible for foot
+        instance.getReaderConfig().setIgnoredHighways(Arrays.asList("motorway"));
         instance.getCHPreparationHandler().setCHProfiles(new CHProfile(profile));
         instance.importOrLoad();
 
@@ -661,6 +669,7 @@ public class GraphHopperOSMTest {
                         putObject("datareader.file", testOsm3).
                         putObject("prepare.min_network_size", 0).
                         putObject("graph.vehicles", vehicle).
+                        putObject("import.osm.ignored_highways", "").
                         setProfiles(Collections.singletonList(new Profile(profile).setVehicle(vehicle).setWeighting(weighting))).
                         setCHProfiles(Collections.singletonList(new CHProfile(profile)))
                 ).
@@ -859,6 +868,7 @@ public class GraphHopperOSMTest {
         hopper.init(new GraphHopperConfig()
                 .putObject("graph.location", ghLoc)
                 .putObject("datareader.file", testOsm)
+                .putObject("import.osm.ignored_highways", "")
                 .setProfiles(profiles)
         );
         return hopper;
diff --git a/core/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java b/core/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
index 5759495bc..2faa90412 100644
--- a/core/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
+++ b/core/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
@@ -886,6 +886,7 @@ public class OSMReaderTest {
         GHResponse response = gh.route(new GHRequest(51.2492152, 9.4317166, 52.133, 9.1)
                 .setProfile("profile")
                 .setPathDetails(Collections.singletonList(RoadClass.KEY)));
+        assertFalse(response.hasErrors(), response.getErrors().toString());
         List<PathDetail> list = response.getBest().getPathDetails().get(RoadClass.KEY);
         assertEquals(3, list.size());
         assertEquals(RoadClass.MOTORWAY.toString(), list.get(0).getValue());
diff --git a/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMTest.java b/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMTest.java
index d09d1a25c..fe30857bf 100644
--- a/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMTest.java
+++ b/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMTest.java
@@ -41,6 +41,8 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
 
+import static com.graphhopper.json.Statement.Op.LIMIT;
+import static com.graphhopper.json.Statement.Op.MULTIPLY;
 import static com.graphhopper.util.Parameters.Algorithms.*;
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -76,12 +78,12 @@ public class RoutingAlgorithmWithOSMTest {
         Graph g = hopper.getBaseGraph();
 
         // When OSM file stays unchanged make static edge and node IDs a requirement
-        assertEquals(GHUtility.asSet(9, 111, 182), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(10)));
-        assertEquals(GHUtility.asSet(19, 21), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(20)));
-        assertEquals(GHUtility.asSet(478, 84, 83), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(480)));
+        assertEquals(GHUtility.asSet(921, 575, 2), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(10)));
+        assertEquals(GHUtility.asSet(291, 369, 19), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(20)));
+        assertEquals(GHUtility.asSet(277, 478, 474), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(480)));
 
-        assertEquals(43.736989, g.getNodeAccess().getLat(10), 1e-6);
-        assertEquals(7.429758, g.getNodeAccess().getLon(201), 1e-6);
+        assertEquals(43.738776, g.getNodeAccess().getLat(10), 1e-6);
+        assertEquals(7.4170402, g.getNodeAccess().getLon(201), 1e-6);
     }
 
     private List<Query> createMonacoCarQueries() {
@@ -122,13 +124,13 @@ public class RoutingAlgorithmWithOSMTest {
     @Test
     public void testMonacoMotorcycleCurvature() {
         List<Query> queries = new ArrayList<>();
-        queries.add(new Query(43.730729, 7.42135, 43.727697, 7.419199, 2681, 119));
+        queries.add(new Query(43.730729, 7.42135, 43.727697, 7.419199, 2675, 117));
         queries.add(new Query(43.727687, 7.418737, 43.74958, 7.436566, 3727, 170));
         queries.add(new Query(43.728677, 7.41016, 43.739213, 7.4277, 3157, 165));
         queries.add(new Query(43.733802, 7.413433, 43.739662, 7.424355, 2423, 141));
         queries.add(new Query(43.730949, 7.412338, 43.739643, 7.424542, 2253, 120));
         queries.add(new Query(43.727592, 7.419333, 43.727712, 7.419333, 0, 1));
-        CustomModel model = new CustomModel().addToPriority(Statement.If("true", Statement.Op.MULTIPLY, "curvature"));
+        CustomModel model = new CustomModel().addToPriority(Statement.If("true", MULTIPLY, "curvature"));
 
         GraphHopper hopper = createHopper(MONACO, new CustomProfile("motorcycle").setCustomModel(model).
                 setVehicle("motorcycle").setWeighting("custom"));
@@ -144,8 +146,9 @@ public class RoutingAlgorithmWithOSMTest {
         queries.add(new Query(52.349969, 8.013813, 52.349713, 8.013293, 56, 7));
         // reverse route avoids the location
 //        list.add(new OneRun(52.349713, 8.013293, 52.349969, 8.013813, 293, 21));
+        CustomModel model = new CustomModel();
         GraphHopper hopper = createHopper(DIR + "/map-bug432.osm.gz",
-                new Profile("bike2").setVehicle("bike2").setWeighting("fastest"));
+                new CustomProfile("bike2").setCustomModel(model).setVehicle("bike").setWeighting("custom"));
         hopper.setElevationProvider(new SRTMProvider(DIR));
         hopper.importOrLoad();
         checkQueries(hopper, queries);
@@ -273,12 +276,12 @@ public class RoutingAlgorithmWithOSMTest {
         Graph g = hopper.getBaseGraph();
 
         // see testMonaco for a similar ID test
-        assertEquals(GHUtility.asSet(2, 909, 571), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(10)));
-        assertEquals(GHUtility.asSet(444, 956, 740), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(441)));
-        assertEquals(GHUtility.asSet(911, 404, 122, 914), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(912)));
+        assertEquals(GHUtility.asSet(921, 575, 2), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(10)));
+        assertEquals(GHUtility.asSet(967, 440, 286), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(441)));
+        assertEquals(GHUtility.asSet(580, 910, 911), GHUtility.getNeighbors(g.createEdgeExplorer().setBaseNode(912)));
 
-        assertEquals(43.743705, g.getNodeAccess().getLat(100), 1e-6);
-        assertEquals(7.426362, g.getNodeAccess().getLon(702), 1e-6);
+        assertEquals(43.7467818, g.getNodeAccess().getLat(100), 1e-6);
+        assertEquals(7.4311381, g.getNodeAccess().getLon(702), 1e-6);
     }
 
     @Test
@@ -322,25 +325,31 @@ public class RoutingAlgorithmWithOSMTest {
     }
 
     @Test
-    public void testMonacoBike3D_twoSpeedsPerEdge() {
+    public void testMonacoBike3D() {
         List<Query> queries = new ArrayList<>();
         // 1. alternative: go over steps 'Rampe Major' => 1.7km vs. around 2.7km
-        queries.add(new Query(43.730864, 7.420771, 43.727687, 7.418737, 2689, 118));
+        queries.add(new Query(43.730864, 7.420771, 43.727687, 7.418737, 1999, 101));
         // 2.
-        queries.add(new Query(43.728499, 7.417907, 43.74958, 7.436566, 3735, 194));
+        queries.add(new Query(43.728499, 7.417907, 43.74958, 7.436566, 3939, 187));
         // 3.
-        queries.add(new Query(43.728677, 7.41016, 43.739213, 7.427806, 2776, 167));
+        queries.add(new Query(43.728677, 7.41016, 43.739213, 7.427806, 2776, 163));
         // 4.
         queries.add(new Query(43.733802, 7.413433, 43.739662, 7.424355, 1544, 84));
 
         // try reverse direction
         // 1.
         queries.add(new Query(43.727687, 7.418737, 43.730864, 7.420771, 2599, 115));
-        queries.add(new Query(43.74958, 7.436566, 43.728499, 7.417907, 4180, 165));
-        queries.add(new Query(43.739213, 7.427806, 43.728677, 7.41016, 2805, 145));
+        queries.add(new Query(43.74958, 7.436566, 43.728499, 7.417907, 3902, 199));
+        queries.add(new Query(43.739213, 7.427806, 43.728677, 7.41016, 2870, 154));
         // 4. avoid tunnel(s)!
-        queries.add(new Query(43.739662, 7.424355, 43.733802, 7.413433, 2436, 112));
-        GraphHopper hopper = createHopper(MONACO, new Profile("bike2").setVehicle("bike2").setWeighting("fastest"));
+        queries.add(new Query(43.739662, 7.424355, 43.733802, 7.413433, 1795, 96));
+        CustomModel model = new CustomModel();
+        model.addToSpeed(Statement.If("average_slope >= 10", LIMIT, "4")).
+                addToSpeed(Statement.If("average_slope >= 5", MULTIPLY, "0.45")).
+                addToSpeed(Statement.If("average_slope >= 3.5", MULTIPLY, "0.7")).
+                addToSpeed(Statement.If("average_slope >= 2", MULTIPLY, "0.9")).
+                addToSpeed(Statement.If("average_slope < -5", MULTIPLY, "1.25"));
+        GraphHopper hopper = createHopper(MONACO, new CustomProfile("bike2").setCustomModel(model).setVehicle("bike").setWeighting("custom"));
         hopper.setElevationProvider(new SRTMProvider(DIR));
         hopper.importOrLoad();
         checkQueries(hopper, queries);
@@ -571,7 +580,8 @@ public class RoutingAlgorithmWithOSMTest {
 
         Helper.removeDir(new File(GH_LOCATION));
 
-        hopper = createHopper(BAYREUTH, new Profile("bike2").setVehicle("bike2").setWeighting("fastest"));
+        CustomModel model = new CustomModel();
+        hopper = createHopper(BAYREUTH, new CustomProfile("bike2").setCustomModel(model).setVehicle("bike").setWeighting("custom"));
         hopper.setElevationProvider(new SRTMProvider(DIR));
         hopper.importOrLoad();
         checkQueries(hopper, list);
@@ -686,6 +696,7 @@ public class RoutingAlgorithmWithOSMTest {
                 setStoreOnFlush(true).
                 setOSMFile(osmFile).
                 setProfiles(profiles).
+                setEncodedValuesString("average_slope,max_slope").
                 setGraphHopperLocation(GH_LOCATION);
         hopper.getRouterConfig().setSimplifyResponse(false);
         hopper.setMinNetworkSize(0);
diff --git a/core/src/test/java/com/graphhopper/routing/ev/IntEncodedValueImplTest.java b/core/src/test/java/com/graphhopper/routing/ev/IntEncodedValueImplTest.java
index 964a71e7b..052b1c936 100644
--- a/core/src/test/java/com/graphhopper/routing/ev/IntEncodedValueImplTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ev/IntEncodedValueImplTest.java
@@ -51,6 +51,15 @@ public class IntEncodedValueImplTest {
         assertEquals(20, prop.getInt(true, ref));
     }
 
+    @Test
+    public void maxValue() {
+        IntEncodedValue prop = new IntEncodedValueImpl("test", 31, false);
+        prop.init(new EncodedValue.InitializerConfig());
+        IntsRef ref = new IntsRef(2);
+        prop.setInt(false, ref, (1 << 31) - 1);
+        assertEquals(2_147_483_647L, prop.getInt(false, ref));
+    }
+
     @Test
     public void testSignedInt() {
         IntEncodedValue prop = new IntEncodedValueImpl("test", 31, -5, false, true);
diff --git a/core/src/test/java/com/graphhopper/routing/util/Bike2WeightTagParserTest.java b/core/src/test/java/com/graphhopper/routing/util/Bike2WeightTagParserTest.java
deleted file mode 100644
index 63a147859..000000000
--- a/core/src/test/java/com/graphhopper/routing/util/Bike2WeightTagParserTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *  Licensed to GraphHopper GmbH under one or more contributor
- *  license agreements. See the NOTICE file distributed with this work for
- *  additional information regarding copyright ownership.
- *
- *  GraphHopper GmbH licenses this file to you under the Apache License,
- *  Version 2.0 (the "License"); you may not use this file except in
- *  compliance with the License. You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package com.graphhopper.routing.util;
-
-import com.graphhopper.reader.ReaderWay;
-import com.graphhopper.reader.osm.conditional.DateRangeParser;
-import com.graphhopper.routing.ev.*;
-import com.graphhopper.routing.util.parsers.OSMBikeNetworkTagParser;
-import com.graphhopper.routing.util.parsers.OSMSmoothnessParser;
-import com.graphhopper.storage.BaseGraph;
-import com.graphhopper.storage.Graph;
-import com.graphhopper.storage.IntsRef;
-import com.graphhopper.storage.NodeAccess;
-import com.graphhopper.util.*;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * @author Peter Karich
- */
-public class Bike2WeightTagParserTest extends BikeTagParserTest {
-
-    @Override
-    protected EncodingManager createEncodingManager() {
-        return EncodingManager.create("bike2");
-    }
-
-    @Override
-    protected BikeCommonTagParser createBikeTagParser(EncodedValueLookup lookup, PMap pMap) {
-        Bike2WeightTagParser parser = new Bike2WeightTagParser(lookup, pMap) {
-            @Override
-            public IntsRef applyWayTags(ReaderWay way, IntsRef intsRef) {
-                if (!way.hasTag("point_list") || !way.hasTag("edge_distance"))
-                    return intsRef;
-                else
-                    return super.applyWayTags(way, intsRef);
-            }
-        };
-        parser.init(new DateRangeParser());
-        return parser;
-    }
-
-    @Override
-    protected OSMParsers createOSMParsers(BikeCommonTagParser parser, EncodedValueLookup lookup) {
-        return new OSMParsers()
-                .addRelationTagParser(relConfig -> new OSMBikeNetworkTagParser(lookup.getEnumEncodedValue(BikeNetwork.KEY, RouteNetwork.class), relConfig))
-                .addWayTagParser(new OSMSmoothnessParser(lookup.getEnumEncodedValue(Smoothness.KEY, Smoothness.class)))
-                .addVehicleTagParser(parser);
-    }
-
-    private Graph initExampleGraph() {
-        BaseGraph gs = new BaseGraph.Builder(encodingManager).set3D(true).create();
-        NodeAccess na = gs.getNodeAccess();
-        // 50--(0.0001)-->49--(0.0004)-->55--(0.0005)-->60
-        na.setNode(0, 51.1, 12.001, 50);
-        na.setNode(1, 51.1, 12.002, 60);
-        EdgeIteratorState edge = gs.edge(0, 1).
-                setDistance(100).
-                setWayGeometry(Helper.createPointList3D(51.1, 12.0011, 49, 51.1, 12.0015, 55));
-        edge.set(avgSpeedEnc, 10, 15);
-        edge.set(parser.getAccessEnc(), true, true);
-        return gs;
-    }
-
-    @Test
-    public void testApplyWayTags() {
-        Graph graph = initExampleGraph();
-        EdgeIteratorState edge = GHUtility.getEdge(graph, 0, 1);
-        ReaderWay way = new ReaderWay(1);
-        way.setTag("point_list", edge.fetchWayGeometry(FetchMode.ALL));
-        way.setTag("edge_distance", edge.getDistance());
-        edge.setFlags(((Bike2WeightTagParser) parser).applyWayTags(way, edge.getFlags()));
-
-        IntsRef flags = edge.getFlags();
-        // decrease speed
-        assertEquals(2, avgSpeedEnc.getDecimal(false, flags), 1e-1);
-        // increase speed but use maximum speed (calculated was 24)
-        assertEquals(18, avgSpeedEnc.getDecimal(true, flags), 1e-1);
-    }
-
-    @Test
-    public void testUnchangedForStepsBridgeAndTunnel() {
-        Graph graph = initExampleGraph();
-        EdgeIteratorState edge = GHUtility.getEdge(graph, 0, 1);
-        IntsRef oldFlags = IntsRef.deepCopyOf(edge.getFlags());
-        ReaderWay way = new ReaderWay(1);
-        way.setTag("highway", "steps");
-        way.setTag("point_list", edge.fetchWayGeometry(FetchMode.ALL));
-        way.setTag("edge_distance", edge.getDistance());
-        edge.setFlags(((Bike2WeightTagParser) parser).applyWayTags(way, edge.getFlags()));
-
-        assertEquals(oldFlags, edge.getFlags());
-    }
-
-    @Test
-    public void testSetSpeed0_issue367() {
-        IntsRef edgeFlags = encodingManager.createEdgeFlags();
-        avgSpeedEnc.setDecimal(false, edgeFlags, 10);
-        avgSpeedEnc.setDecimal(true, edgeFlags, 10);
-        parser.getAccessEnc().setBool(false, edgeFlags, true);
-        parser.getAccessEnc().setBool(true, edgeFlags, true);
-
-        parser.setSpeed(false, edgeFlags, 0);
-
-        assertEquals(0, avgSpeedEnc.getDecimal(false, edgeFlags), .1);
-        assertEquals(10, avgSpeedEnc.getDecimal(true, edgeFlags), .1);
-        assertFalse(parser.getAccessEnc().getBool(false, edgeFlags));
-        assertTrue(parser.getAccessEnc().getBool(true, edgeFlags));
-    }
-
-    @Test
-    public void testRoutingFailsWithInvalidGraph_issue665() {
-        BaseGraph graph = new BaseGraph.Builder(encodingManager).set3D(true).create();
-        ReaderWay way = new ReaderWay(0);
-        way.setTag("route", "ferry");
-        way.setTag("edge_distance", 500.0);
-
-        assertNotEquals(WayAccess.CAN_SKIP, parser.getAccess(way));
-        IntsRef edgeFlags = encodingManager.createEdgeFlags();
-        edgeFlags = osmParsers.handleWayTags(edgeFlags, way, encodingManager.createRelationFlags());
-        graph.edge(0, 1).setDistance(247).setFlags(edgeFlags);
-
-        assertTrue(isGraphValid(graph, parser.getAccessEnc()));
-    }
-
-    private boolean isGraphValid(Graph graph, BooleanEncodedValue accessEnc) {
-        EdgeExplorer explorer = graph.createEdgeExplorer();
-        // iterator at node 0 considers the edge 0-1 to be undirected
-        EdgeIterator iter0 = explorer.setBaseNode(0);
-        iter0.next();
-        boolean iter0flag
-                = iter0.getBaseNode() == 0 && iter0.getAdjNode() == 1
-                && iter0.get(accessEnc) && iter0.getReverse(accessEnc);
-
-        // iterator at node 1 considers the edge 1-0 to be directed
-        EdgeIterator iter1 = explorer.setBaseNode(1);
-        iter1.next();
-        boolean iter1flag
-                = iter1.getBaseNode() == 1 && iter1.getAdjNode() == 0
-                && iter1.get(accessEnc) && iter1.getReverse(accessEnc);
-
-        return iter0flag && iter1flag;
-    }
-}
diff --git a/core/src/test/java/com/graphhopper/routing/util/TagParsingTest.java b/core/src/test/java/com/graphhopper/routing/util/TagParsingTest.java
index 7ad71cbbc..c6b7b8878 100644
--- a/core/src/test/java/com/graphhopper/routing/util/TagParsingTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/TagParsingTest.java
@@ -128,37 +128,6 @@ class TagParsingTest {
         assertTrue(bikePriorityEnc.getDecimal(false, edgeFlags) > mtbPriorityEnc.getDecimal(false, edgeFlags));
     }
 
-    @Test
-    public void testCompatibilityBug() {
-        EncodingManager manager2 = EncodingManager.create("mtb");
-        ReaderWay osmWay = new ReaderWay(1);
-        osmWay.setTag("highway", "footway");
-        osmWay.setTag("name", "test");
-
-        MountainBikeTagParser parser = new MountainBikeTagParser(manager2, new PMap());
-        parser.init(new DateRangeParser());
-        IntsRef flags = parser.handleWayTags(manager2.createEdgeFlags(), osmWay);
-        double singleSpeed = parser.avgSpeedEnc.getDecimal(false, flags);
-        assertEquals(BikeCommonTagParser.PUSHING_SECTION_SPEED, singleSpeed, 1e-3);
-        assertEquals(singleSpeed, parser.avgSpeedEnc.getDecimal(true, flags), 1e-3);
-
-        EncodingManager manager = EncodingManager.create("mtb,bike,foot");
-        FootTagParser footParser = new FootTagParser(manager, new PMap());
-        footParser.init(new DateRangeParser());
-        MountainBikeTagParser bikeParser = new MountainBikeTagParser(manager, new PMap());
-        bikeParser.init(new DateRangeParser());
-
-        flags = footParser.handleWayTags(manager.createEdgeFlags(), osmWay);
-        flags = bikeParser.handleWayTags(flags, osmWay);
-        DecimalEncodedValue bikeSpeedEnc = manager.getDecimalEncodedValue(VehicleSpeed.key("mtb"));
-        assertEquals(singleSpeed, bikeSpeedEnc.getDecimal(false, flags), 1e-2);
-        assertEquals(singleSpeed, bikeSpeedEnc.getDecimal(true, flags), 1e-2);
-
-        DecimalEncodedValue footSpeedEnc = manager.getDecimalEncodedValue(VehicleSpeed.key("foot"));
-        assertEquals(5, footSpeedEnc.getDecimal(false, flags), 1e-2);
-        assertEquals(5, footSpeedEnc.getDecimal(true, flags), 1e-2);
-    }
-
     @Test
     public void testSharedEncodedValues() {
         BooleanEncodedValue carAccessEnc = VehicleAccess.create("car");
diff --git a/navigation/src/test/java/com/graphhopper/navigation/NavigateResponseConverterTest.java b/navigation/src/test/java/com/graphhopper/navigation/NavigateResponseConverterTest.java
index 93438d830..5defc5de6 100644
--- a/navigation/src/test/java/com/graphhopper/navigation/NavigateResponseConverterTest.java
+++ b/navigation/src/test/java/com/graphhopper/navigation/NavigateResponseConverterTest.java
@@ -273,7 +273,7 @@ public class NavigateResponseConverterTest {
 
         step = steps.get(4);
         intersection = step.get("intersections").get(3);
-        assertEquals(1, intersection.get("in").asInt());
+        assertEquals(2, intersection.get("in").asInt());
         assertEquals(0, intersection.get("out").asInt());
         location = intersection.get("location");
         assertEquals(1.534679, location.get(0).asDouble(), .000001);
diff --git a/reader-gtfs/src/test/java/com/graphhopper/AnotherAgencyIT.java b/reader-gtfs/src/test/java/com/graphhopper/AnotherAgencyIT.java
index 0624c536f..bba801c36 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/AnotherAgencyIT.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/AnotherAgencyIT.java
@@ -54,6 +54,7 @@ public class AnotherAgencyIT {
     public static void init() {
         GraphHopperConfig ghConfig = new GraphHopperConfig();
         ghConfig.putObject("graph.location", GRAPH_LOC);
+        ghConfig.putObject("import.osm.ignored_highways", "");
         ghConfig.putObject("datareader.file", "files/beatty.osm");
         ghConfig.putObject("gtfs.file", "files/sample-feed,files/another-sample-feed");
         ghConfig.setProfiles(Arrays.asList(
diff --git a/reader-gtfs/src/test/java/com/graphhopper/ExtendedRouteTypeIT.java b/reader-gtfs/src/test/java/com/graphhopper/ExtendedRouteTypeIT.java
index 8b0a33867..756f5a7a0 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/ExtendedRouteTypeIT.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/ExtendedRouteTypeIT.java
@@ -50,6 +50,7 @@ public class ExtendedRouteTypeIT {
         GraphHopperConfig ghConfig = new GraphHopperConfig();
         ghConfig.putObject("graph.location", GRAPH_LOC);
         ghConfig.putObject("gtfs.file", "files/another-sample-feed-extended-route-type.zip");
+        ghConfig.putObject("import.osm.ignored_highways", "");
         ghConfig.setProfiles(Arrays.asList(
                 new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                 new Profile("car").setVehicle("car").setWeighting("fastest")));
diff --git a/reader-gtfs/src/test/java/com/graphhopper/FreeWalkIT.java b/reader-gtfs/src/test/java/com/graphhopper/FreeWalkIT.java
index 88455f099..d1e2e54b5 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/FreeWalkIT.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/FreeWalkIT.java
@@ -55,6 +55,7 @@ public class FreeWalkIT {
         ghConfig.putObject("datareader.file", "files/beatty.osm");
         ghConfig.putObject("gtfs.file", "files/sample-feed,files/another-sample-feed");
         ghConfig.putObject("gtfs.max_transfer_interpolation_walk_time_seconds", 0);
+        ghConfig.putObject("import.osm.ignored_highways", "");
         // TODO: This setting vv is currently "dead", as in production it switches to PtRouterFreeWalkImpl, but
         // TODO: here it is instantiated directly. Refactor by having only one Router but two Solvers, similar
         // TODO: to the street router.
diff --git a/reader-gtfs/src/test/java/com/graphhopper/GraphHopperGtfsIT.java b/reader-gtfs/src/test/java/com/graphhopper/GraphHopperGtfsIT.java
index 1a875f113..f73f83642 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/GraphHopperGtfsIT.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/GraphHopperGtfsIT.java
@@ -56,6 +56,7 @@ public class GraphHopperGtfsIT {
     public static void init() {
         GraphHopperConfig ghConfig = new GraphHopperConfig();
         ghConfig.putObject("graph.location", GRAPH_LOC);
+        ghConfig.putObject("import.osm.ignored_highways", "");
         ghConfig.putObject("gtfs.file", "files/sample-feed");
         ghConfig.setProfiles(Arrays.asList(
                 new Profile("foot").setVehicle("foot").setWeighting("fastest"),
diff --git a/reader-gtfs/src/test/java/com/graphhopper/GraphHopperMultimodalIT.java b/reader-gtfs/src/test/java/com/graphhopper/GraphHopperMultimodalIT.java
index 7c7354cbf..4bb86fcb5 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/GraphHopperMultimodalIT.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/GraphHopperMultimodalIT.java
@@ -57,6 +57,7 @@ public class GraphHopperMultimodalIT {
     public static void init() {
         GraphHopperConfig ghConfig = new GraphHopperConfig();
         ghConfig.putObject("datareader.file", "files/beatty.osm");
+        ghConfig.putObject("import.osm.ignored_highways", "");
         ghConfig.putObject("gtfs.file", "files/sample-feed");
         ghConfig.putObject("graph.location", GRAPH_LOC);
         ghConfig.setProfiles(Arrays.asList(
diff --git a/reader-gtfs/src/test/java/com/graphhopper/RealtimeIT.java b/reader-gtfs/src/test/java/com/graphhopper/RealtimeIT.java
index 2ac7c4aa1..6ac65eaa6 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/RealtimeIT.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/RealtimeIT.java
@@ -53,6 +53,7 @@ public class RealtimeIT {
         GraphHopperConfig ghConfig = new GraphHopperConfig();
         ghConfig.putObject("gtfs.file", "files/sample-feed");
         ghConfig.putObject("graph.location", GRAPH_LOC);
+        ghConfig.putObject("import.osm.ignored_highways", "");
         ghConfig.setProfiles(Arrays.asList(
                 new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                 new Profile("car").setVehicle("car").setWeighting("fastest")));
diff --git a/reader-gtfs/src/test/java/com/graphhopper/gtfs/analysis/AnalysisTest.java b/reader-gtfs/src/test/java/com/graphhopper/gtfs/analysis/AnalysisTest.java
index 924d155ef..ae7791be0 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/gtfs/analysis/AnalysisTest.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/gtfs/analysis/AnalysisTest.java
@@ -45,6 +45,7 @@ public class AnalysisTest {
         ghConfig.putObject("graph.location", GRAPH_LOC);
         ghConfig.putObject("datareader.file", "files/beatty.osm");
         ghConfig.putObject("gtfs.file", "files/sample-feed,files/another-sample-feed");
+        ghConfig.putObject("import.osm.ignored_highways", "");
         ghConfig.setProfiles(Arrays.asList(
                 new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                 new Profile("car").setVehicle("car").setWeighting("fastest")));
diff --git a/web/src/test/java/com/graphhopper/application/GraphHopperLandmarksTest.java b/web/src/test/java/com/graphhopper/application/GraphHopperLandmarksTest.java
index 00e3525be..2234137dc 100644
--- a/web/src/test/java/com/graphhopper/application/GraphHopperLandmarksTest.java
+++ b/web/src/test/java/com/graphhopper/application/GraphHopperLandmarksTest.java
@@ -54,6 +54,7 @@ public class GraphHopperLandmarksTest {
                 putObject("graph.vehicles", "car").
                 putObject("datareader.file", "../core/files/belarus-east.osm.gz").
                 putObject("prepare.min_network_size", 0).
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR)
                 // force landmark creation even for tiny networks
                 .putObject("prepare.lm.min_network_size", 2)
diff --git a/web/src/test/java/com/graphhopper/application/MapMatchingTest.java b/web/src/test/java/com/graphhopper/application/MapMatchingTest.java
index 7321b3e74..56224818e 100644
--- a/web/src/test/java/com/graphhopper/application/MapMatchingTest.java
+++ b/web/src/test/java/com/graphhopper/application/MapMatchingTest.java
@@ -141,7 +141,7 @@ public class MapMatchingTest {
         assertEquals(route.getDistance(), mr.getMatchLength(), 0.5);
         // GraphHopper travel times aren't exactly additive
         assertThat(Math.abs(route.getTime() - mr.getMatchMillis()), is(lessThan(1000L)));
-        assertEquals(142, mr.getEdgeMatches().size());
+        assertEquals(208, mr.getEdgeMatches().size());
     }
 
     @ParameterizedTest
diff --git a/web/src/test/java/com/graphhopper/application/resources/I18nResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/I18nResourceTest.java
index d4c0b3b8b..6f793db98 100644
--- a/web/src/test/java/com/graphhopper/application/resources/I18nResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/I18nResourceTest.java
@@ -49,6 +49,7 @@ public class I18nResourceTest {
                 putObject("graph.vehicles", "car").
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
                 putObject("graph.location", DIR).
+                putObject("import.osm.ignored_highways", "").
                 setProfiles(Collections.singletonList(new Profile("car").setVehicle("car").setWeighting("fastest")));
         return config;
     }
diff --git a/web/src/test/java/com/graphhopper/application/resources/IsochroneResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/IsochroneResourceTest.java
index 29dad4b00..f5bd2ba07 100644
--- a/web/src/test/java/com/graphhopper/application/resources/IsochroneResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/IsochroneResourceTest.java
@@ -55,6 +55,7 @@ public class IsochroneResourceTest {
         config.getGraphHopperConfiguration().
                 putObject("graph.vehicles", "car|turn_costs=true").
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR).
                 setProfiles(Arrays.asList(
                         new Profile("fast_car").setVehicle("car").setWeighting("fastest").setTurnCosts(true),
diff --git a/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTest.java
index 9b7a08491..8d49dbd25 100644
--- a/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTest.java
@@ -56,6 +56,7 @@ public class MapMatchingResourceTest {
         config.getGraphHopperConfiguration().
                 putObject("graph.vehicles", "car,bike").
                 putObject("datareader.file", "../map-matching/files/leipzig_germany.osm.pbf").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR).
                 setProfiles(Arrays.asList(
                         new Profile("fast_car").setVehicle("car").setWeighting("fastest"),
diff --git a/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTurnCostsTest.java b/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTurnCostsTest.java
index d0a1b7f2d..c1c3b632e 100644
--- a/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTurnCostsTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/MapMatchingResourceTurnCostsTest.java
@@ -20,7 +20,6 @@ package com.graphhopper.application.resources;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.graphhopper.application.GraphHopperApplication;
 import com.graphhopper.application.GraphHopperServerConfiguration;
-import com.graphhopper.application.util.TestUtils;
 import com.graphhopper.config.CHProfile;
 import com.graphhopper.config.LMProfile;
 import com.graphhopper.config.Profile;
@@ -60,6 +59,7 @@ public class MapMatchingResourceTurnCostsTest {
         config.getGraphHopperConfiguration().
                 putObject("graph.vehicles", "car|turn_costs=true,bike").
                 putObject("datareader.file", "../map-matching/files/leipzig_germany.osm.pbf").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR).
                 setProfiles(Arrays.asList(
                         new Profile("car").setVehicle("car").setWeighting("fastest").setTurnCosts(true),
diff --git a/web/src/test/java/com/graphhopper/application/resources/MvtResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/MvtResourceTest.java
index ba521a83e..dee45fec0 100644
--- a/web/src/test/java/com/graphhopper/application/resources/MvtResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/MvtResourceTest.java
@@ -57,6 +57,7 @@ public class MvtResourceTest {
                 putObject("graph.encoded_values", "road_class,road_environment,max_speed,surface").
                 putObject("prepare.min_network_size", 0).
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR).
                 setProfiles(Collections.singletonList(new Profile("car").setVehicle("car").setWeighting("fastest")));
         return config;
diff --git a/web/src/test/java/com/graphhopper/application/resources/NearestResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/NearestResourceTest.java
index 7711dc9e4..57aa0b5a5 100644
--- a/web/src/test/java/com/graphhopper/application/resources/NearestResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/NearestResourceTest.java
@@ -52,6 +52,7 @@ public class NearestResourceTest {
                 putObject("graph.vehicles", "car").
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
                 putObject("graph.location", dir).
+                putObject("import.osm.ignored_highways", "").
                 setProfiles(Collections.singletonList(new Profile("car").setVehicle("car").setWeighting("fastest")));
         return config;
     }
diff --git a/web/src/test/java/com/graphhopper/application/resources/NearestResourceWithEleTest.java b/web/src/test/java/com/graphhopper/application/resources/NearestResourceWithEleTest.java
index dcf234332..f7224699c 100644
--- a/web/src/test/java/com/graphhopper/application/resources/NearestResourceWithEleTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/NearestResourceWithEleTest.java
@@ -53,6 +53,7 @@ public class NearestResourceWithEleTest {
                 putObject("prepare.min_network_size", 0).
                 putObject("graph.vehicles", "car").
                 putObject("datareader.file", "../core/files/monaco.osm.gz").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", dir).
                 setProfiles(Collections.singletonList(new Profile("car").setVehicle("car").setWeighting("fastest")));
         return config;
@@ -73,7 +74,7 @@ public class NearestResourceWithEleTest {
         double lon = point.get(0).asDouble();
         double lat = point.get(1).asDouble();
         double ele = point.get(2).asDouble();
-        assertTrue(lat == 43.7307001 && lon == 7.4213923 && ele == 66.0, "nearest point wasn't correct: lat=" + lat + ", lon=" + lon + ", ele=" + ele);
+        assertTrue(lat == 43.73084185257864 && lon == 7.420749379140277 && ele == 59.0, "nearest point wasn't correct: lat=" + lat + ", lon=" + lon + ", ele=" + ele);
     }
 
     @Test
@@ -84,7 +85,7 @@ public class NearestResourceWithEleTest {
         assertEquals(2, point.size(), "returned point is not 2D: " + point);
         double lon = point.get(0).asDouble();
         double lat = point.get(1).asDouble();
-        assertTrue(lat == 43.7307001 && lon == 7.4213923, "nearest point wasn't correct: lat=" + lat + ", lon=" + lon);
+        assertTrue(lat == 43.73084185257864 && lon == 7.420749379140277, "nearest point wasn't correct: lat=" + lat + ", lon=" + lon);
 
         // Default elevation is false        
         json = clientTarget(app, "/nearest?point=43.730864,7.420771").request().buildGet().invoke().readEntity(JsonNode.class);
@@ -93,6 +94,6 @@ public class NearestResourceWithEleTest {
         assertEquals(2, point.size(), "returned point is not 2D: " + point);
         lon = point.get(0).asDouble();
         lat = point.get(1).asDouble();
-        assertTrue(lat == 43.7307001 && lon == 7.4213923, "nearest point wasn't correct: lat=" + lat + ", lon=" + lon);
+        assertTrue(lat == 43.73084185257864 && lon == 7.420749379140277, "nearest point wasn't correct: lat=" + lat + ", lon=" + lon);
     }
 }
diff --git a/web/src/test/java/com/graphhopper/application/resources/PtIsochroneTest.java b/web/src/test/java/com/graphhopper/application/resources/PtIsochroneTest.java
index 5d810e207..f12b99ffd 100644
--- a/web/src/test/java/com/graphhopper/application/resources/PtIsochroneTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/PtIsochroneTest.java
@@ -58,7 +58,8 @@ public class PtIsochroneTest {
         config.getGraphHopperConfiguration()
                 .putObject("graph.vehicles", "foot")
                 .putObject("graph.location", GRAPH_LOC)
-                .putObject("gtfs.file", "../reader-gtfs/files/sample-feed").
+                .putObject("gtfs.file", "../reader-gtfs/files/sample-feed")
+                .putObject("import.osm.ignored_highways", "").
                 setProfiles(Collections.singletonList(new Profile("foot").setVehicle("foot").setWeighting("fastest")));
         Helper.removeDir(new File(GRAPH_LOC));
         return config;
diff --git a/web/src/test/java/com/graphhopper/application/resources/PtRouteResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/PtRouteResourceTest.java
index f36d4bf69..e22401f7d 100644
--- a/web/src/test/java/com/graphhopper/application/resources/PtRouteResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/PtRouteResourceTest.java
@@ -54,6 +54,7 @@ public class PtRouteResourceTest {
                 putObject("datareader.file", "../reader-gtfs/files/beatty.osm").
                 putObject("gtfs.file", "../reader-gtfs/files/sample-feed").
                 putObject("graph.location", DIR).
+                putObject("import.osm.ignored_highways", "").
                 setProfiles(Collections.singletonList(new Profile("foot").setVehicle("foot").setWeighting("fastest")));
         return config;
     }
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceClientHCTest.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceClientHCTest.java
index d76c3617f..723d8d002 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceClientHCTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceClientHCTest.java
@@ -65,6 +65,7 @@ public class RouteResourceClientHCTest {
                 putObject("graph.elevation.cache_dir", "../core/files/").
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
                 putObject("graph.encoded_values", "road_class,surface,road_environment,max_speed").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR)
                 .setProfiles(Arrays.asList(
                         new Profile("car").setVehicle("car").setWeighting("fastest"),
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelLMTest.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelLMTest.java
index 6cd248783..988018f60 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelLMTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelLMTest.java
@@ -56,6 +56,7 @@ public class RouteResourceCustomModelLMTest {
                 putObject("graph.vehicles", "car,foot").
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
                 putObject("graph.location", DIR).
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.encoded_values", "surface").
                 setProfiles(Arrays.asList(
                         // give strange profile names to ensure that we do not mix vehicle and profile:
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelTest.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelTest.java
index 6997d8b03..993e3fca5 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceCustomModelTest.java
@@ -64,6 +64,7 @@ public class RouteResourceCustomModelTest {
                 putObject("graph.location", DIR).
                 putObject("graph.encoded_values", "max_height,max_weight,max_width,hazmat,toll,surface,track_type,hgv").
                 putObject("custom_model_folder", "./src/test/resources/com/graphhopper/application/resources").
+                putObject("import.osm.ignored_highways", "").
                 setProfiles(Arrays.asList(
                         new Profile("wheelchair"),
                         new CustomProfile("roads").setCustomModel(new CustomModel()).setVehicle("roads"),
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue1574Test.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue1574Test.java
index 28409ad21..e5f7d1306 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue1574Test.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue1574Test.java
@@ -54,6 +54,7 @@ public class RouteResourceIssue1574Test {
                 putObject("graph.vehicles", "car").
                 putObject("prepare.min_network_size", 0).
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR)
                 .setProfiles(Collections.singletonList(
                         new Profile("car_profile").setVehicle("car").setWeighting("fastest")
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue2020Test.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue2020Test.java
index 0c1f0a931..478e41a68 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue2020Test.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceIssue2020Test.java
@@ -52,6 +52,7 @@ public class RouteResourceIssue2020Test {
                 putObject("prepare.lm.split_area_location", "../core/files/split.geo.json").
                 putObject("datareader.file", "../core/files/north-bayreuth.osm.gz").
                 putObject("graph.encoded_values", "road_class,surface,road_environment,max_speed").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR).
                 setProfiles(Collections.singletonList(new Profile("my_car").setVehicle("car").setWeighting("fastest"))).
                 setLMProfiles(Collections.singletonList(new LMProfile("my_car")));
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceProfileSelectionTest.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceProfileSelectionTest.java
index f0cd85e2a..24b4a7b2c 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceProfileSelectionTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceProfileSelectionTest.java
@@ -54,6 +54,7 @@ public class RouteResourceProfileSelectionTest {
                 putObject("prepare.min_network_size", 0).
                 putObject("datareader.file", "../core/files/monaco.osm.gz").
                 putObject("graph.encoded_values", "road_class,surface,road_environment,max_speed").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR)
                 .setProfiles(Arrays.asList(
                         new Profile("my_car").setVehicle("car").setWeighting("fastest"),
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceTest.java
index 9cfa1fe86..eaed06572 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceTest.java
@@ -25,7 +25,6 @@ import com.graphhopper.api.GraphHopperWeb;
 import com.graphhopper.application.GraphHopperApplication;
 import com.graphhopper.application.GraphHopperServerConfiguration;
 import com.graphhopper.application.util.GraphHopperServerTestConfiguration;
-import com.graphhopper.application.util.TestUtils;
 import com.graphhopper.config.CHProfile;
 import com.graphhopper.config.Profile;
 import com.graphhopper.routing.ev.RoadClass;
@@ -83,6 +82,7 @@ public class RouteResourceTest {
                 putObject("prepare.min_network_size", 0).
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
                 putObject("graph.encoded_values", "road_class,surface,road_environment,max_speed").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR)
                 // adding this so the corresponding check is not just skipped...
                 .putObject(MAX_NON_CH_POINT_DISTANCE, 10e6)
@@ -295,10 +295,10 @@ public class RouteResourceTest {
         assertEquals(5, averageSpeedList.get(1).getLength());
 
         List<PathDetail> edgeIdDetails = pathDetails.get("edge_id");
-        assertEquals(77, edgeIdDetails.size());
-        assertEquals(882L, edgeIdDetails.get(0).getValue());
+        assertEquals(78, edgeIdDetails.size());
+        assertEquals(924L, edgeIdDetails.get(0).getValue());
         assertEquals(2, edgeIdDetails.get(0).getLength());
-        assertEquals(883L, edgeIdDetails.get(1).getValue());
+        assertEquals(925L, edgeIdDetails.get(1).getValue());
         assertEquals(8, edgeIdDetails.get(1).getLength());
 
         long expectedTime = rsp.getBest().getTime();
@@ -353,8 +353,8 @@ public class RouteResourceTest {
         JsonNode edgeIds = details.get("edge_id");
         int firstLink = edgeIds.get(0).get(2).asInt();
         int lastLink = edgeIds.get(edgeIds.size() - 1).get(2).asInt();
-        assertEquals(882, firstLink);
-        assertEquals(1425, lastLink);
+        assertEquals(924, firstLink);
+        assertEquals(1584, lastLink);
 
         JsonNode maxSpeed = details.get("max_speed");
         assertEquals(-1, maxSpeed.get(0).get(2).asDouble(-1), .01);
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceTurnCostsTest.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceTurnCostsTest.java
index 8a69177d2..2d453b8ef 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceTurnCostsTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceTurnCostsTest.java
@@ -56,6 +56,7 @@ public class RouteResourceTurnCostsTest {
                 putObject("prepare.min_network_size", 0).
                 putObject("datareader.file", "../core/files/moscow.osm.gz").
                 putObject("graph.encoded_values", "road_class,surface,road_environment,max_speed").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR)
                 .setProfiles(Arrays.asList(
                         new Profile("my_car_turn_costs").setVehicle("car").setWeighting("fastest").setTurnCosts(true),
diff --git a/web/src/test/java/com/graphhopper/application/resources/RouteResourceWithEleTest.java b/web/src/test/java/com/graphhopper/application/resources/RouteResourceWithEleTest.java
index 2c640c952..63c2e3777 100644
--- a/web/src/test/java/com/graphhopper/application/resources/RouteResourceWithEleTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/RouteResourceWithEleTest.java
@@ -54,6 +54,7 @@ public class RouteResourceWithEleTest {
                 putObject("graph.vehicles", "car").
                 putObject("datareader.file", "../core/files/monaco.osm.gz").
                 putObject("graph.location", dir).
+                putObject("import.osm.ignored_highways", "").
                 setProfiles(Collections.singletonList(
                         new Profile("profile").setVehicle("car").setWeighting("fastest")
                 ));
diff --git a/web/src/test/java/com/graphhopper/application/resources/SPTResourceTest.java b/web/src/test/java/com/graphhopper/application/resources/SPTResourceTest.java
index baa4eff5e..4e2b9e29e 100644
--- a/web/src/test/java/com/graphhopper/application/resources/SPTResourceTest.java
+++ b/web/src/test/java/com/graphhopper/application/resources/SPTResourceTest.java
@@ -50,6 +50,7 @@ public class SPTResourceTest {
                 putObject("graph.vehicles", "car|turn_costs=true").
                 putObject("graph.encoded_values", "max_speed,road_class").
                 putObject("datareader.file", "../core/files/andorra.osm.pbf").
+                putObject("import.osm.ignored_highways", "").
                 putObject("graph.location", DIR).
                 setProfiles(Arrays.asList(
                         new Profile("car_without_turncosts").setVehicle("car").setWeighting("fastest"),
@@ -72,10 +73,10 @@ public class SPTResourceTest {
         List<String> headers = Arrays.asList(lines[0].split(","));
         assertEquals("[longitude, latitude, time, distance]", headers.toString());
         String[] row = lines[166].split(",");
-        assertEquals(1.5552, Double.parseDouble(row[0]), 0.0001);
-        assertEquals(42.5179, Double.parseDouble(row[1]), 0.0001);
-        assertEquals(118, Integer.parseInt(row[2]) / 1000, 1);
-        assertEquals(2263, Integer.parseInt(row[3]), 1);
+        assertEquals(1.5740, Double.parseDouble(row[0]), 0.0001);
+        assertEquals(42.5362, Double.parseDouble(row[1]), 0.0001);
+        assertEquals(111, Integer.parseInt(row[2]) / 1000, 1);
+        assertEquals(1505, Integer.parseInt(row[3]), 1);
 
         rsp = clientTarget(app, "/spt?profile=car_without_turncosts&point=42.531073,1.573792&columns=prev_time").request().buildGet().invoke();
         rspCsvString = rsp.readEntity(String.class);
@@ -86,7 +87,7 @@ public class SPTResourceTest {
         assertNotEquals(-1, prevTimeIndex);
 
         row = lines[20].split(",");
-        assertEquals(41, Integer.parseInt(row[prevTimeIndex]) / 1000);
+        assertEquals(50, Integer.parseInt(row[prevTimeIndex]) / 1000);
     }
 
     @Test
@@ -96,9 +97,9 @@ public class SPTResourceTest {
         String[] lines = rspCsvString.split("\n");
         assertTrue(lines.length > 500);
         assertEquals("prev_node_id,edge_id,node_id,time,distance", lines[0]);
-        assertEquals("-1,-1,1948,0,0", lines[1]);
-        assertEquals("1948,2277,1324,3817,74", lines[2]);
-        assertEquals("1948,2276,263,13496,262", lines[3]);
+        assertEquals("-1,-1,2385,0,0", lines[1]);
+        assertEquals("2385,2821,1571,3817,74", lines[2]);
+        assertEquals("2385,2820,274,13496,262", lines[3]);
     }
 
     @Test
@@ -108,14 +109,14 @@ public class SPTResourceTest {
         String[] lines = rspCsvString.split("\n");
 
         String[] row = lines[368].split(",");
-        assertEquals("", row[0]);
-        assertEquals("service", row[1]);
-        assertEquals(20, Double.parseDouble(row[2]), .1);
+        assertEquals("Placeta Na Maria Pla", row[0]);
+        assertEquals("residential", row[1]);
+        assertEquals(50, Double.parseDouble(row[2]), .1);
 
         row = lines[249].split(",");
-        assertEquals("Carretera d'Engolasters", row[0]);
-        assertEquals("secondary", row[1]);
-        assertTrue(Double.isInfinite(Double.parseDouble(row[2])));
+        assertEquals("", row[0]);
+        assertEquals("primary", row[1]);
+        assertEquals(80, Double.parseDouble(row[2]), .1);
     }
 
     @Test
diff --git a/web/src/test/resources/com/graphhopper/application/resources/car4wd.yml b/web/src/test/resources/com/graphhopper/application/resources/car4wd.yml
deleted file mode 100644
index 930eb4364..000000000
--- a/web/src/test/resources/com/graphhopper/application/resources/car4wd.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-# use this custom model with vehicle: roads
-distance_influence: 1
-speed:
-  - if: "track_type == GRADE4 || track_type == GRADE5"
-    limit_to: 5
-  - else: ""
-    limit_to: "car_average_speed"
-priority:
-  - if: "track_type != GRADE4 && track_type != GRADE5 && car_access == false"
-    multiply_by: "0"
\ No newline at end of file