Merge branch 'develop'

This commit is contained in:
Dennis Luxen 2012-12-24 10:35:51 +01:00
commit 6574436c33
87 changed files with 786 additions and 690 deletions

View File

@ -41,7 +41,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "../DataStructures/NodeCoords.h" #include "../DataStructures/NodeCoords.h"
#include "../DataStructures/Percent.h" #include "../DataStructures/Percent.h"
#include "../DataStructures/Restriction.h" #include "../DataStructures/Restriction.h"
#include "../DataStructures/TurnInstructions.h"
// Strongly connected components using Tarjan's Algorithm // Strongly connected components using Tarjan's Algorithm
@ -66,7 +66,7 @@ private:
unsigned nameID; unsigned nameID;
bool forward; bool forward;
bool backward; bool backward;
short turnInstruction; TurnInstruction turnInstruction;
}; };
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;

View File

@ -60,7 +60,7 @@ public:
NodeID via; NodeID via;
unsigned nameID; unsigned nameID;
int distance; int distance;
short turnInstruction; TurnInstruction turnInstruction;
bool shortcut:1; bool shortcut:1;
bool forward:1; bool forward:1;
bool backward:1; bool backward:1;

View File

@ -122,8 +122,7 @@ public:
assert( newEdge.data.distance > 0 ); assert( newEdge.data.distance > 0 );
#ifndef NDEBUG #ifndef NDEBUG
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) { if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
std::cout << "Edge Weight too large -> May lead to invalid CH" << std::endl; WARN("Edge weight large -> " << newEdge.data.distance);
continue;
} }
#endif #endif
edges.push_back( newEdge ); edges.push_back( newEdge );

View File

@ -95,8 +95,6 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdg
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) { void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty"); GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
GUARANTEE(0 != edgeBasedEdges.size(), "No edges in edge based graph");
edgeBasedEdges.swap(outputEdgeList); edgeBasedEdges.swap(outputEdgeList);
} }
@ -280,7 +278,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
if(_trafficLights.find(v) != _trafficLights.end()) { if(_trafficLights.find(v) != _trafficLights.end()) {
distance += speedProfile.trafficSignalPenalty; distance += speedProfile.trafficSignalPenalty;
} }
short turnInstruction = AnalyzeTurn(u, v, w); TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
if(turnInstruction == TurnInstructions.UTurn) if(turnInstruction == TurnInstructions.UTurn)
distance += speedProfile.uTurnPenalty; distance += speedProfile.uTurnPenalty;
// if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) { // if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
@ -297,7 +295,6 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
} }
OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction); OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction);
EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false ); EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false );
assert(u != w);
originalEdgeData.push_back(oed); originalEdgeData.push_back(oed);
if(originalEdgeData.size() > 100000) { if(originalEdgeData.size() > 100000) {
originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData)); originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
@ -334,7 +331,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
INFO("Generated " << edgeBasedNodes.size() << " edge based nodes"); INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
} }
short EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const { TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const {
if(u == w) { if(u == w) {
return TurnInstructions.UTurn; return TurnInstructions.UTurn;
} }

View File

@ -69,7 +69,7 @@ private:
unsigned nameID; unsigned nameID;
bool forward; bool forward;
bool backward; bool backward;
short turnInstruction; TurnInstruction turnInstruction;
}; };
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
@ -138,7 +138,7 @@ public:
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes); void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes);
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData); void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
short AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const; TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
unsigned GetNumberOfNodes() const; unsigned GetNumberOfNodes() const;
}; };

View File

@ -57,23 +57,7 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
assert(lon1 != INT_MIN); assert(lon1 != INT_MIN);
assert(lat2 != INT_MIN); assert(lat2 != INT_MIN);
assert(lon2 != INT_MIN); assert(lon2 != INT_MIN);
// static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
// //Earth's quatratic mean radius for WGS-84
// static const double EARTH_RADIUS_IN_METERS = 6372797.560856;
// double latitudeArc = ( lat1/100000. - lat2/100000. ) * DEG_TO_RAD;
// double longitudeArc = ( lon1/100000. - lon2/100000. ) * DEG_TO_RAD;
// double latitudeH = sin( latitudeArc * 0.5 );
// latitudeH *= latitudeH;
// double lontitudeH = sin( longitudeArc * 0.5 );
// lontitudeH *= lontitudeH;
// double tmp = cos( lat1/100000. * DEG_TO_RAD ) * cos( lat2/100000. * DEG_TO_RAD );
// double distanceArc = 2.0 * asin( sqrt( latitudeH + tmp * lontitudeH ) );
// return EARTH_RADIUS_IN_METERS * distanceArc;
//double PI = 3.14159265358979323846;//4.0*atan(1.0);
double RAD = 0.017453292519943295769236907684886; double RAD = 0.017453292519943295769236907684886;
//std::cout << "RAD: " << RAD << std::endl;
//main code inside the class
double lt1 = lat1/100000.; double lt1 = lat1/100000.;
double ln1 = lon1/100000.; double ln1 = lon1/100000.;
double lt2 = lat2/100000.; double lt2 = lat2/100000.;
@ -94,12 +78,29 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
const double earth=6372797.560856;//I am doing miles, just change this to radius in kilometers to get distances in km const double earth=6372797.560856;//I am doing miles, just change this to radius in kilometers to get distances in km
double distance=earth*cHarv; double distance=earth*cHarv;
return distance; return distance;
} }
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) { inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon ); return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
} }
inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordinate &c2) {
assert(c1.lat != INT_MIN);
assert(c1.lon != INT_MIN);
assert(c2.lat != INT_MIN);
assert(c2.lon != INT_MIN);
const double RAD = 0.017453292519943295769236907684886;
const double lat1 = (c1.lat/100000.)*RAD;
const double lon1 = (c1.lon/100000.)*RAD;
const double lat2 = (c2.lat/100000.)*RAD;
const double lon2 = (c2.lon/100000.)*RAD;
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
const double y = (lat2-lat1);
const double earthRadius = 6372797.560856;
const double d = sqrt(x*x + y*y) * earthRadius;
return d;
}
#endif /* COORDINATE_H_ */ #endif /* COORDINATE_H_ */

View File

@ -85,7 +85,7 @@ public:
return origEdgeData.at(id).nameID; return origEdgeData.at(id).nameID;
} }
inline short getTurnInstructionFromEdgeID(const unsigned id) const { inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
return origEdgeData.at(id).turnInstruction; return origEdgeData.at(id).turnInstruction;
} }

View File

@ -23,16 +23,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef QUERYEDGE_H_ #ifndef QUERYEDGE_H_
#define QUERYEDGE_H_ #define QUERYEDGE_H_
#include <climits> #include "TurnInstructions.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <climits>
struct OriginalEdgeData{ struct OriginalEdgeData{
explicit OriginalEdgeData(NodeID v, unsigned n, short t) : viaNode(v), nameID(n), turnInstruction(t) {} explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {}
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(SHRT_MAX) {} OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
NodeID viaNode; NodeID viaNode;
unsigned nameID; unsigned nameID;
short turnInstruction; TurnInstruction turnInstruction;
}; };
struct QueryEdge { struct QueryEdge {

View File

@ -23,17 +23,19 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <climits> #include <climits>
#include "TurnInstructions.h"
struct SegmentInformation { struct SegmentInformation {
_Coordinate location; _Coordinate location;
NodeID nameID; NodeID nameID;
double length; double length;
unsigned duration; unsigned duration;
double bearing; double bearing;
short turnInstruction; TurnInstruction turnInstruction;
bool necessary; bool necessary;
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const short tInstr, const bool nec) : SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {} location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const short tInstr) : SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {} location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
}; };

View File

