diff --git a/map/extrapolation/extrapolator.cpp b/map/extrapolation/extrapolator.cpp index fbab3cbc99..9a7474cc74 100644 --- a/map/extrapolation/extrapolator.cpp +++ b/map/extrapolation/extrapolator.cpp @@ -20,14 +20,16 @@ double LinearExtrapolationOfOneParam(double param1, double param2, uint64_t time { return (param2 - param1) * timeAfterPoint2Ms / timeBetweenPointsMs; } +} // namespace -/// \brief Returns extrapolated position after |point2| in |timeAfterPoint2Ms|. -/// \note This function is assumed that between |point1| and |point2| passed one second. -/// \note |timeAfterPoint2Ms| should be relevantly small (several seconds maximum). -location::GpsInfo LinearExtrapolation(location::GpsInfo const & point1, location::GpsInfo & point2, +namespace position_extrapolator +{ +using namespace std; + +location::GpsInfo LinearExtrapolation(location::GpsInfo const & point1, location::GpsInfo const & point2, uint64_t timeAfterPoint2Ms) { - uint64_t const timeBetweenPointsMs = + auto const timeBetweenPointsMs = static_cast((point2.m_timestamp - point1.m_timestamp) * 1000); location::GpsInfo extrapolated = point2; @@ -66,14 +68,8 @@ location::GpsInfo LinearExtrapolation(location::GpsInfo const & point1, location } return extrapolated; } -} // namespace - -namespace position_extrapolator -{ -using namespace std; // Extrapolator::Routine --------------------------------------------------------------------------- - Extrapolator::Routine::Routine(ExtrapolatedLocationUpdate const & update) : m_extrapolatedLocationUpdate(update) { diff --git a/map/extrapolation/extrapolator.hpp b/map/extrapolation/extrapolator.hpp index fe7c8b883b..85ce5502ca 100644 --- a/map/extrapolation/extrapolator.hpp +++ b/map/extrapolation/extrapolator.hpp @@ -12,6 +12,12 @@ namespace position_extrapolator { +/// \brief Returns extrapolated position after |point2| in |timeAfterPoint2Ms|. +/// \note This function is assumed that between |point1| and |point2| passed one second. +/// \note |timeAfterPoint2Ms| should be relevantly small (several seconds maximum). +location::GpsInfo LinearExtrapolation(location::GpsInfo const & point1, location::GpsInfo const & point2, + uint64_t timeAfterPoint2Ms); + class Extrapolator { public: diff --git a/map/map_tests/CMakeLists.txt b/map/map_tests/CMakeLists.txt index 30a27473ff..a9d342fbe8 100644 --- a/map/map_tests/CMakeLists.txt +++ b/map/map_tests/CMakeLists.txt @@ -10,6 +10,7 @@ set( bookmarks_test.cpp chart_generator_tests.cpp cloud_tests.cpp + extrapolator_tests.cpp feature_getters_tests.cpp framework_light_tests.cpp ge0_parser_tests.cpp diff --git a/map/map_tests/extrapolator_tests.cpp b/map/map_tests/extrapolator_tests.cpp new file mode 100644 index 0000000000..a93a4ca082 --- /dev/null +++ b/map/map_tests/extrapolator_tests.cpp @@ -0,0 +1,103 @@ +#include "testing/testing.hpp" + +#include "map/extrapolation/extrapolator.hpp" + +#include "platform/location.hpp" + +#include "base/math.hpp" + +namespace +{ +using namespace location; +using namespace position_extrapolator; + +void TestGpsInfo(GpsInfo const & tested, GpsInfo const & expected) +{ + double constexpr kEpsilon = 1e-5; + TEST_EQUAL(tested.m_source, expected.m_source, ()); + TEST(my::AlmostEqualAbs(tested.m_latitude, expected.m_latitude, kEpsilon), ()); + TEST(my::AlmostEqualAbs(tested.m_longitude, expected.m_longitude, kEpsilon), ()); + TEST(my::AlmostEqualAbs(tested.m_horizontalAccuracy, expected.m_horizontalAccuracy, kEpsilon), ()); + TEST(my::AlmostEqualAbs(tested.m_altitude, expected.m_altitude, kEpsilon), ()); + TEST(my::AlmostEqualAbs(tested.m_verticalAccuracy, expected.m_verticalAccuracy, kEpsilon), ()); + TEST(my::AlmostEqualAbs(tested.m_bearing, expected.m_bearing, kEpsilon), ()); + TEST(my::AlmostEqualAbs(tested.m_speed, expected.m_speed, kEpsilon), ()); +} + +UNIT_TEST(LinearExtrapolation) +{ + GpsInfo const point1 = {EAppleNative, + 0.0 /* m_timestamp in seconds */, + 1.0 /* m_latitude */, + 1.0 /* m_longitude */, + 10.0 /* m_horizontalAccuracy */, + 1.0 /* m_altitude */, + 10.0 /* m_verticalAccuracy */, + 0.0 /* m_bearing */, + 10.0 /* m_speed */}; + GpsInfo const point2 = {EAppleNative, + 1.0 /* m_timestamp in seconds */, + 1.01 /* m_latitude */, + 1.01 /* m_longitude */, + 11.0 /* m_horizontalAccuracy */, + 2.0 /* m_altitude */, + 10.0 /* m_verticalAccuracy */, + 1.0 /* m_bearing */, + 12.0 /* m_speed */}; + // 0 ms after |point2|. + { + GpsInfo const expected = {EAppleNative, + 1.0 /* m_timestamp */, + 1.01 /* m_latitude */, + 1.01 /* m_longitude */, + 11.0 /* m_horizontalAccuracy */, + 2.0 /* m_altitude */, + 10.0 /* m_verticalAccuracy */, + 1.0 /* m_bearing */, + 12.0 /* m_speed */}; + TestGpsInfo(LinearExtrapolation(point1, point2, 0 /* timeAfterPoint2Ms */), expected); + } + + // 100 ms after |point2|. + { + GpsInfo const expected = {EAppleNative, + 1.1 /* m_timestamp */, + 1.011 /* m_latitude */, + 1.011 /* m_longitude */, + 11.1 /* m_horizontalAccuracy */, + 2.1 /* m_altitude */, + 10.0 /* m_verticalAccuracy */, + 1.1 /* m_bearing */, + 12.2 /* m_speed */}; + TestGpsInfo(LinearExtrapolation(point1, point2, 100 /* timeAfterPoint2Ms */), expected); + } + + // 200 ms after |point2|. + { + GpsInfo const expected = {EAppleNative, + 1.2 /* m_timestamp */, + 1.012 /* m_latitude */, + 1.012 /* m_longitude */, + 11.2 /* m_horizontalAccuracy */, + 2.2 /* m_altitude */, + 10.0 /* m_verticalAccuracy */, + 1.2 /* m_bearing */, + 12.4 /* m_speed */}; + TestGpsInfo(LinearExtrapolation(point1, point2, 200 /* timeAfterPoint2Ms */), expected); + } + + // 1000 ms after |point2|. + { + GpsInfo const expected = {EAppleNative, + 2.0 /* m_timestamp */, + 1.02 /* m_latitude */, + 1.02 /* m_longitude */, + 12.0 /* m_horizontalAccuracy */, + 3.0 /* m_altitude */, + 10.0 /* m_verticalAccuracy */, + 2.0 /* m_bearing */, + 14.0 /* m_speed */}; + TestGpsInfo(LinearExtrapolation(point1, point2, 1000 /* timeAfterPoint2Ms */), expected); + } +} +} // namespace diff --git a/xcode/map/map.xcodeproj/project.pbxproj b/xcode/map/map.xcodeproj/project.pbxproj index 657725d898..19aaa01b03 100644 --- a/xcode/map/map.xcodeproj/project.pbxproj +++ b/xcode/map/map.xcodeproj/project.pbxproj @@ -95,6 +95,7 @@ 47A9D82420A19EC300E4671B /* libkml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 47A9D82320A19EC300E4671B /* libkml.a */; }; 56C116602090E5670068BBC0 /* extrapolator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56C1165E2090E5670068BBC0 /* extrapolator.cpp */; }; 56C116612090E5670068BBC0 /* extrapolator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56C1165F2090E5670068BBC0 /* extrapolator.hpp */; }; + 56D1C15E20A0AB9D005C689E /* extrapolator_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56D1C15D20A0AB9D005C689E /* extrapolator_tests.cpp */; }; 56EE14D31FE80E900036F20C /* libtransit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56EE14D41FE80E900036F20C /* libtransit.a */; }; 56EE14D51FE80EBD0036F20C /* libmwm_diff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56EE14D61FE80EBD0036F20C /* libmwm_diff.a */; }; 56EE14D71FE80F290036F20C /* libbsdiff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56EE14D81FE80F290036F20C /* libbsdiff.a */; }; @@ -301,6 +302,7 @@ 47A9D82320A19EC300E4671B /* libkml.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libkml.a; sourceTree = BUILT_PRODUCTS_DIR; }; 56C1165E2090E5670068BBC0 /* extrapolator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = extrapolator.cpp; path = extrapolation/extrapolator.cpp; sourceTree = ""; }; 56C1165F2090E5670068BBC0 /* extrapolator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = extrapolator.hpp; path = extrapolation/extrapolator.hpp; sourceTree = ""; }; + 56D1C15D20A0AB9D005C689E /* extrapolator_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = extrapolator_tests.cpp; sourceTree = ""; }; 56EE14D41FE80E900036F20C /* libtransit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libtransit.a; sourceTree = BUILT_PRODUCTS_DIR; }; 56EE14D61FE80EBD0036F20C /* libmwm_diff.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libmwm_diff.a; sourceTree = BUILT_PRODUCTS_DIR; }; 56EE14D81FE80F290036F20C /* libbsdiff.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libbsdiff.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -580,6 +582,7 @@ 674A29CA1B26FCC0001A525C /* map_tests */ = { isa = PBXGroup; children = ( + 56D1C15D20A0AB9D005C689E /* extrapolator_tests.cpp */, 679624A01D1017C200AE4E3C /* address_tests.cpp */, 674A29CB1B26FCFE001A525C /* bookmarks_test.cpp */, 454523AB202A00B9009275C1 /* cloud_tests.cpp */, @@ -1033,6 +1036,7 @@ 348AB57C1D7EE0C6009F8301 /* chart_generator.cpp in Sources */, 342D833A1D5233E8000D8AEA /* displacement_mode_manager.cpp in Sources */, 3D47B2C71F20EF06000828D2 /* displayed_categories_modifiers.cpp in Sources */, + 56D1C15E20A0AB9D005C689E /* extrapolator_tests.cpp in Sources */, 45201E931CE4AC90008A4842 /* api_mark_point.cpp in Sources */, F6FC3CB61FC323430001D929 /* discovery_manager.cpp in Sources */, 675346661A4054E800A0A8C3 /* ge0_parser.cpp in Sources */,