Use median sample time instead of average to harden against outliers

This commit is contained in:
Patrick Niklaus 2015-09-01 23:03:54 +02:00
parent f167c3e12e
commit 57608628a4

View File

@ -74,7 +74,7 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
using QueryHeap = SearchEngineData::QueryHeap; using QueryHeap = SearchEngineData::QueryHeap;
SearchEngineData &engine_working_data; SearchEngineData &engine_working_data;
unsigned GetAverageSampleTime(const std::vector<unsigned>& timestamps) const unsigned GetMedianSampleTime(const std::vector<unsigned>& timestamps) const
{ {
BOOST_ASSERT(timestamps.size() > 1); BOOST_ASSERT(timestamps.size() > 1);
@ -83,8 +83,10 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
std::adjacent_difference(timestamps.begin(), timestamps.end(), sample_times.begin()); std::adjacent_difference(timestamps.begin(), timestamps.end(), sample_times.begin());
// don't use first element of sample_times -> will not be a difference. // don't use first element of sample_times -> will not be a difference.
auto sum_sample_times = std::accumulate(std::next(sample_times.begin()), sample_times.end(), 0); auto first_elem = std::next(sample_times.begin());
return sum_sample_times / (sample_times.size() - 1); auto median = first_elem + std::distance(first_elem, sample_times.end())/2;
std::nth_element(first_elem, median, sample_times.end());
return *median;
} }
public: public:
@ -102,21 +104,21 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
{ {
BOOST_ASSERT(candidates_list.size() == trace_coordinates.size()); BOOST_ASSERT(candidates_list.size() == trace_coordinates.size());
const auto avg_sample_time = [&]() { const auto median_sample_time = [&]() {
if (trace_timestamps.size() > 1) if (trace_timestamps.size() > 1)
{ {
return GetAverageSampleTime(trace_timestamps); return GetMedianSampleTime(trace_timestamps);
} }
else else
{ {
return 0u; return 0u;
} }
}(); }();
const auto max_broken_time = avg_sample_time * osrm::matching::MAX_BROKEN_STATES; const auto max_broken_time = median_sample_time * osrm::matching::MAX_BROKEN_STATES;
const auto max_distance_delta = [&]() { const auto max_distance_delta = [&]() {
if (trace_timestamps.size() > 1) if (trace_timestamps.size() > 1)
{ {
return avg_sample_time * osrm::matching::MAX_SPEED; return median_sample_time * osrm::matching::MAX_SPEED;
} }
else else
{ {