13 #error "This header is C++-only." 23 #include <Eigen/Geometry> 25 #include "flexkalman/EigenQuatExponentialMap.h" 27 DEBUG_GET_ONCE_BOOL_OPTION(simple_imu_debug,
"SIMPLE_IMU_DEBUG",
false)
28 DEBUG_GET_ONCE_BOOL_OPTION(simple_imu_spew, "SIMPLE_IMU_SPEW", false)
30 #define SIMPLE_IMU_DEBUG(MSG) \ 33 printf("SimpleIMU(%p): " MSG "\n", \ 34 (const void *)this); \ 38 #define SIMPLE_IMU_SPEW(MSG) \ 41 printf("SimpleIMU(%p): " MSG "\n", \ 42 (const void *)this); \ 50 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
56 : gravity_scale_(gravity_rate),
57 debug_(debug_get_bool_option_simple_imu_debug()),
58 spew_(debug_get_bool_option_simple_imu_spew())
60 SIMPLE_IMU_DEBUG(
"Creating instance");
87 return flexkalman::util::quat_ln(quat_);
96 return quat_.toRotationMatrix();
113 Eigen::Vector3d
const &
155 Eigen::Vector3d adjusted_accel = accel * getAccelScaleFactor_();
156 return (quat_ * adjusted_accel) -
178 getAccelScaleFactor_()
const 186 Eigen::Vector3d angVel_{Eigen::Vector3d::Zero()};
188 Eigen::Quaterniond quat_{Eigen::Quaterniond::Identity()};
189 double gravity_scale_;
211 uint64_t last_accel_timestamp_{0};
212 uint64_t last_gyro_timestamp_{0};
213 double gyro_min_squared_length_{1.e-8};
214 bool started_{
false};
219 inline Eigen::Quaterniond
223 std::max(last_accel_timestamp_, last_gyro_timestamp_);
224 if (state_time == 0) {
226 return Eigen::Quaterniond::Identity();
229 float dt = time_ns_to_s(delta_ns);
230 return quat_ * flexkalman::util::quat_exp(angVel_ * dt * 0.5);
238 "Discarding gyro report before first usable accel " 244 : timestamp - last_gyro_timestamp_;
245 if (delta_ns > 1e10) {
247 SIMPLE_IMU_DEBUG(
"Clamping integration period");
252 float dt = time_ns_to_s(delta_ns);
253 last_gyro_timestamp_ = timestamp;
254 Eigen::Vector3d incRot = gyro * dt;
256 if (incRot.squaredNorm() < gyro_min_squared_length_) {
258 "Discarding gyro data that is approximately zero");
265 quat_ = quat_ * flexkalman::util::quat_exp(incRot * 0.5);
273 uint64_t delta_ns = (last_accel_timestamp_ == 0)
275 : timestamp - last_accel_timestamp_;
276 float dt = time_ns_to_s(delta_ns);
283 "Can't start tracker with this accel " 284 "sample: we're moving too much.");
290 quat_ = Eigen::Quaterniond::FromTwoVectors(
291 accel.normalized(), Eigen::Vector3d::UnitY());
292 accel_filter_.
addSample(accel, timestamp);
293 gravity_filter_.
addSample(accel.norm(), timestamp);
294 last_accel_timestamp_ = timestamp;
296 SIMPLE_IMU_DEBUG(
"Got a usable startup accel report");
299 last_accel_timestamp_ = timestamp;
300 accel_filter_.
addSample(accel, timestamp);
301 gravity_filter_.
addSample(accel.norm(), timestamp);
304 Eigen::Vector3d adjusted_accel =
305 accel_filter_.
getState() * getAccelScaleFactor_();
309 auto scale = 1. - diff;
313 SIMPLE_IMU_SPEW(
"Too far from gravity to be useful/trusted.");
319 Eigen::Vector3d measuredGravityDirection =
320 (quat_ * adjusted_accel).normalized();
321 auto incremental = Eigen::Quaterniond::FromTwoVectors(
322 measuredGravityDirection, Eigen::Vector3d::UnitY());
324 double alpha = scale * gravity_scale_ * dt;
325 Eigen::Quaterniond scaledIncrementalQuat =
326 Eigen::Quaterniond::Identity().slerp(alpha, incremental);
329 quat_ = scaledIncrementalQuat * quat_;
bool handleGyro(Eigen::Vector3d const &gyro, timepoint_ns timestamp)
Process a gyroscope report.
Definition: t_imu_fusion.hpp:233
void addSample(Vector const &sample, std::uint64_t timestamp_ns, Scalar weight=1)
Filter a sample, with an optional weight.
Definition: t_lowpass_vector.hpp:67
#define MATH_GRAVITY_M_S2
Standard gravity acceleration constant.
Definition: m_api.h:49
int64_t time_duration_ns
Integer duration type in nanoseconds.
Definition: u_time.h:45
Definition: t_imu_fusion.hpp:47
Eigen::Quaterniond getPredictedQuat(timepoint_ns timestamp) const
Get the predicted orientation at some point in the future.
Definition: t_imu_fusion.hpp:220
void postCorrect()
Normalize internal state.
Definition: t_imu_fusion.hpp:167
void addSample(Scalar sample, timepoint_ns timestamp_ns, Scalar weight=1)
Filter a sample, with an optional weight.
Definition: t_lowpass.hpp:147
Time-keeping: a clock that is steady, convertible to system time, and ideally high-resolution.
int64_t timepoint_ns
Integer timestamp type.
Definition: u_time.h:34
Eigen::Quaterniond getQuat() const
Get the current state orientation.
Definition: t_imu_fusion.hpp:76
Scalar getState() const noexcept
Access the filtered value.
Definition: t_lowpass.hpp:156
bool valid() const noexcept
Definition: t_imu_fusion.hpp:67
Vector const & getState() const noexcept
Access the filtered value.
Definition: t_lowpass_vector.hpp:78
Low-pass IIR filter on vectors.
Eigen::Vector3d const & getAngVel() const
Get the angular velocity in body space.
Definition: t_imu_fusion.hpp:114
Definition: t_fusion.hpp:25
Eigen::Vector3d getRotationVec() const
Get the current state orientation as a rotation vector.
Definition: t_imu_fusion.hpp:85
EIGEN_MAKE_ALIGNED_OPERATOR_NEW SimpleIMUFusion(double gravity_rate=0.9)
Definition: t_imu_fusion.hpp:55
Eigen::Matrix3d getRotationMatrix() const
Get the current state orientation as a rotation matrix.
Definition: t_imu_fusion.hpp:94
C interface to math library.
Eigen::Vector3d getCorrectedWorldAccel(Eigen::Vector3d const &accel) const
Use this to obtain the residual, world-space acceleration in m/s/s not associated with gravity...
Definition: t_imu_fusion.hpp:153
bool handleAccel(Eigen::Vector3d const &accel, timepoint_ns timestamp)
Process an accelerometer report.
Definition: t_imu_fusion.hpp:270