1 #include "mm/stmatch/stmatch_algorithm.hpp"
2 #include "algorithm/geom_algorithm.hpp"
3 #include "util/debug.hpp"
4 #include "util/util.hpp"
14 STMATCHConfig::STMATCHConfig(
15 int k_arg,
double r_arg,
double gps_error_arg,
16 double vmax_arg,
double factor_arg) :
17 k(k_arg), radius(r_arg), gps_error(gps_error_arg),
18 vmax(vmax_arg), factor(factor_arg) {
22 SPDLOG_INFO(
"STMATCHAlgorithmConfig");
23 SPDLOG_INFO(
"k {} radius {} gps_error {} vmax {} factor {}",
28 const boost::property_tree::ptree &xml_data) {
29 int k = xml_data.get(
"config.parameters.k", 8);
30 double radius = xml_data.get(
"config.parameters.r", 300.0);
31 double gps_error = xml_data.get(
"config.parameters.gps_error", 50.0);
32 double vmax = xml_data.get(
"config.parameters.vmax", 80.0);;
33 double factor = xml_data.get(
"config.parameters.factor", 1.5);;
38 const cxxopts::ParseResult &arg_data) {
39 int k = arg_data[
"candidates"].as<
int>();
40 double radius = arg_data[
"radius"].as<
double>();
41 double gps_error = arg_data[
"error"].as<
double>();
42 double vmax = arg_data[
"vmax"].as<
double>();
43 double factor = arg_data[
"factor"].as<
double>();
49 SPDLOG_CRITICAL(
"Invalid mm parameter k {} r {} gps error {} vmax {} f {}",
59 std::vector<double> timestamps;
63 output.
id = result.
id;
91 SPDLOG_TRACE(
"Search candidates");
94 SPDLOG_TRACE(
"Trajectory candidate {}", tc);
96 SPDLOG_TRACE(
"Generate dummy graph");
98 SPDLOG_TRACE(
"Generate composite_graph");
100 SPDLOG_TRACE(
"Generate composite_graph");
102 SPDLOG_TRACE(
"Update cost in transition graph");
105 SPDLOG_TRACE(
"Optimal path inference");
107 SPDLOG_TRACE(
"Optimal path size {}", tg_opath.size());
109 std::transform(tg_opath.begin(), tg_opath.end(),
110 matched_candidate_path.begin(),
112 return MatchedCandidate{
113 *(a->c), a->ep, a->tp, a->sp_dist
116 O_Path opath(tg_opath.size());
117 std::transform(tg_opath.begin(), tg_opath.end(),
120 return a->c->edge->id;
122 std::vector<int> indices;
123 C_Path cpath = build_cpath(tg_opath, &indices);
124 SPDLOG_TRACE(
"Opath is {}", opath);
125 SPDLOG_TRACE(
"Indices is {}", indices);
126 SPDLOG_TRACE(
"Complete path is {}", cpath);
127 LineString mgeom = network_.complete_path_to_geometry(
130 traj.
id, matched_candidate_path, opath, cpath, indices, mgeom};
137 SPDLOG_TRACE(
"Update transition graph");
138 std::vector<TGLayer> &layers = tg->
get_layers();
140 int N = layers.size();
141 for (
int i = 0; i < N - 1; ++i) {
143 SPDLOG_TRACE(
"Update layer {} ", i);
146 delta = eu_dists[i] * config.
factor * 4;
149 delta = config.
factor * config.
vmax * duration;
151 update_layer(i, &(layers[i]), &(layers[i + 1]),
152 cg, eu_dists[i], delta);
154 SPDLOG_TRACE(
"Update transition graph done");
163 for (
auto iter = la_ptr->begin(); iter != la_ptr->end(); ++iter) {
165 SPDLOG_TRACE(
" Calculate distance from source {}", source);
167 std::vector<NodeIndex> targets(lb.size());
168 std::transform(lb.begin(), lb.end(), targets.begin(),
172 SPDLOG_TRACE(
" Upperbound shortest path {} ", delta);
173 std::vector<double> distances = shortest_path_upperbound(
174 level, cg, source, targets, delta);
175 SPDLOG_TRACE(
" Update property of transition graph ");
176 for (
int i = 0; i < distances.size(); ++i) {
177 double tp = TransitionGraph::calc_tp(distances[i], eu_dist);
178 if (lb[i].cumu_prob < iter->cumu_prob + tp * lb[i].ep) {
179 lb[i].cumu_prob = iter->cumu_prob + tp * lb[i].ep;
180 lb[i].prev = &(*iter);
182 lb[i].sp_dist = distances[i];
186 SPDLOG_TRACE(
"Update layer done");
189 std::vector<double> STMATCH::shortest_path_upperbound(
191 const std::vector<NodeIndex> &targets,
double delta) {
192 SPDLOG_TRACE(
"Upperbound shortest path source {}", source);
193 SPDLOG_TRACE(
"Upperbound shortest path targets {}", targets);
194 std::unordered_set<NodeIndex> unreached_targets;
195 for (
auto &node:targets) {
196 unreached_targets.insert(node);
202 pmap.insert({source, source});
203 dmap.insert({source, 0});
204 double temp_dist = 0;
206 while (!Q.
empty() && !unreached_targets.empty()) {
209 SPDLOG_TRACE(
" Node u {} dist {}", node.
index, node.
value);
211 auto iter = unreached_targets.find(u);
212 if (iter != unreached_targets.end()) {
214 SPDLOG_TRACE(
" Remove target {}", u);
215 unreached_targets.erase(iter);
217 if (node.
value > delta)
break;
218 std::vector<CompEdgeProperty> out_edges = cg.
out_edges(u);
219 for (
auto node_iter = out_edges.begin(); node_iter != out_edges.end();
222 temp_dist = node.
value + node_iter->cost;
223 SPDLOG_TRACE(
" Examine node v {} temp dist {}", v, temp_dist);
224 auto v_iter = dmap.find(v);
225 if (v_iter != dmap.end()) {
227 if (v_iter->second - temp_dist > 1e-6) {
229 SPDLOG_TRACE(
" Update key {} {} in pdmap prev dist {}",
230 v, temp_dist, v_iter->second);
237 if (temp_dist <= delta) {
238 SPDLOG_TRACE(
" Insert key {} {} into pmap and dmap",
240 Q.
push(v, temp_dist);
242 dmap.insert({v, temp_dist});
248 SPDLOG_TRACE(
" Update distances");
249 std::vector<double> distances;
250 for (
int i = 0; i < targets.size(); ++i) {
251 if (dmap.find(targets[i]) != dmap.end()) {
252 distances.push_back(dmap[targets[i]]);
254 distances.push_back(std::numeric_limits<double>::max());
257 SPDLOG_TRACE(
" Distance value {}", distances);
261 C_Path STMATCH::build_cpath(
const TGOpath &opath, std::vector<int> *indices) {
262 SPDLOG_DEBUG(
"Build cpath from optimal candidate path");
264 if (!indices->empty()) indices->clear();
265 if (opath.empty())
return cpath;
266 const std::vector<Edge> &edges = network_.get_edges();
267 int N = opath.size();
268 cpath.push_back(opath[0]->c->edge->id);
270 SPDLOG_TRACE(
"Insert index {}", current_idx);
271 indices->push_back(current_idx);
272 for (
int i = 0; i < N - 1; ++i) {
275 SPDLOG_TRACE(
"Check a {} b {}", a->
edge->
id, b->
edge->
id);
277 auto segs = graph_.shortest_path_dijkstra(a->
edge->
target,
284 SPDLOG_TRACE(
"Edges found {}", segs);
286 cpath.push_back(edges[e].
id);
289 cpath.push_back(b->
edge->
id);
291 SPDLOG_TRACE(
"Insert index {}", current_idx);
292 indices->push_back(current_idx);
294 SPDLOG_TRACE(
"Insert index {}", current_idx);
295 indices->push_back(current_idx);
298 SPDLOG_DEBUG(
"Build cpath from optimal candidate path done");
Transition graph class in HMM.
std::vector< MatchedCandidate > MatchedCandidatePath
A vector of candidates, used for representing the matching result of a trajectory.
LineString geom
Geometry of the trajectory.
double factor
factor multiplied to vmax*deltaT to limit the search of shortest path
static STMATCHConfig load_from_arg(const cxxopts::ParseResult &arg_data)
Load from argument parsed data.
CORE::LineString mgeom
Geometry of the matched path.
Heap data structure used in the routing query
std::vector< Point_Candidates > Traj_Candidates
trajectory candidates
void add_point(double x, double y)
Add a point to the end of the current line.
FMM::CORE::Point point
boost point
std::vector< const TGNode * > TGOpath
The optimal path of nodes in the transition graph.
double vmax
maximum speed of the vehicle, unit is map_unit/second
std::vector< double > timestamps
Timestamps of the trajectory.
void decrease_key(NodeIndex index, double value)
Decrease a node in the heap.
NETWORK::Edge * edge
candidate edge
Candidate c
Candidate matched to a point.
HeapNode top()
Get a copy of the top node in the heap.
Map matched result representation.
void push(NodeIndex index, double value)
Push a node into the heap.
Node in the heap structure.
std::vector< PyCandidate > candidates
Candidate matched to each point.
NodeIndex index
Index of a node in the heap.
double gps_error
GPS error, unit is map_unit.
TGOpath backtrack()
Backtrack the transition graph to find an optimal path.
double radius
search radius for candidates, unit is map_unit
EdgeID id
Edge ID, can be discontinuous integers.
std::unordered_map< NodeIndex, double > DistanceMap
Distance map.
POD Match result type used in Python API.
std::vector< FMM::NETWORK::EdgeID > C_Path
Complete path, ids of a sequence of topologically connected edges.
double dist
distance from original point p to map matched point p'
C_Path cpath
the complete path, containing ids of a sequence of topologically connected edges traversed by the tra...
void print() const
Print configuration data.
static STMATCHConfig load_from_xml(const boost::property_tree::ptree &xml_data)
Load from xml data.
std::vector< int > indices
index of matched edge in the cpath
std::vector< CompEdgeProperty > out_edges(NETWORK::NodeIndex u) const
Get out edges leaving a node u in the composite graph.
FMM::MM::Traj_Candidates search_tr_cs_knn(FMM::CORE::Trajectory &trajectory, std::size_t k, double radius) const
Search for k nearest neighboring (KNN) candidates of a trajectory within a search radius.
CORE::LineString pgeom
Point position matched for each GPS point.
CORE::LineString mgeom
the geometry of the matched path
int id
id of the trajectory to be matched
Candidate edge matched to a GPS point
void pop()
Pop a node from the heap.
bool empty()
Check if the heap is empty.
double tp
transition probability to previous matched candidate
double offset
offset distance from the start of polyline to p'
void update_tg(TransitionGraph *tg, const CompositeGraph &cg, const CORE::Trajectory &traj, const STMATCHConfig &config)
Update probabilities in a transition graph.
MM::O_Path opath
Edge ID matched for each point of the trajectory
Linestring geometry class.
MatchedCandidatePath opt_candidate_path
A vector of candidate matched to each point of a trajectory.
Class related with map matching.
O_Path opath
the optimal path, containing id of edges matched to each point in a trajectory
Classes related with network and graph.
std::vector< FMM::NETWORK::EdgeID > O_Path
Optimal path, edge id matched to each point in the trajectory.
A graph containing dummy nodes and edges used in map matching.
Composite Graph as a wrapper of network graph and dummy graph.
int get_node_id(NodeIndex idx) const
Get node ID from a node index.
Configuration of stmatch algorithm.
LineString wkt2linestring(const std::string &wkt)
Convert a wkt into a linestring.
std::vector< int > indices
index of opath edge in cpath
A candidate matched to a point.
std::vector< TGLayer > & get_layers()
Get a reference to the inner layers of the transition graph.
NodeIndex source
source node index
unsigned int NodeIndex
Node Index in the network, range from [0,num_vertices-1 ].
std::vector< double > cal_eu_dist(const FMM::CORE::LineString &trajectory)
Calculate segment length of a trajectory.
MM::C_Path cpath
Edge ID traversed by the matched path.
int get_num_points() const
Get the number of points in a line.
PYTHON::PyMatchResult match_wkt(const std::string &wkt, const STMATCHConfig &config)
Match a wkt linestring to the road network.
double length
length of the edge polyline
MatchResult match_traj(const CORE::Trajectory &traj, const STMATCHConfig &config)
Match a trajectory to the road network.
std::unordered_map< NodeIndex, NodeIndex > PredecessorMap
Predecessor Map.
A node in the transition graph.
double sp_dist
shortest path distance to previous matched candidate
std::vector< TGNode > TGLayer
A layer of nodes in the transition graph.
Data type for Python API.
double value
Value of a node in the heap.
NodeIndex target
target node index
int k
number of candidates
double ep
emission probability
bool validate() const
Check the validity of the configuration.