Use ceres solver for extrinsics calibration
Using auto differentiation to solve for camera mount angle and imu bias.
Change-Id: I434f5bc7ac97acb5d18f09ec9174d79e6f5bbb06
Signed-off-by: milind-u <milind.upadhyay@gmail.com>
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/frc971/control_loops/quaternion_utils_test.cc b/frc971/control_loops/quaternion_utils_test.cc
index f472a46..ada5e60 100644
--- a/frc971/control_loops/quaternion_utils_test.cc
+++ b/frc971/control_loops/quaternion_utils_test.cc
@@ -2,8 +2,10 @@
#include <random>
-#include "frc971/control_loops/quaternion_utils.h"
#include "aos/testing/random_seed.h"
+#include "frc971/control_loops/jacobian.h"
+#include "frc971/control_loops/quaternion_utils.h"
+#include "frc971/control_loops/runge_kutta.h"
#include "glog/logging.h"
#include "gtest/gtest.h"
@@ -147,6 +149,68 @@
}
}
+// Do a known transformation to see if quaternion integration is working
+// correctly.
+TEST(DownEstimatorTest, QuaternionIntegral) {
+ Eigen::Vector3d ux = Eigen::Vector3d::UnitX();
+ Eigen::Vector3d uy = Eigen::Vector3d::UnitY();
+ Eigen::Vector3d uz = Eigen::Vector3d::UnitZ();
+
+ Eigen::Quaternion<double> q(
+ Eigen::AngleAxis<double>(0.5 * M_PI, Eigen::Vector3d::UnitY()));
+
+ Eigen::Quaternion<double> q0(
+ Eigen::AngleAxis<double>(0, Eigen::Vector3d::UnitY()));
+
+ auto qux = q * ux;
+
+ VLOG(1) << "Q is w: " << q.w() << " vec: " << q.vec();
+ VLOG(1) << "ux is " << ux;
+ VLOG(1) << "qux is " << qux;
+
+ // Start by rotating around the X body vector for pi/2
+ Eigen::Quaternion<double> integral1(control_loops::RungeKutta(
+ std::bind(&QuaternionDerivative, ux, std::placeholders::_1), q0.coeffs(),
+ 0.5 * M_PI));
+
+ VLOG(1) << "integral1 * uz => " << integral1 * uz;
+
+ // Then rotate around the Y body vector for pi/2
+ Eigen::Quaternion<double> integral2(control_loops::RungeKutta(
+ std::bind(&QuaternionDerivative, uy, std::placeholders::_1),
+ integral1.normalized().coeffs(), 0.5 * M_PI));
+
+ VLOG(1) << "integral2 * uz => " << integral2 * uz;
+
+ // Then rotate around the X body vector for -pi/2
+ Eigen::Quaternion<double> integral3(control_loops::RungeKutta(
+ std::bind(&QuaternionDerivative, -ux, std::placeholders::_1),
+ integral2.normalized().coeffs(), 0.5 * M_PI));
+
+ integral1.normalize();
+ integral2.normalize();
+ integral3.normalize();
+
+ VLOG(1) << "Integral is w: " << integral1.w() << " vec: " << integral1.vec()
+ << " norm " << integral1.norm();
+
+ VLOG(1) << "Integral is w: " << integral3.w() << " vec: " << integral3.vec()
+ << " norm " << integral3.norm();
+
+ VLOG(1) << "ux => " << integral3 * ux;
+ EXPECT_NEAR(0.0, (ux - integral1 * ux).norm(), 5e-2);
+ EXPECT_NEAR(0.0, (uz - integral1 * uy).norm(), 5e-2);
+ EXPECT_NEAR(0.0, (-uy - integral1 * uz).norm(), 5e-2);
+
+ EXPECT_NEAR(0.0, (uy - integral2 * ux).norm(), 5e-2);
+ EXPECT_NEAR(0.0, (uz - integral2 * uy).norm(), 5e-2);
+ EXPECT_NEAR(0.0, (ux - integral2 * uz).norm(), 5e-2);
+
+ EXPECT_NEAR(0.0, (uy - integral3 * ux).norm(), 5e-2);
+ EXPECT_NEAR(0.0, (-ux - integral3 * uy).norm(), 5e-2);
+ EXPECT_NEAR(0.0, (uz - integral3 * uz).norm(), 5e-2);
+}
+
} // namespace testing
} // namespace controls
} // namespace frc971