@ -23,30 +23,32 @@
#include <string> #include <string>
typedef unsigned char TurnInstruction;
//This is a hack until c++0x is available enough to use scoped enums //This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass { struct TurnInstructionsClass {
const static short NoTurn = 0; //Give no instruction at all const static TurnInstruction NoTurn = 0; //Give no instruction at all
const static short GoStraight = 1; //Tell user to go straight! const static TurnInstruction GoStraight = 1; //Tell user to go straight!
const static short TurnSlightRight = 2; const static TurnInstruction TurnSlightRight = 2;
const static short TurnRight = 3; const static TurnInstruction TurnRight = 3;
const static short TurnSharpRight = 4; const static TurnInstruction TurnSharpRight = 4;
const static short UTurn = 5; const static TurnInstruction UTurn = 5;
const static short TurnSharpLeft = 6; const static TurnInstruction TurnSharpLeft = 6;
const static short TurnLeft = 7; const static TurnInstruction TurnLeft = 7;
const static short TurnSlightLeft = 8; const static TurnInstruction TurnSlightLeft = 8;
const static short ReachViaPoint = 9; const static TurnInstruction ReachViaPoint = 9;
const static short HeadOn = 10; const static TurnInstruction HeadOn = 10;
const static short EnterRoundAbout = 11; const static TurnInstruction EnterRoundAbout = 11;
const static short LeaveRoundAbout = 12; const static TurnInstruction LeaveRoundAbout = 12;
const static short StayOnRoundAbout = 13; const static TurnInstruction StayOnRoundAbout = 13;
const static short StartAtEndOfStreet = 14; const static TurnInstruction StartAtEndOfStreet = 14;
const static short ReachedYourDestination = 15; const static TurnInstruction ReachedYourDestination = 15;
const static short AccessRestrictionFlag = (1<<14); const static TurnInstruction AccessRestrictionFlag = 128;
const static short InverseAccessRestrictionFlag = ~(1<<14); const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
// std::string TurnStrings[16]; // std::string TurnStrings[16];
// std::string Ordinals[12]; // std::string Ordinals[12];
@ -84,7 +86,7 @@ struct TurnInstructionsClass {
// Ordinals[11] = "one of the too many"; // Ordinals[11] = "one of the too many";
// }; // };
static inline double GetTurnDirectionOfInstruction( const double angle ) { static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
if(angle >= 23 && angle < 67) { if(angle >= 23 && angle < 67) {
return TurnSharpRight; return TurnSharpRight;
} }

View File

@ -91,7 +91,7 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
/** starts at index 1 */ /** starts at index 1 */
pathDescription[0].length = 0; pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) { for(unsigned i = 1; i < pathDescription.size(); ++i) {
pathDescription[i].length = ApproximateDistance(pathDescription[i-1].location, pathDescription[i].location); pathDescription[i].length = ApproximateDistanceByEuclid(pathDescription[i-1].location, pathDescription[i].location);
} }
double lengthOfSegment = 0; double lengthOfSegment = 0;
@ -111,32 +111,37 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
becomes: becomes:
10. Turn left on B 36 for 35 km 10. Turn left on B 36 for 35 km
*/ */
unsigned lastTurn = 0; //TODO: rework to check only end and start of string.
for(unsigned i = 1; i < pathDescription.size(); ++i) { // stl string is way to expensive
string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) { // unsigned lastTurn = 0;
if(std::string::npos != string0.find(string1+";") || // for(unsigned i = 1; i < pathDescription.size(); ++i) {
std::string::npos != string0.find(";"+string1) || // string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
std::string::npos != string0.find(string1+" ;") || // if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
std::string::npos != string0.find("; "+string1)){ // if(std::string::npos != string0.find(string1+";")
// || std::string::npos != string0.find(";"+string1)
// || std::string::npos != string0.find(string1+" ;")
// || std::string::npos != string0.find("; "+string1)
// ){
// INFO("->next correct: " << string0 << " contains " << string1); // INFO("->next correct: " << string0 << " contains " << string1);
for(; lastTurn != i; ++lastTurn) // for(; lastTurn != i; ++lastTurn)
pathDescription[lastTurn].nameID = pathDescription[i].nameID; // pathDescription[lastTurn].nameID = pathDescription[i].nameID;
pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn; // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
} else if(std::string::npos != string1.find(string0+";") || // } else if(std::string::npos != string1.find(string0+";")
std::string::npos != string1.find(";"+string0) || // || std::string::npos != string1.find(";"+string0)
std::string::npos != string1.find(string0+" ;")|| // || std::string::npos != string1.find(string0+" ;")
std::string::npos != string1.find("; "+string0)) { // || std::string::npos != string1.find("; "+string0)
// ){
// INFO("->prev correct: " << string1 << " contains " << string0); // INFO("->prev correct: " << string1 << " contains " << string0);
pathDescription[i].nameID = pathDescription[i-1].nameID; // pathDescription[i].nameID = pathDescription[i-1].nameID;
pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn; // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
} // }
} // }
if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) { // if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
lastTurn = i; // lastTurn = i;
} // }
string0 = string1; // string0 = string1;
} // }
for(unsigned i = 1; i < pathDescription.size(); ++i) { for(unsigned i = 1; i < pathDescription.size(); ++i) {

View File

@ -69,7 +69,9 @@ public:
void SetConfig(const _DescriptorConfig & c) { config = c; } void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) { void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
WriteHeaderToOutput(reply.content); WriteHeaderToOutput(reply.content);
if(rawRoute.lengthOfShortestPath != INT_MAX) { if(rawRoute.lengthOfShortestPath != INT_MAX) {
descriptionFactory.SetStartSegment(phantomNodes.startPhantom); descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
reply.content += "0," reply.content += "0,"
@ -102,7 +104,7 @@ public:
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments); BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
} else { } else {
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) { BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag; TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction); numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
} }
} }
@ -155,7 +157,7 @@ public:
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments); BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
} else { } else {
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) { BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag; TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction); numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
} }
} }
@ -242,7 +244,6 @@ public:
reply.content += "},"; reply.content += "},";
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\""; reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
reply.content += "}"; reply.content += "}";
} }
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, SearchEngineT &sEngine, RouteNames & routeNames) { void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, SearchEngineT &sEngine, RouteNames & routeNames) {
@ -312,7 +313,7 @@ public:
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction; std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
//Fetch data from Factory and generate a string from it. //Fetch data from Factory and generate a string from it.
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) { BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag; TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction); numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) { if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
if(TurnInstructions.EnterRoundAbout == currentInstruction) { if(TurnInstructions.EnterRoundAbout == currentInstruction) {
@ -384,7 +385,6 @@ public:
reply.content += "0.0"; reply.content += "0.0";
reply.content += "]"; reply.content += "]";
} }
} }
}; };

View File

@ -24,8 +24,6 @@ extern "C" {
#include <lualib.h> #include <lualib.h>
} }
#include <boost/foreach.hpp>
#include "ScriptingEnvironment.h" #include "ScriptingEnvironment.h"
#include "../typedefs.h" #include "../typedefs.h"
#include "../Util/OpenMPWrapper.h" #include "../Util/OpenMPWrapper.h"

View File

@ -36,7 +36,7 @@ struct RouteParameters {
bool geometry; bool geometry;
bool compression; bool compression;
bool deprecatedAPI; bool deprecatedAPI;
int checkSum; unsigned checkSum;
std::string service; std::string service;
std::string outputFormat; std::string outputFormat;
std::string jsonpParameter; std::string jsonpParameter;
@ -58,7 +58,7 @@ struct RouteParameters {
deprecatedAPI = true; deprecatedAPI = true;
} }
void setChecksum(const int c) { void setChecksum(const unsigned c) {
checkSum = c; checkSum = c;
} }

View File

@ -34,7 +34,6 @@ public:
std::string GetVersionString() const { return std::string("0.3 (DL)"); } std::string GetVersionString() const { return std::string("0.3 (DL)"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) { void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
std::string tmp; std::string tmp;
std::string JSONParameter;
//json //json
if("" != routeParameters.jsonpParameter) { if("" != routeParameters.jsonpParameter) {
@ -53,7 +52,7 @@ public:
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\""; reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
reply.content += ("}"); reply.content += ("}");
reply.headers.resize(3); reply.headers.resize(3);
if("" != JSONParameter) { if("" != routeParameters.jsonpParameter) {
reply.content += ")"; reply.content += ")";
reply.headers[1].name = "Content-Type"; reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript"; reply.headers[1].value = "text/javascript";

View File

@ -6,6 +6,7 @@ require 'sys/proctable'
DATA_FOLDER = 'sandbox' DATA_FOLDER = 'sandbox'
PROFILE = 'bicycle' PROFILE = 'bicycle'
OSRM_PORT = 5000
Cucumber::Rake::Task.new do |t| Cucumber::Rake::Task.new do |t|
t.cucumber_opts = %w{--format pretty} t.cucumber_opts = %w{--format pretty}
@ -32,7 +33,7 @@ task osm_data_area_name.to_sym {} #define empty task to prevent rake from whin
def each_process name, &block def each_process name, &block
Sys::ProcTable.ps do |process| Sys::ProcTable.ps do |process|
if process.comm.strip == name.strip if process.comm.strip == name.strip && process.state != 'zombie'
yield process.pid.to_i, process.state.strip yield process.pid.to_i, process.state.strip
end end
end end
@ -60,7 +61,7 @@ def write_server_ini osm_file
s=<<-EOF s=<<-EOF
Threads = 1 Threads = 1
IP = 0.0.0.0 IP = 0.0.0.0
Port = 5000 Port = #{OSRM_PORT}
hsgrData=#{osm_file}.osrm.hsgr hsgrData=#{osm_file}.osrm.hsgr
nodesData=#{osm_file}.osrm.nodes nodesData=#{osm_file}.osrm.nodes
@ -68,6 +69,7 @@ def write_server_ini osm_file
ramIndex=#{osm_file}.osrm.ramIndex ramIndex=#{osm_file}.osrm.ramIndex
fileIndex=#{osm_file}.osrm.fileIndex fileIndex=#{osm_file}.osrm.fileIndex
namesData=#{osm_file}.osrm.names namesData=#{osm_file}.osrm.names
timestamp=#{osm_file}.osrm.timestamp
EOF EOF
File.open( 'server.ini', 'w') {|f| f.write( s ) } File.open( 'server.ini', 'w') {|f| f.write( s ) }
end end
@ -150,7 +152,7 @@ task :up => :setup do
timeout = 5 timeout = 5
(timeout*10).times do (timeout*10).times do
begin begin
socket = TCPSocket.new('localhost', 5000) socket = TCPSocket.new('localhost', OSRM_PORT)
socket.puts 'ping' socket.puts 'ping'
rescue Errno::ECONNREFUSED rescue Errno::ECONNREFUSED
sleep 0.1 sleep 0.1

View File

@ -59,7 +59,7 @@ public:
std::vector<NodeID> alternativePath; std::vector<NodeID> alternativePath;
std::vector<NodeID> viaNodeCandidates; std::vector<NodeID> viaNodeCandidates;
std::deque <NodeID> packedShortestPath; std::vector <NodeID> packedShortestPath;
std::vector<PreselectedNode> nodesThatPassPreselection; std::vector<PreselectedNode> nodesThatPassPreselection;
HeapPtr & forwardHeap = super::_queryData.forwardHeap; HeapPtr & forwardHeap = super::_queryData.forwardHeap;
@ -161,7 +161,7 @@ private:
inline void retrievePackedViaPath(const HeapPtr & _forwardHeap1, const HeapPtr & _backwardHeap1, const HeapPtr & _forwardHeap2, const HeapPtr & _backwardHeap2, inline void retrievePackedViaPath(const HeapPtr & _forwardHeap1, const HeapPtr & _backwardHeap1, const HeapPtr & _forwardHeap2, const HeapPtr & _backwardHeap2,
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) { const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
//unpack [s,v) //unpack [s,v)
std::deque<NodeID> packed_s_v_path, packed_v_t_path; std::vector<NodeID> packed_s_v_path, packed_v_t_path;
super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path); super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path);
packed_s_v_path.resize(packed_s_v_path.size()-1); packed_s_v_path.resize(packed_s_v_path.size()-1);
//unpack [v,t] //unpack [v,t]
@ -171,7 +171,7 @@ private:
} }
inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath, inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath,
const int offset, const std::deque<NodeID> & packedShortestPath) { const int offset, const std::vector<NodeID> & packedShortestPath) {
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues //compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
//only half-searches have to be done at this stage //only half-searches have to be done at this stage
super::_queryData.InitializeOrClearSecondThreadLocalStorage(); super::_queryData.InitializeOrClearSecondThreadLocalStorage();
@ -181,8 +181,8 @@ private:
HeapPtr & newForwardHeap = super::_queryData.forwardHeap2; HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2; HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
std::deque < NodeID > packed_s_v_path; std::vector < NodeID > packed_s_v_path;
std::deque < NodeID > packed_v_t_path; std::vector < NodeID > packed_v_t_path;
std::vector<NodeID> partiallyUnpackedShortestPath; std::vector<NodeID> partiallyUnpackedShortestPath;
std::vector<NodeID> partiallyUnpackedViaPath; std::vector<NodeID> partiallyUnpackedViaPath;
@ -258,8 +258,8 @@ private:
//finished partial unpacking spree! Amount of sharing is stored to appropriate poiner variable //finished partial unpacking spree! Amount of sharing is stored to appropriate poiner variable
} }
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::deque<NodeID> & packedShortestPath) { inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
std::deque<NodeID> packedAlternativePath; std::vector<NodeID> packedAlternativePath;
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath); super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
if(packedShortestPath.size() < 2 || packedAlternativePath.size() < 2) if(packedShortestPath.size() < 2 || packedAlternativePath.size() < 2)
@ -336,8 +336,8 @@ private:
//conduct T-Test //conduct T-Test
inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) { inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
std::deque < NodeID > packed_s_v_path; std::vector < NodeID > packed_s_v_path;
std::deque < NodeID > packed_v_t_path; std::vector < NodeID > packed_v_t_path;
super::_queryData.InitializeOrClearSecondThreadLocalStorage(); super::_queryData.InitializeOrClearSecondThreadLocalStorage();
*s_v_middle = UINT_MAX; *s_v_middle = UINT_MAX;

View File

@ -104,7 +104,7 @@ public:
} }
} }
inline void UnpackPath(std::deque<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const { inline void UnpackPath(std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
const unsigned sizeOfPackedPath = packedPath.size(); const unsigned sizeOfPackedPath = packedPath.size();
std::stack<std::pair<NodeID, NodeID> > recursionStack; std::stack<std::pair<NodeID, NodeID> > recursionStack;
@ -204,13 +204,15 @@ public:
unpackedPath.push_back(t); unpackedPath.push_back(t);
} }
inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::deque<NodeID>& packedPath) { inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) {
NodeID pathNode = middle; NodeID pathNode = middle;
while(pathNode != _fHeap->GetData(pathNode).parent) { while(pathNode != _fHeap->GetData(pathNode).parent) {
pathNode = _fHeap->GetData(pathNode).parent; pathNode = _fHeap->GetData(pathNode).parent;
packedPath.push_front(pathNode); packedPath.push_back(pathNode);
} }
std::reverse(packedPath.begin(), packedPath.end());
packedPath.push_back(middle); packedPath.push_back(middle);
pathNode = middle; pathNode = middle;
while (pathNode != _bHeap->GetData(pathNode).parent){ while (pathNode != _bHeap->GetData(pathNode).parent){

View File

@ -47,8 +47,8 @@ public:
bool searchFrom2ndStartNode(true); bool searchFrom2ndStartNode(true);
NodeID middle1 = ( NodeID ) UINT_MAX; NodeID middle1 = ( NodeID ) UINT_MAX;
NodeID middle2 = ( NodeID ) UINT_MAX; NodeID middle2 = ( NodeID ) UINT_MAX;
std::deque<NodeID> packedPath1; std::vector<NodeID> packedPath1;
std::deque<NodeID> packedPath2; std::vector<NodeID> packedPath2;
typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap; typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap;
typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap; typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap;
@ -141,8 +141,8 @@ public:
// INFO("middle1: " << middle1); // INFO("middle1: " << middle1);
//Unpack paths if they exist //Unpack paths if they exist
std::deque<NodeID> temporaryPackedPath1; std::vector<NodeID> temporaryPackedPath1;
std::deque<NodeID> temporaryPackedPath2; std::vector<NodeID> temporaryPackedPath2;
if(INT_MAX != _localUpperbound1) { if(INT_MAX != _localUpperbound1) {
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1); super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1);
// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) ); // INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) );

View File

@ -32,8 +32,8 @@ namespace qi = boost::spirit::qi;
template <typename Iterator, class HandlerT> template <typename Iterator, class HandlerT>
struct APIGrammar : qi::grammar<Iterator> { struct APIGrammar : qi::grammar<Iterator> {
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) { APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> ('?') >> query; api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
query = (*(zoom | output | jsonp | checksum | location | hint | compressed_geometry | language | instruction | alt_route | old_API) ) ; query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | alt_route | old_API) ) ;
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
@ -53,7 +53,7 @@ struct APIGrammar : qi::grammar<Iterator> {
} }
qi::rule<Iterator> api_call, query; qi::rule<Iterator> api_call, query;
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint, qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
compressed_geometry, stringwithDot, language, instruction, geometry, stringwithDot, language, instruction, geometry,
cmp, alt_route, old_API; cmp, alt_route, old_API;
HandlerT * handler; HandlerT * handler;

View File

@ -46,8 +46,8 @@ QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIn
} }
if(!timestamp.length()) if(!timestamp.length())
timestamp = "n/a"; timestamp = "n/a";
if(15 < timestamp.length()) if(25 < timestamp.length())
timestamp.resize(15); timestamp.resize(25);
INFO("Loading auxiliary information"); INFO("Loading auxiliary information");
//Init nearest neighbor data structure //Init nearest neighbor data structure

