My Project 1.0
Holistic Fusion: A Generic Framework for Multimodal Sensor Fusion
Loading...
Searching...
No Matches
test_yaw_factor.cpp
Go to the documentation of this file.
1#include <cmath>
2#include <functional>
3#include <iostream>
4#include <stdexcept>
5#include <string>
6
7#include <gtsam/base/numericalDerivative.h>
8#include <gtsam/geometry/Pose3.h>
9#include <gtsam/linear/NoiseModel.h>
10
12
13namespace {
14
15void require(bool condition, const std::string& message) {
16 if (!condition) {
17 throw std::runtime_error(message);
18 }
19}
20
21const gtsam::SharedNoiseModel kNoise = gtsam::noiseModel::Isotropic::Sigma(1, 0.1);
22
23void constrainsYawOfUpsideDownImu() {
24 const gtsam::Rot3 R_I_S = gtsam::Rot3::Rx(M_PI);
25 const gtsam::Pose3 T_W_I(gtsam::Rot3::Rz(0.7) * R_I_S.inverse(), gtsam::Point3(1.0, 2.0, 3.0));
26 const holistic_fusion::YawFactor factor(0, 0.5, kNoise, R_I_S);
27
28 gtsam::Matrix H;
29 const gtsam::Vector error = factor.evaluateError(T_W_I, H);
30
31 require(std::abs(error(0) - 0.2) < 1e-9, "Yaw error of the measurement frame is wrong: " + std::to_string(error(0)));
32 require(H.norm() > 0.5, "Upside-down IMU has no yaw Jacobian");
33}
34
35void jacobianMatchesNumericalDerivative() {
36 const gtsam::Rot3 R_I_S = gtsam::Rot3::RzRyRx(2.9, -0.3, 0.4);
37 const gtsam::Pose3 T_W_I(gtsam::Rot3::RzRyRx(0.2, 0.1, -2.5), gtsam::Point3(0.5, -1.0, 0.2));
38 const holistic_fusion::YawFactor factor(0, -1.2, kNoise, R_I_S);
39
40 gtsam::Matrix H;
41 factor.evaluateError(T_W_I, H);
42 const std::function<gtsam::Vector1(const gtsam::Pose3&)> yawError = [&factor](const gtsam::Pose3& pose) {
43 return gtsam::Vector1(factor.evaluateError(pose, nullptr));
44 };
45 const gtsam::Matrix H_numerical = gtsam::numericalDerivative11<gtsam::Vector1, gtsam::Pose3>(yawError, T_W_I);
46
47 require(H.isApprox(H_numerical, 1e-6), "Analytic yaw Jacobian differs from the numerical one");
48}
49
50void skipsGimbalLockOfMeasurementFrame() {
51 const gtsam::Rot3 R_I_S = gtsam::Rot3::Rx(M_PI);
52 const gtsam::Pose3 T_W_I(gtsam::Rot3::Ry(M_PI / 2.0) * R_I_S.inverse(), gtsam::Point3());
53 const holistic_fusion::YawFactor factor(0, 0.3, kNoise, R_I_S);
54
55 gtsam::Matrix H;
56 const gtsam::Vector error = factor.evaluateError(T_W_I, H);
57
58 require(error.isZero() && H.isZero(), "Yaw factor acts at gimbal lock of the measurement frame");
59}
60
61} // namespace
62
63int main() {
64 try {
65 constrainsYawOfUpsideDownImu();
66 jacobianMatchesNumericalDerivative();
67 skipsGimbalLockOfMeasurementFrame();
68 } catch (const std::exception& error) {
69 std::cerr << error.what() << '\n';
70 return 1;
71 }
72 return 0;
73}
int main()