diff --git a/shared/include/HDMapping/PoseInterpolation.h b/shared/include/HDMapping/PoseInterpolation.h index 4718c150..86ee5f0d 100644 --- a/shared/include/HDMapping/PoseInterpolation.h +++ b/shared/include/HDMapping/PoseInterpolation.h @@ -27,6 +27,11 @@ inline Eigen::Matrix4d getInterpolatedPose(const std::mapfirst > query_time) { it_lower = std::prev(it_lower); @@ -35,10 +40,6 @@ inline Eigen::Matrix4d getInterpolatedPose(const std::mapfirst; diff --git a/shared/tests/CMakeLists.txt b/shared/tests/CMakeLists.txt index 82be362f..ed7d3bd4 100644 --- a/shared/tests/CMakeLists.txt +++ b/shared/tests/CMakeLists.txt @@ -22,5 +22,11 @@ if (MSVC) target_compile_definitions(hdmapping_shared_tests PRIVATE _USE_MATH_DEFINES) endif() +# Build in libstdc++ debug mode so iterator misuse (e.g. dereferencing end()) +# fails the test run instead of passing by luck. Safe because the code under +# test is header-only and no other C++ library is linked in; other standard +# libraries ignore the macro. +target_compile_definitions(hdmapping_shared_tests PRIVATE _GLIBCXX_DEBUG) + include(CTest) add_test(NAME hdmapping_shared_tests COMMAND hdmapping_shared_tests) diff --git a/shared/tests/test_pose_interpolation.cpp b/shared/tests/test_pose_interpolation.cpp index ac357c44..e95c0e2e 100644 --- a/shared/tests/test_pose_interpolation.cpp +++ b/shared/tests/test_pose_interpolation.cpp @@ -39,6 +39,19 @@ TEST_CASE("getInterpolatedPose: query before the first timestamp returns a zero CHECK(isZeroMatrix(getInterpolatedPose(traj, -100.0))); } +TEST_CASE("getInterpolatedPose: query after the last timestamp returns a zero matrix") +{ + // lower_bound() returns end() here, which must not be dereferenced -- + // the _GLIBCXX_DEBUG build of this test (see CMakeLists.txt) aborts if it is. + std::map traj{ + { 1.0, makePose(0, 0, 0) }, + { 2.0, makePose(10, 0, 0) }, + { 3.0, makePose(20, 0, 0) }, + }; + CHECK(isZeroMatrix(getInterpolatedPose(traj, 3.5))); + CHECK(isZeroMatrix(getInterpolatedPose(traj, 100.0))); +} + TEST_CASE("getInterpolatedPose: exact match at an interior timestamp returns that exact pose") { // Interior = not the very first key -- see the "first segment" case below