View File

@ -61,7 +61,7 @@ struct ServerFactory {
ERR("file index file not found"); ERR("file index file not found");
} }
unsigned threads = omp_get_num_procs(); int threads = omp_get_num_procs();
if(serverConfig.GetParameter("IP") == "") if(serverConfig.GetParameter("IP") == "")
serverConfig.SetParameter("IP", "0.0.0.0"); serverConfig.SetParameter("IP", "0.0.0.0");
if(serverConfig.GetParameter("Port") == "") if(serverConfig.GetParameter("Port") == "")

View File

@ -41,6 +41,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h" #include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/QueryEdge.h" #include "../DataStructures/QueryEdge.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/BaseConfiguration.h" #include "../Util/BaseConfiguration.h"
#include "../Util/InputFileUtil.h" #include "../Util/InputFileUtil.h"
#include "../Util/GraphLoader.h" #include "../Util/GraphLoader.h"

View File

@ -1,87 +0,0 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
** Interface to the GridSquares. Template parameter determines which kind of
* raw data is used (NASA, or reduced). GridSquare data is globally cached, so
* that many queries can be answered without having to constantly mmap & unmmap
* the data files.
*
* Typical usage:
*
* Grid<NasaGridSquare> g();
* cout << g.height(lng,lat) << endl;
*
*/
#ifndef SRTMLOOKUP_H
#define SRTMLOOKUP_H
#include <cassert>
#include <string>
#include "NASAGridSquare.h"
#include "../DataStructures/LRUCache.h"
class SRTMLookup {
public:
SRTMLookup(std::string & _rp) : cache(MAX_CACHE_SIZE), ROOT_PATH(_rp) {
// Double check that this compiler truncates towards zero.
assert(-1 == int(float(-1.9)));
}
/** Returns the height above sea level for the given lat/lng. */
short height(const float longitude, const float latitude) {
if(0 == ROOT_PATH.size())
return 0;
int lng,lat;
float lng_fraction,lat_fraction;
split(longitude,lng,lng_fraction);
split(latitude ,lat,lat_fraction);
int k = key(lng,lat);
if(!cache.Holds(k)) {
cache.Insert(k , new NasaGridSquare(lng,lat, ROOT_PATH));
}
NasaGridSquare * result;
cache.Fetch(k, result);
return result->getHeight(lng_fraction,lat_fraction);
}
private:
/** Split a floating point number (num) into integer (i) & fraction (f)
* components. */
inline void split(float num, int& i, float& f) const {
if(num>=0.0)
i=int(num);
else
i=int(num)-1;
f=num-float(i);
}
/** Formula for grid squares' unique keys. */
int key(int lng, int lat) {
return 1000*lat + lng;
}
LRUCache<NasaGridSquare*> cache;
static const int MAX_CACHE_SIZE = 250;
std::string ROOT_PATH;
};
#endif // SRTMLOOKUP_H

View File

@ -1,4 +1,5 @@
# config/cucumber.yml # config/cucumber.yml
##YAML Template ##YAML Template
--- ---
default: --require features default: --require features
verify: --require features --tags ~@todo --tag ~@stress -f progress

View File

@ -18,14 +18,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt. or see http://www.gnu.org/licenses/agpl.txt.
*/ */
#define VERBOSE(x) x
#define VERBOSE2(x)
#ifdef NDEBUG
#undef VERBOSE
#undef VERBOSE2
#endif
extern "C" { extern "C" {
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
@ -139,7 +131,6 @@ int main (int argc, char *argv[]) {
speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1); speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1);
std::vector<ImportEdge> edgeList; std::vector<ImportEdge> edgeList;
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions); NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
in.close(); in.close();

View File

@ -3,7 +3,7 @@ Feature: Bike - Restricted access
Reference: http://wiki.openstreetmap.org/wiki/Key:access Reference: http://wiki.openstreetmap.org/wiki/Key:access
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Access tag hierachy on ways Scenario: Bike - Access tag hierachy on ways
Then routability should be Then routability should be

View File

@ -2,7 +2,7 @@
Feature: Bike - Squares and other areas Feature: Bike - Squares and other areas
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
@square @square
Scenario: Bike - Route along edge of a squares Scenario: Bike - Route along edge of a squares

View File

@ -2,7 +2,7 @@
Feature: Barriers Feature: Barriers
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Barriers Scenario: Bike - Barriers
Then routability should be Then routability should be
@ -10,6 +10,7 @@ Feature: Barriers
| | x | | | x |
| bollard | x | | bollard | x |
| gate | x | | gate | x |
| cycle_barrier | x |
| cattle_grid | x | | cattle_grid | x |
| border_control | x | | border_control | x |
| toll_booth | x | | toll_booth | x |

View File

@ -3,7 +3,7 @@ Feature: Bike - Cycle tracks/lanes
Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Cycle tracks/lanes should enable biking Scenario: Bike - Cycle tracks/lanes should enable biking
Then routability should be Then routability should be

View File

@ -2,7 +2,7 @@
Feature: Bike - Destination only, no passing through Feature: Bike - Destination only, no passing through
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Destination only street Scenario: Bike - Destination only street
Given the node map Given the node map

View File

@ -2,7 +2,7 @@
Feature: Bike - Handle ferry routes Feature: Bike - Handle ferry routes
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Ferry route Scenario: Bike - Ferry route
Given the node map Given the node map
@ -113,7 +113,8 @@ Feature: Bike - Handle ferry routes
| from | to | route | time | | from | to | route | time |
| a | g | abcdefg | 23400s +-1 | | a | g | abcdefg | 23400s +-1 |
| g | a | abcdefg | 23400s +-1 | | g | a | abcdefg | 23400s +-1 |
@todo
Scenario: Bike - Ferry duration, individual parts Scenario: Bike - Ferry duration, individual parts
Given the node map Given the node map
| x | y | | z | | | v | | x | y | | z | | | v |

View File

@ -2,7 +2,7 @@
Feature: Bike - Max speed restrictions Feature: Bike - Max speed restrictions
Background: Use specific speeds Background: Use specific speeds
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Respect maxspeeds when lower that way type speed Scenario: Bike - Respect maxspeeds when lower that way type speed
Given the node map Given the node map

View File

