This commit is contained in:
GitHub Merge Button 2012-02-01 08:37:01 -08:00
commit 1ece534826
32 changed files with 1328 additions and 113 deletions

15
.gitignore vendored
View File

@ -1,3 +1,13 @@
# Test folder #
###################
test/speedprofile.ini
test/data/*.osrm
test/data/*.osrm.*
test/data/denmark.osm.pbf
test/data/regh.osm.pbf
test/data/test.osm
test/data/test.osm.pbf
# Compiled source #
###################
*.com
@ -6,6 +16,9 @@
*.exe
*.o
*.so
osrm-extract
osrm-prepare
osrm-routed
# Packages #
############
@ -70,4 +83,4 @@ win/*.suo
win/Debug/
win/Release/
win/bin/
win/bin-debug/
win/bin-debug/

View File

@ -210,10 +210,6 @@ public:
return true;
}
if ( w.direction == _Way::opposite ){
std::reverse( w.path.begin(), w.path.end() );
}
for(vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) {
externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, highway == settings.excludeFromGrid));
externalMemory->usedNodeIDs.push_back(w.path[n]);

View File

@ -122,15 +122,15 @@ public:
_forwardHeap2->Clear();
//insert new starting nodes into forward heap, adjusted by previous distances.
if(searchFrom1stStartNode) {
_forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, distance1-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
_forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode, distance2-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
_forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
_forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode << " with weight " << phantomNodePair.startPhantom.weight1);
// } else {
// INFO("Skipping first start node");
}
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
_forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance1-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
_forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance2-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
_forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
_forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("1)forw insert " << phantomNodePair.startPhantom.edgeBasedNode+1 << " with weight " << distance1-phantomNodePair.startPhantom.weight1);
// INFO("2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode+1 << " with weight " << distance2-phantomNodePair.startPhantom.weight1);
// } else if(!searchFrom2ndStartNode) {

125
Rakefile Normal file
View File

@ -0,0 +1,125 @@
require 'OSM/StreamParser'
#$:.unshift(File.dirname(__FILE__) + '/../../lib')
require 'cucumber/rake/task'
Cucumber::Rake::Task.new do |t|
t.cucumber_opts = %w{--format pretty}
end
areas = {
:test => {},
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
:dk => { :country => 'denmark', :bbox => nil },
:skaane => { :counry => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
}
osm_data_area_name = ENV['area'] ? ENV['area'].to_s.to_sym : :test
raise "Unknown data area." unless areas[osm_data_area_name]
osm_data_country = areas[osm_data_area_name][:country]
osm_data_area_bbox = areas[osm_data_area_name][:bbox]
desc "Rebuild and run tests"
task :default => [:build, :cucumber]
desc "Build using Scons"
task :build do
system "scons"
end
namespace :data do
desc "Download OSM data"
task :download do
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/osm/europe/#{osm_data_country}.osm.pbf -o test/data/#{osm_data_country}.osm.pbf"
if osm_data_area_bbox
raise "Error while cropping data." unless system "osmosis --read-pbf file=test/data/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=test/data/#{osm_data_area_name}.osm.pbf omitmetadata=true"
end
end
desc "Crop OSM data"
task :crop do
if osm_data_area_bbox
raise "Error while cropping data." unless system "osmosis --read-pbf file=test/data/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=test/data/#{osm_data_area_name}.osm.pbf omitmetadata=true"
end
end
desc "Reprocess OSM data"
task :process do
Dir.chdir "test" do #we must be in the test_folder folder to use the speedprofile.ini in that folder
raise "Error while extracting data." unless system "./osrm-extract data/#{osm_data_area_name}.osm.pbf"
puts
raise "Error while preparing data." unless system "./osrm-prepare data/#{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions"
puts
end
end
desc "Convert test file to protobuffer format"
task :protofy do
Dir.chdir "test" do
system "osmosis --read-xml data/test.osm --write-pbf data/test.osm.pbf omitmetadata=true"
puts
end
end
desc "Delete preprocessing files"
task :clean do
File.delete *Dir.glob('test/data/*.osrm')
File.delete *Dir.glob('test/data/*.osrm.*')
end
end
desc "Launch the routing server"
task :run do
Dir.chdir "test" do
system "./osrm-routed"
end
end
desc "Run all test"
task :test do
system "cucumber --tags @syn"
puts
end
desc "Prepare test data"
task :prep => ['data:protofy', 'data:process'] do
end
class OSMTestParserCallbacks < OSM::Callbacks
attr_accessor :locations
def initialize
@locations = {}
end
def node(node)
puts node
@locations[node.name] = [node.lat,node.lon]
end
def way(way)
puts way
end
def relation(relation)
puts relation
end
end
task :read do
Dir.chdir "test" do
file = 'data/test.osm'
callbacks = OSMTestParserCallbacks.new
parser = OSM::StreamParser.new(:filename => file, :callbacks => callbacks)
parser.parse
puts callbacks.locations
end
end

View File

@ -49,49 +49,72 @@ def CheckProtobuf(context, version):
context.Result(ret)
return ret
AddOption('--cxx', dest='cxx', type='string', nargs=1, action='store', metavar='STRING', help='C++ Compiler')
AddOption('--stxxlroot', dest='stxxlroot', type='string', nargs=1, action='store', metavar='STRING', help='root directory of STXXL')
AddOption('--verbosity', dest='verbosity', type='string', nargs=1, action='store', metavar='STRING', help='make Scons talking')
AddOption('--buildconfiguration', dest='buildconfiguration', type='string', nargs=1, action='store', metavar='STRING', help='debug or release')
env = Environment(ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
if sys.platform.startswith("freebsd"):
env.ParseConfig('pkg-config --cflags --libs protobuf')
env = Environment( ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
if GetOption('cxx') is None:
#default Compiler
print 'Using default C++ Compiler: ', env['CXX']
else:
env.Replace(CXX = GetOption('cxx'))
print 'Using user supplied C++ Compiler: ', env['CXX']
if GetOption('stxxlroot') is not None:
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
print 'STXXLROOT = ', GetOption('stxxlroot')
if sys.platform == 'win32':
#SCons really wants to use Microsoft compiler
print "Compiling is not yet supported on Windows"
Exit(-1)
else: #Mac OS X
if sys.platform == 'darwin':
print "Compiling is experimental on Mac"
env.Append(CPPPATH = ['/opt/local/include/', '/opt/local/include/libxml2'])
env.Append(LIBPATH = ['/opt/local/lib'])
elif sys.platform.startswith('freebsd'):
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
env.Append(LIBPATH = ['/usr/local/lib'])
else:
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
if GetOption('buildconfiguration') == 'debug':
env.Append(CCFLAGS = ['-Wall', '-g3', '-rdynamic'])
else:
env.Append(CCFLAGS = ['-O3', '-DNDEBUG', '-march=native'])
#print "Compiling with: ", env['CXX']
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
if not conf.CheckHeader('omp.h'):
print "Compiler does not support OpenMP. Exiting"
if sys.platform == 'darwin':
print "Continuing because we are on Mac. This might be fatal."
else:
env.Append(CCFLAGS = ['-O3', '-DNDEBUG'])
if sys.platform == 'darwin': #Mac OS X
env.Append(CPPPATH = ['/usr/include/libxml2'] ) #comes with os x
#assume dependencies are installed with homebrew, and call out get folder locations
import subprocess
stxxl_prefix = subprocess.check_output(["brew", "--prefix", "libstxxl"]).strip()
env.Append(CPPPATH = [stxxl_prefix+"/include"] )
env.Append(LIBPATH = [stxxl_prefix+"/lib"] )
boost_prefix = subprocess.check_output(["brew", "--prefix", "boost"]).strip()
env.Append(CPPPATH = [boost_prefix+"/include"] )
env.Append(LIBPATH = [boost_prefix+"/lib"] )
#libxml2_prefix = subprocess.check_output(["brew", "--prefix", "libxml2"]).strip()
#env.Append(CPPPATH = [libxml2_prefix+"/include"] )
#env.Append(LIBPATH = [libxml2_prefix+"/lib"] )
elif sys.platform.startswith("freebsd"):
env.ParseConfig('pkg-config --cflags --libs protobuf')
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
env.Append(LIBPATH = ['/usr/local/lib'])
if GetOption('stxxlroot') is not None:
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
print 'STXXLROOT = ', GetOption('stxxlroot')
if GetOption('buildconfiguration') != 'debug':
env.Append(CCFLAGS = ['-march=native'])
#print "Compiling with: ", env['CXX']
env.Append(CCFLAGS = ['-fopenmp'])
env.Append(LINKFLAGS = ['-fopenmp'])
elif sys.platform == 'win32':
#SCons really wants to use Microsoft compiler
print "Compiling is not yet supported on Windows"
Exit(-1)
else:
print "Unknown platform.."
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
if sys.platform != 'darwin':
if not conf.CheckHeader('omp.h'):
print "Compiler does not support OpenMP. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'):
print "bz2 library not found. Exiting"
Exit(-1)
@ -132,9 +155,6 @@ if not conf.CheckLibWithHeader('Magick++', 'ImageMagick/Magick++.h', 'CXX'):
if not (conf.CheckBoost('1.41')):
print 'Boost version >= 1.41 needed'
Exit(-1);
if not conf.CheckLib('boost_system', language="C++"):
print "boost_system library not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
if not conf.CheckLibWithHeader('boost_thread-mt', 'boost/thread.hpp', 'CXX'):
print "boost thread library not found. Exiting"
@ -144,14 +164,21 @@ if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
env.Append(CCFLAGS = ' -lboost_thread-mt')
env.Append(LINKFLAGS = ' -lboost_thread-mt')
if not conf.CheckLibWithHeader('boost_regex', 'boost/regex.hpp', 'CXX'):
print "boost/regex.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/array.hpp'):
print "boost/thread.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/asio.hpp'):
print "boost/thread.hpp not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('boost_regex-mt', 'boost/regex.hpp', 'CXX'):
print "boost/regex.hpp not found. Exiting"
Exit(-1)
else:
print "using boost_regex -mt"
env.Append(CCFLAGS = ' -lboost_regex-mt')
env.Append(LINKFLAGS = ' -lboost_regex-mt')
if not conf.CheckLib('boost_system', language="C++"):
if not conf.CheckLib('boost_system-mt', language="C++"):
print "boost_system library not found. Exiting"
Exit(-1)
else:
print "using boost -mt"
env.Append(CCFLAGS = ' -lboost_system-mt')
env.Append(LINKFLAGS = ' -lboost_system-mt')
if not conf.CheckCXXHeader('boost/bind.hpp'):
print "boost/bind.hpp not found. Exiting"
Exit(-1)
@ -194,18 +221,27 @@ if not conf.CheckCXXHeader('boost/tuple/tuple.hpp'):
if not conf.CheckCXXHeader('boost/unordered_map.hpp'):
print "boost thread header not found. Exiting"
Exit(-1)
#if os.sysconf('SC_NPROCESSORS_ONLN') > 1:
# env.Append(CCFLAGS = ' -D_GLIBCXX_PARALLEL');
if not (conf.CheckBoost('1.41')):
print 'Boost version >= 1.41 needed'
Exit(-1);
#check for protobuf 2.3.0, else rebuild proto files
if not (conf.CheckProtobuf('2.3.0')):
print 'libprotobuf version >= 2.3.0 needed'
Exit(-1);
if not (env.Detect('protoc')):
print 'protobuffer compiler not found'
protobld = Builder(action = 'protoc -I=DataStructures/pbf-proto --cpp_out=DataStructures/pbf-proto $SOURCE')
env.Append(BUILDERS = {'Protobuf' : protobld})
env.Protobuf('DataStructures/pbf-proto/fileformat.proto')
env.Protobuf('DataStructures/pbf-proto/osmformat.proto')
env.Append(CCFLAGS = ['-fopenmp'])
env.Append(LINKFLAGS = ['-fopenmp'])
#env.Append(LINKFLAGS = ['-lboost_system'])
env.Program(target = 'osrm-extract', source = ["extractor.cpp", Glob('DataStructures/pbf-proto/*.pb.cc'), Glob('Util/*.cpp')])
env.Program(target = 'osrm-prepare', source = ["createHierarchy.cpp", 'Contractor/EdgeBasedGraphFactory.cpp', Glob('Util/SRTMLookup/*.cpp')])
env.Append(CCFLAGS = ['-lboost_regex', '-lboost_iostreams', '-lbz2', '-lz', '-lprotobuf'])
env.Append(LINKFLAGS = ['-lboost_system'])
env.Program(target = 'osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp'], CCFLAGS = ['-DROUTED'])
env.Program(target = 'test/osrm-extract', source = ["extractor.cpp", 'DataStructures/pbf-proto/fileformat.pb.cc', 'DataStructures/pbf-proto/osmformat.pb.cc'])
env.Program(target = 'test/osrm-prepare', source = ["createHierarchy.cpp", 'Contractor/EdgeBasedGraphFactory.cpp'])
env.Program(target = 'test/osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp'])
env = conf.Finish()

View File

@ -1,2 +0,0 @@
Threads = 4
SRTM = /opt/storage/srtm/Eurasia

View File

@ -79,7 +79,7 @@ int main (int argc, char *argv[]) {
INFO("Loading SRTM from/to " << SRTM_ROOT);
omp_set_num_threads(numberOfThreads);
INFO("preprocessing data from input file " << argv[2] << " using STL "
INFO("preprocessing data from input file " << argv[1] << " using STL "
#ifdef _GLIBCXX_PARALLEL
"parallel (GCC)"
#else

View File

@ -1 +0,0 @@
Memory = 2

View File

@ -0,0 +1,25 @@
@process
Feature: Preprocessing OpenStreetMap data
In order to enable efficient routing
As the OSRM server
I want to be able to preprocess OpenStreetMap data
Scenario: Processing OpenStreetMap data using bicycle profile
Given I am in the test folder
And the data file "data/kbh.osm.pbf" is present
And the "bicycle" speedprofile is used
When I run the extractor with "./osrm-extract data/kbh.osm.pbf"
Then the response should include "extracting data from input file data/kbh.osm.pbf"
And the response should include 'Using profile "bicycle"'
And the response should include "[extractor] finished"
And I should see the file "data/kbh.osrm"
And I should see the file "data/kbh.osrm.names"
And I should see the file "data/kbh.osrm.restrictions"
When I run the preprocessor with "./osrm-prepare data/kbh.osrm data/kbh.osrm.restrictions"
Then the response should include "finished preprocessing"
And I should see the file "data/kbh.osrm.hsgr"
And I should see the file "data/kbh.osrm.nodes"
And I should see the file "data/kbh.osrm.ramIndex"
And I should see the file "data/kbh.osrm.fileIndex"

13
features/1_launch.feature Normal file
View File

@ -0,0 +1,13 @@
@launch
Feature: Launching OSRM server
In order to handle routing request
As a user
I want to launch the OSRM server
Scenario: Launching the OSRM server
Given I am in the test folder
And the preprocessed files for "data/kbh" are present and up to date
When I start the server with "./osrm-routed"
Then a process called "osrm-routed" should be running
And I should see "running and waiting for requests" on the terminal

100
features/basic.feature Normal file
View File

@ -0,0 +1,100 @@
@routing @basic
Feature: Basic Routing
Scenario Outline: Smallest possible datasat
Given the nodes
| a | b |
And the ways
| nodes |
| ab |
When I route between "<from>" and "<to>"
Then "<route>" should be returned
Examples:
| from | to | route |
| a | b | ab |
| b | a | ba |
Scenario Outline: Smallest possible datasat
Given the nodes
| a | b |
And the ways
| nodes |
| ab |
When I route between "<from>" and "<to>"
Then "<route>" should be returned
Examples:
| from | to | route |
| a | b | ab |
| b | a | ba |
Scenario Outline: Connected ways
Given the nodes
| a | | c |
| | b | |
And the ways
| nodes |
| ab |
| bc |
When I route between "<from>" and "<to>"
Then "<route>" should be returned
Examples:
| from | to | route |
| a | c | abc |
| c | a | cba |
| a | b | ab |
| b | a | ba |
| b | c | bc |
| c | b | cb |
Scenario Outline: Unconnected ways
Given the nodes
| a | b |
| c | d |
And the ways
| nodes |
| ab |
| cd |
When I route between "<from>" and "<to>"
Then "<route>" should be returned
Examples:
| from | to | route |
| a | b | ab |
| b | a | ba |
| c | d | cd |
| d | c | dc |
| a | c | |
| c | a | |
| b | d | |
| d | c | |
| a | d | |
| d | a | |
Scenario Outline: Pick the fastest way type
Given the nodes
| a | s |
| p | b |
And the ways
| nodes | highway |
| apb | primary |
| asb | secondary |
When I route between "<from>" and "<to>"
Then "<route>" should be returned
Examples:
| from | to | route |
| a | b | apb |
| b | a | bpa |

5
features/bicycle.feature Normal file
View File

@ -0,0 +1,5 @@
@routing @bicycle
Feature: Bicycle Routing from A to B
To enable bicycle routing
OSRM should handle all relevant bicycle tags

37
features/kbh.feature Normal file
View File

@ -0,0 +1,37 @@
@routing
Feature: Real-world routing test in the Copenhagen area
Scenario: Phantom shortcut
When I request a route from 55.662740149207,12.576105114488& to 55.665753800212,12.575547215013
Then I should get a route
And the distance should be close to 450m
Scenario: Start and stop markers should snap to closest streets
When I request a route from 55.6634,12.5724 to 55.6649,12.5742
Then I should get a route
And the route should stay on "Islands Brygge"
And the distance should be close to 200m
Scenario: Crossing roundabout at Amalienborg
When I request a route from 55.683797649183,12.593940686704 to 55.6842149924,12.592476200581
Then I should get a route
And the distance should be close to 150m
Scenario: Requesting invalid routes
When I request a route from 0,0 to 0,0
Then I should not get a route
And no error should be reported in terminal
Scenario: Dont flicker
When I request a route from 55.658833555366,12.592788454378 to 55.663871808364,12.583497282355
Then I should get a route
And the route should follow "Amagerfælledvej, Njalsgade, Artillerivej"
And no error should be reported in terminal
When I request a route from 55.658821450674,12.592466589296 to 55.663871808364,12.583497282355
Then I should get a route
And the route should follow "Kaj Munks Vej, Tom Kristensens Vej, Ørestads Boulevard, Njalsgade, Artillerivej"
And no error should be reported in terminal
When I request a route from 55.658857764739,12.592058893525 to 55.663871808364,12.583497282355
Then I should get a route
And the route should follow "Kaj Munks Vej, Tom Kristensens Vej, Ørestads Boulevard, Njalsgade, Artillerivej"
And no error should be reported in terminal

96
features/oneways.feature Normal file
View File

@ -0,0 +1,96 @@
@routing @oneways
Feature: Oneway streets
Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing
Scenario: Implied oneways
Given the speedprofile "car"
Then routability should be
| highway | junction | forw | backw |
| motorway | | x | x |
| motorway_link | | x | |
| trunk | | x | x |
| trunk_link | | x | |
| primary | roundabout | x | |
Scenario: Overriding implied oneways
Given the defaults
Then routability should be
| highway | junction | oneway | forw | backw |
| motorway_link | | no | x | x |
| trunk_link | | no | x | x |
| primary | roundabout | no | x | x |
| motorway_link | | -1 | | x |
| trunk_link | | -1 | | x |
| primary | roundabout | -1 | | x |
Scenario: Handle various oneway tag values
Given the defaults
Then routability should be
| highway | oneway | forw | backw |
| primary | | x | x |
| primary | nonsense | x | x |
| primary | no | x | x |
| primary | false | x | x |
| primary | 0 | x | x |
| primary | yes | x | |
| primary | true | x | |
| primary | 1 | x | |
| primary | -1 | | x |
Scenario: Disabling oneways in speedprofile
Given the speedprofile settings
| obeyOneways | no |
Then routability should be
| highway | junction | oneway | forw | backw |
| primary | | yes | x | x |
| primary | | true | x | x |
| primary | | 1 | x | x |
| primary | | -1 | x | x |
| motorway_link | | | x | x |
| trunk_link | | | x | x |
| primary | roundabout | | x | x |
Scenario: Oneways and bicycles
Given the defaults
Then routability should be
| highway | junction | oneway | oneway:bicycle | forw | backw |
| primary | | | yes | x | |
| primary | | yes | yes | x | |
| primary | | no | yes | x | |
| primary | | -1 | yes | x | |
| motorway | | | yes | x | |
| motorway_link | | | yes | x | |
| primary | roundabout | | yes | x | |
| primary | | | no | x | x |
| primary | | yes | no | x | x |
| primary | | no | no | x | x |
| primary | | -1 | no | x | x |
| motorway | | | no | x | x |
| motorway_link | | | no | x | x |
| primary | roundabout | | no | x | x |
| primary | | | -1 | | x |
| primary | | yes | -1 | | x |
| primary | | no | -1 | | x |
| primary | | -1 | -1 | | x |
| motorway | | | -1 | | x |
| motorway_link | | | -1 | | x |
| primary | roundabout | | -1 | | x |
Scenario: Cars should not be affected by bicycle tags
Given the speedprofile settings
| accessTag | motorcar |
Then routability should be
| highway | junction | oneway | oneway:bicycle | forw | backw |
| primary | | yes | yes | x | |
| primary | | yes | no | x | |
| primary | | yes | -1 | x | |
| primary | | no | yes | x | x |
| primary | | no | no | x | x |
| primary | | no | -1 | x | x |
| primary | | -1 | yes | | x |
| primary | | -1 | no | | x |
| primary | | -1 | -1 | | x |
| primary | roundabout | | yes | x | |
| primary | roundabout | | no | x | |
| primary | roundabout | | -1 | x | |

65
features/other.feature Normal file
View File

@ -0,0 +1,65 @@
@other
Feature: Other stuff
Scenario: No left turn when crossing a oneway street
When I request a route from 55.689741159238,12.574720202639 to 55.689741159232,12.57455927015
Then I should get a route
And the route should start at "Sølvgade"
And the route should end at "Øster Farimagsgade"
And the route should not include "Sølvgade, Øster Farimagsgade"
And no error should be reported in terminal
Scenario: No left turn at T-junction: Don't turn left from side road into main road
When I request a route from 55.66442995717,12.549384056343 to 55.664218154805,12.5502638209
Then I should get a route
And the route should start at "Sigerstedgade"
And the route should end at "Ingerslevsgade"
And the route should not include "Sigerstedgade, Ingerslevsgade"
And there should be more than 1 turn
Scenario: No left turn at T-junction: OK to turn right from side road into main road
When I request a route from 55.66442995717,12.549384056343 to 55.664060815164,12.548944174065
Then I should get a route
And the route should start at "Sigerstedgade"
And the route should end at "Ingerslevsgade"
And the route should include "Sigerstedgade, Ingerslevsgade"
And there should be 1 turn
Scenario: No left turn at T-junction: OK to go straight on main road
When I request a route from 55.66419092299,12.550333558335 to 55.664060815164,12.548944174065
Then I should get a route
And the route should stay on "Ingerslevsgade"
Scenario: No left turn at T-junction: OK to turn right from main road into side road
When I request a route from 55.664060815164,12.548944174065 to 55.66442995717,12.549384056343
Then I should get a route
And the route should start at "Ingerslevsgade"
And the route should end at "Sigerstedgade"
And the route should include "Ingerslevsgade, Sigerstedgade"
And there should be 1 turn
Scenario: No left turn at T-junction: OK to turn left from main road into side road
When I request a route from 55.664218154805,12.5502638209 to 55.66442995717,12.549384056343
Then I should get a route
And the route should start at "Ingerslevsgade"
And the route should end at "Sigerstedgade"
And the route should include "Ingerslevsgade, Sigerstedgade"
And there should be 1 turn
Scenario: oneway:bicycle
When I request a route from 55.673168935147,12.563557740441 to 55.67380116846,12.563107129324&
Then I should get a route
And the route should follow "Banegårdspladsen"
And there should not be any turns
And the distance should be close to 80m
Scenario: cycleway=opposite_lane
When I request a route from 55.689126237262,12.553137305887 to 55.688666612359,12.55296564451
Then I should get a route
And the route should follow "Kapelvej"
And there should not be any turns
And the distance should be close to 50m

25
features/outlines.feature Normal file
View File

@ -0,0 +1,25 @@
@outlines
Feature: Outlines
Scenario outlines is another way to test routes... not sure which method is best?
Scenario Outline: ways
Given the nodes
| a | | c |
| | b | |
And the ways
| nodes |
| ab |
| bc |
When I route from "<from>" to "<to>"
Then I should get the route "<route>"
Examples:
| from | to | route |
| a | c | abc |
| c | a | cba |
| a | b | ab |
| b | a | ba |
| b | c | bc |
| c | b | cb |

View File

@ -0,0 +1,30 @@
@routing @restrictions
Feature: Turn restrictions
Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction
Scenario Outline: No left turn at T-junction
Given the nodes
| a | j | b |
| | s | |
And the ways
| nodes |
| aj |
| jb |
| sj |
And the relations
| from | to | via | restriction |
| sj | ja | j | no_left_turn |
When I route between "<from>" and "<to>"
Then "<route>" should be returned
Examples:
| from | to | route |
| a | b | ajb |
| a | s | ajs |
| b | a | bja |
| b | s | bjs |
| s | a | |
| s | b | sjb |

View File

@ -0,0 +1,96 @@
require 'pathname'
require 'json'
require 'open4'
require "net/http"
require "uri"
$stdout.sync = true
$server_pipe = nil
$server_running = false
def read_terminal
return $server_pipe.read_nonblock 10000 rescue nil
end
def running?
`ps -eo command | grep #{@test_folder}/osrm-running$`.size != 0
end
def launch cmd = "./osrm-routed"
$server_pipe = IO.popen(cmd)
sleep 2 # so the daemon has a chance to boot
at_exit do
if $server_pipe
Process.kill("KILL", $server_pipe.pid) # clean up the daemon when the tests finish
end
end
end
def kill
if $server_pipe
Process.kill("KILL", $server_pipe.pid)
$server_pipe = nil
sleep 2 # so the daemon has a chance to quit
end
end
Given /^I am in the test folder$/ do
@root = Pathname.new(File.dirname(__FILE__)).parent.parent.expand_path
@test_folder = "#{@root}/test"
Dir.chdir @test_folder
end
Given /^the server is configured for bike routing$/ do
pending # express the regexp above with the code you wish you had
end
Given /^the "([^"]*)" speedprofile is used$/ do |profile|
FileUtils.cp "speedprofiles/#{profile}.ini", "speedprofile.ini"
end
Then /^the response should include "([^"]*)"$/ do |string|
@response.include?(string).should_not == nil
end
Then /^the response should include '([^']*)'$/ do |string|
@response.include?(string).should_not == nil
end
Given /^the server is running$/ do
unless $server_running
step 'a process called "osrm-routed" should be running'
@server_running = true
end
end
When /^I start the server with "([^']*)"$/ do |cmd|
launch cmd
end
When /^I stop the server$/ do
kill
end
Then /^a process called "([^']*)" should be running$/ do |daemon|
#puts `ps -eo command | grep #{@test_folder}/#{daemon}`
`ps -eo command | grep #{@test_folder}/#{daemon}`.size.should > 0
end
Then /^a process called "([^']*)" should not be running$/ do |daemon|
`ps -eo command | grep #{@test_folder}/#{daemon}$`.size.should == 0
end
Then /^a process called "([^']*)" is not running$/ do |daemon|
step "a process called \"#{daemon}\" should not be running"
end
Then /^I should see "([^']*)" on the terminal$/ do |string|
out = read_terminal
out.should =~ /#{string}/
end
Then /^no error should be reported in terminal$/ do
read_terminal.should_not =~ /error/
end

View File

@ -0,0 +1,77 @@
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
def way(way)
end
def relation(relation)
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.ramIndex").should == true
File.exists?("#{area}.osrm.fileIndex").should == true
end
Then /^I should see the file "([^"]*)"$/ do |file|
File.exists?(file).should == true
end
When /^preprocessed files for "([^"]*)" has been removed$/ do |file|
FileUtils.rm_r Dir["#{file}.*"], :secure => true
end

View File

@ -0,0 +1,234 @@
def request_route a,b
uri = URI.parse "http://localhost:5000/viaroute&start=#{a}&dest=#{b}&output=json&geomformat=cmp"
#puts "routing: #{uri}"
Net::HTTP.get_response uri
rescue Errno::ECONNREFUSED => e
raise "*** osrm-routed is not running."
rescue Timeout::Error
raise "*** osrm-routed didn't respond."
end
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|
computed_route.should == sanitize_route(route)
end
Then /^the route should not follow "([^"]*)"$/ do |route|
computed_route.should_not == sanitize_route(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
def parse_response response
if response.code == "200" && response.body.empty? == false
json = JSON.parse response.body
#puts response.body
if json['status'] == 0
route = json['route_instructions'].map { |r| r[1] }.reject(&:empty?).join(', ')
if route.empty?
"Empty route: #{json['route_instructions']}"
else
route
end
elsif json['status'] == 207
nil #no route found
else
"Status: #{json['status']}"
end
else
"HTTP: #{response.code}"
end
end
When /^I route I should get$/ do |table|
actual = []
reprocess_if_needed
Dir.chdir 'test' do
launch
table.hashes.each do |row|
from_node = @name_node_hash[ row['from'] ]
to_node = @name_node_hash[ row['to'] ]
route = parse_response( request_route("#{from_node.lon},#{from_node.lat}", "#{to_node.lat},#{to_node.lat}") )
actual << { 'from' => row['from'].dup, 'to' => row['to'].dup, 'route' => route }
end
kill
end
table.diff! actual
end
When /^I route on tagged ways I should get $/ do |table|
pending
end
When /^I route between "([^"]*)" and "([^"]*)"$/ do |from,to|
end
Then /^"([^"]*)" should be returned$/ do |route|
end
def build_ways_from_table table
#add one unconnected way for each row
table.hashes.each_with_index do |row,ri|
#two nodes...
node1 = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+0*ZOOM, ORIGIN[1]-ri*ZOOM
node2 = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+1*ZOOM, ORIGIN[1]-ri*ZOOM
node1.uid = OSM_UID
node2.uid = OSM_UID
osm_db << node1
osm_db << node2
#...with a way between them
way = OSM::Way.new -ri-1, OSM_USER, OSM_TIMESTAMP
way.uid = OSM_UID
tags = row.dup
tags.delete 'forw'
tags.delete 'backw'
tags.reject! { |k,v| v=='' }
way << tags
way << node1
way << node2
osm_db << way
end
Dir.chdir TEST_FOLDER do
write_osm
end
must_reprocess
end
Then /^routability should be$/ do |table|
build_ways_from_table table
reprocess_if_needed
actual = [ table.column_names ]
Dir.chdir 'test' do
launch
p "#{ORIGIN[0]+0*ZOOM},#{ORIGIN[1]-0*ZOOM}", "#{ORIGIN[0]+1*ZOOM},#{ORIGIN[1]-0*ZOOM}"
p request_route("#{ORIGIN[0]+0*ZOOM},#{ORIGIN[1]-0*ZOOM}", "#{ORIGIN[0]+1*ZOOM},#{ORIGIN[1]-0*ZOOM}").body
kill
end
table.diff! actual
end

View File

@ -0,0 +1,183 @@
require 'OSM/objects' #osmlib gem
require 'OSM/Database'
require 'builder'
OSM_USER = 'osrm'
OSM_TIMESTAMP = '2012-01-01T00:00:00Z'
OSM_GENERATOR = 'osrm-test'
OSM_UID = 1
TEST_FOLDER = 'test'
DATA_FOLDER = 'data'
OSM_FILE = 'test'
LOG_FILE = 'test.log'
DEFAULT_SPEEDPROFILE = 'bicycle'
ORIGIN = [1,1]
ZOOM = 0.001
def must_reprocess
@must_reprocess = true
end
def must_reprocess?
@must_reprocess ||= true
end
def reprocess_if_needed
if must_reprocess?
raise "*** osrm-routed is running. Please stop it before running tests." if running?
#puts "Reprocessing: #{@osm_db.nodes.size} nodes, #{@name_way_hash.size} ways, #{@relations.size} relations... "
Dir.chdir TEST_FOLDER do
write_speedprofile
write_osm
reprocess
end
@must_reprocess = false
end
end
def reprocess
file = "#{DATA_FOLDER}/#{OSM_FILE}"
raise "*** osrm-extract failed. Please see test.log for more info." unless system "./osrm-extract #{file}.osm.pbf 1>>#{LOG_FILE} 2>>#{LOG_FILE}"
raise "*** osrm-prepare failed. Please see test.log for more info." unless system "./osrm-prepare #{file}.osrm #{file}.restrictions 1>>#{LOG_FILE} 2>>#{LOG_FILE}"
end
def find_node_by_name s
name_node_hash[s.to_s]
end
def find_way_by_name s
name_way_hash[s.to_s] || name_way_hash[s.to_s.reverse]
end
def reset_data
Dir.chdir "#{TEST_FOLDER}" do
clear_log
clear_data_files
end
osm_db.clear
name_node_hash.clear
name_way_hash.clear
must_reprocess
reset_speedprofile
end
def clear_data_files
File.delete *Dir.glob("#{DATA_FOLDER}/test.*")
end
def clear_log
File.delete *Dir.glob("*.log")
end
def speedprofile
@speedprofile ||= reset_speedprofile
end
def reset_speedprofile
@speedprofile = {}
read_speedprofile DEFAULT_SPEEDPROFILE
end
def read_speedprofile profile
@speedprofile = {}
s = File.read "test/speedprofiles/#{profile}.ini"
s.scan /(.*)=(.*)/ do |option|
@speedprofile[option[0].strip] = option[1].strip
end
end
def dump_speedprofile
"[default]\n" + @speedprofile.map { |k,v| "\t#{k} = #{v}" }.join("\n")
end
def write_speedprofile
File.open( 'speedprofile.ini', 'w') {|f| f.write( dump_speedprofile ) }
end
def osm_db
@osm_db ||= OSM::Database.new
end
def name_node_hash
@name_node_hash ||= {}
end
def name_way_hash
@name_way_hash ||= {}
end
def write_osm
xml = ''
doc = Builder::XmlMarkup.new :indent => 2, :target => xml
doc.instruct!
osm_db.to_xml doc, OSM_GENERATOR
#write .oms file
file = "#{DATA_FOLDER}/#{OSM_FILE}"
File.open( "#{file}.osm", 'w') {|f| f.write(xml) }
#convert from .osm to .osm.pbf, which is the format osrm reads
#convert. redirect stdout and stderr to a log file avoid output in the cucumber console
unless system "osmosis --read-xml #{file}.osm --write-pbf #{file}.osm.pbf omitmetadata=true 1>>#{LOG_FILE} 2>>#{LOG_FILE}"
raise "Failed to convert to proto buffer format. Please see #{file}.log for more info."
end
end
Given /^the speedprofile "([^"]*)"$/ do |profile|
read_speedprofile profile
end
Given /^the speedprofile settings$/ do |table|
table.raw.each do |row|
speedprofile[ row[0] ] = row[1]
end
end
Given /^the nodes$/ do |table|
table.raw.each_with_index do |row,ri|
row.each_with_index do |name,ci|
unless name.empty?
node = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+ci*ZOOM, ORIGIN[1]-ri*ZOOM
node << { :name => name }
node.uid = OSM_UID
osm_db << node
name_node_hash[name] = node
end
end
end
end
Given /^the ways$/ do |table|
must_reprocess
table.hashes.each do |row|
name = row.delete 'nodes'
way = OSM::Way.new nil, OSM_USER, OSM_TIMESTAMP
defaults = { 'highway' => 'primary' }
way << defaults.merge( 'name' => name ).merge(row)
way.uid = OSM_UID
name.each_char { |c| way << find_node_by_name(c) }
osm_db << way
name_way_hash[name] = way
end
end
Given /^the relations$/ do |table|
must_reprocess
table.hashes.each do |row|
relation = OSM::Relation.new nil, OSM_USER, OSM_TIMESTAMP
relation << { :type => :restriction, :restriction => 'no_left_turn' }
relation << OSM::Member.new( 'way', find_way_by_name(row['from']).id, 'from' )
relation << OSM::Member.new( 'way', find_way_by_name(row['to']).id, 'to' )
relation << OSM::Member.new( 'node', find_node_by_name(row['via']).id, 'via' )
relation.uid = OSM_UID
osm_db << relation
end
end
Given /^the defaults$/ do
end

View File

@ -0,0 +1,3 @@
Before do
reset_data
end

View File

@ -2,8 +2,8 @@ Threads = 8
IP = 0.0.0.0
Port = 5000
hsgrData=/opt/osm/germany.osrm.hsgr
nodesData=/opt/osm/germany.osrm.nodes
ramIndex=/opt/osm/germany.osrm.ramIndex
fileIndex=/opt/osm/germany.osrm.fileIndex
namesData=/opt/osm/germany.osrm.names
hsgrData=data/kbh.osrm.hsgr
nodesData=data/kbh.osrm.nodes
ramIndex=data/kbh.osrm.ramIndex
fileIndex=data/kbh.osrm.fileIndex
namesData=data/kbh.osrm.names

View File

@ -1,48 +0,0 @@
[car]
motorway = 110
motorway_link = 90
trunk = 90
trunk_link = 70
primary = 70
primary_link = 60
secondary = 60
secondary_link = 50
tertiary = 55
unclassified = 25
residential = 40
living_street = 10
service = 30
ferry = 5
pier = 5
obeyBollards = yes
obeyOneways = yes
useRestrictions = yes
accessTag = motorcar
excludeFromGrid = ferry
defaultSpeed = 50
trafficLightPenalty = 15
[bike]
trunk = 16
trunk_link = 16
primary = 16
primary_link = 16
secondary = 16
secondary_link = 16
tertiary = 16
unclassified = 16
residential = 16
living_street = 16
service = 16
track = 16
cycleway = 16
path = 16
ferry = 5
pier = 5
obeyOneways = yes
useRestrictions = no
accessTag = bicycle
excludeFromGrid = ferry
defaultSpeed = 5
trafficLightPenalty = 15
obeyBollards = no

2
test/contractor.ini Normal file
View File

@ -0,0 +1,2 @@
Threads = 4
SRTM = data/srtm/Eurasia

BIN
test/data/kbh.osm.pbf Normal file

Binary file not shown.

1
test/extractor.ini Normal file
View File

@ -0,0 +1 @@
Memory = 1

9
test/server.ini Normal file
View File

@ -0,0 +1,9 @@
Threads = 8
IP = 0.0.0.0
Port = 5000
hsgrData=data/test.osrm.hsgr
nodesData=data/test.osrm.nodes
ramIndex=data/test.osrm.ramIndex
fileIndex=data/test.osrm.fileIndex
namesData=data/test.osrm.names

View File

@ -0,0 +1,28 @@
[bicycle]
cycleway = 19
trunk = 19
trunk_link = 19
primary = 19
primary_link = 19
secondary = 17
secondary_link = 17
tertiary = 15
residential = 15
unclassified = 15
living_street = 13
service = 12
track = 12
path = 12
footway = 10
pedestrian = 5
pier = 5
steps = 3
ferry = 5
obeyOneways = yes
useRestrictions = yes
accessTag = bicycle
excludeFromGrid = ferry
defaultSpeed = 17
obeyBollards = no
trafficLightPenalty = 20

View File

@ -0,0 +1,22 @@
[car]
motorway = 110
motorway_link = 90
trunk = 90
trunk_link = 70
primary = 70
primary_link = 60
secondary = 60
secondary_link = 50
tertiary = 55
unclassified = 25
residential = 40
living_street = 10
service = 30
ferry = 5
pier = 5
barrier = bollard
obeyOneways = yes
useRestrictions = yes
accessTag = motorcar
excludeFromGrid = ferry
defaultSpeed = 50

View File

@ -0,0 +1,20 @@
[default]
accessTag = motorcar
defaultSpeed = 50
barrier = bollard
motorway = 110
motorway_link = 90
trunk = 90
trunk_link = 70
primary = 70
primary_link = 60
secondary = 60
secondary_link = 50
tertiary = 40
residential = 30
living_street = 25
service = 25
unclassified = 25

View File

@ -0,0 +1,25 @@
[ebike]
cycleway = 25
trunk = 25
trunk_link = 25
primary = 25
primary_link = 25
secondary = 25
secondary_link = 25
tertiary = 25
unclassified = 25
residential = 25
living_street = 20
service = 20
track = 20
path = 15
ferry = 5
pier = 5
pedestrian = 5
footway = 5
steps = 3
obeyOneways = yes
useRestrictions = no
accessTag = bicycle
excludeFromGrid = ferry
defaultSpeed = 25