Candidate query for match is now only depending on gps_precision

This commit is contained in:
Patrick Niklaus 2015-08-29 15:53:33 +02:00
parent ee0c20ae44
commit 262b380280
6 changed files with 73 additions and 97 deletions

View File

@ -91,13 +91,23 @@ template <class CandidateLists> struct HiddenMarkovModel
: breakage(candidates_list.size()), candidates_list(candidates_list),
emission_log_probability(emission_log_probability)
{
for (const auto &l : candidates_list)
viterbi.resize(candidates_list.size());
parents.resize(candidates_list.size());
path_lengths.resize(candidates_list.size());
suspicious.resize(candidates_list.size());
pruned.resize(candidates_list.size());
for (const auto i : osrm::irange<std::size_t>(0u, candidates_list.size()))
{
viterbi.emplace_back(l.size());
parents.emplace_back(l.size());
path_lengths.emplace_back(l.size());
suspicious.emplace_back(l.size());
pruned.emplace_back(l.size());
const auto& num_candidates = candidates_list[i].size();
// add empty vectors
if (num_candidates > 0)
{
viterbi[i].resize(num_candidates);
parents[i].resize(num_candidates);
path_lengths[i].resize(num_candidates);
suspicious[i].resize(num_candidates);
pruned[i].resize(num_candidates);
}
}
clear(0);
@ -121,10 +131,11 @@ template <class CandidateLists> struct HiddenMarkovModel
std::size_t initialize(std::size_t initial_timestamp)
{
BOOST_ASSERT(initial_timestamp < candidates_list.size());
auto num_points = candidates_list.size();
do
{
BOOST_ASSERT(initial_timestamp < num_points);
for (const auto s : osrm::irange<std::size_t>(0u, viterbi[initial_timestamp].size()))
{
viterbi[initial_timestamp][s] =
@ -139,9 +150,9 @@ template <class CandidateLists> struct HiddenMarkovModel
}
++initial_timestamp;
} while (breakage[initial_timestamp - 1]);
} while (initial_timestamp < num_points && breakage[initial_timestamp - 1]);
if (initial_timestamp >= viterbi.size())
if (initial_timestamp >= num_points)
{
return osrm::matching::INVALID_STATE;
}

View File

@ -783,32 +783,18 @@ class StaticRTree
// Returns elements within max_distance.
// If the minium of elements could not be found in the search radius, widen
// it until the minimum can be satisfied.
// At the number of returned nodes is capped at the given maximum.
bool IncrementalFindPhantomNodeForCoordinateWithDistance(
const FixedPointCoordinate &input_coordinate,
std::vector<std::pair<PhantomNode, double>> &result_phantom_node_vector,
const double max_distance,
const unsigned min_number_of_phantom_nodes,
const unsigned max_number_of_phantom_nodes,
const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE)
{
unsigned inspected_elements = 0;
unsigned number_of_elements_from_big_cc = 0;
unsigned number_of_elements_from_tiny_cc = 0;
// is true if a big cc was added to the queue to we also have a lower bound
// for them. it actives pruning for big components
bool has_big_cc = false;
unsigned pruned_elements = 0;
std::pair<double, double> projected_coordinate = {
mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
input_coordinate.lon / COORDINATE_PRECISION};
// upper bound pruning technique
upper_bound<float> pruning_bound(max_number_of_phantom_nodes);
// initialize queue with root element
std::priority_queue<IncrementalQueryCandidate> traversal_queue;
traversal_queue.emplace(0.f, m_search_tree[0]);
@ -818,6 +804,11 @@ class StaticRTree
const IncrementalQueryCandidate current_query_node = traversal_queue.top();
traversal_queue.pop();
if (current_query_node.min_dist > max_distance || inspected_elements >= max_checked_elements)
{
break;
}
if (current_query_node.node.template is<TreeNode>())
{ // current object is a tree node
const TreeNode &current_tree_node =
@ -839,16 +830,9 @@ class StaticRTree
// distance must be non-negative
BOOST_ASSERT(0.f <= current_perpendicular_distance);
if (pruning_bound.get() >= current_perpendicular_distance ||
(!has_big_cc && !current_edge.is_in_tiny_cc()))
if (current_perpendicular_distance <= max_distance)
{
pruning_bound.insert(current_perpendicular_distance);
traversal_queue.emplace(current_perpendicular_distance, current_edge);
has_big_cc = has_big_cc || !current_edge.is_in_tiny_cc();
}
else
{
++pruned_elements;
}
}
}
@ -865,10 +849,13 @@ class StaticRTree
child_rectangle.GetMinDist(input_coordinate);
BOOST_ASSERT(0.f <= lower_bound_to_element);
if (lower_bound_to_element <= max_distance)
{
traversal_queue.emplace(lower_bound_to_element, child_tree_node);
}
}
}
}
else
{ // current object is a leaf node
++inspected_elements;
@ -876,14 +863,6 @@ class StaticRTree
const EdgeDataT &current_segment =
current_query_node.node.template get<EdgeDataT>();
// continue searching for the first segment from a big component
if (number_of_elements_from_big_cc == 0 &&
number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes - 1 &&
current_segment.is_in_tiny_cc())
{
continue;
}
// check if it is smaller than what we had before
float current_ratio = 0.f;
FixedPointCoordinate foot_point_coordinate_on_segment;
@ -894,9 +873,7 @@ class StaticRTree
m_coordinate_list->at(current_segment.v), input_coordinate,
projected_coordinate, foot_point_coordinate_on_segment, current_ratio);
if (number_of_elements_from_big_cc > 0 &&
result_phantom_node_vector.size() >= min_number_of_phantom_nodes &&
current_perpendicular_distance >= max_distance)
if (current_perpendicular_distance >= max_distance)
{
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
continue;
@ -920,36 +897,14 @@ class StaticRTree
// set forward and reverse weights on the phantom node
SetForwardAndReverseWeightsOnPhantomNode(current_segment,
result_phantom_node_vector.back().first);
// update counts on what we found from which result class
if (current_segment.is_in_tiny_cc())
{ // found an element in tiny component
++number_of_elements_from_tiny_cc;
}
else
{ // found an element in a big component
++number_of_elements_from_big_cc;
}
}
// stop the search by flushing the queue
if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes &&
number_of_elements_from_big_cc > 0) ||
inspected_elements >= max_checked_elements)
if (inspected_elements >= max_checked_elements)
{
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
}
}
// SimpleLogger().Write() << "result_phantom_node_vector.size(): " <<
// result_phantom_node_vector.size();
// SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes;
// SimpleLogger().Write() << "number_of_elements_from_big_cc: " <<
// number_of_elements_from_big_cc;
// SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " <<
// number_of_elements_from_tiny_cc;
// SimpleLogger().Write() << "inspected_elements: " << inspected_elements;
// SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements;
// SimpleLogger().Write() << "pruned_elements: " << pruned_elements;
return !result_phantom_node_vector.empty();
}