@ -2,7 +2,7 @@
Feature: Bike - Street names in instructions Feature: Bike - Street names in instructions
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - A named street Scenario: Bike - A named street
Given the node map Given the node map
@ -19,26 +19,14 @@ Feature: Bike - Street names in instructions
| a | c | My Way,Your Way | | a | c | My Way,Your Way |
Scenario: Bike - Use way type to describe unnamed ways Scenario: Bike - Use way type to describe unnamed ways
Given the node map
| a | b | c |
And the ways
| nodes | highway | name |
| ab | cycleway | |
| bc | track | |
When I route I should get
| from | to | route |
| a | c | cycleway,track |
Scenario: Bike - Don't create instructions for every node of unnamed ways
Given the node map Given the node map
| a | b | c | d | | a | b | c | d |
And the ways And the ways
| nodes | highway | name | | nodes | highway | name |
| abcd | cycleway | | | ab | cycleway | |
| bcd | track | |
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | d | cycleway | | a | d | cycleway,track |

View File

@ -3,7 +3,7 @@ Feature: Bike - Oneway streets
Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Simple oneway Scenario: Bike - Simple oneway
Then routability should be Then routability should be

View File

@ -4,7 +4,7 @@ Feature: Bike - Turn restrictions
Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes. Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
Background: Use car routing Background: Use car routing
Given the speedprofile "bicycle" Given the profile "bicycle"
@no_turning @no_turning
Scenario: Bike - No left turn Scenario: Bike - No left turn

View File

@ -0,0 +1,37 @@
@routing @bicycle @stop_area @todo
Feature: Bike - Stop areas for public transport
Platforms and railway/bus lines are connected using a relation rather that a way, as specified in:
http://wiki.openstreetmap.org/wiki/Tag:public_transport%3Dstop_area
Background:
Given the profile "bicycle"
Scenario: Bike - Platforms tagged using public_transport
Then routability should be
| highway | public_transport | bicycle | bothw |
| primary | | | x |
| (nil) | platform | | x |
Scenario: Bike - railway platforms
Given the node map
| a | b | c | d |
| | s | t | |
And the nodes
| node | public_transport |
| c | stop_position |
And the ways
| nodes | highway | railway | bicycle | public_transport |
| abcd | (nil) | train | yes | |
| st | (nil) | (nil) | | platform |
And the relations
| type | public_transport | node:stop | way:platform |
| public_transport | stop_area | c | st |
When I route I should get
| from | to | route |
| a | d | abcd |
| s | t | st |
| s | d | /st,.+,abcd/ |

View File

@ -3,7 +3,7 @@ Feature: Bike - Handle ferry routes
Bringing bikes on trains and subways Bringing bikes on trains and subways
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Bringing bikes on trains Scenario: Bike - Bringing bikes on trains
Then routability should be Then routability should be

View File

@ -2,11 +2,11 @@
Feature: Bike - Accessability of different way types Feature: Bike - Accessability of different way types
Background: Background:
Given the speedprofile "bicycle" Given the profile "bicycle"
Scenario: Bike - Basic access Scenario: Bike - Basic access
Bikes are allowed on footways etc because you can pull your bike at a lower speed. Bikes are allowed on footways etc because you can pull your bike at a lower speed.
Given the speedprofile "bicycle" Given the profile "bicycle"
Then routability should be Then routability should be
| highway | forw | | highway | forw |
| (nil) | | | (nil) | |

View File

@ -3,7 +3,7 @@ Feature: Car - Restricted access
Reference: http://wiki.openstreetmap.org/wiki/Key:access Reference: http://wiki.openstreetmap.org/wiki/Key:access
Background: Background:
Given the speedprofile "car" Given the profile "car"
Scenario: Car - Access tag hierachy on ways Scenario: Car - Access tag hierachy on ways
Then routability should be Then routability should be
@ -92,7 +92,7 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access
| no | | | no | |
| private | | | private | |
| agricultural | | | agricultural | |
| forestery | | | forestry | |
| some_tag | x | | some_tag | x |
@ -105,7 +105,7 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access
| no | | | no | |
| private | | | private | |
| agricultural | | | agricultural | |
| forestery | | | forestry | |
| some_tag | x | | some_tag | x |
Scenario: Car - Access tags on both node and way Scenario: Car - Access tags on both node and way

View File

@ -2,7 +2,7 @@
Feature: Car - Barriers Feature: Car - Barriers
Background: Background:
Given the speedprofile "car" Given the profile "car"
Scenario: Car - Barriers Scenario: Car - Barriers
Then routability should be Then routability should be

View File

@ -2,7 +2,7 @@
Feature: Car - Destination only, no passing through Feature: Car - Destination only, no passing through
Background: Background:
Given the speedprofile "car" Given the profile "car"
Scenario: Car - Destination only street Scenario: Car - Destination only street
Given the node map Given the node map

View File

@ -2,7 +2,7 @@
Feature: Car - Handle ferry routes Feature: Car - Handle ferry routes
Background: Background:
Given the speedprofile "car" Given the profile "car"
Scenario: Car - Use a ferry route Scenario: Car - Use a ferry route
Given the node map Given the node map

View File

@ -2,7 +2,7 @@
Feature: Car - Max speed restrictions Feature: Car - Max speed restrictions
Background: Use specific speeds Background: Use specific speeds
Given the speedprofile "car" Given the profile "car"
Given a grid size of 1000 meters Given a grid size of 1000 meters
Scenario: Car - Respect maxspeeds when lower that way type speed Scenario: Car - Respect maxspeeds when lower that way type speed

View File

@ -2,7 +2,7 @@
Feature: Car - Street names in instructions Feature: Car - Street names in instructions
Background: Background:
Given the speedprofile "car" Given the profile "car"
Scenario: Car - A named street Scenario: Car - A named street
Given the node map Given the node map
@ -10,35 +10,24 @@ Feature: Car - Street names in instructions
| | c | | | c |
And the ways And the ways
| nodes | name | | nodes | name |
| ab | My Way | | ab | My Way |
| bc | Your Way | | bc | Your Way |
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | c | My Way,Your Way | | a | c | My Way,Your Way |
@todo
Scenario: Car - Use way type to describe unnamed ways Scenario: Car - Use way type to describe unnamed ways
Given the node map
| a | b | c |
And the ways
| nodes | highway | name |
| ab | tertiary | |
| bc | residential | |
When I route I should get
| from | to | route |
| a | c | tertiary,residential |
Scenario: Car - Don't create instructions for every node of unnamed ways
Given the node map Given the node map
| a | b | c | d | | a | b | c | d |
And the ways And the ways
| nodes | highway | name | | nodes | highway | name |
| abcd | primary | | | ab | tertiary | |
| bcd | residential | |
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | d | primary | | a | c | tertiary,residential |

View File

@ -3,7 +3,7 @@ Feature: Car - Oneway streets
Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
Background: Background:
Given the speedprofile "car" Given the profile "car"
Scenario: Car - Simple oneway Scenario: Car - Simple oneway
Then routability should be Then routability should be

View File

@ -4,7 +4,7 @@ Feature: Car - Turn restrictions
Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes. Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
Background: Use car routing Background: Use car routing
Given the speedprofile "car" Given the profile "car"
@no_turning @no_turning
Scenario: Car - No left turn Scenario: Car - No left turn

View File

@ -2,7 +2,7 @@
Feature: Car - Accessability of different way types Feature: Car - Accessability of different way types
Background: Background:
Given the speedprofile "car" Given the profile "car"
Scenario: Car - Basic access Scenario: Car - Basic access
Then routability should be Then routability should be

View File

@ -3,7 +3,7 @@ Feature: Foot - Oneway streets
Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
Background: Background:
Given the speedprofile "foot" Given the profile "foot"
Scenario: Foot - Walking should not be affected by oneways Scenario: Foot - Walking should not be affected by oneways
Then routability should be Then routability should be

View File

@ -2,7 +2,7 @@
Feature: Foot - Accessability of different way types Feature: Foot - Accessability of different way types
Background: Background:
Given the speedprofile "foot" Given the profile "foot"
Scenario: Foot - Basic access Scenario: Foot - Basic access
Then routability should be Then routability should be

View File

@ -2,7 +2,7 @@
Feature: Weird routings discovered Feature: Weird routings discovered
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Routing on a oneway roundabout Scenario: Routing on a oneway roundabout
Given the node map Given the node map

View File

@ -1,5 +1,5 @@
Given /^the speedprofile "([^"]*)"$/ do |profile| Given /^the profile "([^"]*)"$/ do |profile|
read_speedprofile profile set_profile profile
end end
Given /^a grid size of (\d+) meters$/ do |meters| Given /^a grid size of (\d+) meters$/ do |meters|

View File

@ -1,15 +0,0 @@
When /^I preprocess data$/ do
begin
osrm_kill
reprocess
rescue OSRMError => e
@process_error = e
end
end
Then /^preparing should return code (\d+)$/ do |code|
@process_error.class.should == OSRMError
@process_error.process.should == 'osrm-prepare'
@process_error.code.to_i.should == code.to_i
end

View File

@ -1,73 +0,0 @@
require 'OSM/StreamParser'
class OSMTestParserCallbacks < OSM::Callbacks
@@locations = nil
def self.locations
if @@locations
@@locations
else
#parse the test file, so we can later reference nodes and ways by name in tests
@@locations = {}
file = 'test/data/test.osm'
callbacks = OSMTestParserCallbacks.new
parser = OSM::StreamParser.new(:filename => file, :callbacks => callbacks)
parser.parse
puts @@locations
end
end
def node(node)
@@locations[node.name] = [node.lat,node.lon]
end
end
Given /^the OSM file contains$/ do |string|
file = 'data/test.osm'
File.open( file, 'w') {|f| f.write(string) }
#convert from .osm to .osm.pbf, which is the format osrm reads
system "osmosis --read-xml data/test.osm --write-pbf data/test.osm.pbf omitmetadata=true"
end
Given /^the speedprofile contains$/ do |string|
File.open( 'speedprofile.ini', 'w') {|f| f.write(string) }
end
Given /^the data file "([^"]*)" is present$/ do |file|
File.exists?(file).should == true
end
When /^I run the extractor with "([^"]*)"$/ do |cmd|
@response = `#{cmd}`
#Dir.chdir @test_folder do
# @response = IO.popen([cmd, :err=>[:child, :out]]) { |ls_io| ls_result_with_error = ls_io.read }
#end
end
When /^I run the preprocessor with "([^"]*)"$/ do |cmd|
@response = `#{cmd}`
end
Given /^the preprocessed files for "([^"]*)" are present and up to date$/ do |area|
File.exists?("#{area}.osrm").should == true
File.exists?("#{area}.osrm.names").should == true
File.exists?("#{area}.osrm.restrictions").should == true
File.exists?("#{area}.osrm.hsgr").should == true
File.exists?("#{area}.osrm.nodes").should == true
File.exists?("#{area}.osrm.edges").should == true
File.exists?("#{area}.osrm.ramIndex").should == true
File.exists?("#{area}.osrm.fileIndex").should == true
end
Then /^I should see the file "([^"]*)"$/ do |file|
File.exists?(file).should == true
end
When /^preprocessed files for "([^"]*)" has been removed$/ do |file|
FileUtils.rm_r Dir["#{file}.*"], :secure => true
end

