TODO fixes

This commit is contained in:
Lev Dragunov 2017-03-20 18:49:50 +03:00 committed by Patrick Niklaus
parent a49c6f433b
commit cce4f6344c
3 changed files with 95 additions and 72 deletions

View File

@ -2,6 +2,7 @@
#define ENGINE_API_MATCH_HPP
#include "engine/api/match_parameters.hpp"
#include "engine/api/match_parameters_tidy.hpp"
#include "engine/api/route_api.hpp"
#include "engine/datafacade/datafacade_base.hpp"
@ -21,8 +22,10 @@ namespace api
class MatchAPI final : public RouteAPI
{
public:
MatchAPI(const datafacade::BaseDataFacade &facade_, const MatchParameters &parameters_)
: RouteAPI(facade_, parameters_), parameters(parameters_)
MatchAPI(const datafacade::BaseDataFacade &facade_,
const MatchParameters &parameters_,
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(
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};
}
}
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];
if (matching_index.NotMatched())
{
@ -111,6 +121,7 @@ class MatchAPI final : public RouteAPI
}
const MatchParameters &parameters;
const tidy::Result &tidy_result;
};
} // ns api

View File

@ -36,18 +36,56 @@ struct Result
// Masking the MatchParameter parallel arrays for items which should be removed.
Mask can_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 &params)
{
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 &params, Thresholds cfg = {15., 5})
{
Result result;
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.original_to_tidied.push_back(0);
result.tidied_to_original.push_back(0);
std::size_t last_good = 0;
const auto uses_timestamps = !params.timestamps.empty();
@ -74,6 +112,7 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
{
result.can_be_removed.set(next, false);
last_good = next;
result.tidied_to_original.push_back(next);
running = {0., 0}; // reset running distance and time
}
else
@ -87,6 +126,7 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
{
result.can_be_removed.set(next, false);
last_good = next;
result.tidied_to_original.push_back(next);
running = {0., 0}; // reset running distance and time
}
else
@ -94,19 +134,13 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
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(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.
// 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)
{
if (!result.can_be_removed[i])
@ -126,6 +160,7 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
result.parameters.timestamps.push_back(params.timestamps[i]);
}
}
BOOST_ASSERT(result.tidied_to_original.size() == result.parameters.coordinates.size());
return result;
}

View File

@ -146,20 +146,33 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
"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
// that models GPS noise (in this model), x3 should give us the correct
// search radius with > 99% confidence
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);
}
else
{
search_radiuses.resize(parameters.coordinates.size());
std::transform(parameters.radiuses.begin(),
parameters.radiuses.end(),
search_radiuses.resize(tidied.parameters.coordinates.size());
std::transform(tidied.parameters.radiuses.begin(),
tidied.parameters.radiuses.end(),
search_radiuses.begin(),
[](const boost::optional<double> &maybe_radius) {
if (maybe_radius)
@ -174,61 +187,27 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
});
}
SubMatchingList sub_matchings;
if (parameters.use_tidying)
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();
}))
{
// Transparently tidy match parameters, do map matching on tidied parameters.
// Then use the mapping to restore the original <-> tidied relationship.
auto tidied = api::tidy::tidy(parameters);
// 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);
return Error("NoSegment",
std::string("Could not find a matching segment for any coordinate."),
json_result);
}
else
{
auto candidates_lists = GetPhantomNodesInRange(facade, parameters, search_radiuses);
filterCandidates(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,
parameters.coordinates,
parameters.timestamps,
parameters.radiuses,
parameters.gaps_processing ==
api::MatchParameters::GapsType::Split);
}
// 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);
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);
}
// TODO: restore original coordinates for tidyied parameters
api::MatchAPI match_api{facade, parameters};
api::MatchAPI match_api{facade, parameters, tidied};
match_api.MakeResponse(sub_matchings, sub_routes, json_result);
return Status::Ok;