View File

@ -92,11 +92,13 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
}
bool getCandiates(const std::vector<FixedPointCoordinate> &input_coords,
const double gps_precision,
std::vector<double> &sub_trace_lengths,
osrm::matching::CandidateLists &candidates_lists)
{
double last_distance =
coordinate_calculation::great_circle_distance(input_coords[0], input_coords[1]);
double query_radius = 10 * gps_precision;
double last_distance = coordinate_calculation::great_circle_distance(input_coords[0], input_coords[1]);
sub_trace_lengths.resize(input_coords.size());
sub_trace_lengths[0] = 0;
for (const auto current_coordinate : osrm::irange<std::size_t>(0, input_coords.size()))
@ -104,8 +106,8 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
bool allow_uturn = false;
if (0 < current_coordinate)
{
last_distance = coordinate_calculation::great_circle_distance(
input_coords[current_coordinate - 1], input_coords[current_coordinate]);
last_distance = coordinate_calculation::great_circle_distance(input_coords[current_coordinate - 1], input_coords[current_coordinate]);
sub_trace_lengths[current_coordinate] +=
sub_trace_lengths[current_coordinate - 1] + last_distance;
}
@ -124,18 +126,27 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
}
std::vector<std::pair<PhantomNode, double>> candidates;
if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
input_coords[current_coordinate], candidates, last_distance / 2.0, 5,
max_number_of_candidates))
{
return false;
}
facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
input_coords[current_coordinate], candidates, query_radius);
if (allow_uturn)
{
candidates_lists.push_back(candidates);
}
else
// sort by foward id, then by reverse id and then by distance
std::sort(candidates.begin(), candidates.end(),
[](const std::pair<PhantomNode, double>& lhs, const std::pair<PhantomNode, double>& rhs) {
return lhs.first.forward_node_id < rhs.first.forward_node_id ||
(lhs.first.forward_node_id == rhs.first.forward_node_id &&
(lhs.first.reverse_node_id < rhs.first.reverse_node_id ||
(lhs.first.reverse_node_id == rhs.first.reverse_node_id &&
lhs.second < rhs.second)));
});
auto new_end = std::unique(candidates.begin(), candidates.end(),
[](const std::pair<PhantomNode, double>& lhs, const std::pair<PhantomNode, double>& rhs) {
return lhs.first.forward_node_id == rhs.first.forward_node_id &&
lhs.first.reverse_node_id == rhs.first.reverse_node_id;
});
candidates.resize(new_end - candidates.begin());
if (!allow_uturn)
{
const auto compact_size = candidates.size();
for (const auto i : osrm::irange<std::size_t>(0, compact_size))
@ -151,8 +162,15 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
candidates[i].first.reverse_node_id = SPECIAL_NODEID;
}
}
candidates_lists.push_back(candidates);
}
// sort by distance to make pruning effective
std::sort(candidates.begin(), candidates.end(),
[](const std::pair<PhantomNode, double>& lhs, const std::pair<PhantomNode, double>& rhs) {
return lhs.second < rhs.second;
});
candidates_lists.push_back(std::move(candidates));
}
return true;
@ -246,7 +264,7 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
}
const bool found_candidates =
getCandiates(input_coords, sub_trace_lengths, candidates_lists);
getCandiates(input_coords, route_parameters.gps_precision, sub_trace_lengths, candidates_lists);
if (!found_candidates)
{
json_result.values["status"] = "No suitable matching candidates found.";

View File

@ -107,9 +107,7 @@ template <class EdgeDataT> class BaseDataFacade
virtual bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
const FixedPointCoordinate &input_coordinate,
std::vector<std::pair<PhantomNode, double>> &resulting_phantom_node_vector,
const double max_distance,
const unsigned min_number_of_phantom_nodes,
const unsigned max_number_of_phantom_nodes) = 0;
const double max_distance) = 0;
virtual unsigned GetCheckSum() const = 0;