View File

@ -0,0 +1,45 @@
When /^I request \/(.*)$/ do |path|
reprocess
OSRMLauncher.new do
@response = request_path path
end
end
Then /^I should get a response/ do
@response.code.should == "200"
@response.body.should_not == nil
@response.body.should_not == ''
end
Then /^response should be valid JSON$/ do
@json = JSON.parse @response.body
end
Then /^response should be well-formed$/ do
@json['version'].class.should == Float
@json['status'].class.should == Fixnum
@json['transactionId'].class.should == String
end
Then /^response should be a well-formed route$/ do
step "response should be well-formed"
@json['status_message'].class.should == String
@json['route_summary'].class.should == Hash
@json['route_geometry'].class.should == String
@json['route_instructions'].class.should == Array
@json['via_points'].class.should == Array
end
When /^I preprocess data$/ do
begin
reprocess
rescue OSRMError => e
@process_error = e
end
end
Then /^"([^"]*)" should return code (\d+)$/ do |binary, code|
@process_error.is_a?(OSRMError).should == true
@process_error.process.should == binary
@process_error.code.to_i.should == code.to_i
end

View File

@ -0,0 +1,40 @@
Then /^routability should be$/ do |table|
build_ways_from_table table
reprocess
actual = []
if table.headers&["forw","backw","bothw"] == []
raise "*** routability tabel must contain either 'forw', 'backw' or 'bothw' column"
end
OSRMLauncher.new do
table.hashes.each_with_index do |row,i|
got = row.dup
attempts = []
['forw','backw','bothw'].each do |direction|
if table.headers.include? direction
if direction == 'forw' || direction == 'bothw'
response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}")
elsif direction == 'backw' || direction == 'bothw'
response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}")
end
got[direction] = route_status response
json = JSON.parse(response.body)
if got[direction].empty? == false
route = way_list json['route_instructions']
if route != "w#{i}"
got[direction] = "testing w#{i}, but got #{route}!?"
elsif row[direction] =~ /\d+s/
time = json['route_summary']['total_time']
got[direction] = "#{time}s"
end
end
if got[direction] != row[direction]
attempts << { :attempt => direction, :query => @query, :response => response }
end
end
end
log_fail row,got,attempts if got != row
actual << got
end
end
table.routing_diff! actual
end

View File

@ -1,194 +1,4 @@
When /^I request a route from ([^"]+) to ([^"]+)$/ do |a,b|
@response = request_route a,b
#puts @response.body
#@response
end
When /^I request a route from "([^"]*)" to "([^"]*)"$/ do |a,b|
locations = OSMTestParserCallbacks.locations
raise "Locations hash is empty. To reference nodes by name, please preprocess the test file earlier in the test." unless locations
raise "Unknown node: #{a}" unless locations[a]
raise "Unknown node: #{b}" unless locations[b]
@response = request_route "#{locations[a][0]},#{locations[a][1]}", "#{locations[b][0]},#{locations[b][1]}"
end
Then /^I should get a response/ do
@response.code.should == "200"
@response.body.should_not == nil
@response.body.should_not == ''
end
Then /^response should be valid JSON$/ do
@json = JSON.parse @response.body
end
Then /^response should be well-formed$/ do
@json['version'].class.should == Float
@json['status'].class.should == Fixnum
@json['status_message'].class.should == String
@json['route_summary'].class.should == Hash
@json['route_geometry'].class.should == String
@json['route_instructions'].class.should == Array
@json['via_points'].class.should == Array
@json['transactionId'].class.should == String
end
Then /^a route should be found$/ do
@json['status'].should == 0
@json['status_message'].should == "Found route between points"
end
Then /^no route should be found$/ do
@json['status'].should == 207
@json['status_message'].should == "Cannot find route between points"
end
Then /^I should get a valid response$/ do
step "I should get a response"
step "response should be valid JSON"
step "response should be well-formed"
#step "no error should be reported in terminal"
end
Then /^I should get a route$/ do
step "I should get a valid response"
step "a route should be found"
#puts @response.body
end
Then /^I should not get a route$/ do
step "I should get a valid response"
step "no route should be found"
end
Then /^the route should start at "([^']*)"$/ do |name|
@json['route_summary']['start_point'].should == name
end
Then /^the route should end at "([^']*)"$/ do |name|
@json['route_summary']['end_point'].should == name
end
Then /^distance should be between (\d+) and (\d+)$/ do |min,max|
@json['route_summary']['total_distance'].to_i.should >= min.to_i
@json['route_summary']['total_distance'].to_i.should <= max.to_i
end
Then /^the distance should be close to (\d+)m$/ do |d|
@json['route_summary']['total_distance'].to_i.should >= d.to_i*0.95
@json['route_summary']['total_distance'].to_i.should <= d.to_i/0.95
end
Then /^number of instructions should be (\d+)$/ do |n|
@json['route_instructions'].size.should == n
end
Then /^there should be 1 turn$/ do
step 'there should be 1 turns'
end
Then /^there should be (\d+) turns$/ do |n|
@json['route_instructions'].map {|t| t.first}.select {|t| t =~ /^Turn/ }.size.should == n.to_i
end
Then /^there should be more than (\d+) turn$/ do |n|
@json['route_instructions'].map {|t| t.first}.select {|t| t =~ /^Turn/ }.size.should > n.to_i
end
Then /^there should not be any turns$/ do
(@json['route_instructions'].size-1).should == 0
end
def sanitize_route route
route.split(',').map{|w| w.strip}.reject(&:empty?).join(', ')
end
def computed_route
@json['route_instructions'].map { |r| r[1] }.reject(&:empty?).join(', ')
end
Then /^the route should follow "([^"]*)"$/ do |route|
sanitize_route(route).should == computed_route
end
Then /^the route should not follow "([^"]*)"$/ do |route|
sanitize_route(route).should_not == computed_route
end
Then /^the route should include "([^"]*)"$/ do |route|
sanitize_route(route).should =~ /#{computed_route}/
end
Then /^the route should not include "([^"]*)"$/ do |route|
sanitize_route(route).should_not =~ /#{computed_route}/
end
Then /^the route should stay on "([^"]*)"$/ do |way|
step "the route should start at \"#{way}\""
step "the route should end at \"#{way}\""
step "the route should follow \"#{way}\""
step "there should not be any turns"
end
When /^I route between "([^"]*)" and "([^"]*)"$/ do |from,to|
reprocess
Dir.chdir 'test' do
from_node = name_node_hash[from]
to_node = name_node_hash[to]
a = "#{from_node.lon},#{from_node.lat}"
b = "#{to_node.lon},#{to_node.lat}"
@route = parse_response( request_route(a,b) )
end
end
Then /^"([^"]*)" should be returned$/ do |route|
@route.should == route.split(',').join(',')
end
Then /^routability should be$/ do |table|
osrm_kill
build_ways_from_table table
reprocess
actual = []
if table.headers&["forw","backw","bothw"] == []
raise "*** routability tabel must contain either 'forw', 'backw' or 'bothw' column"
end
OSRMLauncher.new do
table.hashes.each_with_index do |row,i|
got = row.dup
attempts = []
['forw','backw','bothw'].each do |direction|
if table.headers.include? direction
if direction == 'forw' || direction == 'bothw'
response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}")
elsif direction == 'backw' || direction == 'bothw'
response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}")
end
got[direction] = route_status response
json = JSON.parse(response.body)
if got[direction].empty? == false
route = way_list json['route_instructions']
if route != "w#{i}"
got[direction] = "testing w#{i}, but got #{route}!?"
elsif row[direction] =~ /\d+s/
time = json['route_summary']['total_time']
got[direction] = "#{time}s"
end
end
if got[direction] != row[direction]
attempts << { :attempt => direction, :query => @query, :response => response }
end
end
end
log_fail row,got,attempts if got != row
actual << got
end
end
table.routing_diff! actual
end
When /^I route I should get$/ do |table| When /^I route I should get$/ do |table|
osrm_kill
reprocess reprocess
actual = [] actual = []
OSRMLauncher.new do OSRMLauncher.new do
@ -204,6 +14,7 @@ When /^I route I should get$/ do |table|
instructions = way_list json['route_instructions'] instructions = way_list json['route_instructions']
bearings = bearing_list json['route_instructions'] bearings = bearing_list json['route_instructions']
compasses = compass_list json['route_instructions'] compasses = compass_list json['route_instructions']
turns = turn_list json['route_instructions']
end end
end end
@ -232,11 +43,14 @@ When /^I route I should get$/ do |table|
if table.headers.include? 'compass' if table.headers.include? 'compass'
got['compass'] = compasses got['compass'] = compasses
end end
if table.headers.include? 'turns'
got['turns'] = turns
end
end end
ok = true ok = true
row.keys.each do |key| row.keys.each do |key|
if row[key].match /(.*)\s+~(.+)%$/ if row[key].match /(.*)\s+~(.+)%$/ #percentage range: 100 ~5%
margin = 1 - $2.to_f*0.01 margin = 1 - $2.to_f*0.01
from = $1.to_f*margin from = $1.to_f*margin
to = $1.to_f/margin to = $1.to_f/margin
@ -245,7 +59,7 @@ When /^I route I should get$/ do |table|
else else
ok = false ok = false
end end
elsif row[key].match /(.*)\s+\+\-(.+)$/ elsif row[key].match /(.*)\s+\+\-(.+)$/ #absolute range: 100 +-5
margin = $2.to_f margin = $2.to_f
from = $1.to_f-margin from = $1.to_f-margin
to = $1.to_f+margin to = $1.to_f+margin
@ -254,6 +68,10 @@ When /^I route I should get$/ do |table|
else else
ok = false ok = false
end end
elsif row[key] =~ /^\/(.*)\/$/ #regex: /a,b,.*/
if got[key] =~ /#{$1}/
got[key] = row[key]
end
else else
ok = row[key] == got[key] ok = row[key] == got[key]
end end
@ -269,3 +87,11 @@ When /^I route I should get$/ do |table|
end end
table.routing_diff! actual table.routing_diff! actual
end end
When /^I route (\d+) times I should get$/ do |n,table|
ok = true
n.to_i.times do
ok = false unless step "I route I should get", table
end
ok
end

View File

@ -0,0 +1,7 @@
Then /^I should get a valid timestamp/ do
step "I should get a response"
step "response should be valid JSON"
step "response should be well-formed"
@json['timestamp'].class.should == String
@json['timestamp'].should == OSM_TIMESTAMP
end

View File

