Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1869840f0e | |||
| 8532b5460b | |||
| 1fdbaf4a39 | |||
| 08527175b5 | |||
| d792572ece | |||
| 2a691ac5be | |||
| 2221a34529 | |||
| a8fd4050a2 | |||
| 85ee03dfde | |||
| 694e3854d7 | |||
| 90ed027711 | |||
| ac0c5c27e7 |
+1
-6
@@ -16,8 +16,6 @@ notifications:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
# enable building tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
cache:
|
||||
yarn: true
|
||||
@@ -28,8 +26,6 @@ cache:
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "hk+32aXXF5t1ApaM2Wjqooz3dx1si907L87WRMkO47WlpJmUUU/Ye+MJk9sViH8MdhOcceocVAmdYl5/WFWOIbDWNlBya9QvXDZyIu2KIre/0QyOCTZbrsif8paBXKIO5O/R4OTvIZ8rvWZsadBdmAT9GSbDhih6FzqXAEgeIYQ="
|
||||
- secure: "VE+cFkseFwW4jK6XwkP0yW3h4DixPJ8+Eb3yKcchGZ5iIJxlZ/8i1vKHYxadgPRwSYwPSB14tF70xj2OmiT2keGzZUfphmPXinBaLEhYk+Bde+GZZkoSl5ND109I/LcyNr0nG9dDgtV6pkvFchgchpyP9JnVOOS0+crEZlAz0RE="
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- CASHER_TIME_OUT=599 # one second less than 10m to avoid 10m timeout error: https://github.com/Project-OSRM/osrm-backend/issues/2742
|
||||
@@ -148,8 +144,6 @@ before_install:
|
||||
sudo mdutil -i off /
|
||||
npm install -g yarn
|
||||
fi
|
||||
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
|
||||
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off")
|
||||
- echo "Using ${JOBS} jobs"
|
||||
- yarn install --ignore-scripts
|
||||
# Bootstrap cmake to be able to run mason
|
||||
@@ -234,5 +228,6 @@ after_success:
|
||||
|
||||
- |
|
||||
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
|
||||
source ./scripts/travis/build.sh
|
||||
./scripts/travis/publish.sh
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
- Track preprocessing flag in the map matching plugin.
|
||||
|
||||
# 5.7.0
|
||||
- Changes from 5.6
|
||||
- NodeJs Bindings
|
||||
|
||||
@@ -41,27 +41,19 @@ The easiest and quickest way to setup your own routing engine backend is to use
|
||||
|
||||
### Using Docker
|
||||
|
||||
We base [our Docker images](https://hub.docker.com/r/osrm/osrm-backend/) on Alpine Linux and make sure they are as lightweight as possible.
|
||||
We base the Docker images on Alpine Linux and make sure they are as lightweight as possible (around 10-15 MB).
|
||||
In the following, replace `X.Y.Z` with the current stable release version.
|
||||
|
||||
```
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
|
||||
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend:vX.Y.Z osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend:vX.Y.Z osrm-contract /data/berlin-latest.osrm
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend:vX.Y.Z osrm-routed /data/berlin-latest.osrm
|
||||
|
||||
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
|
||||
curl http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true
|
||||
```
|
||||
|
||||
In case Docker complains about not being able to connect to the Docker daemon make sure you are in the `docker` group.
|
||||
|
||||
```
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
|
||||
|
||||
|
||||
### Building from Source
|
||||
|
||||
The following targets Ubuntu 16.04.
|
||||
|
||||
+3
-9
@@ -141,21 +141,15 @@ SET test_osm=%test_region%.osm.pbf
|
||||
IF NOT EXIST %test_osm% powershell Invoke-WebRequest https://s3.amazonaws.com/mapbox/osrm/testing/monaco.osm.pbf -OutFile %test_osm%
|
||||
%Configuration%\osrm-extract.exe -p ../profiles/car.lua %test_osm%
|
||||
MKDIR ch
|
||||
XCOPY %test_region%.osrm.* ch\
|
||||
XCOPY %test_region%.osrm ch\
|
||||
XCOPY %test_region%.osrm %test_region%.osrm.* ch\
|
||||
MKDIR corech
|
||||
XCOPY %test_region%.osrm.* corech\
|
||||
XCOPY %test_region%.osrm corech\
|
||||
XCOPY %test_region%.osrm %test_region%.osrm.* corech\
|
||||
MKDIR mld
|
||||
XCOPY %test_region%.osrm.* mld\
|
||||
XCOPY %test_region%.osrm mld\
|
||||
XCOPY %test_region%.osrm %test_region%.osrm.* mld\
|
||||
%Configuration%\osrm-contract.exe %test_region_ch%.osrm
|
||||
%Configuration%\osrm-contract.exe --core 0.8 %test_region_corech%.osrm
|
||||
%Configuration%\osrm-partition.exe %test_region_mld%.osrm
|
||||
%Configuration%\osrm-customize.exe %test_region_mld%.osrm
|
||||
XCOPY /Y ch\*.* ..\test\data\ch\
|
||||
XCOPY /Y corech\*.* ..\test\data\corech\
|
||||
XCOPY /Y mld\*.* ..\test\data\mld\
|
||||
unit_tests\%Configuration%\library-tests.exe
|
||||
|
||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="master" GOTO DONE
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
{
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Description": "user for publishing to s3://mapbox-node-binary/osrm",
|
||||
"Resources": {
|
||||
"User": {
|
||||
"Type": "AWS::IAM::User",
|
||||
"Properties": {
|
||||
"Policies": [
|
||||
{
|
||||
"PolicyName": "list",
|
||||
"PolicyDocument": {
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "arn:aws:s3:::mapbox-node-binary",
|
||||
"Condition": {
|
||||
"StringLike": {
|
||||
"s3:prefix": [
|
||||
"osrm/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"PolicyName": "publish",
|
||||
"PolicyDocument": {
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:DeleteObject",
|
||||
"s3:GetObject",
|
||||
"s3:GetObjectAcl",
|
||||
"s3:PutObject",
|
||||
"s3:PutObjectAcl"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "arn:aws:s3:::mapbox-node-binary/osrm/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"AccessKey": {
|
||||
"Type": "AWS::IAM::AccessKey",
|
||||
"Properties": {
|
||||
"UserName": {
|
||||
"Ref": "User"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Outputs": {
|
||||
"AccessKeyId": {
|
||||
"Value": {
|
||||
"Ref": "AccessKey"
|
||||
}
|
||||
},
|
||||
"SecretAccessKey": {
|
||||
"Value": {
|
||||
"Fn::GetAtt": [
|
||||
"AccessKey",
|
||||
"SecretAccessKey"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
var cf = require('@mapbox/cloudfriend');
|
||||
var package_json = require('../package.json')
|
||||
|
||||
module.exports = {
|
||||
AWSTemplateFormatVersion: '2010-09-09',
|
||||
Description: 'user for publishing to s3://mapbox-node-binary/' + package_json.name,
|
||||
Resources: {
|
||||
User: {
|
||||
Type: 'AWS::IAM::User',
|
||||
Properties: {
|
||||
Policies: [
|
||||
{
|
||||
PolicyName: 'list',
|
||||
PolicyDocument: {
|
||||
Statement: [
|
||||
{
|
||||
Action: ['s3:ListBucket'],
|
||||
Effect: 'Allow',
|
||||
Resource: 'arn:aws:s3:::mapbox-node-binary',
|
||||
Condition : {
|
||||
StringLike : {
|
||||
"s3:prefix": [ package_json.name + "/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
PolicyName: 'publish',
|
||||
PolicyDocument: {
|
||||
Statement: [
|
||||
{
|
||||
Action: ['s3:DeleteObject', 's3:GetObject', 's3:GetObjectAcl', 's3:PutObject', 's3:PutObjectAcl'],
|
||||
Effect: 'Allow',
|
||||
Resource: 'arn:aws:s3:::mapbox-node-binary/' + package_json.name + '/*'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
AccessKey: {
|
||||
Type: 'AWS::IAM::AccessKey',
|
||||
Properties: {
|
||||
UserName: cf.ref('User')
|
||||
}
|
||||
}
|
||||
},
|
||||
Outputs: {
|
||||
AccessKeyId: {
|
||||
Value: cf.ref('AccessKey')
|
||||
},
|
||||
SecretAccessKey: {
|
||||
Value: cf.getAtt('AccessKey', 'SecretAccessKey')
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
coverage:
|
||||
|
||||
ignore:
|
||||
- unit_tests/.*
|
||||
- third_party/.*
|
||||
|
||||
comment: off
|
||||
|
||||
+3
-5
@@ -279,8 +279,6 @@ In addition to the [general options](#general-options) the following options are
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. |
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|
||||
|gaps |`split` (default), `ignore` |Allows the input track splitting based on huge timestamp gaps between points. |
|
||||
|tidy |`true`, `false` (default) |Allows the input track modification to obtain better matching quality for noisy tracks. |
|
||||
|
||||
|Parameter |Values |
|
||||
|------------|-----------------------------------|
|
||||
@@ -316,7 +314,7 @@ All other properties might be undefined.
|
||||
|
||||
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm) for 10 or more waypoints and uses brute force for less than 10 waypoints.
|
||||
The returned path does not have to be the fastest path. As TSP is NP-hard it only returns an approximation.
|
||||
Note that all input coordinates have to be connected for the trip service to work.
|
||||
Note that all input coordinates have to be connected for the trip service to work.
|
||||
|
||||
```endpoint
|
||||
GET /trip/v1/{profile}/{coordinates}?roundtrip={true|false}&source{any|first}&destination{any|last}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={simplified|full|false}&annotations={true|false}'
|
||||
@@ -336,7 +334,7 @@ In addition to the [general options](#general-options) the following options are
|
||||
|
||||
**Fixing Start and End Points**
|
||||
|
||||
It is possible to explicitely set the start or end coordinate of the trip.
|
||||
It is possible to explicitely set the start or end coordinate of the trip.
|
||||
When source is set to `first`, the first coordinate is used as start coordinate of the trip in the output. When destination is set to `last`, the last coordinate will be used as destination of the trip in the returned output. If you specify `any`, any of the coordinates can be used as the first or last coordinate in the output.
|
||||
|
||||
However, if `source=any&destination=any` the returned round-trip will still start at the first input coordinate by default.
|
||||
@@ -346,7 +344,7 @@ Right now, the following combinations are possible:
|
||||
|
||||
| roundtrip | source | destination | supported |
|
||||
| :-- | :-- | :-- | :-- |
|
||||
| true | first | last | **yes** |
|
||||
| true | first | last | **yes** |
|
||||
| true | first | any | **yes** |
|
||||
| true | any | last | **yes** |
|
||||
| true | any | any | **yes** |
|
||||
|
||||
+3
-79
@@ -25,18 +25,6 @@ As you scroll down the file you'll see local variables, and then local functions
|
||||
|
||||
`way_function` and `node_function` are the important functions which are called when extracting OpenStreetMap data with `osrm-extract`.
|
||||
|
||||
The following global properties can be set in your profile:
|
||||
|
||||
Attribute | Type | Notes
|
||||
------------------------------|----------|----------------------------------------------------------------------------
|
||||
weight_name | String | Name used in output for the routing weight property (default 'duration')
|
||||
weight_precision | Unsigned | Decimal precision of edge weights (default 1)
|
||||
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance)
|
||||
use_turn_restrictions | Boolean | Are turn instructions followed?
|
||||
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed?
|
||||
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
|
||||
max_turn_weight | Float | Maximum turn penalty weight
|
||||
|
||||
## way_function
|
||||
|
||||
Given an OpenStreetMap way, the way_function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
|
||||
@@ -45,79 +33,15 @@ All other calculations stem from that, including the returned timings in driving
|
||||
|
||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the way_function. Instead a way_function will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
|
||||
|
||||
The following attributes can be set on the result in way_function:
|
||||
|
||||
Attribute | Type | Notes
|
||||
----------------------------------------|----------|--------------------------------------------------------------------------
|
||||
forward_speed | Float | Speed on this way in km/h
|
||||
backward_speed | Float | " "
|
||||
forward_rate | Float | Routing weight, expressed as meters/*weight* (e.g. for a fastest-route weighting, you would want this to be meters/second, so set it to forward_speed/3.6)
|
||||
backward_rate | Float | " "
|
||||
forward_mode | Enum | Mode of travel (e.g. car, ferry). Defined in include/extractor/travel_mode.hpp
|
||||
backward_mode | Enum | " "
|
||||
duration | Float | Alternative setter for duration of the whole way in both directions
|
||||
weight | Float | Alternative setter for weight of the whole way in both directions
|
||||
turn_lanes_forward | String | Directions for individual lanes (normalised OSM turn:lanes value)
|
||||
turn_lanes_backward | String | " "
|
||||
forward_restricted | Boolean | Is this a restricted access road? (e.g. private, or deliveries only; used to enable high turn penalty, so that way is only chosen for start/end of route)
|
||||
backward_restricted | Boolean | " "
|
||||
is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if false, prevents snapping the start point to this way)
|
||||
roundabout | Boolean | Is this part of a roundabout?
|
||||
circular | Boolean | Is this part of a non-roundabout circular junction?
|
||||
name | String | Name of the way
|
||||
ref | String | Road number
|
||||
pronunciation | String | Name pronunciation
|
||||
road_classification.motorway_class | Boolean | Guidance: way is a motorway
|
||||
road_classification.link_class | Boolean | Guidance: way is a slip/link road
|
||||
road_classification.road_priority_class | Enum | Guidance: order in priority list. Defined in include/extractor/guidance/road_classification.hpp
|
||||
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
|
||||
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
|
||||
|
||||
### Guidance
|
||||
## Guidance
|
||||
|
||||
The guidance parameters in profiles are currently a work in progress. They can and will change.
|
||||
Please be aware of this when using guidance configuration possibilities.
|
||||
|
||||
### Road Classification
|
||||
|
||||
Guidance uses road classes to decide on when/if to emit specific instructions and to discover which road is obvious when following a route.
|
||||
Classification uses three flags and a priority-category.
|
||||
The flags indicate whether a road is a motorway (required for on/off ramps), a link type (the ramps itself, if also a motorway) and whether a road may be omittted in considerations (is considered purely for connectivity).
|
||||
The priority-category influences the decision which road is considered the obvious choice and which roads can be seen as fork.
|
||||
Forks can be emitted between roads of similar priority category only. Obvious choices follow a major priority road, if the priority difference is large.
|
||||
|
||||
## node_function
|
||||
|
||||
The following attributes can be set on the result in node_function:
|
||||
|
||||
Attribute | Type | Notes
|
||||
----------------|---------|-------------------------------------------------------
|
||||
barrier | Boolean | Is it an impassable barrier?
|
||||
traffic_lights | Boolean | Is it a traffic light (incurs delay in turn_function)?
|
||||
|
||||
## segment_function
|
||||
|
||||
The following attributes can be read and set on the result in segment_function:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|------------------------------------------------------
|
||||
source.lon | Read | Float | Co-ordinates of segment start
|
||||
source.lat | Read | Float | " "
|
||||
target.lon | Read | Float | Co-ordinates of segment end
|
||||
target.lat | Read | Float | " "
|
||||
target.distance | Read | Float | Length of segment
|
||||
weight | Read/write | Float | Routing weight for this segment
|
||||
duration | Read/write | Float | Duration for this segment
|
||||
|
||||
## turn_function
|
||||
|
||||
The following attributes can be read and set on the result in turn_function:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|------------------------------------------------------
|
||||
direction_modifier | Read | Enum | Geometry of turn. Defined in include/extractor/guidance/turn_instruction.hpp
|
||||
turn_type | Read | Enum | Priority of turn. Defined in include/extractor/guidance/turn_instruction.hpp
|
||||
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
|
||||
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in way_function)
|
||||
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in way_function)
|
||||
angle | Read | Float | Angle of turn in degrees (0-360: 0=u-turn, 180=straight on)
|
||||
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
|
||||
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
|
||||
|
||||
@@ -79,19 +79,3 @@ Feature: Bike - Cycle tracks/lanes
|
||||
| residential | lane | yes | x | x |
|
||||
| footway | lane | yes | x | x |
|
||||
| cycleway | lane | yes | x | x |
|
||||
|
||||
Scenario: Bike - Cycleway on oneways, modes
|
||||
Then routability should be
|
||||
| highway | cycleway | oneway | forw | backw |
|
||||
| motorway | track | yes | cycling | |
|
||||
| residential | track | yes | cycling | pushing bike |
|
||||
| cycleway | track | yes | cycling | pushing bike |
|
||||
| footway | track | yes | pushing bike | pushing bike |
|
||||
|
||||
Scenario: Bike - Cycleway on oneways, speeds
|
||||
Then routability should be
|
||||
| highway | cycleway | oneway | forw | backw |
|
||||
| motorway | track | yes | 15 km/h | |
|
||||
| residential | track | yes | 15 km/h | 6 km/h |
|
||||
| cycleway | track | yes | 15 km/h | 6 km/h |
|
||||
| footway | track | yes | 6 km/h +-1 | 6 km/h +-1 |
|
||||
|
||||
@@ -10,11 +10,11 @@ Feature: osrm-partition command line options: help
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--min-cell-size"
|
||||
And stdout should contain "--balance"
|
||||
And stdout should contain "--boundary"
|
||||
And stdout should contain "--optimizing-cuts"
|
||||
And stdout should contain "--small-component-size"
|
||||
And stdout should contain "--max-cell-sizes"
|
||||
And it should exit with an error
|
||||
|
||||
Scenario: osrm-partition - Help, short
|
||||
@@ -26,11 +26,11 @@ Feature: osrm-partition command line options: help
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--min-cell-size"
|
||||
And stdout should contain "--balance"
|
||||
And stdout should contain "--boundary"
|
||||
And stdout should contain "--optimizing-cuts"
|
||||
And stdout should contain "--small-component-size"
|
||||
And stdout should contain "--max-cell-sizes"
|
||||
And it should exit successfully
|
||||
|
||||
Scenario: osrm-partition - Help, long
|
||||
@@ -42,9 +42,9 @@ Feature: osrm-partition command line options: help
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--min-cell-size"
|
||||
And stdout should contain "--balance"
|
||||
And stdout should contain "--boundary"
|
||||
And stdout should contain "--optimizing-cuts"
|
||||
And stdout should contain "--small-component-size"
|
||||
And stdout should contain "--max-cell-sizes"
|
||||
And it should exit successfully
|
||||
|
||||
@@ -18,15 +18,3 @@ Feature: osrm-partition command line options: invalid options
|
||||
And stderr should contain "option"
|
||||
And stderr should contain "fly-me-to-the-moon"
|
||||
And it should exit with an error
|
||||
|
||||
Scenario: osrm-partition - Check invalid values
|
||||
When I try to run "osrm-partition --max-cell-sizes 4,6@4,16 fly-me-to-the-moon.osrm"
|
||||
Then stdout should be empty
|
||||
And stderr should contain "is invalid"
|
||||
And it should exit with an error
|
||||
|
||||
Scenario: osrm-partition - Check non-descending order
|
||||
When I try to run "osrm-partition --max-cell-sizes 4,64,16 fly-me-to-the-moon.osrm"
|
||||
Then stdout should be empty
|
||||
And stderr should contain "must be sorted in non-descending order"
|
||||
And it should exit with an error
|
||||
|
||||
@@ -40,84 +40,6 @@ Feature: Basic Map Matching
|
||||
| trace | timestamps | matchings |
|
||||
| abcd | 0 1 62 63 | ab,cd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace splitting suppression
|
||||
Given the query options
|
||||
| gaps | ignore |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | matchings |
|
||||
| abcd | 0 1 62 63 | abcd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace tidying. Clean case.
|
||||
Given a grid size of 100 meters
|
||||
|
||||
Given the query options
|
||||
| tidy | true |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | matchings |
|
||||
| abcd | 0 10 20 30 | abcd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace tidying. Dirty case by ts.
|
||||
Given a grid size of 100 meters
|
||||
|
||||
Given the query options
|
||||
| tidy | true |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | matchings |
|
||||
| abacd | 0 10 12 20 30 | abcd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace tidying. Dirty case by dist.
|
||||
Given a grid size of 8 meters
|
||||
|
||||
Given the query options
|
||||
| tidy | true |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a q b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| aqbcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | matchings |
|
||||
| abcbd | abbd |
|
||||
|
||||
Scenario: Testbot - Map matching with core factor
|
||||
Given the contract extra arguments "--core 0.8"
|
||||
Given the node map
|
||||
|
||||
@@ -3,7 +3,7 @@ Feature: Multi level routing
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16,64"
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
|
||||
Scenario: Testbot - Multi level routing check partition
|
||||
Given the node map
|
||||
@@ -31,7 +31,7 @@ Feature: Multi level routing
|
||||
| be | primary |
|
||||
|
||||
And the data has been extracted
|
||||
When I run "osrm-partition --max-cell-sizes 4,16 --small-component-size 1 {processed_file}"
|
||||
When I run "osrm-partition --min-cell-size 4 --small-component-size 1 {processed_file}"
|
||||
Then it should exit successfully
|
||||
And stdout should not contain "level 1 #cells 1 bit size 1"
|
||||
|
||||
@@ -57,6 +57,7 @@ Feature: Multi level routing
|
||||
| cm | primary |
|
||||
| hj | primary |
|
||||
| kp | primary |
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
@@ -87,6 +88,7 @@ Feature: Multi level routing
|
||||
| dim | primary |
|
||||
| glr | primary |
|
||||
| ot | secondary |
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
@@ -111,7 +113,6 @@ Feature: Multi level routing
|
||||
│ │
|
||||
l───k
|
||||
"""
|
||||
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16"
|
||||
And the ways
|
||||
| nodes | maxspeed |
|
||||
| abcda | 5 |
|
||||
@@ -123,6 +124,7 @@ Feature: Multi level routing
|
||||
| fi | 15 |
|
||||
| gi | 15 |
|
||||
| hf | 100 |
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
|
||||
@@ -39,9 +39,9 @@ class CellCustomizer
|
||||
const EdgeWeight weight = heap.GetKey(node);
|
||||
|
||||
if (level == 1)
|
||||
RelaxNode<true>(graph, cells, heap, level, node, weight);
|
||||
RelaxNode<true>(graph, cells, heap, level, id, node, weight);
|
||||
else
|
||||
RelaxNode<false>(graph, cells, heap, level, node, weight);
|
||||
RelaxNode<false>(graph, cells, heap, level, id, node, weight);
|
||||
|
||||
destinations_set.erase(node);
|
||||
}
|
||||
@@ -85,6 +85,7 @@ class CellCustomizer
|
||||
const partition::CellStorage &cells,
|
||||
Heap &heap,
|
||||
LevelID level,
|
||||
CellID id,
|
||||
NodeID node,
|
||||
EdgeWeight weight) const
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define ENGINE_API_MATCH_HPP
|
||||
|
||||
#include "engine/api/match_parameters.hpp"
|
||||
#include "engine/api/match_parameters_tidy.hpp"
|
||||
#include "engine/api/route_api.hpp"
|
||||
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
@@ -22,10 +21,8 @@ namespace api
|
||||
class MatchAPI final : public RouteAPI
|
||||
{
|
||||
public:
|
||||
MatchAPI(const datafacade::BaseDataFacade &facade_,
|
||||
const MatchParameters ¶meters_,
|
||||
const tidy::Result &tidy_result_)
|
||||
: RouteAPI(facade_, parameters_), parameters(parameters_), tidy_result(tidy_result_)
|
||||
MatchAPI(const datafacade::BaseDataFacade &facade_, const MatchParameters ¶meters_)
|
||||
: RouteAPI(facade_, parameters_), parameters(parameters_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -86,20 +83,13 @@ class MatchAPI final : public RouteAPI
|
||||
for (auto point_index : util::irange(
|
||||
0u, static_cast<unsigned>(sub_matchings[sub_matching_index].indices.size())))
|
||||
{
|
||||
trace_idx_to_matching_idx[tidy_result
|
||||
.tidied_to_original[sub_matchings[sub_matching_index]
|
||||
.indices[point_index]]] =
|
||||
trace_idx_to_matching_idx[sub_matchings[sub_matching_index].indices[point_index]] =
|
||||
MatchingIndex{sub_matching_index, point_index};
|
||||
}
|
||||
}
|
||||
|
||||
for (auto trace_index : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
{
|
||||
if (tidy_result.can_be_removed[trace_index])
|
||||
{
|
||||
waypoints.values.push_back(util::json::Null());
|
||||
continue;
|
||||
}
|
||||
auto matching_index = trace_idx_to_matching_idx[trace_index];
|
||||
if (matching_index.NotMatched())
|
||||
{
|
||||
@@ -121,7 +111,6 @@ class MatchAPI final : public RouteAPI
|
||||
}
|
||||
|
||||
const MatchParameters ¶meters;
|
||||
const tidy::Result &tidy_result;
|
||||
};
|
||||
|
||||
} // ns api
|
||||
|
||||
@@ -50,34 +50,23 @@ namespace api
|
||||
*/
|
||||
struct MatchParameters : public RouteParameters
|
||||
{
|
||||
enum class GapsType
|
||||
{
|
||||
Split,
|
||||
Ignore
|
||||
};
|
||||
|
||||
MatchParameters()
|
||||
: RouteParameters(false,
|
||||
false,
|
||||
false,
|
||||
RouteParameters::GeometriesType::Polyline,
|
||||
RouteParameters::OverviewType::Simplified,
|
||||
{}),
|
||||
gaps(GapsType::Split), tidy(false)
|
||||
{})
|
||||
{
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
MatchParameters(std::vector<unsigned> timestamps_, GapsType gaps_, bool tidy_, Args... args_)
|
||||
: RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)},
|
||||
gaps(gaps_), tidy(tidy_)
|
||||
MatchParameters(std::vector<unsigned> timestamps_, Args... args_)
|
||||
: RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)}
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<unsigned> timestamps;
|
||||
GapsType gaps;
|
||||
bool tidy;
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return RouteParameters::IsValid() &&
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
#ifndef COORDINATE_TIDY
|
||||
#define COORDINATE_TIDY
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
|
||||
#include "engine/api/match_parameters.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
namespace api
|
||||
{
|
||||
namespace tidy
|
||||
{
|
||||
|
||||
struct Thresholds
|
||||
{
|
||||
double distance_in_meters;
|
||||
std::int32_t duration_in_seconds;
|
||||
};
|
||||
|
||||
using Mask = boost::dynamic_bitset<>;
|
||||
using Mapping = std::vector<std::size_t>;
|
||||
|
||||
struct Result
|
||||
{
|
||||
// Tidied parameters
|
||||
MatchParameters parameters;
|
||||
// Masking the MatchParameter parallel arrays for items which should be removed.
|
||||
Mask can_be_removed;
|
||||
// Maps the MatchParameter's original items to items which should not be removed.
|
||||
Mapping tidied_to_original;
|
||||
};
|
||||
|
||||
inline Result keep_all(const MatchParameters ¶ms)
|
||||
{
|
||||
Result result;
|
||||
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
result.tidied_to_original.reserve(params.coordinates.size());
|
||||
for (std::size_t current = 0; current < params.coordinates.size(); ++current)
|
||||
{
|
||||
result.tidied_to_original.push_back(current);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
||||
|
||||
// We have to filter parallel arrays that may be empty or the exact same size.
|
||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||
|
||||
for (std::size_t i = 0; i < result.can_be_removed.size(); ++i)
|
||||
{
|
||||
if (!result.can_be_removed[i])
|
||||
{
|
||||
result.parameters.coordinates.push_back(params.coordinates[i]);
|
||||
|
||||
if (!params.hints.empty())
|
||||
result.parameters.hints.push_back(params.hints[i]);
|
||||
|
||||
if (!params.radiuses.empty())
|
||||
result.parameters.radiuses.push_back(params.radiuses[i]);
|
||||
|
||||
if (!params.bearings.empty())
|
||||
result.parameters.bearings.push_back(params.bearings[i]);
|
||||
|
||||
if (!params.timestamps.empty())
|
||||
result.parameters.timestamps.push_back(params.timestamps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
{
|
||||
Result result;
|
||||
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
|
||||
result.tidied_to_original.push_back(0);
|
||||
std::size_t last_good = 0;
|
||||
|
||||
const auto uses_timestamps = !params.timestamps.empty();
|
||||
|
||||
Thresholds running{0., 0};
|
||||
|
||||
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
|
||||
for (std::size_t current = 0; current < params.coordinates.size() - 1; ++current)
|
||||
{
|
||||
const auto next = current + 1;
|
||||
|
||||
auto distance_delta = util::coordinate_calculation::haversineDistance(
|
||||
params.coordinates[current], params.coordinates[next]);
|
||||
running.distance_in_meters += distance_delta;
|
||||
const auto over_distance = running.distance_in_meters >= cfg.distance_in_meters;
|
||||
|
||||
if (uses_timestamps)
|
||||
{
|
||||
auto duration_delta = params.timestamps[next] - params.timestamps[current];
|
||||
running.duration_in_seconds += duration_delta;
|
||||
const auto over_duration = running.duration_in_seconds >= cfg.duration_in_seconds;
|
||||
|
||||
if (over_distance && over_duration)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
else
|
||||
{
|
||||
result.can_be_removed.set(next, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (over_distance)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
else
|
||||
{
|
||||
result.can_be_removed.set(next, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
||||
|
||||
// We have to filter parallel arrays that may be empty or the exact same size.
|
||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||
|
||||
for (std::size_t i = 0; i < result.can_be_removed.size(); ++i)
|
||||
{
|
||||
if (!result.can_be_removed[i])
|
||||
{
|
||||
result.parameters.coordinates.push_back(params.coordinates[i]);
|
||||
|
||||
if (!params.hints.empty())
|
||||
result.parameters.hints.push_back(params.hints[i]);
|
||||
|
||||
if (!params.radiuses.empty())
|
||||
result.parameters.radiuses.push_back(params.radiuses[i]);
|
||||
|
||||
if (!params.bearings.empty())
|
||||
result.parameters.bearings.push_back(params.bearings[i]);
|
||||
|
||||
if (!params.timestamps.empty())
|
||||
result.parameters.timestamps.push_back(params.timestamps[i]);
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(result.tidied_to_original.size() == result.parameters.coordinates.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // ns tidy
|
||||
} // ns api
|
||||
} // ns engine
|
||||
} // ns osrm
|
||||
|
||||
#endif
|
||||
@@ -38,8 +38,7 @@ class RoutingAlgorithmsInterface
|
||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const = 0;
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const = 0;
|
||||
|
||||
virtual std::vector<routing_algorithms::TurnData>
|
||||
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
@@ -80,12 +79,11 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const final override;
|
||||
|
||||
routing_algorithms::SubMatchingList
|
||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const final override;
|
||||
routing_algorithms::SubMatchingList MapMatching(
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const final override;
|
||||
|
||||
std::vector<routing_algorithms::TurnData>
|
||||
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
@@ -165,16 +163,10 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMat
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const
|
||||
{
|
||||
return routing_algorithms::mapMatching(heaps,
|
||||
facade,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision,
|
||||
allow_splitting);
|
||||
return routing_algorithms::mapMatching(
|
||||
heaps, facade, candidates_list, trace_coordinates, trace_timestamps, trace_gps_precision);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
@@ -215,8 +207,7 @@ inline routing_algorithms::SubMatchingList
|
||||
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
|
||||
const std::vector<util::Coordinate> &,
|
||||
const std::vector<unsigned> &,
|
||||
const std::vector<boost::optional<double>> &,
|
||||
const bool) const
|
||||
const std::vector<boost::optional<double>> &) const
|
||||
{
|
||||
throw util::exception("MapMatching is not implemented");
|
||||
}
|
||||
|
||||
@@ -28,8 +28,7 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision);
|
||||
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
@@ -37,8 +36,7 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,17 +110,9 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
|
||||
// which can be smaller then the total number of nodes.
|
||||
// this will save memory in case we sort the border nodes first
|
||||
if (index >= node_to_edge_offset.size() - 1)
|
||||
{
|
||||
// On level 0 all edges are border edges
|
||||
if (level == 0)
|
||||
return SuperT::BeginEdges(node);
|
||||
else
|
||||
return SuperT::EndEdges(node);
|
||||
}
|
||||
return SuperT::BeginEdges(node);
|
||||
else
|
||||
{
|
||||
return SuperT::BeginEdges(node) + node_to_edge_offset[index + level];
|
||||
}
|
||||
}
|
||||
|
||||
// We save the level as sentinel at the end
|
||||
|
||||
@@ -13,12 +13,7 @@ namespace partition
|
||||
|
||||
struct PartitionConfig
|
||||
{
|
||||
PartitionConfig()
|
||||
: requested_num_threads(0), balance(1.2), boundary_factor(0.25), num_optimizing_cuts(10),
|
||||
small_component_size(1000),
|
||||
max_cell_sizes{128, 128 * 32, 128 * 32 * 16, 128 * 32 * 16 * 32}
|
||||
{
|
||||
}
|
||||
PartitionConfig() : requested_num_threads(0) {}
|
||||
|
||||
void UseDefaults()
|
||||
{
|
||||
@@ -54,11 +49,11 @@ struct PartitionConfig
|
||||
|
||||
unsigned requested_num_threads;
|
||||
|
||||
std::size_t minimum_cell_size;
|
||||
double balance;
|
||||
double boundary_factor;
|
||||
std::size_t num_optimizing_cuts;
|
||||
std::size_t small_component_size;
|
||||
std::vector<std::size_t> max_cell_sizes;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,24 +33,13 @@ struct MatchParametersGrammar final : public RouteParametersGrammar<Iterator, Si
|
||||
(qi::uint_ %
|
||||
';')[ph::bind(&engine::api::MatchParameters::timestamps, qi::_r1) = qi::_1];
|
||||
|
||||
gaps_type.add("split", engine::api::MatchParameters::GapsType::Split)(
|
||||
"ignore", engine::api::MatchParameters::GapsType::Ignore);
|
||||
|
||||
root_rule =
|
||||
BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
|
||||
-('?' > (timestamps_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1) |
|
||||
(qi::lit("gaps=") >
|
||||
gaps_type[ph::bind(&engine::api::MatchParameters::gaps, qi::_r1) = qi::_1]) |
|
||||
(qi::lit("tidy=") >
|
||||
qi::bool_[ph::bind(&engine::api::MatchParameters::tidy, qi::_r1) = qi::_1])) %
|
||||
'&');
|
||||
root_rule = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
|
||||
-('?' > (timestamps_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&');
|
||||
}
|
||||
|
||||
private:
|
||||
qi::rule<Iterator, Signature> root_rule;
|
||||
qi::rule<Iterator, Signature> timestamps_rule;
|
||||
|
||||
qi::symbols<char, engine::api::MatchParameters::GapsType> gaps_type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ class SharedMemory
|
||||
#else
|
||||
void WaitForDetach()
|
||||
{
|
||||
util::Log(logDEBUG)
|
||||
util::Log(logWARNING)
|
||||
<< "Shared memory support for non-Linux systems does not wait for clients to "
|
||||
"dettach. Going to sleep for 50ms.";
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
@@ -245,8 +245,8 @@ class SharedMemory
|
||||
void WaitForDetach()
|
||||
{
|
||||
// FIXME this needs an implementation for Windows
|
||||
util::Log(logDEBUG) << "Shared memory support for Windows does not wait for clients to "
|
||||
"dettach. Going to sleep for 50ms.";
|
||||
util::Log(logWARNING) << "Shared memory support for Windows does not wait for clients to "
|
||||
"dettach. Going to sleep for 50ms.";
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
|
||||
+19
-14
@@ -1,12 +1,24 @@
|
||||
{
|
||||
"name": "osrm",
|
||||
"version": "5.7.0-latest.1",
|
||||
"private": false,
|
||||
"version": "5.7.0-alpha.1",
|
||||
"private": true,
|
||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||
"dependencies": {
|
||||
"chalk": "^1.1.3",
|
||||
"cucumber": "^1.2.1",
|
||||
"d3-queue": "^2.0.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nan": "^2.1.0",
|
||||
"node-cmake": "^1.2.1",
|
||||
"node-pre-gyp": "^0.6.34"
|
||||
"node-pre-gyp": "^0.6.34",
|
||||
"node-timeout": "0.0.4",
|
||||
"polyline": "^0.2.0",
|
||||
"request": "^2.69.0",
|
||||
"rimraf": "^2.5.4",
|
||||
"xmlbuilder": "^4.2.1"
|
||||
},
|
||||
"bin": {
|
||||
"cucumber": "./node_modules/cucumber/bin/cucumber.js"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
@@ -17,7 +29,8 @@
|
||||
"scripts": {
|
||||
"lint": "eslint -c ./.eslintrc features/step_definitions/ features/support/",
|
||||
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld",
|
||||
"clean": "rm -rf test/cache",
|
||||
"clean-test": "rm -rf test/cache",
|
||||
"cucumber": "./node_modules/cucumber/bin/cucumber.js",
|
||||
"docs": "./scripts/build_api_docs.sh",
|
||||
"install": "node-pre-gyp install --fallback-to-build=false"
|
||||
},
|
||||
@@ -38,17 +51,9 @@
|
||||
"docbox": "^1.0.5",
|
||||
"documentation": "^4.0.0-beta.18",
|
||||
"eslint": "^2.4.0",
|
||||
"chalk": "^1.1.3",
|
||||
"cucumber": "^1.2.1",
|
||||
"d3-queue": "^2.0.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
|
||||
"aws-sdk": "~2.0.31",
|
||||
"tape": "^4.2.2",
|
||||
"node-timeout": "0.0.4",
|
||||
"polyline": "^0.2.0",
|
||||
"request": "^2.69.0",
|
||||
"rimraf": "^2.5.4",
|
||||
"xmlbuilder": "^4.2.1"
|
||||
"tape": "^4.2.2"
|
||||
},
|
||||
"bundleDependencies": [
|
||||
"node-pre-gyp"
|
||||
|
||||
+6
-18
@@ -444,29 +444,17 @@ function way_function (way, result)
|
||||
end
|
||||
|
||||
-- cycleways
|
||||
local has_cycleway_left, has_cycleway_right
|
||||
if cycleway and profile.cycleway_tags[cycleway] then
|
||||
has_cycleway_left = true
|
||||
has_cycleway_right = true
|
||||
elseif cycleway_left and profile.cycleway_tags[cycleway_left] then
|
||||
has_cycleway_left = true
|
||||
has_cycleway_right = true
|
||||
elseif cycleway_right and profile.cycleway_tags[cycleway_right] then
|
||||
has_cycleway_left = true
|
||||
has_cycleway_right = true
|
||||
end
|
||||
if has_cycleway_right and
|
||||
(result.forward_mode == mode.inaccessible or
|
||||
result.forward_mode == mode.cycling) then
|
||||
result.forward_speed = profile.bicycle_speeds["cycleway"]
|
||||
end
|
||||
if has_cycleway_left and
|
||||
(result.backward_mode == mode.inaccessible or
|
||||
result.backward_mode == mode.cycling) then
|
||||
result.backward_speed = profile.bicycle_speeds["cycleway"]
|
||||
elseif cycleway_left and profile.cycleway_tags[cycleway_left] then
|
||||
result.forward_speed = profile.bicycle_speeds["cycleway"]
|
||||
result.backward_speed = profile.bicycle_speeds["cycleway"]
|
||||
elseif cycleway_right and profile.cycleway_tags[cycleway_right] then
|
||||
result.forward_speed = profile.bicycle_speeds["cycleway"]
|
||||
result.backward_speed = profile.bicycle_speeds["cycleway"]
|
||||
end
|
||||
|
||||
|
||||
-- dismount
|
||||
if bicycle == "dismount" then
|
||||
result.forward_mode = mode.pushing_bike
|
||||
|
||||
@@ -33,7 +33,6 @@ local profile = {
|
||||
'sally_port',
|
||||
'gate',
|
||||
'no',
|
||||
'kerb',
|
||||
'block'
|
||||
},
|
||||
|
||||
|
||||
Executable
+99
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# defaults
|
||||
export ENABLE_COVERAGE=${ENABLE_COVERAGE:-"Off"}
|
||||
export BUILD_TYPE=${BUILD_TYPE:-"Release"}
|
||||
export NODE=${NODE:-4}
|
||||
|
||||
export CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
export DEPS_DIR="$(pwd)/deps"
|
||||
export PATH=${DEPS_DIR}/bin:${PATH}
|
||||
mkdir -p ${DEPS_DIR}
|
||||
|
||||
export CLANG_VERSION="${CLANG_VERSION:-4.0.0}"
|
||||
export CCACHE_VERSION=3.3.1
|
||||
export CMAKE_VERSION=3.7.2
|
||||
|
||||
source ${CURRENT_DIR}/travis_helper.sh
|
||||
|
||||
# ensure we start inside the root directory (two level up)
|
||||
cd ${CURRENT_DIR}/../../
|
||||
|
||||
if [[ ! $(which wget) ]]; then
|
||||
echo "echo wget must be installed";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
SYSTEM_NAME=$(uname -s)
|
||||
if [[ "${SYSTEM_NAME}" == "Darwin" ]]; then
|
||||
OS_NAME="osx"
|
||||
elif [[ "${SYSTEM_NAME}" == "Linux" ]]; then
|
||||
OS_NAME="linux"
|
||||
fi
|
||||
|
||||
# FIXME This should be replaced by proper calls to mason but we currently have a chicken-egg problem
|
||||
# since we rely on osrm-backend to ship mason for us. Once we merged this into osrm-backend this will not be needed.
|
||||
CMAKE_URL="https://s3.amazonaws.com/mason-binaries/${OS_NAME}-x86_64/cmake/${CMAKE_VERSION}.tar.gz"
|
||||
echo "Downloading cmake from ${CMAKE_URL} ..."
|
||||
wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
|
||||
CCACHE_URL="https://s3.amazonaws.com/mason-binaries/${OS_NAME}-x86_64/ccache/${CCACHE_VERSION}.tar.gz"
|
||||
echo "Downloading ccache from ${CCACHE_URL} ..."
|
||||
wget --quiet -O - ${CCACHE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
|
||||
# install clang for linux but use the xcode version on OSX
|
||||
if [[ "${OS_NAME}" != "osx" ]]; then
|
||||
CLANG_URL="https://s3.amazonaws.com/mason-binaries/${OS_NAME}-x86_64/clang++/${CLANG_VERSION}.tar.gz"
|
||||
echo "Downloading clang from ${CLANG_URL} ..."
|
||||
wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
|
||||
export CCOMPILER='clang'
|
||||
export CXXCOMPILER='clang++'
|
||||
export CC='clang'
|
||||
export CXX='clang++'
|
||||
fi
|
||||
|
||||
if [[ "${OS_NAME}" == "osx" ]]; then
|
||||
if [[ -f /etc/sysctl.conf ]] && [[ $(grep shmmax /etc/sysctl.conf) ]]; then
|
||||
echo "Note: found shmmax setting in /etc/sysctl.conf, not modifying"
|
||||
else
|
||||
echo "WARNING: Did not find shmmax setting in /etc/sysctl.conf, adding now (requires sudo and restarting)..."
|
||||
sudo sysctl -w kern.sysv.shmmax=4294967296
|
||||
sudo sysctl -w kern.sysv.shmall=1048576
|
||||
sudo sysctl -w kern.sysv.shmseg=128
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
echo "Now build node-osrm and dependencies"
|
||||
export VERBOSE=1
|
||||
if [[ "${ENABLE_COVERAGE}" == "On" ]]; then
|
||||
mapbox_time "make" make -j4 coverage
|
||||
else
|
||||
mkdir -p build
|
||||
pushd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On
|
||||
mapbox_time "make" make -j4
|
||||
popd
|
||||
fi
|
||||
|
||||
## run tests, with backtrace support
|
||||
#if [[ "${OS_NAME}" == "linux" ]]; then
|
||||
# ulimit -c unlimited -S
|
||||
# RESULT=0
|
||||
# mapbox_time "make-test" make tests || RESULT=$?
|
||||
# for i in $(find ./ -maxdepth 1 -name 'core*' -print);
|
||||
# do gdb $(which node) $i -ex "thread apply all bt" -ex "set pagination 0" -batch;
|
||||
# done;
|
||||
# if [[ ${RESULT} != 0 ]]; then exit $RESULT; fi
|
||||
#else
|
||||
# # todo: coredump support on OS X
|
||||
# RESULT=0
|
||||
# mapbox_time "make-test" make tests || RESULT=$?
|
||||
# if [[ ${RESULT} != 0 ]]; then exit $RESULT; fi
|
||||
#fi
|
||||
|
||||
|
||||
set +eu
|
||||
set +o pipefail
|
||||
+41
-23
@@ -3,31 +3,49 @@
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
if [[ ${PUBLISH} == 'On' ]]; then
|
||||
echo "PUBLISH is set to '${PUBLISH}', publishing!"
|
||||
# should be set for debug builds
|
||||
export NPM_FLAGS=${NPM_FLAGS:-}
|
||||
|
||||
echo "node version is:"
|
||||
which node
|
||||
node -v
|
||||
echo "node version is:"
|
||||
which node
|
||||
node -v
|
||||
|
||||
echo "dumping binary meta..."
|
||||
./node_modules/.bin/node-pre-gyp reveal
|
||||
echo "dumping binary meta..."
|
||||
./node_modules/.bin/node-pre-gyp reveal ${NPM_FLAGS}
|
||||
|
||||
# enforce that binary has proper ORIGIN flags so that
|
||||
# it can portably find libtbb.so in the same directory
|
||||
if [[ $(uname -s) == 'Linux' ]]; then
|
||||
readelf -d ./lib/binding/node-osrm.node > readelf-output.txt
|
||||
if grep -q 'Flags: ORIGIN' readelf-output.txt; then
|
||||
echo "Found ORIGIN flag in readelf output"
|
||||
cat readelf-output.txt
|
||||
else
|
||||
echo "*** Error: Could not found ORIGIN flag in readelf output"
|
||||
cat readelf-output.txt
|
||||
exit 1
|
||||
fi
|
||||
# enforce that binary has proper ORIGIN flags so that
|
||||
# it can portably find libtbb.so in the same directory
|
||||
if [[ $(uname -s) == 'Linux' ]]; then
|
||||
readelf -d ./lib/binding/node-osrm.node > readelf-output.txt
|
||||
if grep -q 'Flags: ORIGIN' readelf-output.txt; then
|
||||
echo "Found ORIGIN flag in readelf output"
|
||||
cat readelf-output.txt
|
||||
else
|
||||
echo "*** Error: Could not found ORIGIN flag in readelf output"
|
||||
cat readelf-output.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./node_modules/.bin/node-pre-gyp package publish info
|
||||
else
|
||||
echo "PUBLISH is set to '${PUBLISH}', skipping."
|
||||
fi
|
||||
|
||||
echo "determining publishing status..."
|
||||
|
||||
if [[ $(./scripts/travis/is_pr_merge.sh) ]]; then
|
||||
echo "Skipping publishing because this is a PR merge commit"
|
||||
else
|
||||
echo "This is a push commit, continuing to package..."
|
||||
./node_modules/.bin/node-pre-gyp package ${NPM_FLAGS}
|
||||
|
||||
export COMMIT_MESSAGE=$(git log --format=%B --no-merges | head -n 1 | tr -d '\n')
|
||||
echo "Commit message: ${COMMIT_MESSAGE}"
|
||||
|
||||
if [[ ${COMMIT_MESSAGE} =~ "[publish binary]" ]]; then
|
||||
echo "Publishing"
|
||||
./node_modules/.bin/node-pre-gyp publish ${NPM_FLAGS}
|
||||
elif [[ ${COMMIT_MESSAGE} =~ "[republish binary]" ]]; then
|
||||
echo "*** Error: Republishing is disallowed for this repository"
|
||||
exit 1
|
||||
#./node_modules/.bin/node-pre-gyp unpublish publish ${NPM_FLAGS}
|
||||
else
|
||||
echo "Skipping publishing"
|
||||
fi;
|
||||
fi
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "engine/api/match_api.hpp"
|
||||
#include "engine/api/match_parameters.hpp"
|
||||
#include "engine/api/match_parameters_tidy.hpp"
|
||||
#include "engine/map_matching/bayes_classifier.hpp"
|
||||
#include "engine/map_matching/sub_matching.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
@@ -146,33 +145,20 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
"InvalidValue", "Timestamps need to be monotonically increasing.", json_result);
|
||||
}
|
||||
|
||||
SubMatchingList sub_matchings;
|
||||
api::tidy::Result tidied;
|
||||
if (parameters.tidy)
|
||||
{
|
||||
// Transparently tidy match parameters, do map matching on tidied parameters.
|
||||
// Then use the mapping to restore the original <-> tidied relationship.
|
||||
tidied = api::tidy::tidy(parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
tidied = api::tidy::keep_all(parameters);
|
||||
}
|
||||
|
||||
// assuming radius is the standard deviation of a normal distribution
|
||||
// that models GPS noise (in this model), x3 should give us the correct
|
||||
// search radius with > 99% confidence
|
||||
std::vector<double> search_radiuses;
|
||||
if (tidied.parameters.radiuses.empty())
|
||||
if (parameters.radiuses.empty())
|
||||
{
|
||||
search_radiuses.resize(tidied.parameters.coordinates.size(),
|
||||
search_radiuses.resize(parameters.coordinates.size(),
|
||||
routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER);
|
||||
}
|
||||
else
|
||||
{
|
||||
search_radiuses.resize(tidied.parameters.coordinates.size());
|
||||
std::transform(tidied.parameters.radiuses.begin(),
|
||||
tidied.parameters.radiuses.end(),
|
||||
search_radiuses.resize(parameters.coordinates.size());
|
||||
std::transform(parameters.radiuses.begin(),
|
||||
parameters.radiuses.end(),
|
||||
search_radiuses.begin(),
|
||||
[](const boost::optional<double> &maybe_radius) {
|
||||
if (maybe_radius)
|
||||
@@ -187,9 +173,9 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
});
|
||||
}
|
||||
|
||||
auto candidates_lists = GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses);
|
||||
auto candidates_lists = GetPhantomNodesInRange(facade, parameters, search_radiuses);
|
||||
|
||||
filterCandidates(tidied.parameters.coordinates, candidates_lists);
|
||||
filterCandidates(parameters.coordinates, candidates_lists);
|
||||
if (std::all_of(candidates_lists.begin(),
|
||||
candidates_lists.end(),
|
||||
[](const std::vector<PhantomNodeWithDistance> &candidates) {
|
||||
@@ -202,12 +188,8 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
}
|
||||
|
||||
// call the actual map matching
|
||||
sub_matchings =
|
||||
algorithms.MapMatching(candidates_lists,
|
||||
tidied.parameters.coordinates,
|
||||
tidied.parameters.timestamps,
|
||||
tidied.parameters.radiuses,
|
||||
parameters.gaps == api::MatchParameters::GapsType::Split);
|
||||
SubMatchingList sub_matchings = algorithms.MapMatching(
|
||||
candidates_lists, parameters.coordinates, parameters.timestamps, parameters.radiuses);
|
||||
|
||||
if (sub_matchings.size() == 0)
|
||||
{
|
||||
@@ -238,7 +220,7 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
BOOST_ASSERT(sub_routes[index].shortest_path_length != INVALID_EDGE_WEIGHT);
|
||||
}
|
||||
|
||||
api::MatchAPI match_api{facade, parameters, tidied};
|
||||
api::MatchAPI match_api{facade, parameters};
|
||||
match_api.MakeResponse(sub_matchings, sub_routes, json_result);
|
||||
|
||||
return Status::Ok;
|
||||
|
||||
@@ -54,8 +54,7 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting)
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision)
|
||||
{
|
||||
map_matching::MatchingConfidence confidence;
|
||||
map_matching::EmissionLogProbability default_emission_log_probability(DEFAULT_GPS_PRECISION);
|
||||
@@ -157,24 +156,16 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t)
|
||||
{
|
||||
|
||||
const bool gap_in_trace = [&]() {
|
||||
// do not determine split if wasn't asked about it
|
||||
if (allow_splitting)
|
||||
const bool gap_in_trace = [&, use_timestamps]() {
|
||||
// use temporal information if available to determine a split
|
||||
if (use_timestamps)
|
||||
{
|
||||
// use temporal information if available to determine a split
|
||||
if (use_timestamps)
|
||||
{
|
||||
return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
|
||||
max_broken_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
return t - prev_unbroken_timestamps.back() > MAX_BROKEN_STATES;
|
||||
}
|
||||
return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
|
||||
max_broken_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
return t - prev_unbroken_timestamps.back() > MAX_BROKEN_STATES;
|
||||
}
|
||||
}();
|
||||
|
||||
@@ -425,16 +416,14 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool use_tidying)
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision)
|
||||
{
|
||||
return mapMatchingImpl(engine_working_data,
|
||||
facade,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision,
|
||||
use_tidying);
|
||||
trace_gps_precision);
|
||||
}
|
||||
|
||||
SubMatchingList
|
||||
@@ -443,8 +432,7 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool use_tidying)
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision)
|
||||
{
|
||||
|
||||
return mapMatchingImpl(engine_working_data,
|
||||
@@ -452,8 +440,7 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision,
|
||||
use_tidying);
|
||||
trace_gps_precision);
|
||||
}
|
||||
|
||||
} // namespace routing_algorithms
|
||||
|
||||
@@ -108,12 +108,12 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
makeBisectionGraph(compressed_node_based_graph.coordinates,
|
||||
adaptToBisectionEdge(std::move(compressed_node_based_graph.edges)));
|
||||
|
||||
util::Log() << " running partition: " << config.max_cell_sizes.front() << " " << config.balance
|
||||
util::Log() << " running partition: " << config.minimum_cell_size << " " << config.balance
|
||||
<< " " << config.boundary_factor << " " << config.num_optimizing_cuts << " "
|
||||
<< config.small_component_size
|
||||
<< " # max_cell_size balance boundary cuts small_component_size";
|
||||
RecursiveBisection recursive_bisection(graph,
|
||||
config.max_cell_sizes.front(),
|
||||
config.minimum_cell_size,
|
||||
config.balance,
|
||||
config.boundary_factor,
|
||||
config.num_optimizing_cuts,
|
||||
@@ -161,7 +161,11 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
std::vector<Partition> partitions;
|
||||
std::vector<std::uint32_t> level_to_num_cells;
|
||||
std::tie(partitions, level_to_num_cells) =
|
||||
bisectionToPartition(edge_based_partition_ids, config.max_cell_sizes);
|
||||
bisectionToPartition(edge_based_partition_ids,
|
||||
{config.minimum_cell_size,
|
||||
config.minimum_cell_size * 32,
|
||||
config.minimum_cell_size * 32 * 16,
|
||||
config.minimum_cell_size * 32 * 16 * 32});
|
||||
|
||||
auto num_unconnected = removeUnconnectedBoundaryNodes(*edge_based_graph, partitions);
|
||||
util::Log() << "Fixed " << num_unconnected << " unconnected nodes";
|
||||
|
||||
+16
-74
@@ -8,15 +8,11 @@
|
||||
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <regex>
|
||||
|
||||
using namespace osrm;
|
||||
|
||||
@@ -27,48 +23,7 @@ enum class return_code : unsigned
|
||||
exit
|
||||
};
|
||||
|
||||
struct MaxCellSizesArgument
|
||||
{
|
||||
std::vector<size_t> value;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const MaxCellSizesArgument &arg)
|
||||
{
|
||||
auto to_string = [](std::size_t x) { return std::to_string(x); };
|
||||
return os << boost::algorithm::join(arg.value | boost::adaptors::transformed(to_string), ",");
|
||||
}
|
||||
|
||||
void validate(boost::any &v, const std::vector<std::string> &values, MaxCellSizesArgument *, int)
|
||||
{
|
||||
using namespace boost::program_options;
|
||||
using namespace boost::adaptors;
|
||||
|
||||
// Make sure no previous assignment to 'v' was made.
|
||||
validators::check_first_occurrence(v);
|
||||
// Extract the first string from 'values'. If there is more than
|
||||
// one string, it's an error, and exception will be thrown.
|
||||
const std::string &s = validators::get_single_string(values);
|
||||
|
||||
std::regex re(",");
|
||||
std::vector<size_t> output;
|
||||
std::transform(std::sregex_token_iterator(s.begin(), s.end(), re, -1),
|
||||
std::sregex_token_iterator(),
|
||||
std::back_inserter(output),
|
||||
[](const auto &x) {
|
||||
try
|
||||
{
|
||||
return boost::lexical_cast<std::size_t>(x);
|
||||
}
|
||||
catch (const boost::bad_lexical_cast &)
|
||||
{
|
||||
throw validation_error(validation_error::invalid_option_value);
|
||||
}
|
||||
});
|
||||
|
||||
v = boost::any(MaxCellSizesArgument{output});
|
||||
}
|
||||
|
||||
return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &config)
|
||||
return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &partition_config)
|
||||
{
|
||||
// declare a group of options that will be allowed only on command line
|
||||
boost::program_options::options_description generic_options("Options");
|
||||
@@ -79,41 +34,40 @@ return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &c
|
||||
config_options.add_options()
|
||||
//
|
||||
("threads,t",
|
||||
boost::program_options::value<unsigned int>(&config.requested_num_threads)
|
||||
boost::program_options::value<unsigned int>(&partition_config.requested_num_threads)
|
||||
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||
"Number of threads to use")
|
||||
//
|
||||
("min-cell-size",
|
||||
boost::program_options::value<std::size_t>(&partition_config.minimum_cell_size)
|
||||
->default_value(128),
|
||||
"Bisection termination citerion based on cell size")
|
||||
//
|
||||
("balance",
|
||||
boost::program_options::value<double>(&config.balance)->default_value(config.balance),
|
||||
boost::program_options::value<double>(&partition_config.balance)->default_value(1.2),
|
||||
"Balance for left and right side in single bisection")
|
||||
//
|
||||
("boundary",
|
||||
boost::program_options::value<double>(&config.boundary_factor)
|
||||
->default_value(config.boundary_factor),
|
||||
boost::program_options::value<double>(&partition_config.boundary_factor)
|
||||
->default_value(0.25),
|
||||
"Percentage of embedded nodes to contract as sources and sinks")
|
||||
//
|
||||
("optimizing-cuts",
|
||||
boost::program_options::value<std::size_t>(&config.num_optimizing_cuts)
|
||||
->default_value(config.num_optimizing_cuts),
|
||||
boost::program_options::value<std::size_t>(&partition_config.num_optimizing_cuts)
|
||||
->default_value(10),
|
||||
"Number of cuts to use for optimizing a single bisection")
|
||||
//
|
||||
("small-component-size",
|
||||
boost::program_options::value<std::size_t>(&config.small_component_size)
|
||||
->default_value(config.small_component_size),
|
||||
"Size threshold for small components.")
|
||||
//
|
||||
("max-cell-sizes",
|
||||
boost::program_options::value<MaxCellSizesArgument>()->default_value(
|
||||
MaxCellSizesArgument{config.max_cell_sizes}),
|
||||
"Maximum cell sizes starting from the level 1. The first cell size value is a bisection "
|
||||
"termination citerion");
|
||||
boost::program_options::value<std::size_t>(&partition_config.small_component_size)
|
||||
->default_value(1000),
|
||||
"Size threshold for small components.");
|
||||
|
||||
// hidden options, will be allowed on command line, but will not be
|
||||
// shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()(
|
||||
"input,i",
|
||||
boost::program_options::value<boost::filesystem::path>(&config.base_path),
|
||||
boost::program_options::value<boost::filesystem::path>(&partition_config.base_path),
|
||||
"Input file in .osrm format");
|
||||
|
||||
// positional option
|
||||
@@ -165,18 +119,6 @@ return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &c
|
||||
return return_code::fail;
|
||||
}
|
||||
|
||||
if (option_variables.count("max-cell-sizes"))
|
||||
{
|
||||
config.max_cell_sizes = option_variables["max-cell-sizes"].as<MaxCellSizesArgument>().value;
|
||||
|
||||
if (!std::is_sorted(config.max_cell_sizes.begin(), config.max_cell_sizes.end()))
|
||||
{
|
||||
util::Log(logERROR)
|
||||
<< "The maximum cell sizes array must be sorted in non-descending order.";
|
||||
return return_code::fail;
|
||||
}
|
||||
}
|
||||
|
||||
return return_code::ok;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
#include "engine/api/match_parameters_tidy.hpp"
|
||||
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(tidy_test)
|
||||
|
||||
using namespace osrm;
|
||||
using namespace osrm::util;
|
||||
using namespace osrm::engine::api;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_item_trace_already_tidied_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
|
||||
params.timestamps.emplace_back(1477090402);
|
||||
params.timestamps.emplace_back(1477090663);
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 15.;
|
||||
thresholds.duration_in_seconds = 5;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||
|
||||
BOOST_CHECK(result.can_be_removed[0] == false);
|
||||
BOOST_CHECK(result.can_be_removed[1] == false);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_item_trace_needs_tidiying_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
|
||||
params.timestamps.emplace_back(1477090402);
|
||||
params.timestamps.emplace_back(1477090663);
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 5000;
|
||||
thresholds.duration_in_seconds = 5 * 60;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[1], true);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207994}, FloatLatitude{52.446380});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207995}, FloatLatitude{52.446381});
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231659}, FloatLatitude{52.465417});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231660}, FloatLatitude{52.465417});
|
||||
|
||||
params.timestamps.emplace_back(1477090402);
|
||||
params.timestamps.emplace_back(1477090403);
|
||||
params.timestamps.emplace_back(1477090404);
|
||||
|
||||
params.timestamps.emplace_back(1477090661);
|
||||
params.timestamps.emplace_back(1477090662);
|
||||
params.timestamps.emplace_back(1477090663);
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 15;
|
||||
thresholds.duration_in_seconds = 5;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||
|
||||
const auto redundant = result.can_be_removed.count();
|
||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207994}, FloatLatitude{52.446380});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207995}, FloatLatitude{52.446381});
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231659}, FloatLatitude{52.465417});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231660}, FloatLatitude{52.465417});
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 15;
|
||||
thresholds.duration_in_seconds = 5;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||
|
||||
const auto redundant = result.can_be_removed.count();
|
||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -46,11 +46,11 @@ BOOST_AUTO_TEST_SUITE(multi_level_graph)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
{
|
||||
// node: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
std::vector<CellID> l1{{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6}};
|
||||
std::vector<CellID> l2{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}};
|
||||
// node: 0 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
std::vector<CellID> l1{{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6}};
|
||||
std::vector<CellID> l2{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}};
|
||||
MultiLevelPartition mlp{{l1, l2, l3, l4}, {7, 5, 3, 2}};
|
||||
|
||||
std::vector<MockEdge> edges = {
|
||||
@@ -69,8 +69,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
{9, 8}, // i i i i
|
||||
{10, 11}, // i i i i
|
||||
{11, 10}, // i i i i
|
||||
{11, 12}, // b b b b
|
||||
{12, 13} // i i i i
|
||||
{11, 12} // b b b b
|
||||
};
|
||||
|
||||
auto graph = makeGraph(mlp, edges);
|
||||
@@ -98,7 +97,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
// the union of border and internal edge needs to equal the adjacent edges
|
||||
for (auto level : util::irange<LevelID>(0, 4))
|
||||
{
|
||||
for (auto node : util::irange<NodeID>(0, 14))
|
||||
for (auto node : util::irange<NodeID>(0, 13))
|
||||
{
|
||||
const auto adjacent = graph.GetAdjacentEdgeRange(node);
|
||||
const auto border = graph.GetBorderEdgeRange(level, node);
|
||||
@@ -123,7 +122,6 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 11).size(), 2);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 13).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 0).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 1).size(), 0);
|
||||
@@ -138,7 +136,6 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 11).size(), 2);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 13).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 0).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 1).size(), 0);
|
||||
@@ -153,7 +150,6 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 11).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 13).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 0).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 1).size(), 0);
|
||||
@@ -168,7 +164,6 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 11).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 13).size(), 0);
|
||||
|
||||
CHECK_EQUAL_RANGE(graph.GetBorderEdgeRange(1, 0), graph.FindEdge(0, 4));
|
||||
CHECK_EQUAL_RANGE(graph.GetBorderEdgeRange(1, 3), graph.FindEdge(3, 7));
|
||||
@@ -199,25 +194,4 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
CHECK_EQUAL_RANGE(graph.GetBorderEdgeRange(4, 12), graph.FindEdge(12, 11));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(check_last_internal_edge)
|
||||
{
|
||||
// a--b--c--d
|
||||
std::vector<CellID> l1{{0, 0, 1, 1}};
|
||||
std::vector<CellID> l2{{0, 0, 1, 1}};
|
||||
MultiLevelPartition mlp{{l1, l2}, {2, 2}};
|
||||
|
||||
std::vector<MockEdge> edges = {{0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 3}, {3, 2}};
|
||||
|
||||
auto graph = makeGraph(mlp, edges);
|
||||
|
||||
auto all_edges = graph.GetAdjacentEdgeRange(3);
|
||||
CHECK_EQUAL_COLLECTIONS(graph.GetBorderEdgeRange(0, 3), all_edges);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 3).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 3).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetInternalEdgeRange(0, 3).size(), 0);
|
||||
CHECK_EQUAL_COLLECTIONS(graph.GetInternalEdgeRange(1, 3), all_edges);
|
||||
CHECK_EQUAL_COLLECTIONS(graph.GetInternalEdgeRange(2, 3), all_edges);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Reference in New Issue
Block a user