Repository: graphhopper/graphhopper
Pull request #1640 (2019-06-22 07:11:32)

Removes TraversalMode.EDGE_BASED_2DIR_UTURN
This PR removes `TraversalMode.EDGE_BASED_2DIR_UTURN` and renames `TraversalMode.EDGE_BASED_2DIR` to `TraversalMode.EDGE_BASED`, see #1520.

So far we were able to set turn costs for each junction via `TurnCostExtension` and wrap a `Weighting` with `TurnWeighting`, which applies turn costs in `calcMillis/calcWeight`. To make sure the turn costs are considered when calculating routes the routing algorithms need to be passed this `TurnWeighting`. For u-turns we can choose a default cost which is defined within the `TurnWeighting` object. So far this default u-turn cost was set to `40s` and to prevent u-turns there were explicit u-turn checks within the algorithms that were or were not applied depending on the `TraversalMode` we used.

I do not see a good reason why there are these explicit u-turn checks and have thus changed the code in this PR such that: 

- default u-turn costs are set to infinity, so no u-turns will be taken unless the cost is reduced
- the algorithms no longer need to perform explicit u-turn checks. if there is a u-turn the turn costs will simply be calculated via the (turn)weighting if they are infinite the turn will not be considered.
- there is only one edge-based traversal mode (the u-turn traversal mode is no longer needed and the same behavior can be achieved by reducing the u-turn cost in `TurnWeighting`).

So for routing with turn costs but without u-turns we previously did this:

```java
TurnWeighting turnWeighting = new TurnWeighting(weighting, turnCostExtension);
Dijkstra dijkstra = new Dijkstra(graph, turnWeighting, TraversalMode.EDGE_BASED_2DIR);
dijkstra.calcPath(5, 6);
```

and now we do this:

```java
TurnWeighting turnWeighting = new TurnWeighting(weighting, turnCostExtension);
Dijkstra dijkstra = new Dijkstra(graph, turnWeighting, TraversalMode.EDGE_BASED);
dijkstra.calcPath(5, 6);
```

For routing with turn costs and including u-turns we previously did this:

```java
TurnWeighting turnWeighting = new TurnWeighting(weighting, turnCostExtension);
// optional: adjust u-turn costs, 40 is the default
turnWeighting.setDefaultUTurnCost(39);
Dijkstra dijkstra = new Dijkstra(graph, turnWeighting, TraversalMode.EDGE_BASED_2DIR_UTURN);
dijkstra.calcPath(5, 6);
```

and now we do this:

```java
TurnWeighting turnWeighting = new TurnWeighting(weighting, turnCostExtension);
// required: set u-turn costs to some finite value
turnWeighting.setDefaultUTurnCost(39);
Dijkstra dijkstra = new Dijkstra(graph, turnWeighting, TraversalMode.EDGE_BASED);
dijkstra.calcPath(5, 6);
```

Note that we now have to choose `TraversalMode.EDGE_BASED` **and** use `TurnWeighting` to enable turn costs and exclude u-turns. If we use `TraversalMode.EDGE_BASED`, with a normal `Weighting` the resulting route might include u-turns. This is the price we pay for removing the explicit u-turn checks I think.

Another issue was that `TurnWeighting#calcTurnWeight` did **not** include the default u-turn costs and returned 0 for u-turns (unless set explicitly). I have changed this so u-turn costs are included now.

The default u-turn costs overwrite any manually set u-turn cost in `TurnCostExtension` and there is no way to apply specific u-turn costs on a per-junction basis. Checking for explicit turn costs in `TurnCostExtension` before applying the default u-turn costs would be expensive. It is probably rare that one needs to set explicit u-turn costs, but if one wants to set default left-turn costs (or similar) this is a problem. To make this more clear I have renamed `defaultUTurnCost` to `uTurnCost`.

I think this PR is a step in the right direction, because 'applying turn costs' is no longer spread over different parts of the code (traversal mode/explicit u-turn checks + turn weighting), but maybe we should go further and remove `TurnWeighting` entirely. I will open another issue/PR for this.

easbar: Thanks for the review!

Patch:
diff --git a/core/files/changelog.txt b/core/files/changelog.txt
index 540749614..585d29114 100644
--- a/core/files/changelog.txt
+++ b/core/files/changelog.txt
@@ -9,7 +9,8 @@
     removed MappedDecimalEncodedValue: should be replaced with FactoredDecimalEncodedValue
     DataFlagEncoder: it is now required to add EncodedValues before. graph.encoded_values: max_speed,road_class,road_environment,road_access
     instead of EncodingManager.ROUNDABOUT use Roundabout.KEY
-    removed TraversalMode.EDGE_BASED_1DIR
+    removed TraversalMode.EDGE_BASED_1DIR and TraversalMode.EDGE_BASED_2DIR_UTURN, renamed TraversalMode.EDGE_BASED_2DIR to TraversalMode.EDGE_BASED
+    to prevent u-turns when using edge-based algorithms it is now required to use TurnWeighting, #1640
 
 0.12
     renamed VirtualEdgeIteratorState.getOriginalEdgeKey to more precise getOriginalEdgeKey #1549
diff --git a/core/src/main/java/com/graphhopper/GraphHopper.java b/core/src/main/java/com/graphhopper/GraphHopper.java
index 7549921f6..d8b7ef95a 100644
--- a/core/src/main/java/com/graphhopper/GraphHopper.java
+++ b/core/src/main/java/com/graphhopper/GraphHopper.java
@@ -167,7 +167,7 @@ public class GraphHopper implements GraphHopperAPI {
         ensureNotLoaded();
         this.encodingManager = em;
         if (em.needsTurnCostsSupport())
-            traversalMode = TraversalMode.EDGE_BASED_2DIR;
+            traversalMode = TraversalMode.EDGE_BASED;
 
         return this;
     }
