diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 13a570e46..c4e3f3be4 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -150,7 +150,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( edgeBasedNodes.push_back(currentNode); } -void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { +void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State *myLuaState) { Percent p(_nodeBasedGraph->GetNumberOfNodes()); int numberOfSkippedTurns(0); int nodeBasedEdgeCounter(0); @@ -273,15 +273,16 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { if(_trafficLights.find(v) != _trafficLights.end()) { distance += speedProfile.trafficSignalPenalty; } - TurnInstruction turnInstruction = AnalyzeTurn(u, v, w); - if(TurnInstructions.UTurn == turnInstruction) { + unsigned penalty = 0; + TurnInstruction turnInstruction = AnalyzeTurn(u, v, w, penalty, myLuaState); + if(turnInstruction == TurnInstructions.UTurn) distance += speedProfile.uTurnPenalty; - } // if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) { // distance += TurnInstructions.AccessRestrictionPenalty; // turnInstruction |= TurnInstructions.AccessRestrictionFlag; // } - + distance += penalty; + //distance += heightPenalty; //distance += ComputeTurnPenalty(u, v, w); @@ -325,7 +326,21 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { INFO("Generated " << edgeBasedNodes.size() << " edge based nodes"); } -TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const { +TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const { + double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); + + if( speedProfile.has_turn_function ) { + try { + //call lua profile to compute turn penalty + penalty = luabind::call_function( myLuaState, "turn_function", 180-angle ); + } catch (const luabind::error &er) { + std::cerr << er.what() << std::endl; + //TODO handle lua errors + } + } else { + penalty = 0; + } + if(u == w) { return TurnInstructions.UTurn; } @@ -371,7 +386,6 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID return TurnInstructions.NoTurn; } - double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); return TurnInstructions.GetTurnDirectionOfInstruction(angle); } diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 1198ae971..76390fbc5 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -50,6 +50,14 @@ #include "../DataStructures/TurnInstructions.h" #include "../Util/BaseConfiguration.h" +extern "C" { +#include +#include +#include +} +#include + + class EdgeBasedGraphFactory : boost::noncopyable { public: struct EdgeBasedNode { @@ -71,9 +79,10 @@ public: }; struct SpeedProfileProperties{ - SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {} + SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_function(false) {} int trafficSignalPenalty; int uTurnPenalty; + bool has_turn_function; } speedProfile; private: @@ -133,10 +142,11 @@ public: template< class InputEdgeT > explicit EdgeBasedGraphFactory(int nodes, std::vector & inputEdges, std::vector & _bollardNodes, std::vector & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector & nI, SpeedProfileProperties speedProfile); - void Run(const char * originalEdgeDataFilename); + void Run(const char * originalEdgeDataFilename, lua_State *myLuaState); void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes); - TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const; + void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData); + TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const; unsigned GetNumberOfNodes() const; }; diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 806164132..04ade55f4 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -133,7 +133,10 @@ int main (int argc, char *argv[]) { ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); } speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1); - + + speedProfile.has_turn_function = lua_function_exists( myLuaState, "turn_function" ); + + std::vector edgeList; NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions); in.close(); INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights"); @@ -148,7 +151,7 @@ int main (int argc, char *argv[]) { INFO("Generating edge-expanded graph representation"); EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile); std::vector().swap(edgeList); - edgeBasedGraphFactory->Run(edgeOut.c_str()); + edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState); std::vector<_Restriction>().swap(inputRestrictions); std::vector().swap(bollardNodes); std::vector().swap(trafficLightNodes); diff --git a/features/bicycle/ferry.feature b/features/bicycle/ferry.feature index 87d9773c9..5d67df7ea 100644 --- a/features/bicycle/ferry.feature +++ b/features/bicycle/ferry.feature @@ -58,6 +58,6 @@ Feature: Bike - Handle ferry routes | abcd | | ferry | yes | 1:00 | When I route I should get - | from | to | route | time | - | a | d | abcd | 3600s +-1 | - | d | a | abcd | 3600s +-1 | \ No newline at end of file + | from | to | route | time | + | a | d | abcd | 3600s +-10 | + | d | a | abcd | 3600s +-10 | diff --git a/features/bicycle/turn_penalty.feature b/features/bicycle/turn_penalty.feature new file mode 100644 index 000000000..157cbf2d6 --- /dev/null +++ b/features/bicycle/turn_penalty.feature @@ -0,0 +1,33 @@ +@routing @bicycle @turn_penalty +Feature: Turn Penalties + + Background: + Given the profile "turnbot" + + Scenario: Bike - turns should incur a delay that depend on the angle + + Given the node map + | c | d | e | + | b | j | f | + | a | s | g | + + And the ways + | nodes | + | sj | + | ja | + | jb | + | jc | + | jd | + | je | + | jf | + | jg | + + When I route I should get + | from | to | route | time | distance | + | s | a | sj,ja | 39s +-1 | 242m +-1 | + | s | b | sj,jb | 30s +-1 | 200m +-1 | + | s | c | sj,jc | 29s +-1 | 242m +-1 | + | s | d | sj,jd | 20s +-1 | 200m +-1 | + | s | e | sj,je | 29s +-1 | 242m +-1 | + | s | f | sj,jf | 30s +-1 | 200m +-1 | + | s | g | sj,jg | 39s +-1 | 242m +-1 | \ No newline at end of file diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 0fba9e730..96c06b555 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -73,6 +73,8 @@ ignore_areas = true -- future feature traffic_signal_penalty = 5 u_turn_penalty = 20 use_turn_restrictions = false +turn_penalty = 60 +turn_bias = 1.4 -- End of globals function get_exceptions(vector) @@ -308,3 +310,13 @@ function way_function (way) way.type = 1 return 1 end + +function turn_function (angle) + -- compute turn penalty as angle^2, with a left/right bias + k = turn_penalty/(90.0*90.0) + if angle>=0 then + return angle*angle*k/turn_bias + else + return angle*angle*k*turn_bias + end +end diff --git a/profiles/turnbot.lua b/profiles/turnbot.lua new file mode 100644 index 000000000..1a96966f1 --- /dev/null +++ b/profiles/turnbot.lua @@ -0,0 +1,8 @@ +-- Testbot, with turn penalty +-- Used for testing turn penalties + +require 'testbot' + +function turn_function (angle) + return 200*math.abs(angle)/180 -- penalty +end