@ -0,0 +1,58 @@
@stress
Feature: Stress testing
Background:
Given the profile "testbot"
Scenario: Stress - 10km star, request 1 route
#osrm-routed hangs very often
Given a grid size of 10000 meters
Given the node map
| h | a | b |
| g | x | c |
| f | e | d |
And the ways
| nodes | highway |
| xa | primary |
| xb | primary |
| xc | primary |
| xd | primary |
| xe | primary |
| xf | primary |
| xg | primary |
| xh | primary |
When I route 100 times I should get
| from | to | route |
| x | h | xh |
Scenario: Stress - 10km star, request 8 routes
#osrm-routed hangs sometimes
Given a grid size of 10000 meters
Given the node map
| h | a | b |
| g | x | c |
| f | e | d |
And the ways
| nodes | highway |
| xa | primary |
| xb | primary |
| xc | primary |
| xd | primary |
| xe | primary |
| xf | primary |
| xg | primary |
| xh | primary |
When I route 100 times I should get
| from | to | route |
| x | a | xa |
| x | b | xb |
| x | c | xc |
| x | d | xd |
| x | e | xe |
| x | f | xf |
| x | g | xg |
| x | h | xh |

View File

@ -1,21 +1,21 @@
def speedprofile def profile
@speedprofile ||= reset_speedprofile @profile ||= reset_profile
end end
def reset_speedprofile def reset_profile
@speedprofile = nil @profile = nil
read_speedprofile DEFAULT_SPEEDPROFILE set_profile DEFAULT_SPEEDPROFILE
end end
def read_speedprofile profile def set_profile profile
@speedprofile = profile @profile = profile
end end
def write_server_ini def write_server_ini
s=<<-EOF s=<<-EOF
Threads = 1 Threads = 1
IP = 0.0.0.0 IP = 0.0.0.0
Port = 5000 Port = #{OSRM_PORT}
hsgrData=#{@osm_file}.osrm.hsgr hsgrData=#{@osm_file}.osrm.hsgr
nodesData=#{@osm_file}.osrm.nodes nodesData=#{@osm_file}.osrm.nodes
@ -23,6 +23,7 @@ edgesData=#{@osm_file}.osrm.edges
ramIndex=#{@osm_file}.osrm.ramIndex ramIndex=#{@osm_file}.osrm.ramIndex
fileIndex=#{@osm_file}.osrm.fileIndex fileIndex=#{@osm_file}.osrm.fileIndex
namesData=#{@osm_file}.osrm.names namesData=#{@osm_file}.osrm.names
timestamp=#{@osm_file}.osrm.timestamp
EOF EOF
File.open( 'server.ini', 'w') {|f| f.write( s ) } File.open( 'server.ini', 'w') {|f| f.write( s ) }
end end

View File

@ -116,7 +116,7 @@ def reset_data
#clear_log #clear_log
#clear_data_files #clear_data_files
end end
reset_speedprofile reset_profile
reset_osm reset_osm
@fingerprint = nil @fingerprint = nil
end end
@ -131,10 +131,6 @@ def reset_osm
name_way_hash.clear name_way_hash.clear
@osm_str = nil @osm_str = nil
@osm_hash = nil @osm_hash = nil
##ID -1 causes trouble, so add a few nodes to avoid it
#node = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, 0,0
#node = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, 0,0
@osm_id = 0 @osm_id = 0
end end
@ -180,9 +176,8 @@ def convert_osm_to_pbf
unless File.exist?("#{@osm_file}.osm.pbf") unless File.exist?("#{@osm_file}.osm.pbf")
log_preprocess_info log_preprocess_info
log "== Converting #{@osm_file}.osm to protobuffer format...", :preprocess log "== Converting #{@osm_file}.osm to protobuffer format...", :preprocess
#redirect stdout and stderr to a log file avoid output in the cucumber console
unless system "osmosis --read-xml #{@osm_file}.osm --write-pbf #{@osm_file}.osm.pbf omitmetadata=true 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE}" unless system "osmosis --read-xml #{@osm_file}.osm --write-pbf #{@osm_file}.osm.pbf omitmetadata=true 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE}"
raise "Failed to convert to proto buffer format. Please see #{hash}.log for more info." raise OsmosisError.new $?, "osmosis exited with code #{$?.exitstatus}"
end end
log '', :preprocess log '', :preprocess
end end
@ -198,25 +193,30 @@ def prepared?
File.exist?("#{@osm_file}.osrm.hsgr") File.exist?("#{@osm_file}.osrm.hsgr")
end end
def write_timestamp
File.open( "#{@osm_file}.osrm.timestamp", 'w') {|f| f.write(OSM_TIMESTAMP) }
end
def reprocess def reprocess
Dir.chdir TEST_FOLDER do Dir.chdir TEST_FOLDER do
write_osm write_osm
write_timestamp
convert_osm_to_pbf convert_osm_to_pbf
unless extracted? unless extracted?
log_preprocess_info log_preprocess_info
log "== Extracting #{@osm_file}.osm...", :preprocess log "== Extracting #{@osm_file}.osm...", :preprocess
unless system "../osrm-extract #{@osm_file}.osm.pbf 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@speedprofile}.lua" unless system "../osrm-extract #{@osm_file}.osm.pbf 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@profile}.lua"
log "*** Exited with code #{$?.exitstatus}.", :preprocess log "*** Exited with code #{$?.exitstatus}.", :preprocess
raise OSRMError.new 'osrm-extract', $?.exitstatus, "*** osrm-extract exited with code #{$?.exitstatus}. The file preprocess.log might contain more info." raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}."
end end
log '', :preprocess log '', :preprocess
end end
unless prepared? unless prepared?
log_preprocess_info log_preprocess_info
log "== Preparing #{@osm_file}.osm...", :preprocess log "== Preparing #{@osm_file}.osm...", :preprocess
unless system "../osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@speedprofile}.lua" unless system "../osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@profile}.lua"
log "*** Exited with code #{$?.exitstatus}.", :preprocess log "*** Exited with code #{$?.exitstatus}.", :preprocess
raise OSRMError.new 'osrm-prepare', $?.exitstatus, "*** osrm-prepare exited with code #{$?.exitstatus}. The file preprocess.log might contain more info." raise PrepareError.new $?.exitstatus, "osrm-prepare exited with code #{$?.exitstatus}."
end end
log '', :preprocess log '', :preprocess
end end

View File

@ -1 +1,18 @@
require 'rspec/expectations' require 'rspec/expectations'
DEFAULT_PORT = 5000
puts "Ruby version #{RUBY_VERSION}"
unless RUBY_VERSION =~ /^1.9/
raise "*** Please upgrade to Ruby 1.9.x to run the OSRM cucumber tests"
end
if ENV["OSRM_PORT"]
OSRM_PORT = ENV["OSRM_PORT"].to_i
puts "Port set to #{OSRM_PORT}"
else
OSRM_PORT = DEFAULT_PORT
puts "Using default port #{OSRM_PORT}"
end

View File

@ -1,14 +1,49 @@
class OSRMError < StandardError class OSRMError < StandardError
attr_accessor :process, :code, :msg attr_accessor :msg, :code, :process
def initialize process, code, msg def initialize process, code, msg, log, lines
@process = process @process = process
@code = code @code = code
@msg = msg @msg = msg
@lines = lines
@log = log
@extract = log_tail @log, @lines
end end
def to_s def to_s
@msg "*** #{@msg}\nLast #{@lines} lines from #{@log}:\n#{@extract}\n"
end end
end
private
def log_tail path, n
File.open(path) do |f|
return f.tail(n).map { |line| " > #{line}" }.join "\n"
end
end
end
class OsmosisError < OSRMError
def initialize code, msg
super 'osmosis', code, msg, PREPROCESS_LOG_FILE, 40
end
end
class ExtractError < OSRMError
def initialize code, msg
super 'osrm-extract', code, msg, PREPROCESS_LOG_FILE, 3
end
end
class PrepareError < OSRMError
def initialize code, msg
super 'osrm-prepare', code, msg, PREPROCESS_LOG_FILE, 3
end
end
class RoutedError < OSRMError
def initialize msg
super 'osrm-routed', nil, msg, OSRM_ROUTED_LOG_FILE, 3
end
end

22
features/support/file.rb Normal file
View File

@ -0,0 +1,22 @@
class File
#read last n lines of a file. useful for getting last part of a big log file.
def tail(n)
buffer = 1024
idx = (size - buffer).abs
chunks = []
lines = 0
begin
seek(idx)
chunk = read(buffer)
lines += chunk.count("\n")
chunks.unshift chunk
idx -= buffer
end while lines < ( n + 1 ) && pos != 0
tail_of_file = chunks.join('')
ary = tail_of_file.split(/\n/)
lines_to_return = ary[ ary.size - n, ary.size - 1 ]
end
end

View File

@ -11,8 +11,9 @@ def hash_of_file path
return hash.hexdigest return hash.hexdigest
end end
def speedprofile_hash def profile_hash
@speedprofile_hash ||= hash_of_file "../profiles/#{@speedprofile}.lua" @@profile_hashes ||= {}
@@profile_hashes[@profile] ||= hash_of_file "../profiles/#{@profile}.lua"
end end
def osm_hash def osm_hash
@ -20,19 +21,19 @@ def osm_hash
end end
def bin_extract_hash def bin_extract_hash
@bin_hash ||= hash_of_file '../osrm-extract' @@bin_extract_hash ||= hash_of_file '../osrm-extract'
end end
def bin_prepare_hash def bin_prepare_hash
@bin_hash ||= hash_of_file '../osrm-prepare' @@bin_prepare_hash ||= hash_of_file '../osrm-prepare'
end end
def bin_routed_hash def bin_routed_hash
@bin_hash ||= hash_of_file '../osrm-routed' @@bin_routed_hash ||= hash_of_file '../osrm-routed'
end end
#combine state of data, speedprofile and binaries into a hash that identifies the exact test scenario #combine state of data, profile and binaries into a hash that identifies the exact test scenario
def fingerprint def fingerprint
@fingerprint ||= Digest::SHA1.hexdigest "#{bin_extract_hash}-#{bin_prepare_hash}-#{bin_routed_hash}-#{speedprofile_hash}-#{osm_hash}" @fingerprint ||= Digest::SHA1.hexdigest "#{bin_extract_hash}-#{bin_prepare_hash}-#{bin_routed_hash}-#{profile_hash}-#{osm_hash}"
end end

View File

