Skip to content

Commit 3ddda08

Browse files
Daniil MordanovDaniil Mordanov
authored andcommitted
Fix quaternion interpolation threshold
1 parent 1bb4071 commit 3ddda08

4 files changed

Lines changed: 64 additions & 1 deletion

File tree

imu_complementary_filter/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ install(DIRECTORY launch config
7171
DESTINATION share/${PROJECT_NAME}
7272
)
7373

74+
if(BUILD_TESTING)
75+
find_package(ament_cmake_gtest REQUIRED)
76+
ament_add_gtest(complementary_filter_test
77+
test/complementary_filter_test.cpp)
78+
target_link_libraries(complementary_filter_test complementary_filter)
79+
endif()
80+
7481
ament_export_include_directories(include)
7582
ament_export_libraries(complementary_filter)
7683
ament_export_targets(

imu_complementary_filter/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<build_depend>std_msgs</build_depend>
1919
<build_depend>tf2</build_depend>
2020
<build_depend>tf2_ros</build_depend>
21+
<test_depend>ament_cmake_gtest</test_depend>
2122
<export>
2223
<build_type>ament_cmake</build_type>
2324
</export>

imu_complementary_filter/src/complementary_filter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,8 @@ void invertQuaternion(double q0, double q1, double q2, double q3,
496496
void scaleQuaternion(double gain, double& dq0, double& dq1, double& dq2,
497497
double& dq3)
498498
{
499-
if (dq0 < 0.0) // 0.9
499+
constexpr double interpolation_threshold = 0.9;
500+
if (dq0 <= interpolation_threshold)
500501
{
501502
// Slerp (Spherical linear interpolation):
502503
double angle = acos(dq0);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* SPDX-License-Identifier: BSD-3-Clause
3+
*/
4+
5+
#include <gtest/gtest.h>
6+
7+
#include <cmath>
8+
9+
#include "imu_complementary_filter/complementary_filter.h"
10+
11+
namespace {
12+
13+
constexpr double kTolerance = 1e-12;
14+
constexpr double kGain = 0.25;
15+
16+
TEST(ScaleQuaternion, UsesSlerpForLargeCorrections)
17+
{
18+
double q0 = 0.8;
19+
double q1 = 0.6;
20+
double q2 = 0.0;
21+
double q3 = 0.0;
22+
23+
const double angle = std::acos(q0);
24+
const double expected_q0 = std::cos(kGain * angle);
25+
const double expected_q1 = std::sin(kGain * angle);
26+
27+
imu_tools::scaleQuaternion(kGain, q0, q1, q2, q3);
28+
29+
EXPECT_NEAR(q0, expected_q0, kTolerance);
30+
EXPECT_NEAR(q1, expected_q1, kTolerance);
31+
EXPECT_DOUBLE_EQ(q2, 0.0);
32+
EXPECT_DOUBLE_EQ(q3, 0.0);
33+
}
34+
35+
TEST(ScaleQuaternion, UsesNormalizedLerpForSmallCorrections)
36+
{
37+
double q0 = 0.95;
38+
double q1 = std::sqrt(1.0 - q0 * q0);
39+
double q2 = 0.0;
40+
double q3 = 0.0;
41+
42+
const double lerp_q0 = (1.0 - kGain) + kGain * q0;
43+
const double lerp_q1 = kGain * q1;
44+
const double norm = std::hypot(lerp_q0, lerp_q1);
45+
46+
imu_tools::scaleQuaternion(kGain, q0, q1, q2, q3);
47+
48+
EXPECT_NEAR(q0, lerp_q0 / norm, kTolerance);
49+
EXPECT_NEAR(q1, lerp_q1 / norm, kTolerance);
50+
EXPECT_DOUBLE_EQ(q2, 0.0);
51+
EXPECT_DOUBLE_EQ(q3, 0.0);
52+
}
53+
54+
} // namespace

0 commit comments

Comments
 (0)