@@ -970,7 +970,7 @@ public class GraphHopper implements GraphHopperAPI {
             String tModeStr = hints.get("traversal_mode", traversalMode.toString());
             TraversalMode tMode = TraversalMode.fromString(tModeStr);
             if (hints.has(Routing.EDGE_BASED))
-                tMode = hints.getBool(Routing.EDGE_BASED, false) ? TraversalMode.EDGE_BASED_2DIR : TraversalMode.NODE_BASED;
+                tMode = hints.getBool(Routing.EDGE_BASED, false) ? TraversalMode.EDGE_BASED : TraversalMode.NODE_BASED;
 
             FlagEncoder encoder = encodingManager.getEncoder(vehicle);
 
diff --git a/core/src/main/java/com/graphhopper/routing/AbstractBidirAlgo.java b/core/src/main/java/com/graphhopper/routing/AbstractBidirAlgo.java
index c0445d30e..d97852661 100644
--- a/core/src/main/java/com/graphhopper/routing/AbstractBidirAlgo.java
+++ b/core/src/main/java/com/graphhopper/routing/AbstractBidirAlgo.java
@@ -215,11 +215,12 @@ public abstract class AbstractBidirAlgo extends AbstractRoutingAlgorithm {
             if (!accept(iter, currEdge, reverse))
                 continue;
 
-            final int origEdgeId = getOrigEdgeId(iter, reverse);
-            final int traversalId = getTraversalId(iter, origEdgeId, reverse);
             final double weight = calcWeight(iter, currEdge, reverse);
-            if (Double.isInfinite(weight))
+            if (Double.isInfinite(weight)) {
                 continue;
+            }
+            final int origEdgeId = getOrigEdgeId(iter, reverse);
+            final int traversalId = getTraversalId(iter, origEdgeId, reverse);
             SPTEntry entry = bestWeightMap.get(traversalId);
             if (entry == null) {
                 entry = createEntry(iter, origEdgeId, weight, currEdge, reverse);
diff --git a/core/src/main/java/com/graphhopper/routing/AbstractBidirectionEdgeCHNoSOD.java b/core/src/main/java/com/graphhopper/routing/AbstractBidirectionEdgeCHNoSOD.java
index 4cc3017e0..6e98c7cee 100644
--- a/core/src/main/java/com/graphhopper/routing/AbstractBidirectionEdgeCHNoSOD.java
+++ b/core/src/main/java/com/graphhopper/routing/AbstractBidirectionEdgeCHNoSOD.java
@@ -25,7 +25,6 @@ import com.graphhopper.routing.util.TraversalMode;
 import com.graphhopper.routing.weighting.TurnWeighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.SPTEntry;
-import com.graphhopper.storage.TurnCostExtension;
 import com.graphhopper.util.EdgeExplorer;
 import com.graphhopper.util.EdgeIterator;
 import com.graphhopper.util.EdgeIteratorState;
@@ -38,20 +37,18 @@ public abstract class AbstractBidirectionEdgeCHNoSOD extends AbstractBidirAlgo {
     private final EdgeExplorer innerInExplorer;
     private final EdgeExplorer innerOutExplorer;
     private final TurnWeighting turnWeighting;
-    private final TurnCostExtension turnCostExtension;
 
     public AbstractBidirectionEdgeCHNoSOD(Graph graph, TurnWeighting weighting) {
-        super(graph, weighting, TraversalMode.EDGE_BASED_2DIR);
+        super(graph, weighting, TraversalMode.EDGE_BASED);
         this.turnWeighting = weighting;
         // we need extra edge explorers, because they get called inside a loop that already iterates over edges
         // important: we have to use different filter ids, otherwise this will not work with QueryGraph's edge explorer
         // cache, see #1623.
         innerInExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.inEdges(flagEncoder).setFilterId(1));
         innerOutExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.outEdges(flagEncoder).setFilterId(1));
-        if (!(graph.getExtension() instanceof TurnCostExtension)) {
-            throw new IllegalArgumentException("edge-based CH algorithms require a turn cost extension");
+        if (!Double.isInfinite(turnWeighting.getUTurnCost())) {
+            throw new IllegalArgumentException("edge-based CH does not support finite u-turn costs at the moment");
         }
-        turnCostExtension = (TurnCostExtension) graph.getExtension();
     }
 
     @Override
@@ -111,9 +108,6 @@ public abstract class AbstractBidirectionEdgeCHNoSOD extends AbstractBidirAlgo {
         while (iter.next()) {
             final int edgeId = getOrigEdgeId(iter, !reverse);
             final int prevOrNextOrigEdgeId = getOrigEdgeId(edgeState, reverse);
-            if (!traversalMode.hasUTurnSupport() && turnCostExtension.isUTurn(edgeId, prevOrNextOrigEdgeId)) {
-                continue;
-            }
             int key = GHUtility.getEdgeKey(graph, edgeId, iter.getBaseNode(), !reverse);
             SPTEntry entryOther = bestWeightMapOther.get(key);
             if (entryOther == null) {
@@ -121,8 +115,8 @@ public abstract class AbstractBidirectionEdgeCHNoSOD extends AbstractBidirAlgo {
             }
 
             double turnCostsAtBridgeNode = reverse ?
-                    turnWeighting.calcTurnWeight(iter.getOrigEdgeLast(), iter.getBaseNode(), prevOrNextOrigEdgeId) :
-                    turnWeighting.calcTurnWeight(prevOrNextOrigEdgeId, iter.getBaseNode(), iter.getOrigEdgeFirst());
+                    turnWeighting.calcTurnWeight(edgeId, iter.getBaseNode(), prevOrNextOrigEdgeId) :
+                    turnWeighting.calcTurnWeight(prevOrNextOrigEdgeId, iter.getBaseNode(), edgeId);
 
             double newWeight = entry.getWeightOfVisitedPath() + entryOther.getWeightOfVisitedPath() + turnCostsAtBridgeNode;
             if (newWeight < bestPath.getWeight()) {
@@ -160,9 +154,12 @@ public abstract class AbstractBidirectionEdgeCHNoSOD extends AbstractBidirAlgo {
     protected boolean accept(EdgeIteratorState edge, SPTEntry currEdge, boolean reverse) {
         final int incEdge = getIncomingEdge(currEdge);
         final int prevOrNextEdgeId = getOrigEdgeId(edge, !reverse);
-        if (!traversalMode.hasUTurnSupport() && turnCostExtension.isUTurn(incEdge, prevOrNextEdgeId))
+        double turnWeight = reverse
+                ? turnWeighting.calcTurnWeight(prevOrNextEdgeId, edge.getBaseNode(), incEdge)
+                : turnWeighting.calcTurnWeight(incEdge, edge.getBaseNode(), prevOrNextEdgeId);
+        if (Double.isInfinite(turnWeight)) {
             return false;
-
+        }
         return additionalEdgeFilter == null || additionalEdgeFilter.accept(edge);
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/AbstractRoutingAlgorithm.java b/core/src/main/java/com/graphhopper/routing/AbstractRoutingAlgorithm.java
index 25b755999..3fa2a68c4 100644
--- a/core/src/main/java/com/graphhopper/routing/AbstractRoutingAlgorithm.java
+++ b/core/src/main/java/com/graphhopper/routing/AbstractRoutingAlgorithm.java
@@ -71,7 +71,9 @@ public abstract class AbstractRoutingAlgorithm implements RoutingAlgorithm {
     }
 
     protected boolean accept(EdgeIteratorState iter, int prevOrNextEdgeId) {
-        if (!traversalMode.hasUTurnSupport() && iter.getEdge() == prevOrNextEdgeId)
+        // for edge-based traversal we leave it for TurnWeighting to decide whether or not a u-turn is acceptable,
+        // but for node-based traversal we exclude such a turn for performance reasons already here
+        if (!traversalMode.isEdgeBased() && iter.getEdge() == prevOrNextEdgeId)
             return false;
 
         return additionalEdgeFilter == null || additionalEdgeFilter.accept(iter);
diff --git a/core/src/main/java/com/graphhopper/routing/Dijkstra.java b/core/src/main/java/com/graphhopper/routing/Dijkstra.java
index 93a5abb25..a61eab106 100644
--- a/core/src/main/java/com/graphhopper/routing/Dijkstra.java
+++ b/core/src/main/java/com/graphhopper/routing/Dijkstra.java
@@ -80,10 +80,11 @@ public class Dijkstra extends AbstractRoutingAlgorithm {
                 if (!accept(iter, currEdge.edge))
                     continue;
 
-                int traversalId = traversalMode.createTraversalId(iter, false);
                 double tmpWeight = weighting.calcWeight(iter, false, currEdge.edge) + currEdge.weight;
-                if (Double.isInfinite(tmpWeight))
+                if (Double.isInfinite(tmpWeight)) {
                     continue;
+                }
+                int traversalId = traversalMode.createTraversalId(iter, false);
 
                 SPTEntry nEdge = fromMap.get(traversalId);
                 if (nEdge == null) {
diff --git a/core/src/main/java/com/graphhopper/routing/PathBidirRef.java b/core/src/main/java/com/graphhopper/routing/PathBidirRef.java
index 207297f91..cc5dc96c4 100644
--- a/core/src/main/java/com/graphhopper/routing/PathBidirRef.java
+++ b/core/src/main/java/com/graphhopper/routing/PathBidirRef.java
@@ -24,8 +24,6 @@ import com.graphhopper.storage.SPTEntry;
 import com.graphhopper.util.EdgeIterator;
 import com.graphhopper.util.EdgeIteratorState;
 
-import static com.graphhopper.util.EdgeIterator.NO_EDGE;
-
 /**
  * This class creates a DijkstraPath from two Edge's resulting from a BidirectionalDijkstra
  * <p>
@@ -118,19 +116,7 @@ public class PathBidirRef extends Path {
     protected void processEdgeBwd(int edgeId, int adjNode, int nextEdgeId) {
         EdgeIteratorState edge = graph.getEdgeIteratorState(edgeId, adjNode);
         distance += edge.getDistance();
-        // special case for loop edges: since they do not have a meaningful direction we always need to read them
-        // in the 'fwd' direction, but be careful the turn costs have to be applied with reverse = true, see also
-        // same comment in EdgeBasedPath4CH
-        // todonow: consolidate this!
-        if (edge.getBaseNode() == edge.getAdjNode()) {
-            long millis = weighting.calcMillis(edge, false, NO_EDGE);
-            if (weighting instanceof TurnWeighting && EdgeIterator.Edge.isValid(nextEdgeId)) {
-                millis += 1000 * (long) ((TurnWeighting) weighting).calcTurnWeight(edge.getEdge(), edge.getBaseNode(), nextEdgeId);
-            }
-            time += millis;
-        } else {
-            time += weighting.calcMillis(edge, true, nextEdgeId);
-        }
+        time += weighting.calcMillis(edge, true, nextEdgeId);
         addEdge(edgeId);
     }
 
@@ -140,10 +126,6 @@ public class PathBidirRef extends Path {
         }
         if (weighting instanceof TurnWeighting) {
             time += ((TurnWeighting) weighting).calcTurnWeight(inEdge, viaNode, outEdge) * 1000;
-            // bugfix: should be cleaned up with u-turn refactoring #1520
-            if (inEdge == outEdge) {
-                time += ((TurnWeighting) weighting).getDefaultTurnCost() * 1000;
-            }
         }
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/ch/CHAlgoFactoryDecorator.java b/core/src/main/java/com/graphhopper/routing/ch/CHAlgoFactoryDecorator.java
index a5d3f7e33..719d50deb 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/CHAlgoFactoryDecorator.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/CHAlgoFactoryDecorator.java
@@ -320,7 +320,7 @@ public class CHAlgoFactoryDecorator implements RoutingAlgorithmFactoryDecorator
             addPreparation(createCHPreparation(ghStorage, weighting, TraversalMode.NODE_BASED));
         }
         for (Weighting weighting : edgeBasedWeightings) {
-            addPreparation(createCHPreparation(ghStorage, weighting, TraversalMode.EDGE_BASED_2DIR));
+            addPreparation(createCHPreparation(ghStorage, weighting, TraversalMode.EDGE_BASED));
         }
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java
index 11917ae4c..6c32d71a7 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java
@@ -24,8 +24,6 @@ import com.graphhopper.routing.util.DefaultEdgeFilter;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.weighting.TurnWeighting;
 import com.graphhopper.storage.CHGraph;
-import com.graphhopper.storage.GraphHopperStorage;
-import com.graphhopper.storage.IntsRef;
 import com.graphhopper.util.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -89,6 +87,9 @@ class EdgeBasedNodeContractor extends AbstractNodeContractor {
         this.encoder = turnWeighting.getFlagEncoder();
         this.pMap = pMap;
         extractParams(pMap);
+        if (!Double.isInfinite(turnWeighting.getUTurnCost())) {
+            throw new IllegalArgumentException("edge-based CH currently does not support finite u-turn costs");
+        }
     }
 
     private void extractParams(PMap pMap) {
@@ -239,7 +240,7 @@ class EdgeBasedNodeContractor extends AbstractNodeContractor {
     /**
      * A given potential loop shortcut is only necessary if there is at least one pair of original in- & out-edges for
      * which taking the loop is cheaper than doing the direct turn. However this is almost always the case, because
-     * doing a u-turn at any of the incoming edges is forbidden, i.e. he costs of the direct turn will be infinite.
+     * doing a u-turn at any of the incoming edges is forbidden, i.e. the costs of the direct turn will be infinite.
      */
     private boolean loopShortcutNecessary(int node, int firstOrigEdge, int lastOrigEdge, double loopWeight) {
         EdgeIterator inIter = loopAvoidanceInEdgeExplorer.setBaseNode(node);
@@ -319,9 +320,6 @@ class EdgeBasedNodeContractor extends AbstractNodeContractor {
     }
 
     private double getTurnCost(int inEdge, int node, int outEdge) {
-        if (illegalUTurn(outEdge, inEdge)) {
-            return Double.POSITIVE_INFINITY;
-        }
         return turnWeighting.calcTurnWeight(inEdge, node, outEdge);
     }
 
@@ -332,10 +330,6 @@ class EdgeBasedNodeContractor extends AbstractNodeContractor {
         numPrevOrigEdges = 0;
     }
 
-    private boolean illegalUTurn(int inEdge, int outEdge) {
-        return outEdge == inEdge;
-    }
-
     private Stats stats() {
         return activeShortcutHandler.getStats();
     }
diff --git a/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedPathCH.java b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedPathCH.java
index 3b97f366b..0574ae359 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedPathCH.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedPathCH.java
@@ -5,12 +5,8 @@ import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.SPTEntry;
 import com.graphhopper.storage.ShortcutUnpacker;
-import com.graphhopper.util.CHEdgeIteratorState;
-import com.graphhopper.util.EdgeIterator;
 import com.graphhopper.util.EdgeIteratorState;
 
-import static com.graphhopper.util.EdgeIterator.NO_EDGE;
-
 
 public class EdgeBasedPathCH extends Path4CH {
 
@@ -30,19 +26,7 @@ public class EdgeBasedPathCH extends Path4CH {
             @Override
             public void visit(EdgeIteratorState edge, boolean reverse, int prevOrNextEdgeId) {
                 distance += edge.getDistance();
-                // a one-way loop that is not a shortcut cannot possibly be read in the 'right' direction, because
-                // there is no way to distinguish the two directions. therefore we always read it in fwd direction.
-                // reverse still has to be considered to decide how to calculate the turn weight
-                // todo: turn cost clean-up, should we move this inside calcMillis ?
-                if (reverse && edge.getBaseNode() == edge.getAdjNode() && !((CHEdgeIteratorState) edge).isShortcut()) {
-                    long millis = weighting.calcMillis(edge, false, NO_EDGE);
-                    if (EdgeIterator.Edge.isValid(prevOrNextEdgeId)) {
-                        millis += 1000 * (long) turnWeighting.calcTurnWeight(edge.getEdge(), edge.getBaseNode(), prevOrNextEdgeId);
-                    }
-                    time += millis;
-                } else {
-                    time += weighting.calcMillis(edge, reverse, prevOrNextEdgeId);
-                }
+                time += turnWeighting.calcMillis(edge, reverse, prevOrNextEdgeId);
                 addEdge(edge.getEdge());
             }
         }, true);
diff --git a/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java b/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java
index b64e478fa..36226f28a 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java
@@ -54,6 +54,9 @@ public class PreparationWeighting implements Weighting {
 
     @Override
     public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
+        if (edgeState instanceof CHEdgeIteratorState && ((CHEdgeIteratorState) edgeState).isShortcut()) {
+            throw new IllegalStateException("calcMillis should only be called on original edges");
+        }
         return userWeighting.calcMillis(edgeState, reverse, prevOrNextEdgeId);
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/ch/WitnessPathSearcher.java b/core/src/main/java/com/graphhopper/routing/ch/WitnessPathSearcher.java
index 0dc46f772..f7dd5cb57 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/WitnessPathSearcher.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/WitnessPathSearcher.java
@@ -229,10 +229,6 @@ public class WitnessPathSearcher {
                 if (isContracted(iter.getAdjNode())) {
                     continue;
                 }
-                // do not allow u-turns
-                if (iter.getOrigEdgeFirst() == incEdges[currKey]) {
-                    continue;
-                }
                 double edgeWeight = turnWeighting.calcWeight(iter, false, incEdges[currKey]);
                 double weight = edgeWeight + weights[currKey];
                 if (isInfinite(weight)) {
@@ -479,9 +475,6 @@ public class WitnessPathSearcher {
     }
 
     private double calcTurnWeight(int inEdge, int viaNode, int outEdge) {
-        if (inEdge == outEdge) {
-            return Double.POSITIVE_INFINITY;
-        }
         return turnWeighting.calcTurnWeight(inEdge, viaNode, outEdge);
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/util/TraversalMode.java b/core/src/main/java/com/graphhopper/routing/util/TraversalMode.java
index eac312554..8ed3d56c0 100644
--- a/core/src/main/java/com/graphhopper/routing/util/TraversalMode.java
+++ b/core/src/main/java/com/graphhopper/routing/util/TraversalMode.java
@@ -37,25 +37,16 @@ public enum TraversalMode {
     /**
      * The simplest traversal mode but without turn restrictions or cost support.
      */
-    NODE_BASED(false, false),
+    NODE_BASED(false),
     /**
-     * The bidirectional edged-based traversal mode with turn restriction and cost support. Without
-     * u-turn support. 2 times slower than node based.
+     * The edged-based traversal mode with turn restriction and cost support. 2 times slower than node based.
      */
-    EDGE_BASED_2DIR(true, false),
-    /**
-     * Not recommended as it leads to strange routes that outsmart the turn costs. The most feature
-     * rich edge-based traversal mode with turn restriction and cost support, including u-turns. 4
-     * times slower than node based.
-     */
-    EDGE_BASED_2DIR_UTURN(true, true);
+    EDGE_BASED(true);
 
     private final boolean edgeBased;
-    private final boolean uTurnSupport;
 
-    TraversalMode(boolean edgeBased, boolean uTurnSupport) {
+    TraversalMode(boolean edgeBased) {
         this.edgeBased = edgeBased;
-        this.uTurnSupport = uTurnSupport;
     }
 
     public static TraversalMode fromString(String name) {
@@ -102,7 +93,4 @@ public enum TraversalMode {
         return edgeBased;
     }
 
-    public final boolean hasUTurnSupport() {
-        return uTurnSupport;
-    }
 }
diff --git a/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java b/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java
index 92366a779..160921d85 100644
--- a/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java
+++ b/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java
@@ -46,6 +46,12 @@ public abstract class AbstractWeighting implements Weighting {
 
     @Override
     public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
+        // special case for loop edges: since they do not have a meaningful direction we always need to read them in
+        // forward direction
+        if (edgeState.getBaseNode() == edgeState.getAdjNode()) {
+            reverse = false;
+        }
+
         if (reverse && !edgeState.getReverse(accessEnc) || !reverse && !edgeState.get(accessEnc))
             throw new IllegalStateException("Calculating time should not require to read speed from edge in wrong direction. " +
                     "(" + edgeState.getBaseNode() + " - " + edgeState.getAdjNode() + ") "
diff --git a/core/src/main/java/com/graphhopper/routing/weighting/TurnWeighting.java b/core/src/main/java/com/graphhopper/routing/weighting/TurnWeighting.java
index b766d2e63..a46c3f08b 100644
--- a/core/src/main/java/com/graphhopper/routing/weighting/TurnWeighting.java
+++ b/core/src/main/java/com/graphhopper/routing/weighting/TurnWeighting.java
@@ -38,34 +38,34 @@ public class TurnWeighting implements Weighting {
     private final TurnCostEncoder turnCostEncoder;
     private final TurnCostExtension turnCostExt;
     private final Weighting superWeighting;
-    private double defaultUTurnCost = 40;
+    private final double uTurnCost;
+
+    public TurnWeighting(Weighting superWeighting, TurnCostExtension turnCostExt) {
+        this(superWeighting, turnCostExt, Double.POSITIVE_INFINITY);
+    }
 
     /**
-     * @param turnCostExt the turn cost storage to be used
+     * @param superWeighting the weighting that is wrapped by this {@link TurnWeighting} and used to calculate the
+     *                       edge weights for example
+     * @param turnCostExt    the turn cost storage to be used
+     * @param uTurnCost      the cost of a u-turn in seconds, this value will be applied to all u-turn costs no matter
+     *                       whether or not turnCostExt contains explicit values for these turns.
      */
-    public TurnWeighting(Weighting superWeighting, TurnCostExtension turnCostExt) {
+    public TurnWeighting(Weighting superWeighting, TurnCostExtension turnCostExt, double uTurnCost) {
         this.turnCostEncoder = superWeighting.getFlagEncoder();
         this.superWeighting = superWeighting;
         this.turnCostExt = turnCostExt;
+        this.uTurnCost = uTurnCost;
 
         if (turnCostExt == null)
             throw new RuntimeException("No storage set to calculate turn weight");
     }
 
-    /**
-     * Set the default cost for an u-turn in seconds. Default is 40s. Should be that high to avoid
-     * 'tricking' other turn costs or restrictions.
-     */
-    public TurnWeighting setDefaultUTurnCost(double costInSeconds) {
-        defaultUTurnCost = costInSeconds;
-        return this;
-    }
-
     /**
      * @return the default u-turn cost in seconds
      */
-    public double getDefaultTurnCost() {
-        return defaultUTurnCost;
+    public double getUTurnCost() {
+        return uTurnCost;
     }
 
     @Override
@@ -84,16 +84,13 @@ public class TurnWeighting implements Weighting {
                 ? calcTurnWeight(origEdgeId, edgeState.getBaseNode(), prevOrNextEdgeId)
                 : calcTurnWeight(prevOrNextEdgeId, edgeState.getBaseNode(), origEdgeId);
 
-        if (turnCosts == 0 && origEdgeId == prevOrNextEdgeId)
-            return weight + defaultUTurnCost;
-
         return weight + turnCosts;
     }
 
     @Override
     public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
         long millis = superWeighting.calcMillis(edgeState, reverse, prevOrNextEdgeId);
-        if (prevOrNextEdgeId == EdgeIterator.NO_EDGE)
+        if (!EdgeIterator.Edge.isValid(prevOrNextEdgeId))
             return millis;
 
         // should we also separate weighting vs. time for turn? E.g. a fast but dangerous turn - is this common?
@@ -103,19 +100,19 @@ public class TurnWeighting implements Weighting {
                 ? calcTurnWeight(origEdgeId, edgeState.getBaseNode(), prevOrNextEdgeId)
                 : calcTurnWeight(prevOrNextEdgeId, edgeState.getBaseNode(), origEdgeId));
 
-        if (turnCostsInSeconds == 0 && origEdgeId == prevOrNextEdgeId)
-            return millis + (long) defaultUTurnCost * 1000;
-
         return millis + 1000 * turnCostsInSeconds;
     }
 
     /**
      * This method calculates the turn weight separately.
-     * Be aware that it always returns 0 turn weight unless a turn weight was explicitly set. This means it does
-     * NOT include default u-turn costs and calling methods have to check for u-turns.
-     * todo: this should be cleaned up in #1520.
      */
     public double calcTurnWeight(int edgeFrom, int nodeVia, int edgeTo) {
+        if (!EdgeIterator.Edge.isValid(edgeFrom) || !EdgeIterator.Edge.isValid(edgeTo)) {
+            return 0;
+        }
+        if (turnCostExt.isUTurn(edgeFrom, edgeTo)) {
+            return uTurnCost;
+        }
         long turnFlags = turnCostExt.getTurnCostFlags(edgeFrom, nodeVia, edgeTo);
         if (turnCostEncoder.isTurnRestricted(turnFlags))
             return Double.POSITIVE_INFINITY;
diff --git a/core/src/main/java/com/graphhopper/storage/GraphBuilder.java b/core/src/main/java/com/graphhopper/storage/GraphBuilder.java
index fe2a6b416..7f03bd5d8 100644
--- a/core/src/main/java/com/graphhopper/storage/GraphBuilder.java
+++ b/core/src/main/java/com/graphhopper/storage/GraphBuilder.java
@@ -35,6 +35,7 @@ public class GraphBuilder {
     private boolean mmap;
     private boolean store;
     private boolean elevation;
+    private boolean turnCosts;
     private boolean edgeBasedCH;
     private long byteCapacity = 100;
     private Weighting singleCHWeighting;
@@ -76,6 +77,11 @@ public class GraphBuilder {
         return this;
     }
 
+    public GraphBuilder withTurnCosts(boolean turnCosts) {
+        this.turnCosts = turnCosts;
+        return this;
+    }
+
     public GraphBuilder setEdgeBasedCH(boolean edgeBasedCH) {
         this.edgeBasedCH = edgeBasedCH;
         return this;
@@ -102,7 +108,7 @@ public class GraphBuilder {
                 new MMapDirectory(location) :
                 new RAMDirectory(location, store);
 
-        GraphExtension graphExtension = encodingManager.needsTurnCostsSupport() ?
+        GraphExtension graphExtension = encodingManager.needsTurnCostsSupport() || turnCosts ?
                 new TurnCostExtension() :
                 new TurnCostExtension.NoOpExtension();
 
diff --git a/core/src/main/java/com/graphhopper/util/GHUtility.java b/core/src/main/java/com/graphhopper/util/GHUtility.java
index a6c95799c..af404f290 100644
--- a/core/src/main/java/com/graphhopper/util/GHUtility.java
+++ b/core/src/main/java/com/graphhopper/util/GHUtility.java
@@ -414,6 +414,11 @@ public class GHUtility {
     }
 
     public static EdgeIteratorState createMockedEdgeIteratorState(final double distance, final IntsRef flags) {
+        return createMockedEdgeIteratorState(distance, flags, 0, 1, 2, 3, 4);
+    }
+
+    public static EdgeIteratorState createMockedEdgeIteratorState(final double distance, final IntsRef flags,
+                                                                  final int base, final int adj, final int edge, final int origFirst, final int origLast) {
         return new GHUtility.DisabledEdgeIterator() {
             @Override
             public double getDistance() {
@@ -454,6 +459,36 @@ public class GHUtility {
             public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
                 return property.getEnum(true, flags);
             }
+
+            @Override
+            public int getEdge() {
+                return edge;
+            }
+
+            @Override
+            public int getBaseNode() {
+                return base;
+            }
+
+            @Override
+            public int getAdjNode() {
+                return adj;
+            }
+
+            @Override
+            public PointList fetchWayGeometry(int type) {
+                return Helper.createPointList(0, 2, 6, 4);
+            }
+
+            @Override
+            public int getOrigEdgeFirst() {
+                return origFirst;
+            }
+
+            @Override
+            public int getOrigEdgeLast() {
+                return origLast;
+            }
         };
     }
 
diff --git a/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/Isochrone.java b/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/Isochrone.java
index 7e6c1e5ee..081bdaaf9 100644
--- a/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/Isochrone.java
+++ b/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/Isochrone.java
@@ -190,10 +190,6 @@ public class Isochrone extends AbstractRoutingAlgorithm {
                 if (!accept(iter, currEdge.edge)) {
                     continue;
                 }
-                // minor speed up
-                if (currEdge.edge == iter.getEdge()) {
-                    continue;
-                }
 
                 double tmpWeight = weighting.calcWeight(iter, reverseFlow, currEdge.edge) + currEdge.weight;
                 if (Double.isInfinite(tmpWeight))


Test patch:
diff --git a/core/src/main/java/com/graphhopper/routing/util/TestAlgoCollector.java b/core/src/main/java/com/graphhopper/routing/util/TestAlgoCollector.java
index d3194e920..c2db76981 100644
--- a/core/src/main/java/com/graphhopper/routing/util/TestAlgoCollector.java
+++ b/core/src/main/java/com/graphhopper/routing/util/TestAlgoCollector.java
@@ -54,7 +54,7 @@ public class TestAlgoCollector {
         FlagEncoder encoder = opts.getWeighting().getFlagEncoder();
         if (encoder.supports(TurnWeighting.class)) {
             if (!opts.getTraversalMode().isEdgeBased()) {
-                errors.add("Cannot use TurnWeighting with a node based traversal");
+                errors.add("Cannot use TurnWeighting with node based traversal");
                 return this;
             }
             algoEntry.setAlgorithmOptions(AlgorithmOptions.start(opts).weighting(new TurnWeighting(opts.getWeighting(), (TurnCostExtension) queryGraph.getExtension())).build());
diff --git a/core/src/test/java/com/graphhopper/routing/AStarBidirectionEdgeCHTest.java b/core/src/test/java/com/graphhopper/routing/AStarBidirectionEdgeCHTest.java
index 7ad0a8fc5..da6075e4a 100644
--- a/core/src/test/java/com/graphhopper/routing/AStarBidirectionEdgeCHTest.java
+++ b/core/src/test/java/com/graphhopper/routing/AStarBidirectionEdgeCHTest.java
@@ -54,7 +54,7 @@ public class AStarBidirectionEdgeCHTest extends AbstractRoutingAlgorithmTester {
     public RoutingAlgorithmFactory createFactory(GraphHopperStorage ghStorage, AlgorithmOptions opts) {
         ghStorage.freeze();
         PrepareContractionHierarchies ch = PrepareContractionHierarchies.fromGraphHopperStorage(
-                ghStorage, opts.getWeighting(), TraversalMode.EDGE_BASED_2DIR);
+                ghStorage, opts.getWeighting(), TraversalMode.EDGE_BASED);
         ch.doWork();
         return ch;
     }
diff --git a/core/src/test/java/com/graphhopper/routing/AStarBidirectionTest.java b/core/src/test/java/com/graphhopper/routing/AStarBidirectionTest.java
index bc07cd7e4..1c1b63a3a 100644
--- a/core/src/test/java/com/graphhopper/routing/AStarBidirectionTest.java
+++ b/core/src/test/java/com/graphhopper/routing/AStarBidirectionTest.java
@@ -19,9 +19,12 @@ package com.graphhopper.routing;
 
 import com.graphhopper.routing.util.TraversalMode;
 import com.graphhopper.routing.weighting.ShortestWeighting;
+import com.graphhopper.routing.weighting.TurnWeighting;
+import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphHopperStorage;
 import com.graphhopper.storage.SPTEntry;
+import com.graphhopper.storage.TurnCostExtension;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -39,9 +42,11 @@ import static org.junit.Assert.assertEquals;
 @RunWith(Parameterized.class)
 public class AStarBidirectionTest extends AbstractRoutingAlgorithmTester {
     private final TraversalMode traversalMode;
+    private final boolean allowUTurns;
 
-    public AStarBidirectionTest(TraversalMode tMode) {
+    public AStarBidirectionTest(TraversalMode tMode, boolean allowUTurns) {
         this.traversalMode = tMode;
+        this.allowUTurns = allowUTurns;
     }
 
     /**
@@ -50,9 +55,9 @@ public class AStarBidirectionTest extends AbstractRoutingAlgorithmTester {
     @Parameters(name = "{0}")
     public static Collection<Object[]> configs() {
         return Arrays.asList(new Object[][]{
-                {TraversalMode.NODE_BASED},
-                {TraversalMode.EDGE_BASED_2DIR},
-                {TraversalMode.EDGE_BASED_2DIR_UTURN}
+                {TraversalMode.NODE_BASED, false},
+                {TraversalMode.EDGE_BASED, false},
+                {TraversalMode.EDGE_BASED, true}
         });
     }
 
@@ -61,7 +66,12 @@ public class AStarBidirectionTest extends AbstractRoutingAlgorithmTester {
         return new RoutingAlgorithmFactory() {
             @Override
             public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
-                return new AStarBidirection(g, opts.getWeighting(), traversalMode);
+                Weighting w = opts.getWeighting();
+                if (traversalMode.isEdgeBased()) {
+                    double uTurnCost = allowUTurns ? 40 : Double.POSITIVE_INFINITY;
+                    w = new TurnWeighting(w, (TurnCostExtension) g.getExtension(), uTurnCost);
+                }
+                return new AStarBidirection(g, w, traversalMode);
             }
         };
     }
diff --git a/core/src/test/java/com/graphhopper/routing/AStarTest.java b/core/src/test/java/com/graphhopper/routing/AStarTest.java
index 5f35819a0..1cfe5e698 100644
--- a/core/src/test/java/com/graphhopper/routing/AStarTest.java
+++ b/core/src/test/java/com/graphhopper/routing/AStarTest.java
@@ -18,8 +18,11 @@
 package com.graphhopper.routing;
 
 import com.graphhopper.routing.util.TraversalMode;
+import com.graphhopper.routing.weighting.TurnWeighting;
+import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphHopperStorage;
+import com.graphhopper.storage.TurnCostExtension;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
@@ -27,36 +30,43 @@ import org.junit.runners.Parameterized.Parameters;
 import java.util.Arrays;
 import java.util.Collection;
 
+
 /**
  * @author Peter Karich
  */
 @RunWith(Parameterized.class)
 public class AStarTest extends AbstractRoutingAlgorithmTester {
     private final TraversalMode traversalMode;
+    private final boolean allowUTurns;
 
-    public AStarTest(TraversalMode tMode) {
+    public AStarTest(TraversalMode tMode, boolean allowUTurns) {
         this.traversalMode = tMode;
+        this.allowUTurns = allowUTurns;
     }
 
     /**
      * Runs the same test with each of the supported traversal modes
      */
     @Parameters(name = "{0}")
-
     public static Collection<Object[]> configs() {
         return Arrays.asList(new Object[][]{
-                {TraversalMode.NODE_BASED},
-                {TraversalMode.EDGE_BASED_2DIR},
-                {TraversalMode.EDGE_BASED_2DIR_UTURN}
+                {TraversalMode.NODE_BASED, false},
+                {TraversalMode.EDGE_BASED, false},
+                {TraversalMode.EDGE_BASED, true}
         });
     }
 
     @Override
-    public RoutingAlgorithmFactory createFactory(GraphHopperStorage prepareGraph, AlgorithmOptions prepareOpts) {
+    public RoutingAlgorithmFactory createFactory(final GraphHopperStorage prepareGraph, final AlgorithmOptions prepareOpts) {
         return new RoutingAlgorithmFactory() {
             @Override
             public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
-                return new AStar(g, opts.getWeighting(), traversalMode);
+                Weighting w = opts.getWeighting();
+                if (traversalMode.isEdgeBased()) {
+                    double uTurnCost = allowUTurns ? 40 : Double.POSITIVE_INFINITY;
+                    w = new TurnWeighting(w, (TurnCostExtension) g.getExtension(), uTurnCost);
+                }
+                return new AStar(g, w, traversalMode);
             }
         };
     }
diff --git a/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java b/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java
index 8ec20d0db..1851e6bf4 100644
--- a/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java
+++ b/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java
@@ -167,7 +167,7 @@ public abstract class AbstractRoutingAlgorithmTester {
     }
 
     protected GraphHopperStorage createGHStorage(EncodingManager em, List<? extends Weighting> weightings, boolean is3D) {
-        return new GraphBuilder(em).set3D(is3D).create();
+        return new GraphBuilder(em).set3D(is3D).withTurnCosts(true).create();
     }
 
     protected GraphHopperStorage createGHStorage(boolean is3D) {
diff --git a/core/src/test/java/com/graphhopper/routing/AlternativeRouteTest.java b/core/src/test/java/com/graphhopper/routing/AlternativeRouteTest.java
index 7a55efa87..3da0516de 100644
--- a/core/src/test/java/com/graphhopper/routing/AlternativeRouteTest.java
+++ b/core/src/test/java/com/graphhopper/routing/AlternativeRouteTest.java
@@ -24,11 +24,9 @@ import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.util.TraversalMode;
 import com.graphhopper.routing.weighting.FastestWeighting;
+import com.graphhopper.routing.weighting.TurnWeighting;
 import com.graphhopper.routing.weighting.Weighting;
-import com.graphhopper.storage.Graph;
-import com.graphhopper.storage.GraphExtension;
-import com.graphhopper.storage.GraphHopperStorage;
-import com.graphhopper.storage.RAMDirectory;
+import com.graphhopper.storage.*;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -44,6 +42,8 @@ import static org.junit.Assert.*;
 public class AlternativeRouteTest {
     private final FlagEncoder carFE = new CarFlagEncoder();
     private final EncodingManager em = EncodingManager.create(carFE);
+    private final TurnCostExtension turnCostExtension = new TurnCostExtension();
+    private final Weighting weighting = new TurnWeighting(new FastestWeighting(carFE), turnCostExtension);
     private final TraversalMode traversalMode;
 
     public AlternativeRouteTest(TraversalMode tMode) {
@@ -57,12 +57,12 @@ public class AlternativeRouteTest {
     public static Collection<Object[]> configs() {
         return Arrays.asList(new Object[][]{
                 {TraversalMode.NODE_BASED},
-                {TraversalMode.EDGE_BASED_2DIR}
+                {TraversalMode.EDGE_BASED}
         });
     }
 
     public GraphHopperStorage createTestGraph(boolean fullGraph, EncodingManager tmpEM) {
-        GraphHopperStorage graph = new GraphHopperStorage(new RAMDirectory(), tmpEM, false, new GraphExtension.NoOpExtension());
+        GraphHopperStorage graph = new GraphHopperStorage(new RAMDirectory(), tmpEM, false, turnCostExtension);
         graph.create(1000);
 
         /* 9
@@ -104,8 +104,7 @@ public class AlternativeRouteTest {
     }
 
     @Test
-    public void testCalcAlternatives() throws Exception {
-        Weighting weighting = new FastestWeighting(carFE);
+    public void testCalcAlternatives() {
         GraphHopperStorage g = createTestGraph(true, em);
         AlternativeRoute altDijkstra = new AlternativeRoute(g, weighting, traversalMode);
         altDijkstra.setMaxShareFactor(0.5);
@@ -133,8 +132,7 @@ public class AlternativeRouteTest {
     }
 
     @Test
-    public void testCalcAlternatives2() throws Exception {
-        Weighting weighting = new FastestWeighting(carFE);
+    public void testCalcAlternatives2() {
         Graph g = createTestGraph(true, em);
         AlternativeRoute altDijkstra = new AlternativeRoute(g, weighting, traversalMode);
         altDijkstra.setMaxPaths(3);
@@ -155,17 +153,17 @@ public class AlternativeRouteTest {
         assertEquals(2416.0, pathInfos.get(2).getPath().getWeight(), .1);
     }
 
-    void checkAlternatives(List<AlternativeRoute.AlternativeInfo> alternativeInfos) {
+    private void checkAlternatives(List<AlternativeRoute.AlternativeInfo> alternativeInfos) {
         assertFalse("alternativeInfos should contain alternatives", alternativeInfos.isEmpty());
         AlternativeRoute.AlternativeInfo bestInfo = alternativeInfos.get(0);
         for (int i = 1; i < alternativeInfos.size(); i++) {
             AlternativeRoute.AlternativeInfo a = alternativeInfos.get(i);
             if (a.getPath().getWeight() < bestInfo.getPath().getWeight())
-                assertTrue("alternative is not longer -> " + a + " vs " + bestInfo, false);
+                fail("alternative is not longer -> " + a + " vs " + bestInfo);
 
             if (a.getShareWeight() > bestInfo.getPath().getWeight()
                     || a.getShareWeight() > a.getPath().getWeight())
-                assertTrue("share or sortby incorrect -> " + a + " vs " + bestInfo, false);
+                fail("share or sortby incorrect -> " + a + " vs " + bestInfo);
         }
     }
 
diff --git a/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionEdgeCHTest.java b/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionEdgeCHTest.java
index ef8a65605..ed84bb20f 100644
--- a/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionEdgeCHTest.java
+++ b/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionEdgeCHTest.java
@@ -43,7 +43,7 @@ public class DijkstraBidirectionEdgeCHTest extends AbstractRoutingAlgorithmTeste
     public RoutingAlgorithmFactory createFactory(GraphHopperStorage ghStorage, AlgorithmOptions opts) {
         ghStorage.freeze();
         PrepareContractionHierarchies ch = PrepareContractionHierarchies.fromGraphHopperStorage(
-                ghStorage, opts.getWeighting(), TraversalMode.EDGE_BASED_2DIR);
+                ghStorage, opts.getWeighting(), TraversalMode.EDGE_BASED);
         ch.doWork();
         return ch;
     }
diff --git a/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionRefTest.java b/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionRefTest.java
index 617ddc249..b405cc9f4 100644
--- a/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionRefTest.java
+++ b/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionRefTest.java
@@ -18,8 +18,11 @@
 package com.graphhopper.routing;
 
 import com.graphhopper.routing.util.TraversalMode;
+import com.graphhopper.routing.weighting.TurnWeighting;
+import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphHopperStorage;
+import com.graphhopper.storage.TurnCostExtension;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
@@ -33,9 +36,11 @@ import java.util.Collection;
 @RunWith(Parameterized.class)
 public class DijkstraBidirectionRefTest extends AbstractRoutingAlgorithmTester {
     private final TraversalMode traversalMode;
+    private final boolean allowUTurns;
 
-    public DijkstraBidirectionRefTest(TraversalMode tMode) {
+    public DijkstraBidirectionRefTest(TraversalMode tMode, boolean allowUTurns) {
         this.traversalMode = tMode;
+        this.allowUTurns = allowUTurns;
     }
 
     /**
@@ -44,9 +49,9 @@ public class DijkstraBidirectionRefTest extends AbstractRoutingAlgorithmTester {
     @Parameters(name = "{0}")
     public static Collection<Object[]> configs() {
         return Arrays.asList(new Object[][]{
-                {TraversalMode.NODE_BASED},
-                {TraversalMode.EDGE_BASED_2DIR},
-                {TraversalMode.EDGE_BASED_2DIR_UTURN}
+                {TraversalMode.NODE_BASED, false},
+                {TraversalMode.EDGE_BASED, false},
+                {TraversalMode.EDGE_BASED, true}
         });
     }
 
@@ -55,7 +60,12 @@ public class DijkstraBidirectionRefTest extends AbstractRoutingAlgorithmTester {
         return new RoutingAlgorithmFactory() {
             @Override
             public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
-                return new DijkstraBidirectionRef(g, opts.getWeighting(), traversalMode);
+                Weighting w = opts.getWeighting();
+                if (traversalMode.isEdgeBased()) {
+                    double uTurnCost = allowUTurns ? 40 : Double.POSITIVE_INFINITY;
+                    w = new TurnWeighting(w, (TurnCostExtension) g.getExtension(), uTurnCost);
+                }
+                return new DijkstraBidirectionRef(g, w, traversalMode);
             }
         };
     }
diff --git a/core/src/test/java/com/graphhopper/routing/DijkstraOneToManyTest.java b/core/src/test/java/com/graphhopper/routing/DijkstraOneToManyTest.java
index c3780d2f2..158867463 100644
--- a/core/src/test/java/com/graphhopper/routing/DijkstraOneToManyTest.java
+++ b/core/src/test/java/com/graphhopper/routing/DijkstraOneToManyTest.java
@@ -55,9 +55,8 @@ public class DijkstraOneToManyTest extends AbstractRoutingAlgorithmTester {
         return Arrays.asList(new Object[][]{
                 {
                         TraversalMode.NODE_BASED
-                }, //            TODO { TraversalMode.EDGE_BASED_1DIR },
-                //            TODO { TraversalMode.EDGE_BASED_2DIR },
-                //            TODO { TraversalMode.EDGE_BASED_2DIR_UTURN }
+                },
+                //            TODO { TraversalMode.EDGE_BASED },
         });
     }
 
diff --git a/core/src/test/java/com/graphhopper/routing/DijkstraTest.java b/core/src/test/java/com/graphhopper/routing/DijkstraTest.java
index 2ba58ff0e..0eee6f0cd 100644
--- a/core/src/test/java/com/graphhopper/routing/DijkstraTest.java
+++ b/core/src/test/java/com/graphhopper/routing/DijkstraTest.java
@@ -18,8 +18,11 @@
 package com.graphhopper.routing;
 
 import com.graphhopper.routing.util.TraversalMode;
+import com.graphhopper.routing.weighting.TurnWeighting;
+import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphHopperStorage;
+import com.graphhopper.storage.TurnCostExtension;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
@@ -33,9 +36,11 @@ import java.util.Collection;
 @RunWith(Parameterized.class)
 public class DijkstraTest extends AbstractRoutingAlgorithmTester {
     private final TraversalMode traversalMode;
+    private final boolean allowUTurns;
 
-    public DijkstraTest(TraversalMode tMode) {
+    public DijkstraTest(TraversalMode tMode, boolean allowUTurns) {
         this.traversalMode = tMode;
+        this.allowUTurns = allowUTurns;
     }
 
     /**
@@ -44,9 +49,9 @@ public class DijkstraTest extends AbstractRoutingAlgorithmTester {
     @Parameters(name = "{0}")
     public static Collection<Object[]> configs() {
         return Arrays.asList(new Object[][]{
-                {TraversalMode.NODE_BASED},
-                {TraversalMode.EDGE_BASED_2DIR},
-                {TraversalMode.EDGE_BASED_2DIR_UTURN}
+                {TraversalMode.NODE_BASED, false},
+                {TraversalMode.EDGE_BASED, false},
+                {TraversalMode.EDGE_BASED, true}
         });
     }
 
@@ -55,7 +60,12 @@ public class DijkstraTest extends AbstractRoutingAlgorithmTester {
         return new RoutingAlgorithmFactory() {
             @Override
             public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
-                return new Dijkstra(g, opts.getWeighting(), traversalMode);
+                Weighting w = opts.getWeighting();
+                if (traversalMode.isEdgeBased()) {
+                    double uTurnCost = allowUTurns ? 40 : Double.POSITIVE_INFINITY;
+                    w = new TurnWeighting(w, (TurnCostExtension) g.getExtension(), uTurnCost);
+                }
+                return new Dijkstra(g, w, traversalMode);
             }
         };
     }
diff --git a/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java b/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java
index 9b3e95f75..97b87e2de 100644
--- a/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java
+++ b/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java
@@ -39,8 +39,7 @@ import org.junit.runners.Parameterized.Parameters;
 
 import java.util.*;
 
-import static com.graphhopper.routing.util.TraversalMode.EDGE_BASED_2DIR;
-import static com.graphhopper.routing.util.TraversalMode.EDGE_BASED_2DIR_UTURN;
+import static com.graphhopper.routing.util.TraversalMode.EDGE_BASED;
 import static com.graphhopper.util.GHUtility.getEdge;
 import static com.graphhopper.util.Parameters.Algorithms.*;
 import static org.junit.Assert.*;
@@ -99,7 +98,7 @@ public class EdgeBasedRoutingAlgorithmTest {
     }
 
     public Path calcPath(Graph g, int from, int to) {
-        return createAlgo(g, createWeighting(), EDGE_BASED_2DIR).calcPath(from, to);
+        return createAlgo(g, createWeighting(), EDGE_BASED).calcPath(from, to);
     }
 
     public RoutingAlgorithm createAlgo(Graph g, Weighting weighting, TraversalMode traversalMode) {
@@ -143,11 +142,11 @@ public class EdgeBasedRoutingAlgorithmTest {
     }
 
     private Weighting createWeighting() {
-        return createWeighting(carEncoder, 40);
+        return createWeighting(carEncoder, Double.POSITIVE_INFINITY);
     }
 
     private Weighting createWeighting(FlagEncoder encoder, double uTurnCosts) {
-        return new TurnWeighting(new FastestWeighting(encoder), tcs).setDefaultUTurnCost(uTurnCosts);
+        return new TurnWeighting(new FastestWeighting(encoder), tcs, uTurnCosts);
     }
 
     @Test
@@ -166,7 +165,7 @@ public class EdgeBasedRoutingAlgorithmTest {
             int from = rnd.nextInt(g.getNodes());
             int to = rnd.nextInt(g.getNodes());
             Weighting w = createWeighting();
-            RoutingAlgorithm refAlgo = new Dijkstra(g, w, EDGE_BASED_2DIR);
+            RoutingAlgorithm refAlgo = new Dijkstra(g, w, EDGE_BASED);
             Path refPath = refAlgo.calcPath(from, to);
             double refWeight = refPath.getWeight();
             if (!refPath.isFound()) {
@@ -311,29 +310,29 @@ public class EdgeBasedRoutingAlgorithmTest {
         GraphHopperStorage g = createStorage(createEncodingManager(true));
         initGraph(g);
 
-        // force u-turn at node 3 via lowering the cost for it
+        // force u-turn at node 3 by using finite u-turn costs
         getEdge(g, 3, 6).setDistance(0.1);
         getEdge(g, 3, 2).setDistance(864);
         getEdge(g, 1, 0).setDistance(864);
 
         addTurnRestriction(g, 7, 6, 5);
         addTurnRestriction(g, 4, 3, 6);
-        Path p = createAlgo(g, createWeighting(carEncoder, 50), EDGE_BASED_2DIR_UTURN).calcPath(7, 5);
+        Path p = createAlgo(g, createWeighting(carEncoder, 50), EDGE_BASED).calcPath(7, 5);
 
         assertEquals(2 + 2 * 0.1, p.getDistance(), 1.e-6);
         assertEquals(2.2 * 0.06 + 50, p.getWeight(), 1.e-6);
         assertEquals((2.2 * 0.06 + 50) * 1000, p.getTime(), 1.e-6);
         assertEquals(IntArrayList.from(7, 6, 3, 6, 5), p.calcNodes());
 
-        // without u-turn mode enabled we need to take an expensive detour
+        // with default infinite u-turn costs we need to take an expensive detour
         p = calcPath(g, 7, 5);
         assertEquals(1.1 + 864 + 0.5, p.getDistance(), 1.e-6);
         assertEquals(865.6 * 0.06, p.getWeight(), 1.e-6);
         assertEquals(IntArrayList.from(7, 6, 3, 2, 5), p.calcNodes());
 
-        // no more u-turn 6-3-6 -> now we have to take the expensive roads even with u-turn mode
+        // no more u-turn 6-3-6 -> now we have to take the expensive roads even with finite u-turn costs
         addTurnRestriction(g, 6, 3, 6);
-        p = createAlgo(g, createWeighting(carEncoder, 100), EDGE_BASED_2DIR_UTURN).calcPath(7, 5);
+        p = createAlgo(g, createWeighting(carEncoder, 100), EDGE_BASED).calcPath(7, 5);
 
         assertEquals(1.1 + 864 + 0.5, p.getDistance(), 1.e-6);
         assertEquals(865.6 * 0.06, p.getWeight(), 1.e-6);
@@ -355,16 +354,16 @@ public class EdgeBasedRoutingAlgorithmTest {
         // cannot go straight at node 2
         addTurnRestriction(g, 1, 2, 4);
 
-        // without u-turn mode there is no shortest path
+        // with default/infinite u-turn costs there is no shortest path
         {
             Path path = calcPath(g, 0, 5);
             assertFalse(path.isFound());
         }
 
-        // with u-turn mode enabled it is possible, the u-turn costs should be included
+        // with finite u-turn costs it is possible, the u-turn costs should be included
         // here we make sure the default u-turn time is also included at the meeting node for bidir algos
         {
-            Path path = createAlgo(g, createWeighting(carEncoder, 67), EDGE_BASED_2DIR_UTURN).calcPath(0, 5);
+            Path path = createAlgo(g, createWeighting(carEncoder, 67), EDGE_BASED).calcPath(0, 5);
             assertEquals(60, path.getDistance(), 1.e-6);
             assertEquals(60 * 0.06 + 67, path.getWeight(), 1.e-6);
             assertEquals((36 + 670) * 100, path.getTime(), 1.e-6);
@@ -407,8 +406,8 @@ public class EdgeBasedRoutingAlgorithmTest {
                     assertNotNull("edge " + edgeTo + " to " + nodeVia + " does not exist", g.getEdgeIteratorState(edgeTo, nodeVia));
                 return super.calcTurnWeight(edgeFrom, nodeVia, edgeTo);
             }
-        }.setDefaultUTurnCost(40);
-        Path p = createAlgo(g, weighting, EDGE_BASED_2DIR).calcPath(5, 1);
+        };
+        Path p = createAlgo(g, weighting, EDGE_BASED).calcPath(5, 1);
         assertEquals(IntArrayList.from(5, 6, 7, 4, 3, 1), p.calcNodes());
         assertEquals(5 * 0.06 + 1, p.getWeight(), 1.e-6);
         assertEquals(1300, p.getTime(), .1);
diff --git a/core/src/test/java/com/graphhopper/routing/RandomCHRoutingTest.java b/core/src/test/java/com/graphhopper/routing/RandomCHRoutingTest.java
index 20fe67a9c..c8e7e5f60 100644
--- a/core/src/test/java/com/graphhopper/routing/RandomCHRoutingTest.java
+++ b/core/src/test/java/com/graphhopper/routing/RandomCHRoutingTest.java
@@ -45,7 +45,7 @@ public class RandomCHRoutingTest {
     public static Object[] params() {
         return new Object[]{
                 TraversalMode.NODE_BASED,
-                TraversalMode.EDGE_BASED_2DIR
+                TraversalMode.EDGE_BASED
         };
     }
 
diff --git a/core/src/test/java/com/graphhopper/routing/ch/CHAlgoFactoryDecoratorTest.java b/core/src/test/java/com/graphhopper/routing/ch/CHAlgoFactoryDecoratorTest.java
index 38360de6c..b3915467b 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/CHAlgoFactoryDecoratorTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/CHAlgoFactoryDecoratorTest.java
@@ -35,7 +35,7 @@ import org.junit.Test;
 import java.util.Arrays;
 import java.util.List;
 
-import static com.graphhopper.routing.util.TraversalMode.EDGE_BASED_2DIR;
+import static com.graphhopper.routing.util.TraversalMode.EDGE_BASED;
 import static com.graphhopper.routing.util.TraversalMode.NODE_BASED;
 import static org.junit.Assert.*;
 
@@ -134,7 +134,7 @@ public class CHAlgoFactoryDecoratorTest {
     }
 
     private PrepareContractionHierarchies createPreparation(Weighting weighting, boolean edgedBased) {
-        TraversalMode traversalMode = edgedBased ? EDGE_BASED_2DIR : NODE_BASED;
+        TraversalMode traversalMode = edgedBased ? EDGE_BASED : NODE_BASED;
         return PrepareContractionHierarchies.fromGraphHopperStorage(ghStorage, weighting, traversalMode);
     }
 
diff --git a/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java b/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java
index 20b425e28..2a255c20e 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java
@@ -794,7 +794,7 @@ public class CHTurnCostTest {
         QueryGraph queryGraph = new QueryGraph(chGraph);
         queryGraph.lookup(queryResults);
         RoutingAlgorithm chAlgo = pch.createAlgo(queryGraph, AlgorithmOptions.start()
-                .traversalMode(TraversalMode.EDGE_BASED_2DIR)
+                .traversalMode(TraversalMode.EDGE_BASED)
                 .build());
         Path path = chAlgo.calcPath(5, 6);
         // there should not be a path from 5 to 6, because first we cannot go directly 5-4-6, so we need to go left
@@ -843,7 +843,7 @@ public class CHTurnCostTest {
         queryGraph.lookup(Collections.singletonList(qr));
         assertEquals("expected one virtual node", 1, queryGraph.getNodes() - chGraph.getNodes());
         RoutingAlgorithm chAlgo = pch.createAlgo(queryGraph, AlgorithmOptions.start()
-                .traversalMode(TraversalMode.EDGE_BASED_2DIR)
+                .traversalMode(TraversalMode.EDGE_BASED)
                 .build());
         Path path = chAlgo.calcPath(2, 1);
         assertFalse("no path should be found, but found " + path.calcNodes(), path.isFound());
@@ -878,7 +878,7 @@ public class CHTurnCostTest {
         assertEquals(2, qr1.getClosestNode());
         assertEquals(3, qr2.getClosestNode());
         RoutingAlgorithm chAlgo = pch.createAlgo(queryGraph, AlgorithmOptions.start()
-                .traversalMode(TraversalMode.EDGE_BASED_2DIR)
+                .traversalMode(TraversalMode.EDGE_BASED)
                 .build());
         Path path = chAlgo.calcPath(2, 3);
         assertTrue("no path found", path.isFound());
@@ -905,7 +905,7 @@ public class CHTurnCostTest {
         assertEquals(3, qr.getClosestNode());
         assertEquals(0, qr.getClosestEdge().getEdge());
         RoutingAlgorithm chAlgo = pch.createAlgo(queryGraph, AlgorithmOptions.start()
-                .traversalMode(TraversalMode.EDGE_BASED_2DIR)
+                .traversalMode(TraversalMode.EDGE_BASED)
                 .build());
         Path path = chAlgo.calcPath(0, 2);
         assertTrue("it should be possible to route via a virtual node, but no path found", path.isFound());
@@ -935,7 +935,7 @@ public class CHTurnCostTest {
         assertEquals(3, qr.getClosestNode());
         assertEquals(0, qr.getClosestEdge().getEdge());
         RoutingAlgorithm chAlgo = pch.createAlgo(queryGraph, AlgorithmOptions.start()
-                .traversalMode(TraversalMode.EDGE_BASED_2DIR)
+                .traversalMode(TraversalMode.EDGE_BASED)
                 .build());
         Path path = chAlgo.calcPath(1, 0);
         assertEquals(IntArrayList.from(1, 3, 0), path.calcNodes());
@@ -1018,7 +1018,7 @@ public class CHTurnCostTest {
     }
 
     private Path findPathUsingDijkstra(int from, int to) {
-        Dijkstra dijkstra = new Dijkstra(graph, turnWeighting, TraversalMode.EDGE_BASED_2DIR);
+        Dijkstra dijkstra = new Dijkstra(graph, turnWeighting, TraversalMode.EDGE_BASED);
         return dijkstra.calcPath(from, to);
     }
 
@@ -1042,7 +1042,7 @@ public class CHTurnCostTest {
                 return contractionOrder.size();
             }
         };
-        PrepareContractionHierarchies ch = new PrepareContractionHierarchies(chGraph, weighting, TraversalMode.EDGE_BASED_2DIR)
+        PrepareContractionHierarchies ch = new PrepareContractionHierarchies(chGraph, weighting, TraversalMode.EDGE_BASED)
                 .useFixedNodeOrdering(nodeOrderingProvider);
         ch.doWork();
         return ch;
@@ -1055,7 +1055,7 @@ public class CHTurnCostTest {
         pMap.put(NEIGHBOR_UPDATES, 4);
         pMap.put(LOG_MESSAGES, 10);
         PrepareContractionHierarchies ch = new PrepareContractionHierarchies(
-                chGraph, weighting, TraversalMode.EDGE_BASED_2DIR);
+                chGraph, weighting, TraversalMode.EDGE_BASED);
         ch.setParams(pMap);
         ch.doWork();
         return ch;
diff --git a/core/src/test/java/com/graphhopper/routing/template/RoundTripRoutingTemplateTest.java b/core/src/test/java/com/graphhopper/routing/template/RoundTripRoutingTemplateTest.java
index ea913eb2b..57d62929d 100644
--- a/core/src/test/java/com/graphhopper/routing/template/RoundTripRoutingTemplateTest.java
+++ b/core/src/test/java/com/graphhopper/routing/template/RoundTripRoutingTemplateTest.java
@@ -49,7 +49,7 @@ import static org.junit.Assert.assertEquals;
 public class RoundTripRoutingTemplateTest {
     private final FlagEncoder carFE = new CarFlagEncoder();
     private final EncodingManager em = EncodingManager.create(carFE);
-    // TODO private final TraversalMode tMode = TraversalMode.EDGE_BASED_2DIR;
+    // TODO private final TraversalMode tMode = TraversalMode.EDGE_BASED;
     private final TraversalMode tMode = TraversalMode.NODE_BASED;
     private final GHPoint ghPoint1 = new GHPoint(0, 0);
     private final GHPoint ghPoint2 = new GHPoint(1, 1);
diff --git a/core/src/test/java/com/graphhopper/routing/weighting/TurnWeightingTest.java b/core/src/test/java/com/graphhopper/routing/weighting/TurnWeightingTest.java
index e4206fcf7..99163de6e 100644
--- a/core/src/test/java/com/graphhopper/routing/weighting/TurnWeightingTest.java
+++ b/core/src/test/java/com/graphhopper/routing/weighting/TurnWeightingTest.java
@@ -45,7 +45,7 @@ public class TurnWeightingTest {
     public void calcWeightAndTime_defaultUTurn() {
         // for u-turns default costs get applied
         EdgeIteratorState edge = graph.edge(0, 1, 100, true);
-        TurnWeighting turnWeighting = new TurnWeighting(weighting, turnCostExt);
+        TurnWeighting turnWeighting = new TurnWeighting(weighting, turnCostExt, 40);
         assertEquals(6 + 40, turnWeighting.calcWeight(edge, false, 0), 1.e-6);
         assertEquals((6 + 40) * 1000, turnWeighting.calcMillis(edge, false, 0), 1.e-6);
     }
diff --git a/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java b/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java
index 9ce917bde..11c888d1b 100644
--- a/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java
+++ b/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java
@@ -35,7 +35,7 @@ public class ShortcutUnpackerTest {
     public static Object[] params() {
         return new Object[]{
                 TraversalMode.NODE_BASED,
-                TraversalMode.EDGE_BASED_2DIR
+                TraversalMode.EDGE_BASED
         };
     }
 
@@ -259,7 +259,7 @@ public class ShortcutUnpackerTest {
             // unpack the shortcut 0->6, traverse original edges in 'forward' order (from node 0 to 6)
             TurnWeightingVisitor visitor = new TurnWeightingVisitor();
             new ShortcutUnpacker(chGraph, visitor, edgeBased).visitOriginalEdgesFwd(10, 6, false, PREV_EDGE);
-            assertEquals("wrong weight", 6 * 0.06, visitor.weight, 1.e-3);
+            assertEquals("wrong weight", 6 * 0.06 + 17, visitor.weight, 1.e-3);
             assertEquals("wrong time", (6 * 60 + 17000), visitor.time);
         }
 
@@ -267,7 +267,7 @@ public class ShortcutUnpackerTest {
             // unpack the shortcut 0->6, traverse original edges in 'backward' order (from node 6 to 0)
             TurnWeightingVisitor visitor = new TurnWeightingVisitor();
             new ShortcutUnpacker(chGraph, visitor, edgeBased).visitOriginalEdgesFwd(10, 6, true, PREV_EDGE);
-            assertEquals("wrong weight", 6 * 0.06, visitor.weight, 1.e-3);
+            assertEquals("wrong weight", 6 * 0.06 + 17, visitor.weight, 1.e-3);
             assertEquals("wrong time", (6 * 60 + 17000), visitor.time);
         }
 
@@ -275,7 +275,7 @@ public class ShortcutUnpackerTest {
             // unpack the shortcut 6<-0, traverse original edges in 'forward' order (from node 6 to 0)
             TurnWeightingVisitor visitor = new TurnWeightingVisitor();
             new ShortcutUnpacker(chGraph, visitor, edgeBased).visitOriginalEdgesBwd(10, 0, false, NEXT_EDGE);
-            assertEquals("wrong weight", 6 * 0.06, visitor.weight, 1.e-3);
+            assertEquals("wrong weight", 6 * 0.06 + 21, visitor.weight, 1.e-3);
             assertEquals("wrong time", (6 * 60 + 21000), visitor.time);
         }
 
@@ -283,7 +283,7 @@ public class ShortcutUnpackerTest {
             // unpack the shortcut 6<-0, traverse original edges in 'backward' order (from node 0 to 6)
             TurnWeightingVisitor visitor = new TurnWeightingVisitor();
             new ShortcutUnpacker(chGraph, visitor, edgeBased).visitOriginalEdgesBwd(10, 0, true, NEXT_EDGE);
-            assertEquals("wrong weight", 6 * 0.06, visitor.weight, 1.e-3);
+            assertEquals("wrong weight", 6 * 0.06 + 21, visitor.weight, 1.e-3);
             assertEquals("wrong time", (6 * 60 + 21000), visitor.time);
         }
     }
@@ -332,7 +332,7 @@ public class ShortcutUnpackerTest {
         @Override
         public void visit(EdgeIteratorState edge, boolean reverse, int prevOrNextEdgeId) {
             time += turnWeighting.calcMillis(edge, reverse, prevOrNextEdgeId);
-            weight += weighting.calcWeight(edge, reverse, prevOrNextEdgeId);
+            weight += turnWeighting.calcWeight(edge, reverse, prevOrNextEdgeId);
         }
     }
 }
\ No newline at end of file
diff --git a/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java b/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java
index a6c8551f9..1ea121c3d 100644
--- a/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java
+++ b/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java
@@ -580,7 +580,7 @@ public class RoutingAlgorithmWithOSMIT {
             hopper.importOrLoad();
 
             TraversalMode tMode = importVehicles.contains("turn_costs=true")
-                    ? TraversalMode.EDGE_BASED_2DIR : TraversalMode.NODE_BASED;
+                    ? TraversalMode.EDGE_BASED : TraversalMode.NODE_BASED;
             FlagEncoder encoder = hopper.getEncodingManager().getEncoder(vehicle);
             HintsMap hints = new HintsMap().setWeighting(weightStr).setVehicle(vehicle);