Compare commits

..

12 Commits

Author SHA1 Message Date
Patrick Niklaus 1869840f0e [publish binary] Test building node binaries with MLD 2017-03-22 00:51:07 +00:00
Patrick Niklaus 8532b5460b Disable doc builds because they are broken 2017-03-22 00:30:42 +00:00
Patrick Niklaus 1fdbaf4a39 Upgrade docbox 2017-03-22 00:04:46 +00:00
Patrick Niklaus 08527175b5 Fresh lock file 2017-03-21 23:44:08 +00:00
Patrick Niklaus d792572ece Install yarn on OSX by hand and update lock file 2017-03-21 23:26:32 +00:00
Patrick Niklaus 2a691ac5be Integrate documentation JS and make travis file slightly more readable 2017-03-21 22:50:08 +00:00
Patrick Niklaus 2221a34529 Switch to yarn 2017-03-21 22:37:16 +00:00
Patrick Niklaus a8fd4050a2 Integrate node-osrm docs 2017-03-21 22:29:00 +00:00
Patrick Niklaus 85ee03dfde Also copy osrm-partition and osrm-customize 2017-03-21 20:15:08 +00:00
Patrick Niklaus 694e3854d7 Test routing on CH, MLD, CoreCH via node bindings 2017-03-21 20:15:08 +00:00
Patrick Niklaus 90ed027711 Integrate MLD into node-bindings 2017-03-21 20:15:06 +00:00
Patrick Niklaus ac0c5c27e7 First steps towards integrating MLD in node bindings 2017-03-21 20:12:56 +00:00
35 changed files with 270 additions and 966 deletions
+1 -6
View File
@@ -16,8 +16,6 @@ notifications:
branches: branches:
only: only:
- master - master
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
cache: cache:
yarn: true yarn: true
@@ -28,8 +26,6 @@ cache:
env: env:
global: global:
- secure: "hk+32aXXF5t1ApaM2Wjqooz3dx1si907L87WRMkO47WlpJmUUU/Ye+MJk9sViH8MdhOcceocVAmdYl5/WFWOIbDWNlBya9QvXDZyIu2KIre/0QyOCTZbrsif8paBXKIO5O/R4OTvIZ8rvWZsadBdmAT9GSbDhih6FzqXAEgeIYQ="
- secure: "VE+cFkseFwW4jK6XwkP0yW3h4DixPJ8+Eb3yKcchGZ5iIJxlZ/8i1vKHYxadgPRwSYwPSB14tF70xj2OmiT2keGzZUfphmPXinBaLEhYk+Bde+GZZkoSl5ND109I/LcyNr0nG9dDgtV6pkvFchgchpyP9JnVOOS0+crEZlAz0RE="
- CCACHE_TEMPDIR=/tmp/.ccache-temp - CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1 - 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 - 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 / sudo mdutil -i off /
npm install -g yarn npm install -g yarn
fi 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" - echo "Using ${JOBS} jobs"
- yarn install --ignore-scripts - yarn install --ignore-scripts
# Bootstrap cmake to be able to run mason # Bootstrap cmake to be able to run mason
@@ -234,5 +228,6 @@ after_success:
- | - |
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
source ./scripts/travis/build.sh
./scripts/travis/publish.sh ./scripts/travis/publish.sh
fi fi
-2
View File
@@ -1,5 +1,3 @@
- Track preprocessing flag in the map matching plugin.
# 5.7.0 # 5.7.0
- Changes from 5.6 - Changes from 5.6
- NodeJs Bindings - NodeJs Bindings
+6 -14
View File
@@ -41,27 +41,19 @@ The easiest and quickest way to setup your own routing engine backend is to use
### Using Docker ### 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 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:vX.Y.Z 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 -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 osrm-routed /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 ### Building from Source
The following targets Ubuntu 16.04. The following targets Ubuntu 16.04.
+3 -9
View File
@@ -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% 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% %Configuration%\osrm-extract.exe -p ../profiles/car.lua %test_osm%
MKDIR ch MKDIR ch
XCOPY %test_region%.osrm.* ch\ XCOPY %test_region%.osrm %test_region%.osrm.* ch\
XCOPY %test_region%.osrm ch\
MKDIR corech MKDIR corech
XCOPY %test_region%.osrm.* corech\ XCOPY %test_region%.osrm %test_region%.osrm.* corech\
XCOPY %test_region%.osrm corech\
MKDIR mld MKDIR mld
XCOPY %test_region%.osrm.* mld\ XCOPY %test_region%.osrm %test_region%.osrm.* mld\
XCOPY %test_region%.osrm mld\
%Configuration%\osrm-contract.exe %test_region_ch%.osrm %Configuration%\osrm-contract.exe %test_region_ch%.osrm
%Configuration%\osrm-contract.exe --core 0.8 %test_region_corech%.osrm %Configuration%\osrm-contract.exe --core 0.8 %test_region_corech%.osrm
%Configuration%\osrm-partition.exe %test_region_mld%.osrm %Configuration%\osrm-partition.exe %test_region_mld%.osrm
%Configuration%\osrm-customize.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 unit_tests\%Configuration%\library-tests.exe
IF NOT "%APPVEYOR_REPO_BRANCH%"=="master" GOTO DONE IF NOT "%APPVEYOR_REPO_BRANCH%"=="master" GOTO DONE
-75
View File
@@ -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"
]
}
}
}
}
-59
View File
@@ -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
View File
@@ -1,6 +1,7 @@
coverage: coverage:
ignore: ignore:
- unit_tests/.*
- third_party/.* - third_party/.*
comment: off comment: off
-2
View File
@@ -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.| |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. | |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.| |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 | |Parameter |Values |
|------------|-----------------------------------| |------------|-----------------------------------|
+3 -79
View File
@@ -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`. `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 ## 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. 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. 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: ## Guidance
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
The guidance parameters in profiles are currently a work in progress. They can and will change. 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. 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. 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. 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 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. 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. 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)
-16
View File
@@ -79,19 +79,3 @@ Feature: Bike - Cycle tracks/lanes
| residential | lane | yes | x | x | | residential | lane | yes | x | x |
| footway | lane | yes | x | x | | footway | lane | yes | x | x |
| cycleway | 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 |
+3 -3
View File
@@ -10,11 +10,11 @@ Feature: osrm-partition command line options: help
And stdout should contain "--help" And stdout should contain "--help"
And stdout should contain "Configuration:" And stdout should contain "Configuration:"
And stdout should contain "--threads" And stdout should contain "--threads"
And stdout should contain "--min-cell-size"
And stdout should contain "--balance" And stdout should contain "--balance"
And stdout should contain "--boundary" And stdout should contain "--boundary"
And stdout should contain "--optimizing-cuts" And stdout should contain "--optimizing-cuts"
And stdout should contain "--small-component-size" And stdout should contain "--small-component-size"
And stdout should contain "--max-cell-sizes"
And it should exit with an error And it should exit with an error
Scenario: osrm-partition - Help, short 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 "--help"
And stdout should contain "Configuration:" And stdout should contain "Configuration:"
And stdout should contain "--threads" And stdout should contain "--threads"
And stdout should contain "--min-cell-size"
And stdout should contain "--balance" And stdout should contain "--balance"
And stdout should contain "--boundary" And stdout should contain "--boundary"
And stdout should contain "--optimizing-cuts" And stdout should contain "--optimizing-cuts"
And stdout should contain "--small-component-size" And stdout should contain "--small-component-size"
And stdout should contain "--max-cell-sizes"
And it should exit successfully And it should exit successfully
Scenario: osrm-partition - Help, long 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 "--help"
And stdout should contain "Configuration:" And stdout should contain "Configuration:"
And stdout should contain "--threads" And stdout should contain "--threads"
And stdout should contain "--min-cell-size"
And stdout should contain "--balance" And stdout should contain "--balance"
And stdout should contain "--boundary" And stdout should contain "--boundary"
And stdout should contain "--optimizing-cuts" And stdout should contain "--optimizing-cuts"
And stdout should contain "--small-component-size" And stdout should contain "--small-component-size"
And stdout should contain "--max-cell-sizes"
And it should exit successfully 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 "option"
And stderr should contain "fly-me-to-the-moon" And stderr should contain "fly-me-to-the-moon"
And it should exit with an error 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
-78
View File
@@ -40,84 +40,6 @@ Feature: Basic Map Matching
| trace | timestamps | matchings | | trace | timestamps | matchings |
| abcd | 0 1 62 63 | ab,cd | | 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 Scenario: Testbot - Map matching with core factor
Given the contract extra arguments "--core 0.8" Given the contract extra arguments "--core 0.8"
Given the node map Given the node map
+5 -3
View File
@@ -3,7 +3,7 @@ Feature: Multi level routing
Background: Background:
Given the profile "testbot" 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 Scenario: Testbot - Multi level routing check partition
Given the node map Given the node map
@@ -31,7 +31,7 @@ Feature: Multi level routing
| be | primary | | be | primary |
And the data has been extracted 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 Then it should exit successfully
And stdout should not contain "level 1 #cells 1 bit size 1" And stdout should not contain "level 1 #cells 1 bit size 1"
@@ -57,6 +57,7 @@ Feature: Multi level routing
| cm | primary | | cm | primary |
| hj | primary | | hj | primary |
| kp | primary | | kp | primary |
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
When I route I should get When I route I should get
| from | to | route | time | | from | to | route | time |
@@ -87,6 +88,7 @@ Feature: Multi level routing
| dim | primary | | dim | primary |
| glr | primary | | glr | primary |
| ot | secondary | | ot | secondary |
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
When I route I should get When I route I should get
| from | to | route | time | | from | to | route | time |
@@ -111,7 +113,6 @@ Feature: Multi level routing
lk lk
""" """
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16"
And the ways And the ways
| nodes | maxspeed | | nodes | maxspeed |
| abcda | 5 | | abcda | 5 |
@@ -123,6 +124,7 @@ Feature: Multi level routing
| fi | 15 | | fi | 15 |
| gi | 15 | | gi | 15 |
| hf | 100 | | hf | 100 |
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
When I route I should get When I route I should get
| from | to | route | time | | from | to | route | time |
+3 -2
View File
@@ -39,9 +39,9 @@ class CellCustomizer
const EdgeWeight weight = heap.GetKey(node); const EdgeWeight weight = heap.GetKey(node);
if (level == 1) if (level == 1)
RelaxNode<true>(graph, cells, heap, level, node, weight); RelaxNode<true>(graph, cells, heap, level, id, node, weight);
else else
RelaxNode<false>(graph, cells, heap, level, node, weight); RelaxNode<false>(graph, cells, heap, level, id, node, weight);
destinations_set.erase(node); destinations_set.erase(node);
} }
@@ -85,6 +85,7 @@ class CellCustomizer
const partition::CellStorage &cells, const partition::CellStorage &cells,
Heap &heap, Heap &heap,
LevelID level, LevelID level,
CellID id,
NodeID node, NodeID node,
EdgeWeight weight) const EdgeWeight weight) const
{ {
+3 -14
View File
@@ -2,7 +2,6 @@
#define ENGINE_API_MATCH_HPP #define ENGINE_API_MATCH_HPP
#include "engine/api/match_parameters.hpp" #include "engine/api/match_parameters.hpp"
#include "engine/api/match_parameters_tidy.hpp"
#include "engine/api/route_api.hpp" #include "engine/api/route_api.hpp"
#include "engine/datafacade/datafacade_base.hpp" #include "engine/datafacade/datafacade_base.hpp"
@@ -22,10 +21,8 @@ namespace api
class MatchAPI final : public RouteAPI class MatchAPI final : public RouteAPI
{ {
public: public:
MatchAPI(const datafacade::BaseDataFacade &facade_, MatchAPI(const datafacade::BaseDataFacade &facade_, const MatchParameters &parameters_)
const MatchParameters &parameters_, : RouteAPI(facade_, parameters_), parameters(parameters_)
const tidy::Result &tidy_result_)
: RouteAPI(facade_, parameters_), parameters(parameters_), tidy_result(tidy_result_)
{ {
} }
@@ -86,20 +83,13 @@ class MatchAPI final : public RouteAPI
for (auto point_index : util::irange( for (auto point_index : util::irange(
0u, static_cast<unsigned>(sub_matchings[sub_matching_index].indices.size()))) 0u, static_cast<unsigned>(sub_matchings[sub_matching_index].indices.size())))
{ {
trace_idx_to_matching_idx[tidy_result trace_idx_to_matching_idx[sub_matchings[sub_matching_index].indices[point_index]] =
.tidied_to_original[sub_matchings[sub_matching_index]
.indices[point_index]]] =
MatchingIndex{sub_matching_index, point_index}; MatchingIndex{sub_matching_index, point_index};
} }
} }
for (auto trace_index : util::irange<std::size_t>(0UL, parameters.coordinates.size())) 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]; auto matching_index = trace_idx_to_matching_idx[trace_index];
if (matching_index.NotMatched()) if (matching_index.NotMatched())
{ {
@@ -121,7 +111,6 @@ class MatchAPI final : public RouteAPI
} }
const MatchParameters &parameters; const MatchParameters &parameters;
const tidy::Result &tidy_result;
}; };
} // ns api } // ns api
+3 -14
View File
@@ -50,34 +50,23 @@ namespace api
*/ */
struct MatchParameters : public RouteParameters struct MatchParameters : public RouteParameters
{ {
enum class GapsType
{
Split,
Ignore
};
MatchParameters() MatchParameters()
: RouteParameters(false, : RouteParameters(false,
false, false,
false, false,
RouteParameters::GeometriesType::Polyline, RouteParameters::GeometriesType::Polyline,
RouteParameters::OverviewType::Simplified, RouteParameters::OverviewType::Simplified,
{}), {})
gaps(GapsType::Split), tidy(false)
{ {
} }
template <typename... Args> template <typename... Args>
MatchParameters(std::vector<unsigned> timestamps_, GapsType gaps_, bool tidy_, Args... args_) MatchParameters(std::vector<unsigned> timestamps_, Args... args_)
: RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)}, : RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)}
gaps(gaps_), tidy(tidy_)
{ {
} }
std::vector<unsigned> timestamps; std::vector<unsigned> timestamps;
GapsType gaps;
bool tidy;
bool IsValid() const bool IsValid() const
{ {
return RouteParameters::IsValid() && 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 &params)
{
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 &params, 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
+10 -19
View File
@@ -38,8 +38,7 @@ class RoutingAlgorithmsInterface
MapMatching(const routing_algorithms::CandidateLists &candidates_list, MapMatching(const routing_algorithms::CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision) const = 0;
const bool allow_splitting) const = 0;
virtual std::vector<routing_algorithms::TurnData> virtual std::vector<routing_algorithms::TurnData>
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges, 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> &source_indices,
const std::vector<std::size_t> &target_indices) const final override; const std::vector<std::size_t> &target_indices) const final override;
routing_algorithms::SubMatchingList routing_algorithms::SubMatchingList MapMatching(
MapMatching(const routing_algorithms::CandidateLists &candidates_list, const routing_algorithms::CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision) const final override;
const bool allow_splitting) const final override;
std::vector<routing_algorithms::TurnData> std::vector<routing_algorithms::TurnData>
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges, 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 routing_algorithms::CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision) const
const bool allow_splitting) const
{ {
return routing_algorithms::mapMatching(heaps, return routing_algorithms::mapMatching(
facade, heaps, facade, candidates_list, trace_coordinates, trace_timestamps, trace_gps_precision);
candidates_list,
trace_coordinates,
trace_timestamps,
trace_gps_precision,
allow_splitting);
} }
template <typename AlgorithmT> template <typename AlgorithmT>
@@ -215,8 +207,7 @@ inline routing_algorithms::SubMatchingList
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &, RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
const std::vector<util::Coordinate> &, const std::vector<util::Coordinate> &,
const std::vector<unsigned> &, const std::vector<unsigned> &,
const std::vector<boost::optional<double>> &, const std::vector<boost::optional<double>> &) const
const bool) const
{ {
throw util::exception("MapMatching is not implemented"); throw util::exception("MapMatching is not implemented");
} }
@@ -28,8 +28,7 @@ mapMatching(SearchEngineData &engine_working_data,
const CandidateLists &candidates_list, const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision);
const bool allow_splitting);
SubMatchingList SubMatchingList
mapMatching(SearchEngineData &engine_working_data, mapMatching(SearchEngineData &engine_working_data,
@@ -37,8 +36,7 @@ mapMatching(SearchEngineData &engine_working_data,
const CandidateLists &candidates_list, const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision);
const bool allow_splitting);
} }
} }
} }
+1 -9
View File
@@ -110,17 +110,9 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
// which can be smaller then the total number of nodes. // which can be smaller then the total number of nodes.
// this will save memory in case we sort the border nodes first // this will save memory in case we sort the border nodes first
if (index >= node_to_edge_offset.size() - 1) if (index >= node_to_edge_offset.size() - 1)
{ return SuperT::BeginEdges(node);
// On level 0 all edges are border edges
if (level == 0)
return SuperT::BeginEdges(node);
else
return SuperT::EndEdges(node);
}
else else
{
return SuperT::BeginEdges(node) + node_to_edge_offset[index + level]; return SuperT::BeginEdges(node) + node_to_edge_offset[index + level];
}
} }
// We save the level as sentinel at the end // We save the level as sentinel at the end
+2 -7
View File
@@ -13,12 +13,7 @@ namespace partition
struct PartitionConfig struct PartitionConfig
{ {
PartitionConfig() PartitionConfig() : requested_num_threads(0) {}
: 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}
{
}
void UseDefaults() void UseDefaults()
{ {
@@ -54,11 +49,11 @@ struct PartitionConfig
unsigned requested_num_threads; unsigned requested_num_threads;
std::size_t minimum_cell_size;
double balance; double balance;
double boundary_factor; double boundary_factor;
std::size_t num_optimizing_cuts; std::size_t num_optimizing_cuts;
std::size_t small_component_size; std::size_t small_component_size;
std::vector<std::size_t> max_cell_sizes;
}; };
} }
} }
+2 -13
View File
@@ -33,24 +33,13 @@ struct MatchParametersGrammar final : public RouteParametersGrammar<Iterator, Si
(qi::uint_ % (qi::uint_ %
';')[ph::bind(&engine::api::MatchParameters::timestamps, qi::_r1) = qi::_1]; ';')[ph::bind(&engine::api::MatchParameters::timestamps, qi::_r1) = qi::_1];
gaps_type.add("split", engine::api::MatchParameters::GapsType::Split)( root_rule = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
"ignore", engine::api::MatchParameters::GapsType::Ignore); -('?' > (timestamps_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&');
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])) %
'&');
} }
private: private:
qi::rule<Iterator, Signature> root_rule; qi::rule<Iterator, Signature> root_rule;
qi::rule<Iterator, Signature> timestamps_rule; qi::rule<Iterator, Signature> timestamps_rule;
qi::symbols<char, engine::api::MatchParameters::GapsType> gaps_type;
}; };
} }
} }
+3 -3
View File
@@ -151,7 +151,7 @@ class SharedMemory
#else #else
void WaitForDetach() void WaitForDetach()
{ {
util::Log(logDEBUG) util::Log(logWARNING)
<< "Shared memory support for non-Linux systems does not wait for clients to " << "Shared memory support for non-Linux systems does not wait for clients to "
"dettach. Going to sleep for 50ms."; "dettach. Going to sleep for 50ms.";
std::this_thread::sleep_for(std::chrono::milliseconds(50)); std::this_thread::sleep_for(std::chrono::milliseconds(50));
@@ -245,8 +245,8 @@ class SharedMemory
void WaitForDetach() void WaitForDetach()
{ {
// FIXME this needs an implementation for Windows // FIXME this needs an implementation for Windows
util::Log(logDEBUG) << "Shared memory support for Windows does not wait for clients to " util::Log(logWARNING) << "Shared memory support for Windows does not wait for clients to "
"dettach. Going to sleep for 50ms."; "dettach. Going to sleep for 50ms.";
std::this_thread::sleep_for(std::chrono::milliseconds(50)); std::this_thread::sleep_for(std::chrono::milliseconds(50));
} }
+19 -14
View File
@@ -1,12 +1,24 @@
{ {
"name": "osrm", "name": "osrm",
"version": "5.7.0-latest.1", "version": "5.7.0-alpha.1",
"private": false, "private": true,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.", "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": { "dependencies": {
"chalk": "^1.1.3",
"cucumber": "^1.2.1",
"d3-queue": "^2.0.3",
"mkdirp": "^0.5.1",
"nan": "^2.1.0", "nan": "^2.1.0",
"node-cmake": "^1.2.1", "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": { "browserify": {
"transform": [ "transform": [
@@ -17,7 +29,8 @@
"scripts": { "scripts": {
"lint": "eslint -c ./.eslintrc features/step_definitions/ features/support/", "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", "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", "docs": "./scripts/build_api_docs.sh",
"install": "node-pre-gyp install --fallback-to-build=false" "install": "node-pre-gyp install --fallback-to-build=false"
}, },
@@ -38,17 +51,9 @@
"docbox": "^1.0.5", "docbox": "^1.0.5",
"documentation": "^4.0.0-beta.18", "documentation": "^4.0.0-beta.18",
"eslint": "^2.4.0", "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", "aws-sdk": "~2.0.31",
"tape": "^4.2.2", "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"
}, },
"bundleDependencies": [ "bundleDependencies": [
"node-pre-gyp" "node-pre-gyp"
+6 -18
View File
@@ -444,29 +444,17 @@ function way_function (way, result)
end end
-- cycleways -- cycleways
local has_cycleway_left, has_cycleway_right
if cycleway and profile.cycleway_tags[cycleway] then 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"] result.forward_speed = profile.bicycle_speeds["cycleway"]
end result.backward_speed = profile.bicycle_speeds["cycleway"]
if has_cycleway_left and elseif cycleway_left and profile.cycleway_tags[cycleway_left] then
(result.backward_mode == mode.inaccessible or result.forward_speed = profile.bicycle_speeds["cycleway"]
result.backward_mode == mode.cycling) then 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"] result.backward_speed = profile.bicycle_speeds["cycleway"]
end end
-- dismount -- dismount
if bicycle == "dismount" then if bicycle == "dismount" then
result.forward_mode = mode.pushing_bike result.forward_mode = mode.pushing_bike
-1
View File
@@ -33,7 +33,6 @@ local profile = {
'sally_port', 'sally_port',
'gate', 'gate',
'no', 'no',
'kerb',
'block' 'block'
}, },
+99
View File
@@ -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
View File
@@ -3,31 +3,49 @@
set -eu set -eu
set -o pipefail set -o pipefail
if [[ ${PUBLISH} == 'On' ]]; then # should be set for debug builds
echo "PUBLISH is set to '${PUBLISH}', publishing!" export NPM_FLAGS=${NPM_FLAGS:-}
echo "node version is:" echo "node version is:"
which node which node
node -v node -v
echo "dumping binary meta..." echo "dumping binary meta..."
./node_modules/.bin/node-pre-gyp reveal ./node_modules/.bin/node-pre-gyp reveal ${NPM_FLAGS}
# enforce that binary has proper ORIGIN flags so that # enforce that binary has proper ORIGIN flags so that
# it can portably find libtbb.so in the same directory # it can portably find libtbb.so in the same directory
if [[ $(uname -s) == 'Linux' ]]; then if [[ $(uname -s) == 'Linux' ]]; then
readelf -d ./lib/binding/node-osrm.node > readelf-output.txt readelf -d ./lib/binding/node-osrm.node > readelf-output.txt
if grep -q 'Flags: ORIGIN' readelf-output.txt; then if grep -q 'Flags: ORIGIN' readelf-output.txt; then
echo "Found ORIGIN flag in readelf output" echo "Found ORIGIN flag in readelf output"
cat readelf-output.txt cat readelf-output.txt
else else
echo "*** Error: Could not found ORIGIN flag in readelf output" echo "*** Error: Could not found ORIGIN flag in readelf output"
cat readelf-output.txt cat readelf-output.txt
exit 1 exit 1
fi
fi fi
fi
./node_modules/.bin/node-pre-gyp package publish info
else echo "determining publishing status..."
echo "PUBLISH is set to '${PUBLISH}', skipping."
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 fi
+10 -28
View File
@@ -3,7 +3,6 @@
#include "engine/api/match_api.hpp" #include "engine/api/match_api.hpp"
#include "engine/api/match_parameters.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/bayes_classifier.hpp"
#include "engine/map_matching/sub_matching.hpp" #include "engine/map_matching/sub_matching.hpp"
#include "util/coordinate_calculation.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); "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 // assuming radius is the standard deviation of a normal distribution
// that models GPS noise (in this model), x3 should give us the correct // that models GPS noise (in this model), x3 should give us the correct
// search radius with > 99% confidence // search radius with > 99% confidence
std::vector<double> search_radiuses; 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); routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER);
} }
else else
{ {
search_radiuses.resize(tidied.parameters.coordinates.size()); search_radiuses.resize(parameters.coordinates.size());
std::transform(tidied.parameters.radiuses.begin(), std::transform(parameters.radiuses.begin(),
tidied.parameters.radiuses.end(), parameters.radiuses.end(),
search_radiuses.begin(), search_radiuses.begin(),
[](const boost::optional<double> &maybe_radius) { [](const boost::optional<double> &maybe_radius) {
if (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(), if (std::all_of(candidates_lists.begin(),
candidates_lists.end(), candidates_lists.end(),
[](const std::vector<PhantomNodeWithDistance> &candidates) { [](const std::vector<PhantomNodeWithDistance> &candidates) {
@@ -202,12 +188,8 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
} }
// call the actual map matching // call the actual map matching
sub_matchings = SubMatchingList sub_matchings = algorithms.MapMatching(
algorithms.MapMatching(candidates_lists, candidates_lists, parameters.coordinates, parameters.timestamps, parameters.radiuses);
tidied.parameters.coordinates,
tidied.parameters.timestamps,
tidied.parameters.radiuses,
parameters.gaps == api::MatchParameters::GapsType::Split);
if (sub_matchings.size() == 0) 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); 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); match_api.MakeResponse(sub_matchings, sub_routes, json_result);
return Status::Ok; return Status::Ok;
+11 -24
View File
@@ -54,8 +54,7 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
const CandidateLists &candidates_list, const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision)
const bool allow_splitting)
{ {
map_matching::MatchingConfidence confidence; map_matching::MatchingConfidence confidence;
map_matching::EmissionLogProbability default_emission_log_probability(DEFAULT_GPS_PRECISION); 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) for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t)
{ {
const bool gap_in_trace = [&]() { const bool gap_in_trace = [&, use_timestamps]() {
// do not determine split if wasn't asked about it // use temporal information if available to determine a split
if (allow_splitting) if (use_timestamps)
{ {
// use temporal information if available to determine a split return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
if (use_timestamps) max_broken_time;
{
return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
max_broken_time;
}
else
{
return t - prev_unbroken_timestamps.back() > MAX_BROKEN_STATES;
}
} }
else 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 CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision)
const bool use_tidying)
{ {
return mapMatchingImpl(engine_working_data, return mapMatchingImpl(engine_working_data,
facade, facade,
candidates_list, candidates_list,
trace_coordinates, trace_coordinates,
trace_timestamps, trace_timestamps,
trace_gps_precision, trace_gps_precision);
use_tidying);
} }
SubMatchingList SubMatchingList
@@ -443,8 +432,7 @@ mapMatching(SearchEngineData &engine_working_data,
const CandidateLists &candidates_list, const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates, const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps, const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision, const std::vector<boost::optional<double>> &trace_gps_precision)
const bool use_tidying)
{ {
return mapMatchingImpl(engine_working_data, return mapMatchingImpl(engine_working_data,
@@ -452,8 +440,7 @@ mapMatching(SearchEngineData &engine_working_data,
candidates_list, candidates_list,
trace_coordinates, trace_coordinates,
trace_timestamps, trace_timestamps,
trace_gps_precision, trace_gps_precision);
use_tidying);
} }
} // namespace routing_algorithms } // namespace routing_algorithms
+7 -3
View File
@@ -108,12 +108,12 @@ int Partitioner::Run(const PartitionConfig &config)
makeBisectionGraph(compressed_node_based_graph.coordinates, makeBisectionGraph(compressed_node_based_graph.coordinates,
adaptToBisectionEdge(std::move(compressed_node_based_graph.edges))); 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.boundary_factor << " " << config.num_optimizing_cuts << " "
<< config.small_component_size << config.small_component_size
<< " # max_cell_size balance boundary cuts small_component_size"; << " # max_cell_size balance boundary cuts small_component_size";
RecursiveBisection recursive_bisection(graph, RecursiveBisection recursive_bisection(graph,
config.max_cell_sizes.front(), config.minimum_cell_size,
config.balance, config.balance,
config.boundary_factor, config.boundary_factor,
config.num_optimizing_cuts, config.num_optimizing_cuts,
@@ -161,7 +161,11 @@ int Partitioner::Run(const PartitionConfig &config)
std::vector<Partition> partitions; std::vector<Partition> partitions;
std::vector<std::uint32_t> level_to_num_cells; std::vector<std::uint32_t> level_to_num_cells;
std::tie(partitions, 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); auto num_unconnected = removeUnconnectedBoundaryNodes(*edge_based_graph, partitions);
util::Log() << "Fixed " << num_unconnected << " unconnected nodes"; util::Log() << "Fixed " << num_unconnected << " unconnected nodes";
+16 -74
View File
@@ -8,15 +8,11 @@
#include <tbb/task_scheduler_init.h> #include <tbb/task_scheduler_init.h>
#include <boost/algorithm/string/join.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <iostream> #include <iostream>
#include <iterator>
#include <regex>
using namespace osrm; using namespace osrm;
@@ -27,48 +23,7 @@ enum class return_code : unsigned
exit exit
}; };
struct MaxCellSizesArgument return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &partition_config)
{
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)
{ {
// declare a group of options that will be allowed only on command line // declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options"); 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() config_options.add_options()
// //
("threads,t", ("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()), ->default_value(tbb::task_scheduler_init::default_num_threads()),
"Number of threads to use") "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", ("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") "Balance for left and right side in single bisection")
// //
("boundary", ("boundary",
boost::program_options::value<double>(&config.boundary_factor) boost::program_options::value<double>(&partition_config.boundary_factor)
->default_value(config.boundary_factor), ->default_value(0.25),
"Percentage of embedded nodes to contract as sources and sinks") "Percentage of embedded nodes to contract as sources and sinks")
// //
("optimizing-cuts", ("optimizing-cuts",
boost::program_options::value<std::size_t>(&config.num_optimizing_cuts) boost::program_options::value<std::size_t>(&partition_config.num_optimizing_cuts)
->default_value(config.num_optimizing_cuts), ->default_value(10),
"Number of cuts to use for optimizing a single bisection") "Number of cuts to use for optimizing a single bisection")
// //
("small-component-size", ("small-component-size",
boost::program_options::value<std::size_t>(&config.small_component_size) boost::program_options::value<std::size_t>(&partition_config.small_component_size)
->default_value(config.small_component_size), ->default_value(1000),
"Size threshold for small components.") "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");
// hidden options, will be allowed on command line, but will not be // hidden options, will be allowed on command line, but will not be
// shown to the user // shown to the user
boost::program_options::options_description hidden_options("Hidden options"); boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()( hidden_options.add_options()(
"input,i", "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"); "Input file in .osrm format");
// positional option // positional option
@@ -165,18 +119,6 @@ return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &c
return return_code::fail; 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; return return_code::ok;
} }
-132
View File
@@ -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()
+7 -33
View File
@@ -46,11 +46,11 @@ BOOST_AUTO_TEST_SUITE(multi_level_graph)
BOOST_AUTO_TEST_CASE(check_edges_sorting) BOOST_AUTO_TEST_CASE(check_edges_sorting)
{ {
// node: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 // 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, 6}}; 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, 4}}; 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, 2}}; 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, 1}}; 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}}; MultiLevelPartition mlp{{l1, l2, l3, l4}, {7, 5, 3, 2}};
std::vector<MockEdge> edges = { std::vector<MockEdge> edges = {
@@ -69,8 +69,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
{9, 8}, // i i i i {9, 8}, // i i i i
{10, 11}, // i i i i {10, 11}, // i i i i
{11, 10}, // i i i i {11, 10}, // i i i i
{11, 12}, // b b b b {11, 12} // b b b b
{12, 13} // i i i i
}; };
auto graph = makeGraph(mlp, edges); 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 // the union of border and internal edge needs to equal the adjacent edges
for (auto level : util::irange<LevelID>(0, 4)) 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 adjacent = graph.GetAdjacentEdgeRange(node);
const auto border = graph.GetBorderEdgeRange(level, 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, 10).size(), 0);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 11).size(), 2); BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 11).size(), 2);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 12).size(), 1); 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, 0).size(), 1);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 1).size(), 0); 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, 10).size(), 0);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 11).size(), 2); BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 11).size(), 2);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 12).size(), 1); 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, 0).size(), 1);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 1).size(), 0); 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, 10).size(), 0);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 11).size(), 1); BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 11).size(), 1);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 12).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, 0).size(), 0);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 1).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, 10).size(), 0);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 11).size(), 1); BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 11).size(), 1);
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 12).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, 0), graph.FindEdge(0, 4));
CHECK_EQUAL_RANGE(graph.GetBorderEdgeRange(1, 3), graph.FindEdge(3, 7)); 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)); 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() BOOST_AUTO_TEST_SUITE_END()