13#error "This header is C++-only." 
   24#include <Eigen/Geometry> 
   26#include "flexkalman/EigenQuatExponentialMap.h" 
   28DEBUG_GET_ONCE_LOG_OPTION(simple_imu_log, 
"SIMPLE_IMU_LOG", 
U_LOGGING_WARN)
 
   30#define SIMPLE_IMU_TRACE(...) U_LOG_IFL_T(log_level, __VA_ARGS__) 
   31#define SIMPLE_IMU_DEBUG(...) U_LOG_IFL_D(log_level, __VA_ARGS__) 
   32#define SIMPLE_IMU_INFO(...) U_LOG_IFL_I(log_level, __VA_ARGS__) 
   33#define SIMPLE_IMU_WARN(...) U_LOG_IFL_W(log_level, __VA_ARGS__) 
   34#define SIMPLE_IMU_ERROR(...) U_LOG_IFL_E(log_level, __VA_ARGS__) 
   36namespace xrt::auxiliary::tracking {
 
   44        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
 
   50            : gravity_scale_(gravity_rate), log_level(debug_get_log_option_simple_imu_log())
 
   52                SIMPLE_IMU_DEBUG(
"Creating instance");
 
   79                return flexkalman::util::quat_ln(quat_);
 
   88                return quat_.toRotationMatrix();
 
  105        Eigen::Vector3d 
const &
 
  147                Eigen::Vector3d adjusted_accel = accel * getAccelScaleFactor_();
 
  148                return (quat_ * adjusted_accel) - (Eigen::Vector3d::UnitY() * 
MATH_GRAVITY_M_S2);
 
  169        getAccelScaleFactor_()
 const 
  177        Eigen::Vector3d angVel_{Eigen::Vector3d::Zero()};
 
  179        Eigen::Quaterniond quat_{Eigen::Quaterniond::Identity()};
 
  180        double gravity_scale_;
 
  190        math::LowPassIIRVectorFilter<3, double> accel_filter_{200 };
 
  200        math::LowPassIIRFilter<double> gravity_filter_{1 };
 
  201        uint64_t last_accel_timestamp_{0};
 
  202        uint64_t last_gyro_timestamp_{0};
 
  203        double gyro_min_squared_length_{1.e-8};
 
  204        bool started_{
false};
 
  208inline Eigen::Quaterniond
 
  211        timepoint_ns state_time = std::max(last_accel_timestamp_, last_gyro_timestamp_);
 
  212        if (state_time == 0) {
 
  214                return Eigen::Quaterniond::Identity();
 
  218        return quat_ * flexkalman::util::quat_exp(angVel_ * dt * 0.5);
 
  226                    "Discarding gyro report before first usable accel " 
  231            (last_gyro_timestamp_ == 0) ? (
time_duration_ns)1e6 : timestamp - last_gyro_timestamp_;
 
  232        if (delta_ns > 1e10) {
 
  234                SIMPLE_IMU_DEBUG(
"Clamping integration period");
 
  240        last_gyro_timestamp_ = timestamp;
 
  241        Eigen::Vector3d incRot = gyro * dt;
 
  243        if (incRot.squaredNorm() < gyro_min_squared_length_) {
 
  244                SIMPLE_IMU_TRACE(
"Discarding gyro data that is approximately zero");
 
  251        quat_ = quat_ * flexkalman::util::quat_exp(incRot * 0.5);
 
  258        uint64_t delta_ns = (last_accel_timestamp_ == 0) ? 1e6 : timestamp - last_accel_timestamp_;
 
  266                            "Can't start tracker with this accel " 
  267                            "sample: we're moving too much.");
 
  273                quat_ = Eigen::Quaterniond::FromTwoVectors(accel.normalized(), Eigen::Vector3d::UnitY());
 
  274                accel_filter_.
addSample(accel, timestamp);
 
  275                gravity_filter_.
addSample(accel.norm(), timestamp);
 
  276                last_accel_timestamp_ = timestamp;
 
  278                SIMPLE_IMU_DEBUG(
"Got a usable startup accel report");
 
  281        last_accel_timestamp_ = timestamp;
 
  282        accel_filter_.
addSample(accel, timestamp);
 
  283        gravity_filter_.
addSample(accel.norm(), timestamp);
 
  286        Eigen::Vector3d adjusted_accel = accel_filter_.
getState() * getAccelScaleFactor_();
 
  290        auto scale = 1. - diff;
 
  294                SIMPLE_IMU_TRACE(
"Too far from gravity to be useful/trusted.");
 
  300        Eigen::Vector3d measuredGravityDirection = (quat_ * adjusted_accel).normalized();
 
  301        auto incremental = Eigen::Quaterniond::FromTwoVectors(measuredGravityDirection, Eigen::Vector3d::UnitY());
 
  303        double alpha = scale * gravity_scale_ * dt;
 
  304        Eigen::Quaterniond scaledIncrementalQuat = Eigen::Quaterniond::Identity().slerp(alpha, incremental);
 
  307        quat_ = scaledIncrementalQuat * quat_;
 
void addSample(Scalar sample, timepoint_ns timestamp_ns, Scalar weight=1)
Filter a sample, with an optional weight.
Definition: m_lowpass_float.hpp:143
 
Scalar getState() const noexcept
Get the filtered value.
Definition: m_lowpass_float.hpp:152
 
Vector const & getState() const noexcept
Get the filtered value.
Definition: m_lowpass_float_vector.hpp:74
 
void addSample(Vector const &sample, std::uint64_t timestamp_ns, Scalar weight=1)
Filter a sample, with an optional weight.
Definition: m_lowpass_float_vector.hpp:65
 
A simple IMU fusion class.
Definition: t_imu_fusion.hpp:42
 
Eigen::Quaterniond getPredictedQuat(timepoint_ns timestamp) const
Get the predicted orientation at some point in the future.
Definition: t_imu_fusion.hpp:209
 
bool valid() const noexcept
Definition: t_imu_fusion.hpp:59
 
bool handleAccel(Eigen::Vector3d const &accel, timepoint_ns timestamp)
Process an accelerometer report.
Definition: t_imu_fusion.hpp:256
 
void postCorrect()
Normalize internal state.
Definition: t_imu_fusion.hpp:158
 
Eigen::Matrix3d getRotationMatrix() const
Get the current state orientation as a rotation matrix.
Definition: t_imu_fusion.hpp:86
 
bool handleGyro(Eigen::Vector3d const &gyro, timepoint_ns timestamp)
Process a gyroscope report.
Definition: t_imu_fusion.hpp:221
 
Eigen::Vector3d const & getAngVel() const
Get the angular velocity in body space.
Definition: t_imu_fusion.hpp:106
 
Eigen::Vector3d getRotationVec() const
Get the current state orientation as a rotation vector.
Definition: t_imu_fusion.hpp:77
 
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:145
 
EIGEN_MAKE_ALIGNED_OPERATOR_NEW SimpleIMUFusion(double gravity_rate=0.9)
Definition: t_imu_fusion.hpp:49
 
Eigen::Quaterniond getQuat() const
Get the current state orientation.
Definition: t_imu_fusion.hpp:68
 
u_logging_level
Logging level enum.
Definition: u_logging.h:44
 
@ U_LOGGING_WARN
Warning messages: indicating a potential problem.
Definition: u_logging.h:48
 
#define MATH_GRAVITY_M_S2
Standard gravity acceleration constant.
Definition: m_api.h:51
 
int64_t timepoint_ns
Integer timestamp type.
Definition: u_time.h:77
 
static double time_ns_to_s(time_duration_ns ns)
Convert nanoseconds duration to double seconds.
Definition: u_time.h:97
 
int64_t time_duration_ns
Integer duration type in nanoseconds.
Definition: u_time.h:88
 
C interface to math library.
 
Low-pass IIR filter on vectors.
 
Basic logging functionality.
 
Time-keeping: a clock that is steady, convertible to system time, and ideally high-resolution.