@ -1,3 +1,6 @@
STRESS_TIMEOUT = 300
Before do |scenario| Before do |scenario|
@scenario_title = scenario.title @scenario_title = scenario.title
@scenario_time = Time.now.strftime("%Y-%m-%dT%H:%m:%SZ") @scenario_time = Time.now.strftime("%Y-%m-%dT%H:%m:%SZ")
@ -7,12 +10,11 @@ Before do |scenario|
set_grid_size DEFAULT_GRID_SIZE set_grid_size DEFAULT_GRID_SIZE
end end
Around('@routing') do |scenario, block| Around('@stress') do |scenario, block|
Timeout.timeout(10) do Timeout.timeout(STRESS_TIMEOUT) do
block.call block.call
end end
end end
After do After do
osrm_kill
end end

View File

@ -1,71 +1,83 @@
require 'socket' require 'socket'
require 'sys/proctable' require 'open3'
LAUNCH_TIMEOUT = 2
SHUTDOWN_TIMEOUT = 2
OSRM_ROUTED_LOG_FILE = 'osrm-routed.log'
class OSRMLauncher class OSRMLauncher
def initialize &block def initialize &block
Dir.chdir TEST_FOLDER do Dir.chdir TEST_FOLDER do
begin
launch
yield
ensure
shutdown
end
end
end
private
def launch
Timeout.timeout(LAUNCH_TIMEOUT) do
osrm_up osrm_up
yield wait_for_connection
end
rescue Timeout::Error
raise RoutedError.new "Launching osrm-routed timed out."
end
def shutdown
Timeout.timeout(SHUTDOWN_TIMEOUT) do
osrm_down osrm_down
end end
rescue Timeout::Error
kill
raise RoutedError.new "Shutting down osrm-routed timed out."
end end
end
def each_process name, &block def osrm_up?
Sys::ProcTable.ps do |process| if @pid
if process.comm.strip == name.strip `ps -o state -p #{@pid}`.split[1].to_s =~ /^[DRST]/
yield process.pid.to_i, process.state.strip else
false
end end
end end
end
def osrm_up? def osrm_up
find_pid('osrm-routed') != nil return if osrm_up?
end @pid = Process.spawn(['../osrm-routed',''],:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE)
end
def find_pid name def osrm_down
each_process(name) { |pid,state| return pid.to_i } if @pid
return nil Process.kill 'TERM', @pid
end wait_for_shutdown
end
end
def osrm_up def kill
return if osrm_up? if @pid
pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log') Process.kill 'KILL', @pid
timeout = 5 end
(timeout*10).times do end
begin
socket = TCPSocket.new('localhost', 5000) def wait_for_connection
socket.puts 'ping' while true
rescue Errno::ECONNREFUSED begin
socket = TCPSocket.new('localhost', OSRM_PORT)
return
rescue Errno::ECONNREFUSED
sleep 0.1
end
end
end
def wait_for_shutdown
while osrm_up?
sleep 0.1 sleep 0.1
end end
end end
sleep 0.1
end
def osrm_down
each_process('osrm-routed') { |pid,state| Process.kill 'TERM', pid }
each_process('osrm-prepare') { |pid,state| Process.kill 'TERM', pid }
each_process('osrm-extract') { |pid,state| Process.kill 'TERM', pid }
wait_for_shutdown 'osrm-routed'
wait_for_shutdown 'osrm-prepare'
wait_for_shutdown 'osrm-extract'
end
def osrm_kill
each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid }
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
wait_for_shutdown 'osrm-routed'
wait_for_shutdown 'osrm-prepare'
wait_for_shutdown 'osrm-extract'
end
def wait_for_shutdown name
timeout = 10
(timeout*10).times do
return if find_pid(name) == nil
sleep 0.1
end
raise "*** Could not terminate #{name}."
end end

View File

@ -14,7 +14,7 @@ def log_scenario_fail_info
log "Failed scenario: #{@scenario_title}" log "Failed scenario: #{@scenario_title}"
log "Time: #{@scenario_time}" log "Time: #{@scenario_time}"
log "Fingerprint: #{@fingerprint}" log "Fingerprint: #{@fingerprint}"
log "Profile: #{@speedprofile}" log "Profile: #{@profile}"
log log
log '```xml' #so output can be posted directly to github comment fields log '```xml' #so output can be posted directly to github comment fields
log osm_str.strip log osm_str.strip
@ -51,7 +51,7 @@ def log_preprocess_info
log '```', :preprocess log '```', :preprocess
log '', :preprocess log '', :preprocess
log "== Profile:", :preprocess log "== Profile:", :preprocess
log @speedprofile, :preprocess log @profile, :preprocess
log '', :preprocess log '', :preprocess
@has_logged_preprocess_info = true @has_logged_preprocess_info = true
end end

View File

@ -0,0 +1,23 @@
require 'OSM/StreamParser'
class OSMTestParserCallbacks < OSM::Callbacks
@@locations = nil
def self.locations
if @@locations
@@locations
else
#parse the test file, so we can later reference nodes and ways by name in tests
@@locations = {}
file = 'test/data/test.osm'
callbacks = OSMTestParserCallbacks.new
parser = OSM::StreamParser.new(:filename => file, :callbacks => callbacks)
parser.parse
puts @@locations
end
end
def node(node)
@@locations[node.name] = [node.lat,node.lon]
end
end

View File

@ -1,19 +1,26 @@
require 'net/http' require 'net/http'
HOST = "http://localhost:#{OSRM_PORT}"
REQUEST_TIMEOUT = 1
DESTINATION_REACHED = 15 #OSRM instruction code DESTINATION_REACHED = 15 #OSRM instruction code
def request_route a,b def request_path path
@query = "http://localhost:5000/viaroute?loc=#{a}&loc=#{b}&output=json&instructions=true" @query = path
#log @query uri = URI.parse "#{HOST}/#{path}"
uri = URI.parse @query Timeout.timeout(REQUEST_TIMEOUT) do
Net::HTTP.get_response uri Net::HTTP.get_response uri
end
rescue Errno::ECONNREFUSED => e rescue Errno::ECONNREFUSED => e
raise "*** osrm-routed is not running." raise "*** osrm-routed is not running."
rescue Timeout::Error rescue Timeout::Error
raise "*** osrm-routed did not respond." raise "*** osrm-routed did not respond."
end end
def request_route a,b
request_path "viaroute?loc=#{a}&loc=#{b}&output=json&instructions=true&alt=true"
end
def parse_response response def parse_response response
if response.code == "200" && response.body.empty? == false if response.code == "200" && response.body.empty? == false
json = JSON.parse response.body json = JSON.parse response.body
@ -83,3 +90,27 @@ def bearing_list instructions
map { |r| r=="" ? '""' : r }. map { |r| r=="" ? '""' : r }.
join(',') join(',')
end end
def turn_list instructions
types = {
0 => :none,
1 => :straight,
2 => :slight_right,
3 => :right,
4 => :sharp_right,
5 => :u_turn,
6 => :sharp_left,
7 => :left,
8 => :slight_left,
9 => :via,
10 => :head,
11 => :enter_roundabout,
12 => :leave_roundabout,
13 => :stay_roundabout,
14 => :start_end_of_street,
15 => :destination
}
instructions.
map { |r| types[r[0].to_i].to_s }.
join(',')
end

View File

@ -2,7 +2,7 @@
Feature: Handle bad data in a graceful manner Feature: Handle bad data in a graceful manner
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Empty dataset Scenario: Empty dataset
Given the node map Given the node map
@ -12,7 +12,7 @@ Feature: Handle bad data in a graceful manner
| nodes | | nodes |
When I preprocess data When I preprocess data
Then preparing should return code 255 Then "osrm-extract" should return code 255
Scenario: Only dead-end oneways Scenario: Only dead-end oneways
Given the node map Given the node map

View File

@ -2,7 +2,7 @@
Feature: Basic Routing Feature: Basic Routing
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
@smallest @smallest
Scenario: A single way with two nodes Scenario: A single way with two nodes

View File

@ -2,7 +2,7 @@
Feature: Compass bearing Feature: Compass bearing
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Bearing when going northwest Scenario: Bearing when going northwest
Given the node map Given the node map

View File

@ -2,7 +2,7 @@
Feature: Distance calculation Feature: Distance calculation
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: 100m distance Scenario: 100m distance
Given a grid size of 100 meters Given a grid size of 100 meters

View File

@ -2,7 +2,7 @@
Feature: Testbot - Handle ferry routes Feature: Testbot - Handle ferry routes
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Testbot - Ferry duration, single node Scenario: Testbot - Ferry duration, single node
Given the node map Given the node map
@ -38,7 +38,8 @@ Feature: Testbot - Handle ferry routes
| from | to | route | time | | from | to | route | time |
| a | d | abcd | 3600s +-1 | | a | d | abcd | 3600s +-1 |
| d | a | abcd | 3600s +-1 | | d | a | abcd | 3600s +-1 |
@todo
Scenario: Bike - Ferry duration, individual parts Scenario: Bike - Ferry duration, individual parts
Given the node map Given the node map
| x | y | | z | | | v | | x | y | | z | | | v |

View File

@ -2,7 +2,7 @@
Feature: Routing close to the [0,0] origin Feature: Routing close to the [0,0] origin
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: East-west oneways close to the origin Scenario: East-west oneways close to the origin
Given the node locations Given the node locations

View File

@ -3,7 +3,7 @@ Feature: Penalties
Testbot uses a signal penalty of 7s. Testbot uses a signal penalty of 7s.
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Traffic signals should incur a delay, without changing distance Scenario: Traffic signals should incur a delay, without changing distance
Given the node map Given the node map

View File

@ -1,8 +1,7 @@
@routing @planetary @routing @planetary
Feature: Distance calculation Feature: Distance calculation
Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VDistance/
Scenario: Longitudinal distances at equator Scenario: Approximated Longitudinal distances at equator
Given the node locations Given the node locations
| node | lat | lon | | node | lat | lon |
| a | 0 | 80 | | a | 0 | 80 |
@ -16,7 +15,7 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
| from | to | route | distance | | from | to | route | distance |
| a | b | ab | 8905559m ~0.1% | | a | b | ab | 8905559m ~0.1% |
Scenario: Longitudinal distances at latitude 45 Scenario: Approximated Longitudinal distances at latitude 45
Given the node locations Given the node locations
| node | lat | lon | | node | lat | lon |
| c | 45 | 80 | | c | 45 | 80 |
@ -28,9 +27,9 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
When I route I should get When I route I should get
| from | to | route | distance | | from | to | route | distance |
| c | d | cd | 6028844m ~0.5% | | c | d | cd | 6028844m ~4.5% |
Scenario: Longitudinal distances at latitude 80 Scenario: Approximated Longitudinal distances at latitude 80
Given the node locations Given the node locations
| node | lat | lon | | node | lat | lon |
| c | 80 | 80 | | c | 80 | 80 |
@ -42,9 +41,9 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
When I route I should get When I route I should get
| from | to | route | distance | | from | to | route | distance |
| c | d | cd | 1431469m ~0.5% | | c | d | cd | 1431469m ~9.5% |
Scenario: Latitudinal distances at longitude 0 Scenario: Approximated Latitudinal distances at longitude 0
Given the node locations Given the node locations
| node | lat | lon | | node | lat | lon |
| a | 80 | 0 | | a | 80 | 0 |
@ -58,7 +57,7 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
| from | to | route | distance | | from | to | route | distance |
| a | b | ab | 8905559m ~0.1% | | a | b | ab | 8905559m ~0.1% |
Scenario: Latitudinal distances at longitude 45 Scenario: Approximated Latitudinal distances at longitude 45
Given the node locations Given the node locations
| node | lat | lon | | node | lat | lon |
| a | 80 | 45 | | a | 80 | 45 |
@ -72,7 +71,7 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
| from | to | route | distance | | from | to | route | distance |
| a | b | ab | 8905559m ~0.1% | | a | b | ab | 8905559m ~0.1% |
Scenario: Latitudinal distances at longitude 80 Scenario: Approximated Latitudinal distances at longitude 80
Given the node locations Given the node locations
| node | lat | lon | | node | lat | lon |
| a | 80 | 80 | | a | 80 | 80 |

