Compare commits
5 Commits
v5.7.0-rc.3
...
v5.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 4370fd126d | |||
| 15a2fdd1f8 | |||
| 0eedcf69bc | |||
| 62abea30f5 | |||
| 3364be1860 |
@@ -1,5 +1,9 @@
|
|||||||
# 5.7.0
|
# 5.7.0
|
||||||
- Changes from 5.6
|
- Changes from 5.6
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixed 505: Invalid distance value for distance as routing weight.
|
||||||
|
- Fixed 3958: Fix traffic light penalties for non-turns
|
||||||
|
- Fixed 3933: crash when collapsing instructions
|
||||||
- Algorithm:
|
- Algorithm:
|
||||||
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
|
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
|
||||||
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
|
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
@routing @car @traffic_light
|
||||||
|
Feature: Car - Handle traffic lights
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
|
||||||
|
Scenario: Car - Encounters a traffic light
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
|
||||||
|
d-3-e-4-f
|
||||||
|
|
||||||
|
g-h-i k-l-m
|
||||||
|
| |
|
||||||
|
j n
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
| def | primary |
|
||||||
|
| ghi | primary |
|
||||||
|
| klm | primary |
|
||||||
|
| hj | primary |
|
||||||
|
| ln | primary |
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway |
|
||||||
|
| e | traffic_signals |
|
||||||
|
| l | traffic_signals |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | time | # |
|
||||||
|
| 1 | 2 | 11.1s | no turn with no traffic light |
|
||||||
|
| 3 | 4 | 13.1s | no turn with traffic light |
|
||||||
|
| g | j | 18.7s | turn with no traffic light |
|
||||||
|
| k | n | 20.7s | turn with traffic light |
|
||||||
@@ -62,3 +62,28 @@ Feature: Car - weights
|
|||||||
| from | to | route | speed | weight |
|
| from | to | route | speed | weight |
|
||||||
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
||||||
| a | e | ab,be,be | 14 km/h | 112 |
|
| a | e | ab,be,be | 14 km/h | 112 |
|
||||||
|
|
||||||
|
Scenario: Distance weights
|
||||||
|
Given the profile file "car" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.weight_name = 'distance'
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---b---c
|
||||||
|
|
|
||||||
|
d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| bd |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route | distance | weights | times |
|
||||||
|
| a,b | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
|
||||||
|
| b,c | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
|
||||||
|
| a,d | 90 180 | abc,bd,bd | 399.9m | 200,200,0 | 13.2s,11.1s,0s |
|
||||||
|
|||||||
@@ -79,102 +79,102 @@ module.exports = function () {
|
|||||||
|
|
||||||
if (headers.has('route')) {
|
if (headers.has('route')) {
|
||||||
got.route = (instructions || '').trim();
|
got.route = (instructions || '').trim();
|
||||||
|
|
||||||
if (headers.has('summary')) {
|
|
||||||
got.summary = (summary || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('alternative')) {
|
|
||||||
// TODO examine more than first alternative?
|
|
||||||
got.alternative ='';
|
|
||||||
if (json.routes && json.routes.length > 1)
|
|
||||||
got.alternative = this.wayList(json.routes[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
var distance = hasRoute && json.routes[0].distance,
|
|
||||||
time = hasRoute && json.routes[0].duration,
|
|
||||||
weight = hasRoute && json.routes[0].weight;
|
|
||||||
|
|
||||||
if (headers.has('distance')) {
|
|
||||||
if (row.distance.length) {
|
|
||||||
if (!row.distance.match(/\d+m/))
|
|
||||||
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
|
|
||||||
got.distance = instructions ? util.format('%dm', distance) : '';
|
|
||||||
} else {
|
|
||||||
got.distance = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('weight')) {
|
|
||||||
if (row.weight.length) {
|
|
||||||
if (!row.weight.match(/[\d\.]+/))
|
|
||||||
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
|
|
||||||
got.weight = instructions ? util.format('%d', weight) : '';
|
|
||||||
} else {
|
|
||||||
got.weight = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('time')) {
|
|
||||||
if (!row.time.match(/\d+s/))
|
|
||||||
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
|
|
||||||
got.time = instructions ? util.format('%ds', time) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('lanes')) {
|
|
||||||
got.lanes = (lanes || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('speed')) {
|
|
||||||
if (row.speed !== '' && instructions) {
|
|
||||||
if (!row.speed.match(/\d+ km\/h/))
|
|
||||||
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
|
|
||||||
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
|
||||||
got.speed = util.format('%d km/h', speed);
|
|
||||||
} else {
|
|
||||||
got.speed = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('intersections')) {
|
|
||||||
got.intersections = (intersections || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('locations')){
|
|
||||||
got.locations = (locations || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if header matches 'a:*', parse out the values for *
|
|
||||||
// and return in that header
|
|
||||||
headers.forEach((k) => {
|
|
||||||
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
|
||||||
if (k.match(/^a:/)) {
|
|
||||||
let a_type = k.slice(2);
|
|
||||||
if (whitelist.indexOf(a_type) == -1)
|
|
||||||
return cb(new Error('Unrecognized annotation field', a_type));
|
|
||||||
if (annotation && !annotation[a_type])
|
|
||||||
return cb(new Error('Annotation not found in response', a_type));
|
|
||||||
got[k] = annotation && annotation[a_type] || '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var putValue = (key, value) => {
|
|
||||||
if (headers.has(key)) got[key] = instructions ? value : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
putValue('ref', refs);
|
|
||||||
putValue('bearing', bearings);
|
|
||||||
putValue('turns', turns);
|
|
||||||
putValue('modes', modes);
|
|
||||||
putValue('times', times);
|
|
||||||
putValue('distances', distances);
|
|
||||||
putValue('pronunciations', pronunciations);
|
|
||||||
putValue('destinations', destinations);
|
|
||||||
putValue('weight_name', weight_name);
|
|
||||||
putValue('weights', weights);
|
|
||||||
putValue('weight', weight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers.has('summary')) {
|
||||||
|
got.summary = (summary || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('alternative')) {
|
||||||
|
// TODO examine more than first alternative?
|
||||||
|
got.alternative ='';
|
||||||
|
if (json.routes && json.routes.length > 1)
|
||||||
|
got.alternative = this.wayList(json.routes[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var distance = hasRoute && json.routes[0].distance,
|
||||||
|
time = hasRoute && json.routes[0].duration,
|
||||||
|
weight = hasRoute && json.routes[0].weight;
|
||||||
|
|
||||||
|
if (headers.has('distance')) {
|
||||||
|
if (row.distance.length) {
|
||||||
|
if (!row.distance.match(/\d+m/))
|
||||||
|
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
|
||||||
|
got.distance = instructions ? util.format('%dm', distance) : '';
|
||||||
|
} else {
|
||||||
|
got.distance = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('weight')) {
|
||||||
|
if (row.weight.length) {
|
||||||
|
if (!row.weight.match(/[\d\.]+/))
|
||||||
|
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
|
||||||
|
got.weight = instructions ? util.format('%d', weight) : '';
|
||||||
|
} else {
|
||||||
|
got.weight = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('time')) {
|
||||||
|
if (!row.time.match(/\d+s/))
|
||||||
|
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
|
||||||
|
got.time = instructions ? util.format('%ds', time) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('lanes')) {
|
||||||
|
got.lanes = (lanes || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('speed')) {
|
||||||
|
if (row.speed !== '' && instructions) {
|
||||||
|
if (!row.speed.match(/\d+ km\/h/))
|
||||||
|
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
|
||||||
|
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
||||||
|
got.speed = util.format('%d km/h', speed);
|
||||||
|
} else {
|
||||||
|
got.speed = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('intersections')) {
|
||||||
|
got.intersections = (intersections || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('locations')){
|
||||||
|
got.locations = (locations || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if header matches 'a:*', parse out the values for *
|
||||||
|
// and return in that header
|
||||||
|
headers.forEach((k) => {
|
||||||
|
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
||||||
|
if (k.match(/^a:/)) {
|
||||||
|
let a_type = k.slice(2);
|
||||||
|
if (whitelist.indexOf(a_type) == -1)
|
||||||
|
return cb(new Error('Unrecognized annotation field', a_type));
|
||||||
|
if (annotation && !annotation[a_type])
|
||||||
|
return cb(new Error('Annotation not found in response', a_type));
|
||||||
|
got[k] = annotation && annotation[a_type] || '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var putValue = (key, value) => {
|
||||||
|
if (headers.has(key)) got[key] = instructions ? value : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
putValue('ref', refs);
|
||||||
|
putValue('bearing', bearings);
|
||||||
|
putValue('turns', turns);
|
||||||
|
putValue('modes', modes);
|
||||||
|
putValue('times', times);
|
||||||
|
putValue('distances', distances);
|
||||||
|
putValue('pronunciations', pronunciations);
|
||||||
|
putValue('destinations', destinations);
|
||||||
|
putValue('weight_name', weight_name);
|
||||||
|
putValue('weights', weights);
|
||||||
|
putValue('weight', weight);
|
||||||
|
|
||||||
for (var key in row) {
|
for (var key in row) {
|
||||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||||
got[key] = row[key];
|
got[key] = row[key];
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.7.0-rc.3",
|
"version": "5.7.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"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": {
|
||||||
|
|||||||
+6
-6
@@ -392,21 +392,21 @@ function turn_function (turn)
|
|||||||
local turn_penalty = profile.turn_penalty
|
local turn_penalty = profile.turn_penalty
|
||||||
local turn_bias = profile.turn_bias
|
local turn_bias = profile.turn_bias
|
||||||
|
|
||||||
|
if turn.has_traffic_light then
|
||||||
|
turn.duration = profile.traffic_light_penalty
|
||||||
|
end
|
||||||
|
|
||||||
if turn.turn_type ~= turn_type.no_turn then
|
if turn.turn_type ~= turn_type.no_turn then
|
||||||
if turn.angle >= 0 then
|
if turn.angle >= 0 then
|
||||||
turn.duration = turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
||||||
else
|
else
|
||||||
turn.duration = turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.direction_modifier == direction_modifier.u_turn then
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
turn.duration = turn.duration + profile.u_turn_penalty
|
turn.duration = turn.duration + profile.u_turn_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
|
||||||
turn.duration = turn.duration + profile.traffic_light_penalty
|
|
||||||
end
|
|
||||||
|
|
||||||
-- for distance based routing we don't want to have penalties based on turn angle
|
-- for distance based routing we don't want to have penalties based on turn angle
|
||||||
if properties.weight_name == 'distance' then
|
if properties.weight_name == 'distance' then
|
||||||
turn.weight = 0
|
turn.weight = 0
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ end
|
|||||||
|
|
||||||
function Handlers.handle_weights(way,result,data,profile)
|
function Handlers.handle_weights(way,result,data,profile)
|
||||||
if properties.weight_name == 'distance' then
|
if properties.weight_name == 'distance' then
|
||||||
result.weight = 0
|
result.weight = -1
|
||||||
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
||||||
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
||||||
result.forward_rate = 1
|
result.forward_rate = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user