View File

@ -453,9 +453,7 @@ template <class EdgeDataT> class InternalDataFacade final : public BaseDataFacad
bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
const FixedPointCoordinate &input_coordinate,
std::vector<std::pair<PhantomNode, double>> &resulting_phantom_node_vector,
const double max_distance,
const unsigned min_number_of_phantom_nodes,
const unsigned max_number_of_phantom_nodes) override final
const double max_distance) override final
{
if (!m_static_rtree.get())
{
@ -463,8 +461,7 @@ template <class EdgeDataT> class InternalDataFacade final : public BaseDataFacad
}
return m_static_rtree->IncrementalFindPhantomNodeForCoordinateWithDistance(
input_coordinate, resulting_phantom_node_vector, max_distance,
min_number_of_phantom_nodes, max_number_of_phantom_nodes);
input_coordinate, resulting_phantom_node_vector, max_distance);
}
unsigned GetCheckSum() const override final { return m_check_sum; }

View File

@ -424,9 +424,7 @@ template <class EdgeDataT> class SharedDataFacade final : public BaseDataFacade<
bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
const FixedPointCoordinate &input_coordinate,
std::vector<std::pair<PhantomNode, double>> &resulting_phantom_node_vector,
const double max_distance,
const unsigned min_number_of_phantom_nodes,
const unsigned max_number_of_phantom_nodes) override final
const double max_distance) override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
@ -434,8 +432,7 @@ template <class EdgeDataT> class SharedDataFacade final : public BaseDataFacade<
}
return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinateWithDistance(
input_coordinate, resulting_phantom_node_vector, max_distance,
min_number_of_phantom_nodes, max_number_of_phantom_nodes);
input_coordinate, resulting_phantom_node_vector, max_distance);
}
unsigned GetCheckSum() const override final { return m_check_sum; }