View File

@ -2,7 +2,7 @@
Feature: Snap start/end point to the nearest way Feature: Snap start/end point to the nearest way
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Snap to nearest protruding oneway Scenario: Snap to nearest protruding oneway
Given the node map Given the node map
@ -98,7 +98,6 @@ Feature: Snap start/end point to the nearest way
| b | x | xb | | b | x | xb |
| c | x | xc | | c | x | xc |
@xx
Scenario: Find edges within 1km, but not 10km Scenario: Find edges within 1km, but not 10km
Given a grid size of 1000 meters Given a grid size of 1000 meters
Given the node map Given the node map
@ -152,5 +151,4 @@ Feature: Snap start/end point to the nearest way
| x | m | | | x | m | |
| x | n | | | x | n | |
| x | o | | | x | o | |
| x | p | | | x | p | |

View File

@ -6,7 +6,7 @@ Secondary road: 18km/h = 18000m/3600s = 100m/20s
Tertiary road: 12km/h = 12000m/3600s = 100m/30s Tertiary road: 12km/h = 12000m/3600s = 100m/30s
Background: Use specific speeds Background: Use specific speeds
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Basic travel time, 10m scale Scenario: Basic travel time, 10m scale
Given a grid size of 10 meters Given a grid size of 10 meters

View File

@ -0,0 +1,115 @@
@routing @turns
Feature: Turn directions/codes
Background:
Given the profile "testbot"
Scenario: Turn directions
Given the node map
| o | p | a | b | c |
| n | | | | d |
| m | | x | | e |
| l | | | | f |
| k | j | i | h | g |
And the ways
| nodes |
| xa |
| xb |
| xc |
| xd |
| xe |
| xf |
| xg |
| xh |
| xi |
| xj |
| xk |
| xl |
| xm |
| xn |
| xo |
| xp |
When I route I should get
| from | to | route | turns |
| i | k | xi,xk | head,sharp_left,destination |
| i | m | xi,xm | head,left,destination |
| i | o | xi,xo | head,slight_left,destination |
| i | a | xi,xa | head,straight,destination |
| i | c | xi,xc | head,slight_right,destination |
| i | e | xi,xe | head,right,destination |
| i | g | xi,xg | head,sharp_right,destination |
| k | m | xk,xm | head,sharp_left,destination |
| k | o | xk,xo | head,left,destination |
| k | a | xk,xa | head,slight_left,destination |
| k | c | xk,xc | head,straight,destination |
| k | e | xk,xe | head,slight_right,destination |
| k | g | xk,xg | head,right,destination |
| k | i | xk,xi | head,sharp_right,destination |
| m | o | xm,xo | head,sharp_left,destination |
| m | a | xm,xa | head,left,destination |
| m | c | xm,xc | head,slight_left,destination |
| m | e | xm,xe | head,straight,destination |
| m | g | xm,xg | head,slight_right,destination |
| m | i | xm,xi | head,right,destination |
| m | k | xm,xk | head,sharp_right,destination |
| o | a | xo,xa | head,sharp_left,destination |
| o | c | xo,xc | head,left,destination |
| o | e | xo,xe | head,slight_left,destination |
| o | g | xo,xg | head,straight,destination |
| o | i | xo,xi | head,slight_right,destination |
| o | k | xo,xk | head,right,destination |
| o | m | xo,xm | head,sharp_right,destination |
| a | c | xa,xc | head,sharp_left,destination |
| a | e | xa,xe | head,left,destination |
| a | g | xa,xg | head,slight_left,destination |
| a | i | xa,xi | head,straight,destination |
| a | k | xa,xk | head,slight_right,destination |
| a | m | xa,xm | head,right,destination |
| a | o | xa,xo | head,sharp_right,destination |
| c | e | xc,xe | head,sharp_left,destination |
| c | g | xc,xg | head,left,destination |
| c | i | xc,xi | head,slight_left,destination |
| c | k | xc,xk | head,straight,destination |
| c | m | xc,xm | head,slight_right,destination |
| c | o | xc,xo | head,right,destination |
| c | a | xc,xa | head,sharp_right,destination |
| e | g | xe,xg | head,sharp_left,destination |
| e | i | xe,xi | head,left,destination |
| e | k | xe,xk | head,slight_left,destination |
| e | m | xe,xm | head,straight,destination |
| e | o | xe,xo | head,slight_right,destination |
| e | a | xe,xa | head,right,destination |
| e | c | xe,xc | head,sharp_right,destination |
| g | i | xg,xi | head,sharp_left,destination |
| g | k | xg,xk | head,left,destination |
| g | m | xg,xm | head,slight_left,destination |
| g | o | xg,xo | head,straight,destination |
| g | a | xg,xa | head,slight_right,destination |
| g | c | xg,xc | head,right,destination |
| g | e | xg,xe | head,sharp_right,destination |
Scenario: Skadestuevej, København
https://github.com/DennisOSRM/Project-OSRM/issues/532
Given the node locations
| node | lat | lon |
| a | 55.68679 | 12.52360 |
| b | 55.68745 | 12.52407 |
| c | 55.68720 | 12.52509 |
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | route | turns |
| a | c | ab,bc | head,right,destination |

View File

@ -2,7 +2,7 @@
Feature: Handling of UTF characters Feature: Handling of UTF characters
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Streetnames with UTF characters Scenario: Streetnames with UTF characters
Given the node map Given the node map

View File

@ -2,7 +2,7 @@
Feature: Choosing route based on length, speed, etc Feature: Choosing route based on length, speed, etc
Background: Background:
Given the speedprofile "testbot" Given the profile "testbot"
Scenario: Pick the geometrically shortest route, way types being equal Scenario: Pick the geometrically shortest route, way types being equal
Given the node map Given the node map

View File

@ -0,0 +1,12 @@
@timestamp
Feature: Timestamp
Scenario: Request timestamp
Given the node map
| a | b |
And the ways
| nodes |
| ab |
When I request /timestamp
Then I should get a valid timestamp

View File

@ -1,5 +1,5 @@
-- Begin of globals -- Begin of globals
barrier_whitelist = { [""] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true} barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true}
access_tag_whitelist = { ["yes"] = true, ["permissive"] = true, ["designated"] = true } access_tag_whitelist = { ["yes"] = true, ["permissive"] = true, ["designated"] = true }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true } access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true } access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
@ -121,6 +121,7 @@ function way_function (way, numberOfNodesInWay)
local junction = way.tags:Find("junction") local junction = way.tags:Find("junction")
local route = way.tags:Find("route") local route = way.tags:Find("route")
local railway = way.tags:Find("railway") local railway = way.tags:Find("railway")
local public_transport = way.tags:Find("public_transport")
local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") ) local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") )
local man_made = way.tags:Find("man_made") local man_made = way.tags:Find("man_made")
local barrier = way.tags:Find("barrier") local barrier = way.tags:Find("barrier")
@ -135,12 +136,14 @@ function way_function (way, numberOfNodesInWay)
local amenity = way.tags:Find("amenity") local amenity = way.tags:Find("amenity")
local access = find_access_tag(way) local access = find_access_tag(way)
-- only route on things with highway tag set (not buildings, boundaries, etc) -- initial routability check, filters out buildings, boundaries, etc
if (not highway or highway == '') and if (not highway or highway == '') and
(not route or route == '') and (not route or route == '') and
(not railway or railway=='') and (not railway or railway=='') and
(not amenity or amenity=='') then (not amenity or amenity=='') and
return 0 (not public_transport or public_transport=='')
then
return 0
end end
-- access -- access
@ -168,8 +171,11 @@ function way_function (way, numberOfNodesInWay)
way.speed = route_speeds[route] way.speed = route_speeds[route]
end end
elseif railway and platform_speeds[railway] then elseif railway and platform_speeds[railway] then
-- railway platforms -- railway platforms (old tagging scheme)
way.speed = platform_speeds[railway] way.speed = platform_speeds[railway]
elseif platform_speeds[public_transport] then
-- public_transport platforms (new tagging platform)
way.speed = platform_speeds[public_transport]
elseif railway and railway_speeds[railway] then elseif railway and railway_speeds[railway] then
-- railways -- railways
if access and access_tag_whitelist[access] then if access and access_tag_whitelist[access] then

View File

@ -2,7 +2,7 @@
barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true} barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true}
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true } access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true } access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true } access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
access_tags = { "motorcar", "motor_vehicle", "vehicle" } access_tags = { "motorcar", "motor_vehicle", "vehicle" }
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }

View File

@ -82,7 +82,7 @@ int main (int argc, char * argv[0]) {
//} //}
try { try {
std::cout << "[server] starting up engines, saved at " << __TIMESTAMP__ << std::endl; std::cout << std::endl << "[server] starting up engines, saved at " << __TIMESTAMP__ << std::endl;
#ifndef _WIN32 #ifndef _WIN32
int sig = 0; int sig = 0;
@ -135,11 +135,14 @@ int main (int argc, char * argv[0]) {
s->Run(); s->Run();
#endif #endif
std::cout << std::endl << "[server] shutting down" << std::endl; std::cout << "[server] initiating shutdown" << std::endl;
s->Stop(); s->Stop();
std::cout << "[server] stopping threads" << std::endl;
t.join(); t.join();
std::cout << "[server] freeing objects" << std::endl;
delete s; delete s;
delete objects; delete objects;
std::cout << "[server] shutdown completed" << std::endl;
} catch (std::exception& e) { } catch (std::exception& e) {
std::cerr << "[fatal error] exception: " << e.what() << std::endl; std::cerr << "[fatal error] exception: " << e.what() << std::endl;
} }