Program Listing for File imu.cc

Return to documentation for file (devices/imu.cc)

#include "lupnt/devices/imu.h"

#include <fmt/format.h>

#include "lupnt/core/asset_factory.h"
#include "lupnt/core/logger.h"
#include "lupnt/measurements/measurement.h"
#include "lupnt/numerics/math_utils.h"

namespace lupnt {

  // Imu
  Imu::Imu() : Device() {
    Logger::Debug(fmt::format("Creating {}", name_), "Imu");
    model_ = ImuModel::UNDEFINED;
    dynamics_ = MakePtr<ImuDynamics>();
  }

  Imu::Imu(Config& config) : Device(config) {
    Logger::Debug(fmt::format("Creating {}", name_), "Imu");
    model_ = ImuModel::UNDEFINED;
    dynamics_ = MakePtr<ImuDynamics>();
    if (config["model"]) {
      model_ = enum_cast<ImuModel>(config["model"].as<std::string>()).value();
      dynamics_->SetModel(model_);
    }
    if (config["frequency"]) {
      frequency_ = config["frequency"].as<double>();
      // sim_.Schedule(0.0, [this]() { this->Step(); }, Event::Priority::kSensor, frequency_);
    }
  }

  // Setup
  void Imu::Setup() { Logger::Debug(fmt::format("Setting up {}", name_), "Imu"); }

  // Step
  void Imu::Step(Real time) {
    Logger::Debug("Step", "Imu", time);
    LUPNT_CHECK(time >= time_, "Time must be greater than or equal to the current time", "Imu");
    Real sqrt_f = 1.0 / sqrt(time - time_);
    state_ = dynamics_->Propagate(state_, time_, time);
    ImuParameters params = GetParameters(model_);
    LUPNT_CHECK(false, "Not implemented", "Imu");
    ImuMeasurement measurement;
    for (int i = 0; i < 3; i++) {
      measurement.w(i) = SampleNormal(state_.b_w()(i), params.sigma_w * sqrt_f);
      measurement.a(i) = SampleNormal(state_.b_a()(i), params.sigma_a * sqrt_f);
    }
    time_ = time;
    Log(time);
  }

  // GetImuParameters
  ImuParameters Imu::GetParameters(ImuModel imu_model) {
    // https://stechschulte.net/2023/10/11/imu-specs.html
    constexpr double m_s2_per_ug = 9.80665e-6;  // [m/s^2 / µg]
    switch (imu_model) {
      case ImuModel::LN200S: {
        // https://www.northropgrumman.com/what-we-do/mission-solutions/assured-navigation/ln-200s-inertial-measurement-unit

        // Accelerometer
        double sigma_a = 35.0;                      // [ug / sqrt(Hz)]
        sigma_a = sigma_a * m_s2_per_ug;            // [m/s^2 1/sqrt(Hz)]
        double sigma_a_bias = 300.0;                // [ug sqrt(Hz)]
        sigma_a_bias = sigma_a_bias * m_s2_per_ug;  // [m/s^2 sqrt(Hz)]

        // Gyroscope
        double sigma_w = 0.07;            // [deg/hour 1/sqrt(Hz)]
        sigma_w *= RAD / SECS_HOUR;       // [rad/s 1/sqrt(Hz)]
        double sigma_w_bias = 1.0;        // [deg/hour 1/sqrt(Hz)]
        sigma_w_bias *= RAD / SECS_HOUR;  // [rad/s sqrt(Hz)]

        return ImuParameters{sigma_a, sigma_a_bias, sigma_w, sigma_w_bias};
      }
      default: LUPNT_CHECK(false, "Invalid IMU model", "ImuDynamics");
    }
  }

  // Log
  void Imu::Log(Real time) {}

  // Factory
  REGISTER_FACTORY_CLASS(Device, Imu);
}  // namespace lupnt