Merge branch 'develop'
This commit is contained in:
commit
6574436c33
@ -41,7 +41,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include "../DataStructures/NodeCoords.h"
|
||||
#include "../DataStructures/Percent.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
|
||||
// Strongly connected components using Tarjan's Algorithm
|
||||
|
||||
@ -66,7 +66,7 @@ private:
|
||||
unsigned nameID;
|
||||
bool forward;
|
||||
bool backward;
|
||||
short turnInstruction;
|
||||
TurnInstruction turnInstruction;
|
||||
};
|
||||
|
||||
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
NodeID via;
|
||||
unsigned nameID;
|
||||
int distance;
|
||||
short turnInstruction;
|
||||
TurnInstruction turnInstruction;
|
||||
bool shortcut:1;
|
||||
bool forward:1;
|
||||
bool backward:1;
|
||||
|
@ -122,8 +122,7 @@ public:
|
||||
assert( newEdge.data.distance > 0 );
|
||||
#ifndef NDEBUG
|
||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
||||
std::cout << "Edge Weight too large -> May lead to invalid CH" << std::endl;
|
||||
continue;
|
||||
WARN("Edge weight large -> " << newEdge.data.distance);
|
||||
}
|
||||
#endif
|
||||
edges.push_back( newEdge );
|
||||
|
@ -95,8 +95,6 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdg
|
||||
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -280,7 +278,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
|
||||
if(_trafficLights.find(v) != _trafficLights.end()) {
|
||||
distance += speedProfile.trafficSignalPenalty;
|
||||
}
|
||||
short turnInstruction = AnalyzeTurn(u, v, w);
|
||||
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
|
||||
if(turnInstruction == TurnInstructions.UTurn)
|
||||
distance += speedProfile.uTurnPenalty;
|
||||
// if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
|
||||
@ -297,7 +295,6 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
|
||||
}
|
||||
OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction);
|
||||
EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false );
|
||||
assert(u != w);
|
||||
originalEdgeData.push_back(oed);
|
||||
if(originalEdgeData.size() > 100000) {
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
return TurnInstructions.UTurn;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ private:
|
||||
unsigned nameID;
|
||||
bool forward;
|
||||
bool backward;
|
||||
short turnInstruction;
|
||||
TurnInstruction turnInstruction;
|
||||
};
|
||||
|
||||
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
|
||||
@ -138,7 +138,7 @@ public:
|
||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||
void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes);
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -57,23 +57,7 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
|
||||
assert(lon1 != INT_MIN);
|
||||
assert(lat2 != 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;
|
||||
//std::cout << "RAD: " << RAD << std::endl;
|
||||
//main code inside the class
|
||||
double lt1 = lat1/100000.;
|
||||
double ln1 = lon1/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
|
||||
double distance=earth*cHarv;
|
||||
return distance;
|
||||
|
||||
|
||||
}
|
||||
|
||||
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
|
||||
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_ */
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
return origEdgeData.at(id).nameID;
|
||||
}
|
||||
|
||||
inline short getTurnInstructionFromEdgeID(const unsigned id) const {
|
||||
inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
|
||||
return origEdgeData.at(id).turnInstruction;
|
||||
}
|
||||
|
||||
|
@ -23,16 +23,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#ifndef QUERYEDGE_H_
|
||||
#define QUERYEDGE_H_
|
||||
|
||||
#include <climits>
|
||||
|
||||
#include "TurnInstructions.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
struct OriginalEdgeData{
|
||||
explicit OriginalEdgeData(NodeID v, unsigned n, short t) : viaNode(v), nameID(n), turnInstruction(t) {}
|
||||
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(SHRT_MAX) {}
|
||||
explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {}
|
||||
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
|
||||
NodeID viaNode;
|
||||
unsigned nameID;
|
||||
short turnInstruction;
|
||||
TurnInstruction turnInstruction;
|
||||
};
|
||||
|
||||
struct QueryEdge {
|
||||
|
@ -23,17 +23,19 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
#include <climits>
|
||||
|
||||
#include "TurnInstructions.h"
|
||||
|
||||
struct SegmentInformation {
|
||||
_Coordinate location;
|
||||
NodeID nameID;
|
||||
double length;
|
||||
unsigned duration;
|
||||
double bearing;
|
||||
short turnInstruction;
|
||||
TurnInstruction turnInstruction;
|
||||
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) {}
|
||||
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) {}
|
||||
};
|
||||
|
||||
|
@ -23,28 +23,30 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef unsigned char TurnInstruction;
|
||||
|
||||
//This is a hack until c++0x is available enough to use scoped enums
|
||||
struct TurnInstructionsClass {
|
||||
|
||||
const static short NoTurn = 0; //Give no instruction at all
|
||||
const static short GoStraight = 1; //Tell user to go straight!
|
||||
const static short TurnSlightRight = 2;
|
||||
const static short TurnRight = 3;
|
||||
const static short TurnSharpRight = 4;
|
||||
const static short UTurn = 5;
|
||||
const static short TurnSharpLeft = 6;
|
||||
const static short TurnLeft = 7;
|
||||
const static short TurnSlightLeft = 8;
|
||||
const static short ReachViaPoint = 9;
|
||||
const static short HeadOn = 10;
|
||||
const static short EnterRoundAbout = 11;
|
||||
const static short LeaveRoundAbout = 12;
|
||||
const static short StayOnRoundAbout = 13;
|
||||
const static short StartAtEndOfStreet = 14;
|
||||
const static short ReachedYourDestination = 15;
|
||||
const static TurnInstruction NoTurn = 0; //Give no instruction at all
|
||||
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
|
||||
const static TurnInstruction TurnSlightRight = 2;
|
||||
const static TurnInstruction TurnRight = 3;
|
||||
const static TurnInstruction TurnSharpRight = 4;
|
||||
const static TurnInstruction UTurn = 5;
|
||||
const static TurnInstruction TurnSharpLeft = 6;
|
||||
const static TurnInstruction TurnLeft = 7;
|
||||
const static TurnInstruction TurnSlightLeft = 8;
|
||||
const static TurnInstruction ReachViaPoint = 9;
|
||||
const static TurnInstruction HeadOn = 10;
|
||||
const static TurnInstruction EnterRoundAbout = 11;
|
||||
const static TurnInstruction LeaveRoundAbout = 12;
|
||||
const static TurnInstruction StayOnRoundAbout = 13;
|
||||
const static TurnInstruction StartAtEndOfStreet = 14;
|
||||
const static TurnInstruction ReachedYourDestination = 15;
|
||||
|
||||
const static short AccessRestrictionFlag = (1<<14);
|
||||
const static short InverseAccessRestrictionFlag = ~(1<<14);
|
||||
const static TurnInstruction AccessRestrictionFlag = 128;
|
||||
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
|
||||
|
||||
@ -84,7 +86,7 @@ struct TurnInstructionsClass {
|
||||
// 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) {
|
||||
return TurnSharpRight;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
|
||||
/** starts at index 1 */
|
||||
pathDescription[0].length = 0;
|
||||
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;
|
||||
@ -111,32 +111,37 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
|
||||
becomes:
|
||||
10. Turn left on B 36 for 35 km
|
||||
*/
|
||||
unsigned lastTurn = 0;
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||
if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||
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)){
|
||||
//TODO: rework to check only end and start of string.
|
||||
// stl string is way to expensive
|
||||
|
||||
// unsigned lastTurn = 0;
|
||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||
// 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);
|
||||
for(; lastTurn != i; ++lastTurn)
|
||||
pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||
pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
} 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)) {
|
||||
// for(; lastTurn != i; ++lastTurn)
|
||||
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
// } 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)
|
||||
// ){
|
||||
// INFO("->prev correct: " << string1 << " contains " << string0);
|
||||
pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||
pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
}
|
||||
}
|
||||
if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
lastTurn = i;
|
||||
}
|
||||
string0 = string1;
|
||||
}
|
||||
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
// }
|
||||
// }
|
||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
// lastTurn = i;
|
||||
// }
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
|
@ -69,7 +69,9 @@ public:
|
||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
||||
|
||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
|
||||
|
||||
WriteHeaderToOutput(reply.content);
|
||||
|
||||
if(rawRoute.lengthOfShortestPath != INT_MAX) {
|
||||
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
||||
reply.content += "0,"
|
||||
@ -102,7 +104,7 @@ public:
|
||||
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
|
||||
} else {
|
||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
||||
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
||||
}
|
||||
}
|
||||
@ -155,7 +157,7 @@ public:
|
||||
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
|
||||
} else {
|
||||
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
||||
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
||||
}
|
||||
}
|
||||
@ -242,7 +244,6 @@ public:
|
||||
reply.content += "},";
|
||||
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
|
||||
reply.content += "}";
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
//Fetch data from Factory and generate a string from it.
|
||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
||||
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
||||
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
|
||||
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
|
||||
@ -384,7 +385,6 @@ public:
|
||||
reply.content += "0.0";
|
||||
reply.content += "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -24,8 +24,6 @@ extern "C" {
|
||||
#include <lualib.h>
|
||||
}
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "ScriptingEnvironment.h"
|
||||
#include "../typedefs.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
|
@ -36,7 +36,7 @@ struct RouteParameters {
|
||||
bool geometry;
|
||||
bool compression;
|
||||
bool deprecatedAPI;
|
||||
int checkSum;
|
||||
unsigned checkSum;
|
||||
std::string service;
|
||||
std::string outputFormat;
|
||||
std::string jsonpParameter;
|
||||
@ -58,7 +58,7 @@ struct RouteParameters {
|
||||
deprecatedAPI = true;
|
||||
}
|
||||
|
||||
void setChecksum(const int c) {
|
||||
void setChecksum(const unsigned c) {
|
||||
checkSum = c;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,6 @@ public:
|
||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||
std::string tmp;
|
||||
std::string JSONParameter;
|
||||
|
||||
//json
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
@ -53,7 +52,7 @@ public:
|
||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
|
||||
reply.content += ("}");
|
||||
reply.headers.resize(3);
|
||||
if("" != JSONParameter) {
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += ")";
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
|
8
Rakefile
8
Rakefile
@ -6,6 +6,7 @@ require 'sys/proctable'
|
||||
|
||||
DATA_FOLDER = 'sandbox'
|
||||
PROFILE = 'bicycle'
|
||||
OSRM_PORT = 5000
|
||||
|
||||
Cucumber::Rake::Task.new do |t|
|
||||
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
|
||||
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
|
||||
end
|
||||
end
|
||||
@ -60,7 +61,7 @@ def write_server_ini osm_file
|
||||
s=<<-EOF
|
||||
Threads = 1
|
||||
IP = 0.0.0.0
|
||||
Port = 5000
|
||||
Port = #{OSRM_PORT}
|
||||
|
||||
hsgrData=#{osm_file}.osrm.hsgr
|
||||
nodesData=#{osm_file}.osrm.nodes
|
||||
@ -68,6 +69,7 @@ def write_server_ini osm_file
|
||||
ramIndex=#{osm_file}.osrm.ramIndex
|
||||
fileIndex=#{osm_file}.osrm.fileIndex
|
||||
namesData=#{osm_file}.osrm.names
|
||||
timestamp=#{osm_file}.osrm.timestamp
|
||||
EOF
|
||||
File.open( 'server.ini', 'w') {|f| f.write( s ) }
|
||||
end
|
||||
@ -150,7 +152,7 @@ task :up => :setup do
|
||||
timeout = 5
|
||||
(timeout*10).times do
|
||||
begin
|
||||
socket = TCPSocket.new('localhost', 5000)
|
||||
socket = TCPSocket.new('localhost', OSRM_PORT)
|
||||
socket.puts 'ping'
|
||||
rescue Errno::ECONNREFUSED
|
||||
sleep 0.1
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
|
||||
std::vector<NodeID> alternativePath;
|
||||
std::vector<NodeID> viaNodeCandidates;
|
||||
std::deque <NodeID> packedShortestPath;
|
||||
std::vector <NodeID> packedShortestPath;
|
||||
std::vector<PreselectedNode> nodesThatPassPreselection;
|
||||
|
||||
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,
|
||||
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
|
||||
//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);
|
||||
packed_s_v_path.resize(packed_s_v_path.size()-1);
|
||||
//unpack [v,t]
|
||||
@ -171,7 +171,7 @@ private:
|
||||
}
|
||||
|
||||
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
|
||||
//only half-searches have to be done at this stage
|
||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||
@ -181,8 +181,8 @@ private:
|
||||
HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
|
||||
HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
|
||||
|
||||
std::deque < NodeID > packed_s_v_path;
|
||||
std::deque < NodeID > packed_v_t_path;
|
||||
std::vector < NodeID > packed_s_v_path;
|
||||
std::vector < NodeID > packed_v_t_path;
|
||||
|
||||
std::vector<NodeID> partiallyUnpackedShortestPath;
|
||||
std::vector<NodeID> partiallyUnpackedViaPath;
|
||||
@ -258,8 +258,8 @@ private:
|
||||
//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) {
|
||||
std::deque<NodeID> packedAlternativePath;
|
||||
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
|
||||
std::vector<NodeID> packedAlternativePath;
|
||||
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
|
||||
|
||||
if(packedShortestPath.size() < 2 || packedAlternativePath.size() < 2)
|
||||
@ -336,8 +336,8 @@ private:
|
||||
|
||||
//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) {
|
||||
std::deque < NodeID > packed_s_v_path;
|
||||
std::deque < NodeID > packed_v_t_path;
|
||||
std::vector < NodeID > packed_s_v_path;
|
||||
std::vector < NodeID > packed_v_t_path;
|
||||
|
||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||
*s_v_middle = UINT_MAX;
|
||||
|
@ -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();
|
||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
||||
@ -204,13 +204,15 @@ public:
|
||||
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;
|
||||
while(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);
|
||||
pathNode = middle;
|
||||
while (pathNode != _bHeap->GetData(pathNode).parent){
|
||||
|
@ -47,8 +47,8 @@ public:
|
||||
bool searchFrom2ndStartNode(true);
|
||||
NodeID middle1 = ( NodeID ) UINT_MAX;
|
||||
NodeID middle2 = ( NodeID ) UINT_MAX;
|
||||
std::deque<NodeID> packedPath1;
|
||||
std::deque<NodeID> packedPath2;
|
||||
std::vector<NodeID> packedPath1;
|
||||
std::vector<NodeID> packedPath2;
|
||||
|
||||
typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap;
|
||||
typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap;
|
||||
@ -141,8 +141,8 @@ public:
|
||||
// INFO("middle1: " << middle1);
|
||||
|
||||
//Unpack paths if they exist
|
||||
std::deque<NodeID> temporaryPackedPath1;
|
||||
std::deque<NodeID> temporaryPackedPath2;
|
||||
std::vector<NodeID> temporaryPackedPath1;
|
||||
std::vector<NodeID> temporaryPackedPath2;
|
||||
if(INT_MAX != _localUpperbound1) {
|
||||
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1);
|
||||
// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) );
|
||||
|
@ -32,8 +32,8 @@ namespace qi = boost::spirit::qi;
|
||||
template <typename Iterator, class HandlerT>
|
||||
struct APIGrammar : qi::grammar<Iterator> {
|
||||
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
||||
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) ) ;
|
||||
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
|
||||
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)];
|
||||
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, 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;
|
||||
|
||||
HandlerT * handler;
|
||||
|
@ -46,8 +46,8 @@ QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIn
|
||||
}
|
||||
if(!timestamp.length())
|
||||
timestamp = "n/a";
|
||||
if(15 < timestamp.length())
|
||||
timestamp.resize(15);
|
||||
if(25 < timestamp.length())
|
||||
timestamp.resize(25);
|
||||
|
||||
INFO("Loading auxiliary information");
|
||||
//Init nearest neighbor data structure
|
||||
|
@ -61,7 +61,7 @@ struct ServerFactory {
|
||||
ERR("file index file not found");
|
||||
}
|
||||
|
||||
unsigned threads = omp_get_num_procs();
|
||||
int threads = omp_get_num_procs();
|
||||
if(serverConfig.GetParameter("IP") == "")
|
||||
serverConfig.SetParameter("IP", "0.0.0.0");
|
||||
if(serverConfig.GetParameter("Port") == "")
|
||||
|
@ -41,6 +41,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include "../DataStructures/DeallocatingVector.h"
|
||||
#include "../DataStructures/DynamicGraph.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../Util/BaseConfiguration.h"
|
||||
#include "../Util/InputFileUtil.h"
|
||||
#include "../Util/GraphLoader.h"
|
||||
|
@ -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
|
@ -2,3 +2,4 @@
|
||||
##YAML Template
|
||||
---
|
||||
default: --require features
|
||||
verify: --require features --tags ~@todo --tag ~@stress -f progress
|
@ -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.
|
||||
*/
|
||||
|
||||
#define VERBOSE(x) x
|
||||
#define VERBOSE2(x)
|
||||
|
||||
#ifdef NDEBUG
|
||||
#undef VERBOSE
|
||||
#undef VERBOSE2
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
@ -139,7 +131,6 @@ int main (int argc, char *argv[]) {
|
||||
speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1);
|
||||
|
||||
|
||||
|
||||
std::vector<ImportEdge> edgeList;
|
||||
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
|
||||
in.close();
|
||||
|
@ -3,7 +3,7 @@ Feature: Bike - Restricted access
|
||||
Reference: http://wiki.openstreetmap.org/wiki/Key:access
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Access tag hierachy on ways
|
||||
Then routability should be
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Bike - Squares and other areas
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
@square
|
||||
Scenario: Bike - Route along edge of a squares
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Barriers
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Barriers
|
||||
Then routability should be
|
||||
@ -10,6 +10,7 @@ Feature: Barriers
|
||||
| | x |
|
||||
| bollard | x |
|
||||
| gate | x |
|
||||
| cycle_barrier | x |
|
||||
| cattle_grid | x |
|
||||
| border_control | x |
|
||||
| toll_booth | x |
|
||||
|
@ -3,7 +3,7 @@ Feature: Bike - Cycle tracks/lanes
|
||||
Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Cycle tracks/lanes should enable biking
|
||||
Then routability should be
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Bike - Destination only, no passing through
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Destination only street
|
||||
Given the node map
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Bike - Handle ferry routes
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Ferry route
|
||||
Given the node map
|
||||
@ -114,6 +114,7 @@ Feature: Bike - Handle ferry routes
|
||||
| a | g | abcdefg | 23400s +-1 |
|
||||
| g | a | abcdefg | 23400s +-1 |
|
||||
|
||||
@todo
|
||||
Scenario: Bike - Ferry duration, individual parts
|
||||
Given the node map
|
||||
| x | y | | z | | | v |
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Bike - Max speed restrictions
|
||||
|
||||
Background: Use specific speeds
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Respect maxspeeds when lower that way type speed
|
||||
Given the node map
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Bike - Street names in instructions
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - A named street
|
||||
Given the node map
|
||||
@ -19,26 +19,14 @@ Feature: Bike - Street names in instructions
|
||||
| a | c | My Way,Your Way |
|
||||
|
||||
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
|
||||
| a | b | c | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name |
|
||||
| abcd | cycleway | |
|
||||
| ab | cycleway | |
|
||||
| bcd | track | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | d | cycleway |
|
||||
| a | d | cycleway,track |
|
@ -3,7 +3,7 @@ Feature: Bike - Oneway streets
|
||||
Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Simple oneway
|
||||
Then routability should be
|
||||
|
@ -4,7 +4,7 @@ Feature: Bike - Turn restrictions
|
||||
Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
|
||||
|
||||
Background: Use car routing
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
@no_turning
|
||||
Scenario: Bike - No left turn
|
||||
|
37
features/bicycle/stop_area.feature
Normal file
37
features/bicycle/stop_area.feature
Normal 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/ |
|
@ -3,7 +3,7 @@ Feature: Bike - Handle ferry routes
|
||||
Bringing bikes on trains and subways
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Bringing bikes on trains
|
||||
Then routability should be
|
||||
|
@ -2,11 +2,11 @@
|
||||
Feature: Bike - Accessability of different way types
|
||||
|
||||
Background:
|
||||
Given the speedprofile "bicycle"
|
||||
Given the profile "bicycle"
|
||||
|
||||
Scenario: Bike - Basic access
|
||||
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
|
||||
| highway | forw |
|
||||
| (nil) | |
|
||||
|
@ -3,7 +3,7 @@ Feature: Car - Restricted access
|
||||
Reference: http://wiki.openstreetmap.org/wiki/Key:access
|
||||
|
||||
Background:
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - Access tag hierachy on ways
|
||||
Then routability should be
|
||||
@ -92,7 +92,7 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access
|
||||
| no | |
|
||||
| private | |
|
||||
| agricultural | |
|
||||
| forestery | |
|
||||
| forestry | |
|
||||
| some_tag | x |
|
||||
|
||||
|
||||
@ -105,7 +105,7 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access
|
||||
| no | |
|
||||
| private | |
|
||||
| agricultural | |
|
||||
| forestery | |
|
||||
| forestry | |
|
||||
| some_tag | x |
|
||||
|
||||
Scenario: Car - Access tags on both node and way
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Car - Barriers
|
||||
|
||||
Background:
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - Barriers
|
||||
Then routability should be
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Car - Destination only, no passing through
|
||||
|
||||
Background:
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - Destination only street
|
||||
Given the node map
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Car - Handle ferry routes
|
||||
|
||||
Background:
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - Use a ferry route
|
||||
Given the node map
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Car - Max speed restrictions
|
||||
|
||||
Background: Use specific speeds
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
Given a grid size of 1000 meters
|
||||
|
||||
Scenario: Car - Respect maxspeeds when lower that way type speed
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Car - Street names in instructions
|
||||
|
||||
Background:
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - A named street
|
||||
Given the node map
|
||||
@ -18,27 +18,16 @@ Feature: Car - Street names in instructions
|
||||
| from | to | route |
|
||||
| a | c | My Way,Your Way |
|
||||
|
||||
@todo
|
||||
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
|
||||
| a | b | c | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name |
|
||||
| abcd | primary | |
|
||||
| ab | tertiary | |
|
||||
| bcd | residential | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | d | primary |
|
||||
| a | c | tertiary,residential |
|
||||
|
@ -3,7 +3,7 @@ Feature: Car - Oneway streets
|
||||
Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
|
||||
|
||||
Background:
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - Simple oneway
|
||||
Then routability should be
|
||||
|
@ -4,7 +4,7 @@ Feature: Car - Turn restrictions
|
||||
Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
|
||||
|
||||
Background: Use car routing
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
@no_turning
|
||||
Scenario: Car - No left turn
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Car - Accessability of different way types
|
||||
|
||||
Background:
|
||||
Given the speedprofile "car"
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - Basic access
|
||||
Then routability should be
|
||||
|
@ -3,7 +3,7 @@ Feature: Foot - Oneway streets
|
||||
Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
|
||||
|
||||
Background:
|
||||
Given the speedprofile "foot"
|
||||
Given the profile "foot"
|
||||
|
||||
Scenario: Foot - Walking should not be affected by oneways
|
||||
Then routability should be
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Foot - Accessability of different way types
|
||||
|
||||
Background:
|
||||
Given the speedprofile "foot"
|
||||
Given the profile "foot"
|
||||
|
||||
Scenario: Foot - Basic access
|
||||
Then routability should be
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Weird routings discovered
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Routing on a oneway roundabout
|
||||
Given the node map
|
||||
|
@ -1,5 +1,5 @@
|
||||
Given /^the speedprofile "([^"]*)"$/ do |profile|
|
||||
read_speedprofile profile
|
||||
Given /^the profile "([^"]*)"$/ do |profile|
|
||||
set_profile profile
|
||||
end
|
||||
|
||||
Given /^a grid size of (\d+) meters$/ do |meters|
|
||||
|
@ -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
|
@ -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
|
||||
|
45
features/step_definitions/requests.rb
Normal file
45
features/step_definitions/requests.rb
Normal 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
|
40
features/step_definitions/routability.rb
Normal file
40
features/step_definitions/routability.rb
Normal 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
|
@ -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|
|
||||
osrm_kill
|
||||
reprocess
|
||||
actual = []
|
||||
OSRMLauncher.new do
|
||||
@ -204,6 +14,7 @@ When /^I route I should get$/ do |table|
|
||||
instructions = way_list json['route_instructions']
|
||||
bearings = bearing_list json['route_instructions']
|
||||
compasses = compass_list json['route_instructions']
|
||||
turns = turn_list json['route_instructions']
|
||||
end
|
||||
end
|
||||
|
||||
@ -232,11 +43,14 @@ When /^I route I should get$/ do |table|
|
||||
if table.headers.include? 'compass'
|
||||
got['compass'] = compasses
|
||||
end
|
||||
if table.headers.include? 'turns'
|
||||
got['turns'] = turns
|
||||
end
|
||||
end
|
||||
|
||||
ok = true
|
||||
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
|
||||
from = $1.to_f*margin
|
||||
to = $1.to_f/margin
|
||||
@ -245,7 +59,7 @@ When /^I route I should get$/ do |table|
|
||||
else
|
||||
ok = false
|
||||
end
|
||||
elsif row[key].match /(.*)\s+\+\-(.+)$/
|
||||
elsif row[key].match /(.*)\s+\+\-(.+)$/ #absolute range: 100 +-5
|
||||
margin = $2.to_f
|
||||
from = $1.to_f-margin
|
||||
to = $1.to_f+margin
|
||||
@ -254,6 +68,10 @@ When /^I route I should get$/ do |table|
|
||||
else
|
||||
ok = false
|
||||
end
|
||||
elsif row[key] =~ /^\/(.*)\/$/ #regex: /a,b,.*/
|
||||
if got[key] =~ /#{$1}/
|
||||
got[key] = row[key]
|
||||
end
|
||||
else
|
||||
ok = row[key] == got[key]
|
||||
end
|
||||
@ -269,3 +87,11 @@ When /^I route I should get$/ do |table|
|
||||
end
|
||||
table.routing_diff! actual
|
||||
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
|
7
features/step_definitions/timestamp.rb
Normal file
7
features/step_definitions/timestamp.rb
Normal 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
|
58
features/stress/launch.feature
Normal file
58
features/stress/launch.feature
Normal 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 |
|
@ -1,21 +1,21 @@
|
||||
def speedprofile
|
||||
@speedprofile ||= reset_speedprofile
|
||||
def profile
|
||||
@profile ||= reset_profile
|
||||
end
|
||||
|
||||
def reset_speedprofile
|
||||
@speedprofile = nil
|
||||
read_speedprofile DEFAULT_SPEEDPROFILE
|
||||
def reset_profile
|
||||
@profile = nil
|
||||
set_profile DEFAULT_SPEEDPROFILE
|
||||
end
|
||||
|
||||
def read_speedprofile profile
|
||||
@speedprofile = profile
|
||||
def set_profile profile
|
||||
@profile = profile
|
||||
end
|
||||
|
||||
def write_server_ini
|
||||
s=<<-EOF
|
||||
Threads = 1
|
||||
IP = 0.0.0.0
|
||||
Port = 5000
|
||||
Port = #{OSRM_PORT}
|
||||
|
||||
hsgrData=#{@osm_file}.osrm.hsgr
|
||||
nodesData=#{@osm_file}.osrm.nodes
|
||||
@ -23,6 +23,7 @@ edgesData=#{@osm_file}.osrm.edges
|
||||
ramIndex=#{@osm_file}.osrm.ramIndex
|
||||
fileIndex=#{@osm_file}.osrm.fileIndex
|
||||
namesData=#{@osm_file}.osrm.names
|
||||
timestamp=#{@osm_file}.osrm.timestamp
|
||||
EOF
|
||||
File.open( 'server.ini', 'w') {|f| f.write( s ) }
|
||||
end
|
||||
|
@ -116,7 +116,7 @@ def reset_data
|
||||
#clear_log
|
||||
#clear_data_files
|
||||
end
|
||||
reset_speedprofile
|
||||
reset_profile
|
||||
reset_osm
|
||||
@fingerprint = nil
|
||||
end
|
||||
@ -131,10 +131,6 @@ def reset_osm
|
||||
name_way_hash.clear
|
||||
@osm_str = 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
|
||||
end
|
||||
|
||||
@ -180,9 +176,8 @@ def convert_osm_to_pbf
|
||||
unless File.exist?("#{@osm_file}.osm.pbf")
|
||||
log_preprocess_info
|
||||
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}"
|
||||
raise "Failed to convert to proto buffer format. Please see #{hash}.log for more info."
|
||||
raise OsmosisError.new $?, "osmosis exited with code #{$?.exitstatus}"
|
||||
end
|
||||
log '', :preprocess
|
||||
end
|
||||
@ -198,25 +193,30 @@ def prepared?
|
||||
File.exist?("#{@osm_file}.osrm.hsgr")
|
||||
end
|
||||
|
||||
def write_timestamp
|
||||
File.open( "#{@osm_file}.osrm.timestamp", 'w') {|f| f.write(OSM_TIMESTAMP) }
|
||||
end
|
||||
|
||||
def reprocess
|
||||
Dir.chdir TEST_FOLDER do
|
||||
write_osm
|
||||
write_timestamp
|
||||
convert_osm_to_pbf
|
||||
unless extracted?
|
||||
log_preprocess_info
|
||||
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
|
||||
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
|
||||
log '', :preprocess
|
||||
end
|
||||
unless prepared?
|
||||
log_preprocess_info
|
||||
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
|
||||
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
|
||||
log '', :preprocess
|
||||
end
|
||||
|
@ -1 +1,18 @@
|
||||
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
|
||||
|
||||
|
@ -1,14 +1,49 @@
|
||||
|
||||
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
|
||||
@code = code
|
||||
@msg = msg
|
||||
@lines = lines
|
||||
@log = log
|
||||
@extract = log_tail @log, @lines
|
||||
end
|
||||
|
||||
def to_s
|
||||
@msg
|
||||
"*** #{@msg}\nLast #{@lines} lines from #{@log}:\n#{@extract}\n"
|
||||
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
22
features/support/file.rb
Normal 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
|
@ -11,8 +11,9 @@ def hash_of_file path
|
||||
return hash.hexdigest
|
||||
end
|
||||
|
||||
def speedprofile_hash
|
||||
@speedprofile_hash ||= hash_of_file "../profiles/#{@speedprofile}.lua"
|
||||
def profile_hash
|
||||
@@profile_hashes ||= {}
|
||||
@@profile_hashes[@profile] ||= hash_of_file "../profiles/#{@profile}.lua"
|
||||
end
|
||||
|
||||
def osm_hash
|
||||
@ -20,19 +21,19 @@ def osm_hash
|
||||
end
|
||||
|
||||
def bin_extract_hash
|
||||
@bin_hash ||= hash_of_file '../osrm-extract'
|
||||
@@bin_extract_hash ||= hash_of_file '../osrm-extract'
|
||||
end
|
||||
|
||||
def bin_prepare_hash
|
||||
@bin_hash ||= hash_of_file '../osrm-prepare'
|
||||
@@bin_prepare_hash ||= hash_of_file '../osrm-prepare'
|
||||
end
|
||||
|
||||
def bin_routed_hash
|
||||
@bin_hash ||= hash_of_file '../osrm-routed'
|
||||
@@bin_routed_hash ||= hash_of_file '../osrm-routed'
|
||||
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
|
||||
@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
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
|
||||
STRESS_TIMEOUT = 300
|
||||
|
||||
Before do |scenario|
|
||||
@scenario_title = scenario.title
|
||||
@scenario_time = Time.now.strftime("%Y-%m-%dT%H:%m:%SZ")
|
||||
@ -7,12 +10,11 @@ Before do |scenario|
|
||||
set_grid_size DEFAULT_GRID_SIZE
|
||||
end
|
||||
|
||||
Around('@routing') do |scenario, block|
|
||||
Timeout.timeout(10) do
|
||||
Around('@stress') do |scenario, block|
|
||||
Timeout.timeout(STRESS_TIMEOUT) do
|
||||
block.call
|
||||
end
|
||||
end
|
||||
|
||||
After do
|
||||
osrm_kill
|
||||
end
|
||||
|
@ -1,71 +1,83 @@
|
||||
require 'socket'
|
||||
require 'sys/proctable'
|
||||
require 'open3'
|
||||
|
||||
LAUNCH_TIMEOUT = 2
|
||||
SHUTDOWN_TIMEOUT = 2
|
||||
OSRM_ROUTED_LOG_FILE = 'osrm-routed.log'
|
||||
|
||||
class OSRMLauncher
|
||||
def initialize &block
|
||||
Dir.chdir TEST_FOLDER do
|
||||
osrm_up
|
||||
begin
|
||||
launch
|
||||
yield
|
||||
ensure
|
||||
shutdown
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def launch
|
||||
Timeout.timeout(LAUNCH_TIMEOUT) do
|
||||
osrm_up
|
||||
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
|
||||
end
|
||||
rescue Timeout::Error
|
||||
kill
|
||||
raise RoutedError.new "Shutting down osrm-routed timed out."
|
||||
end
|
||||
end
|
||||
|
||||
def each_process name, &block
|
||||
Sys::ProcTable.ps do |process|
|
||||
if process.comm.strip == name.strip
|
||||
yield process.pid.to_i, process.state.strip
|
||||
|
||||
def osrm_up?
|
||||
if @pid
|
||||
`ps -o state -p #{@pid}`.split[1].to_s =~ /^[DRST]/
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def osrm_up?
|
||||
find_pid('osrm-routed') != nil
|
||||
end
|
||||
|
||||
def find_pid name
|
||||
each_process(name) { |pid,state| return pid.to_i }
|
||||
return nil
|
||||
end
|
||||
|
||||
def osrm_up
|
||||
def osrm_up
|
||||
return if osrm_up?
|
||||
pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log')
|
||||
timeout = 5
|
||||
(timeout*10).times do
|
||||
@pid = Process.spawn(['../osrm-routed',''],:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE)
|
||||
end
|
||||
|
||||
def osrm_down
|
||||
if @pid
|
||||
Process.kill 'TERM', @pid
|
||||
wait_for_shutdown
|
||||
end
|
||||
end
|
||||
|
||||
def kill
|
||||
if @pid
|
||||
Process.kill 'KILL', @pid
|
||||
end
|
||||
end
|
||||
|
||||
def wait_for_connection
|
||||
while true
|
||||
begin
|
||||
socket = TCPSocket.new('localhost', 5000)
|
||||
socket.puts 'ping'
|
||||
socket = TCPSocket.new('localhost', OSRM_PORT)
|
||||
return
|
||||
rescue Errno::ECONNREFUSED
|
||||
sleep 0.1
|
||||
end
|
||||
end
|
||||
sleep 0.1
|
||||
end
|
||||
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
|
||||
def wait_for_shutdown
|
||||
while osrm_up?
|
||||
sleep 0.1
|
||||
end
|
||||
raise "*** Could not terminate #{name}."
|
||||
end
|
||||
end
|
||||
|
@ -14,7 +14,7 @@ def log_scenario_fail_info
|
||||
log "Failed scenario: #{@scenario_title}"
|
||||
log "Time: #{@scenario_time}"
|
||||
log "Fingerprint: #{@fingerprint}"
|
||||
log "Profile: #{@speedprofile}"
|
||||
log "Profile: #{@profile}"
|
||||
log
|
||||
log '```xml' #so output can be posted directly to github comment fields
|
||||
log osm_str.strip
|
||||
@ -51,7 +51,7 @@ def log_preprocess_info
|
||||
log '```', :preprocess
|
||||
log '', :preprocess
|
||||
log "== Profile:", :preprocess
|
||||
log @speedprofile, :preprocess
|
||||
log @profile, :preprocess
|
||||
log '', :preprocess
|
||||
@has_logged_preprocess_info = true
|
||||
end
|
||||
|
23
features/support/osm_parser.rb
Normal file
23
features/support/osm_parser.rb
Normal 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
|
@ -1,19 +1,26 @@
|
||||
require 'net/http'
|
||||
|
||||
HOST = "http://localhost:#{OSRM_PORT}"
|
||||
REQUEST_TIMEOUT = 1
|
||||
DESTINATION_REACHED = 15 #OSRM instruction code
|
||||
|
||||
|
||||
def request_route a,b
|
||||
@query = "http://localhost:5000/viaroute?loc=#{a}&loc=#{b}&output=json&instructions=true"
|
||||
#log @query
|
||||
uri = URI.parse @query
|
||||
def request_path path
|
||||
@query = path
|
||||
uri = URI.parse "#{HOST}/#{path}"
|
||||
Timeout.timeout(REQUEST_TIMEOUT) do
|
||||
Net::HTTP.get_response uri
|
||||
end
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
raise "*** osrm-routed is not running."
|
||||
rescue Timeout::Error
|
||||
raise "*** osrm-routed did not respond."
|
||||
end
|
||||
|
||||
def request_route a,b
|
||||
request_path "viaroute?loc=#{a}&loc=#{b}&output=json&instructions=true&alt=true"
|
||||
end
|
||||
|
||||
def parse_response response
|
||||
if response.code == "200" && response.body.empty? == false
|
||||
json = JSON.parse response.body
|
||||
@ -83,3 +90,27 @@ def bearing_list instructions
|
||||
map { |r| r=="" ? '""' : r }.
|
||||
join(',')
|
||||
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Handle bad data in a graceful manner
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Empty dataset
|
||||
Given the node map
|
||||
@ -12,7 +12,7 @@ Feature: Handle bad data in a graceful manner
|
||||
| nodes |
|
||||
|
||||
When I preprocess data
|
||||
Then preparing should return code 255
|
||||
Then "osrm-extract" should return code 255
|
||||
|
||||
Scenario: Only dead-end oneways
|
||||
Given the node map
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Basic Routing
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
@smallest
|
||||
Scenario: A single way with two nodes
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Compass bearing
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Bearing when going northwest
|
||||
Given the node map
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Distance calculation
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: 100m distance
|
||||
Given a grid size of 100 meters
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Testbot - Handle ferry routes
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Testbot - Ferry duration, single node
|
||||
Given the node map
|
||||
@ -39,6 +39,7 @@ Feature: Testbot - Handle ferry routes
|
||||
| a | d | abcd | 3600s +-1 |
|
||||
| d | a | abcd | 3600s +-1 |
|
||||
|
||||
@todo
|
||||
Scenario: Bike - Ferry duration, individual parts
|
||||
Given the node map
|
||||
| x | y | | z | | | v |
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Routing close to the [0,0] origin
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: East-west oneways close to the origin
|
||||
Given the node locations
|
||||
|
@ -3,7 +3,7 @@ Feature: Penalties
|
||||
Testbot uses a signal penalty of 7s.
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Traffic signals should incur a delay, without changing distance
|
||||
Given the node map
|
||||
|
@ -1,8 +1,7 @@
|
||||
@routing @planetary
|
||||
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
|
||||
| node | lat | lon |
|
||||
| a | 0 | 80 |
|
||||
@ -16,7 +15,7 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
|
||||
| from | to | route | distance |
|
||||
| a | b | ab | 8905559m ~0.1% |
|
||||
|
||||
Scenario: Longitudinal distances at latitude 45
|
||||
Scenario: Approximated Longitudinal distances at latitude 45
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| 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
|
||||
| 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
|
||||
| node | lat | lon |
|
||||
| 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
|
||||
| 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
|
||||
| node | lat | lon |
|
||||
| a | 80 | 0 |
|
||||
@ -58,7 +57,7 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
|
||||
| from | to | route | distance |
|
||||
| a | b | ab | 8905559m ~0.1% |
|
||||
|
||||
Scenario: Latitudinal distances at longitude 45
|
||||
Scenario: Approximated Latitudinal distances at longitude 45
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| a | 80 | 45 |
|
||||
@ -72,7 +71,7 @@ Reference distances have been calculated usign http://seismo.cqu.edu.au/CQSRG/VD
|
||||
| from | to | route | distance |
|
||||
| a | b | ab | 8905559m ~0.1% |
|
||||
|
||||
Scenario: Latitudinal distances at longitude 80
|
||||
Scenario: Approximated Latitudinal distances at longitude 80
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| a | 80 | 80 |
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Snap start/end point to the nearest way
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Snap to nearest protruding oneway
|
||||
Given the node map
|
||||
@ -98,7 +98,6 @@ Feature: Snap start/end point to the nearest way
|
||||
| b | x | xb |
|
||||
| c | x | xc |
|
||||
|
||||
@xx
|
||||
Scenario: Find edges within 1km, but not 10km
|
||||
Given a grid size of 1000 meters
|
||||
Given the node map
|
||||
@ -153,4 +152,3 @@ Feature: Snap start/end point to the nearest way
|
||||
| x | n | |
|
||||
| x | o | |
|
||||
| x | p | |
|
||||
|
||||
|
@ -6,7 +6,7 @@ Secondary road: 18km/h = 18000m/3600s = 100m/20s
|
||||
Tertiary road: 12km/h = 12000m/3600s = 100m/30s
|
||||
|
||||
Background: Use specific speeds
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Basic travel time, 10m scale
|
||||
Given a grid size of 10 meters
|
||||
|
115
features/testbot/turns.feature
Normal file
115
features/testbot/turns.feature
Normal 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 |
|
@ -2,7 +2,7 @@
|
||||
Feature: Handling of UTF characters
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Streetnames with UTF characters
|
||||
Given the node map
|
||||
|
@ -2,7 +2,7 @@
|
||||
Feature: Choosing route based on length, speed, etc
|
||||
|
||||
Background:
|
||||
Given the speedprofile "testbot"
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Pick the geometrically shortest route, way types being equal
|
||||
Given the node map
|
||||
|
12
features/timestamp/timestamp.feature
Normal file
12
features/timestamp/timestamp.feature
Normal 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- 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_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true }
|
||||
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
|
||||
@ -121,6 +121,7 @@ function way_function (way, numberOfNodesInWay)
|
||||
local junction = way.tags:Find("junction")
|
||||
local route = way.tags:Find("route")
|
||||
local railway = way.tags:Find("railway")
|
||||
local public_transport = way.tags:Find("public_transport")
|
||||
local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") )
|
||||
local man_made = way.tags:Find("man_made")
|
||||
local barrier = way.tags:Find("barrier")
|
||||
@ -135,11 +136,13 @@ function way_function (way, numberOfNodesInWay)
|
||||
local amenity = way.tags:Find("amenity")
|
||||
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
|
||||
(not route or route == '') and
|
||||
(not railway or railway=='') and
|
||||
(not amenity or amenity=='') then
|
||||
(not amenity or amenity=='') and
|
||||
(not public_transport or public_transport=='')
|
||||
then
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -168,8 +171,11 @@ function way_function (way, numberOfNodesInWay)
|
||||
way.speed = route_speeds[route]
|
||||
end
|
||||
elseif railway and platform_speeds[railway] then
|
||||
-- railway platforms
|
||||
-- railway platforms (old tagging scheme)
|
||||
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
|
||||
-- railways
|
||||
if access and access_tag_whitelist[access] then
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
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_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_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
||||
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
|
||||
|
@ -82,7 +82,7 @@ int main (int argc, char * argv[0]) {
|
||||
//}
|
||||
|
||||
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
|
||||
int sig = 0;
|
||||
@ -135,11 +135,14 @@ int main (int argc, char * argv[0]) {
|
||||
s->Run();
|
||||
#endif
|
||||
|
||||
std::cout << std::endl << "[server] shutting down" << std::endl;
|
||||
std::cout << "[server] initiating shutdown" << std::endl;
|
||||
s->Stop();
|
||||
std::cout << "[server] stopping threads" << std::endl;
|
||||
t.join();
|
||||
std::cout << "[server] freeing objects" << std::endl;
|
||||
delete s;
|
||||
delete objects;
|
||||
std::cout << "[server] shutdown completed" << std::endl;
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "[fatal error] exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user