TODO fixes
This commit is contained in:
parent
a49c6f433b
commit
cce4f6344c
@ -2,6 +2,7 @@
|
|||||||
#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"
|
||||||
@ -21,8 +22,10 @@ namespace api
|
|||||||
class MatchAPI final : public RouteAPI
|
class MatchAPI final : public RouteAPI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MatchAPI(const datafacade::BaseDataFacade &facade_, const MatchParameters ¶meters_)
|
MatchAPI(const datafacade::BaseDataFacade &facade_,
|
||||||
: RouteAPI(facade_, parameters_), parameters(parameters_)
|
const MatchParameters ¶meters_,
|
||||||
|
const tidy::Result &tidy_result_)
|
||||||
|
: RouteAPI(facade_, parameters_), parameters(parameters_), tidy_result(tidy_result_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,13 +86,20 @@ 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[sub_matchings[sub_matching_index].indices[point_index]] =
|
trace_idx_to_matching_idx[tidy_result
|
||||||
|
.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())
|
||||||
{
|
{
|
||||||
@ -111,6 +121,7 @@ class MatchAPI final : public RouteAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MatchParameters ¶meters;
|
const MatchParameters ¶meters;
|
||||||
|
const tidy::Result &tidy_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns api
|
} // ns api
|
||||||
|
@ -36,18 +36,56 @@ struct Result
|
|||||||
// Masking the MatchParameter parallel arrays for items which should be removed.
|
// Masking the MatchParameter parallel arrays for items which should be removed.
|
||||||
Mask can_be_removed;
|
Mask can_be_removed;
|
||||||
// Maps the MatchParameter's original items to items which should not be removed.
|
// Maps the MatchParameter's original items to items which should not be removed.
|
||||||
Mapping original_to_tidied;
|
Mapping tidied_to_original;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Result keep_all(const MatchParameters ¶ms)
|
||||||
|
{
|
||||||
|
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 ¶ms, Thresholds cfg = {15., 5})
|
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||||
{
|
{
|
||||||
Result result;
|
Result result;
|
||||||
|
|
||||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||||
result.original_to_tidied.reserve(params.coordinates.size());
|
|
||||||
|
|
||||||
result.can_be_removed.set(0, false);
|
result.can_be_removed.set(0, false);
|
||||||
result.original_to_tidied.push_back(0);
|
result.tidied_to_original.push_back(0);
|
||||||
std::size_t last_good = 0;
|
std::size_t last_good = 0;
|
||||||
|
|
||||||
const auto uses_timestamps = !params.timestamps.empty();
|
const auto uses_timestamps = !params.timestamps.empty();
|
||||||
@ -74,6 +112,7 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
{
|
{
|
||||||
result.can_be_removed.set(next, false);
|
result.can_be_removed.set(next, false);
|
||||||
last_good = next;
|
last_good = next;
|
||||||
|
result.tidied_to_original.push_back(next);
|
||||||
running = {0., 0}; // reset running distance and time
|
running = {0., 0}; // reset running distance and time
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -87,6 +126,7 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
{
|
{
|
||||||
result.can_be_removed.set(next, false);
|
result.can_be_removed.set(next, false);
|
||||||
last_good = next;
|
last_good = next;
|
||||||
|
result.tidied_to_original.push_back(next);
|
||||||
running = {0., 0}; // reset running distance and time
|
running = {0., 0}; // reset running distance and time
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -94,19 +134,13 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
result.can_be_removed.set(next, true);
|
result.can_be_removed.set(next, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.original_to_tidied.push_back(last_good);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(result.original_to_tidied.size() == params.coordinates.size());
|
|
||||||
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
||||||
BOOST_ASSERT(std::is_sorted(begin(result.original_to_tidied), end(result.original_to_tidied)));
|
|
||||||
|
|
||||||
// We have to filter parallel arrays that may be empty or the exact same 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.
|
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||||
|
|
||||||
const auto to_keep = result.can_be_removed.size() - result.can_be_removed.count();
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < result.can_be_removed.size(); ++i)
|
for (std::size_t i = 0; i < result.can_be_removed.size(); ++i)
|
||||||
{
|
{
|
||||||
if (!result.can_be_removed[i])
|
if (!result.can_be_removed[i])
|
||||||
@ -126,6 +160,7 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
result.parameters.timestamps.push_back(params.timestamps[i]);
|
result.parameters.timestamps.push_back(params.timestamps[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BOOST_ASSERT(result.tidied_to_original.size() == result.parameters.coordinates.size());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -146,20 +146,33 @@ 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.use_tidying)
|
||||||
|
{
|
||||||
|
// 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 (parameters.radiuses.empty())
|
if (tidied.parameters.radiuses.empty())
|
||||||
{
|
{
|
||||||
search_radiuses.resize(parameters.coordinates.size(),
|
search_radiuses.resize(tidied.parameters.coordinates.size(),
|
||||||
routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER);
|
routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
search_radiuses.resize(parameters.coordinates.size());
|
search_radiuses.resize(tidied.parameters.coordinates.size());
|
||||||
std::transform(parameters.radiuses.begin(),
|
std::transform(tidied.parameters.radiuses.begin(),
|
||||||
parameters.radiuses.end(),
|
tidied.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)
|
||||||
@ -174,61 +187,27 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SubMatchingList sub_matchings;
|
auto candidates_lists = GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses);
|
||||||
if (parameters.use_tidying)
|
|
||||||
|
filterCandidates(tidied.parameters.coordinates, candidates_lists);
|
||||||
|
if (std::all_of(candidates_lists.begin(),
|
||||||
|
candidates_lists.end(),
|
||||||
|
[](const std::vector<PhantomNodeWithDistance> &candidates) {
|
||||||
|
return candidates.empty();
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
// Transparently tidy match parameters, do map matching on tidied parameters.
|
return Error("NoSegment",
|
||||||
// Then use the mapping to restore the original <-> tidied relationship.
|
std::string("Could not find a matching segment for any coordinate."),
|
||||||
auto tidied = api::tidy::tidy(parameters);
|
json_result);
|
||||||
|
|
||||||
// TODO is search radiuses still actual
|
|
||||||
auto candidates_lists = GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses);
|
|
||||||
|
|
||||||
filterCandidates(tidied.parameters.coordinates, candidates_lists);
|
|
||||||
if (std::all_of(candidates_lists.begin(),
|
|
||||||
candidates_lists.end(),
|
|
||||||
[](const std::vector<PhantomNodeWithDistance> &candidates) {
|
|
||||||
return candidates.empty();
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
return Error("NoSegment",
|
|
||||||
std::string("Could not find a matching segment for any coordinate."),
|
|
||||||
json_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// call the actual map matching
|
|
||||||
sub_matchings = algorithms.MapMatching(candidates_lists,
|
|
||||||
tidied.parameters.coordinates,
|
|
||||||
tidied.parameters.timestamps,
|
|
||||||
tidied.parameters.radiuses,
|
|
||||||
parameters.gaps_processing ==
|
|
||||||
api::MatchParameters::GapsType::Split);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
auto candidates_lists = GetPhantomNodesInRange(facade, parameters, search_radiuses);
|
// call the actual map matching
|
||||||
|
sub_matchings =
|
||||||
filterCandidates(parameters.coordinates, candidates_lists);
|
algorithms.MapMatching(candidates_lists,
|
||||||
if (std::all_of(candidates_lists.begin(),
|
tidied.parameters.coordinates,
|
||||||
candidates_lists.end(),
|
tidied.parameters.timestamps,
|
||||||
[](const std::vector<PhantomNodeWithDistance> &candidates) {
|
tidied.parameters.radiuses,
|
||||||
return candidates.empty();
|
parameters.gaps_processing == api::MatchParameters::GapsType::Split);
|
||||||
}))
|
|
||||||
{
|
|
||||||
return Error("NoSegment",
|
|
||||||
std::string("Could not find a matching segment for any coordinate."),
|
|
||||||
json_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// call the actual map matching
|
|
||||||
sub_matchings = algorithms.MapMatching(candidates_lists,
|
|
||||||
parameters.coordinates,
|
|
||||||
parameters.timestamps,
|
|
||||||
parameters.radiuses,
|
|
||||||
parameters.gaps_processing ==
|
|
||||||
api::MatchParameters::GapsType::Split);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sub_matchings.size() == 0)
|
if (sub_matchings.size() == 0)
|
||||||
{
|
{
|
||||||
@ -259,9 +238,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: restore original coordinates for tidyied parameters
|
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user