-
Notifications
You must be signed in to change notification settings - Fork 346
/
Copy pathlibosrm_wrapper.cpp
148 lines (117 loc) · 4.61 KB
/
libosrm_wrapper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
This file is part of VROOM.
Copyright (c) 2015-2020, Julien Coupey.
All rights reserved (see LICENSE).
*/
#include "osrm/coordinate.hpp"
#include "osrm/json_container.hpp"
#include "osrm/route_parameters.hpp"
#include "osrm/status.hpp"
#include "osrm/table_parameters.hpp"
#include "routing/libosrm_wrapper.h"
namespace vroom {
namespace routing {
osrm::EngineConfig LibosrmWrapper::get_config(const std::string& profile) {
osrm::EngineConfig config;
// Only update non-default values.
config.max_alternatives = 1;
config.dataset_name = profile;
return config;
}
LibosrmWrapper::LibosrmWrapper(const std::string& profile)
: RoutingWrapper(profile), _config(get_config(profile)), _osrm(_config) {
}
Matrix<Cost>
LibosrmWrapper::get_matrix(const std::vector<Location>& locs) const {
osrm::TableParameters params;
for (auto const& location : locs) {
assert(location.has_coordinates());
params.coordinates
.emplace_back(osrm::util::FloatLongitude({location.lon()}),
osrm::util::FloatLatitude({location.lat()}));
}
osrm::json::Object result;
osrm::Status status = _osrm.Table(params, result);
if (status == osrm::Status::Error) {
throw Exception(ERROR::ROUTING,
"libOSRM: " +
result.values["code"].get<osrm::json::String>().value +
": " +
result.values["message"].get<osrm::json::String>().value);
}
auto& table = result.values["durations"].get<osrm::json::Array>();
// Expected matrix size.
std::size_t m_size = locs.size();
assert(table.values.size() == m_size);
// Build matrix while checking for unfound routes to avoid
// unexpected behavior (OSRM raises 'null').
Matrix<Cost> m(m_size);
std::vector<unsigned> nb_unfound_from_loc(m_size, 0);
std::vector<unsigned> nb_unfound_to_loc(m_size, 0);
std::string reason;
for (std::size_t i = 0; i < m_size; ++i) {
const auto& line = table.values.at(i).get<osrm::json::Array>();
assert(line.values.size() == m_size);
for (std::size_t j = 0; j < m_size; ++j) {
const auto& el = line.values.at(j);
if (el.is<osrm::json::Null>()) {
// No route found between i and j. Just storing info as we
// don't know yet which location is responsible between i
// and j.
++nb_unfound_from_loc[i];
++nb_unfound_to_loc[j];
} else {
auto cost = round_cost(el.get<osrm::json::Number>().value);
m[i][j] = cost;
}
}
}
check_unfound(locs, nb_unfound_from_loc, nb_unfound_to_loc);
return m;
}
void LibosrmWrapper::add_route_info(Route& route) const {
// Default options for routing.
osrm::RouteParameters params(false, // steps
false, // alternatives
false, // annotations
osrm::RouteParameters::GeometriesType::Polyline,
osrm::RouteParameters::OverviewType::Full,
false // continue_straight
);
// Ordering locations for the given steps.
for (auto& step : route.steps) {
params.coordinates
.emplace_back(osrm::util::FloatLongitude({step.location.lon()}),
osrm::util::FloatLatitude({step.location.lat()}));
}
osrm::json::Object result;
osrm::Status status = _osrm.Route(params, result);
if (status == osrm::Status::Error) {
throw Exception(ERROR::ROUTING,
"libOSRM: " +
result.values["code"].get<osrm::json::String>().value +
": " +
result.values["message"].get<osrm::json::String>().value);
}
auto& result_routes = result.values["routes"].get<osrm::json::Array>();
auto& json_route = result_routes.values.at(0).get<osrm::json::Object>();
// Total distance and route geometry.
route.distance =
round_cost(json_route.values["distance"].get<osrm::json::Number>().value);
route.geometry =
std::move(json_route.values["geometry"].get<osrm::json::String>().value);
auto& legs = json_route.values["legs"].get<osrm::json::Array>();
auto nb_legs = legs.values.size();
assert(nb_legs == route.steps.size() - 1);
// Accumulated travel distance stored for each step.
double current_distance = 0;
route.steps[0].distance = 0;
for (unsigned i = 0; i < nb_legs; ++i) {
// Update distance for step after current route leg.
auto& leg = legs.values.at(i).get<osrm::json::Object>();
current_distance += leg.values["distance"].get<osrm::json::Number>().value;
route.steps[i + 1].distance = round_cost(current_distance);
}
}
} // namespace routing
} // namespace vroom