Program Listing for File imu.h¶
↰ Return to documentation for file (map-structure/sensors/include/sensors/imu.h
)
#ifndef SENSORS_IMU_H_
#define SENSORS_IMU_H_
#include <random>
#include <string>
#include <aslam/common/sensor.h>
#include <maplab-common/interpolation-helpers.h>
#include <yaml-cpp/yaml.h>
#include "sensors/measurement.h"
#include "sensors/sensor-types.h"
namespace vi_map {
struct ImuSigmas {
ImuSigmas();
explicit ImuSigmas(
const double _gyro_noise_density, const double _gyro_bias_noise_density,
const double _acc_noise_density, const double _acc_bias_noise_density);
// Gyro noise density. [rad/s*1/sqrt(Hz)]
double gyro_noise_density;
double gyro_bias_random_walk_noise_density;
// Accelerometer noise density. [m/s^2*1/sqrt(Hz)]
double acc_noise_density;
double acc_bias_random_walk_noise_density;
bool isValid() const {
return gyro_noise_density > 0.0 &&
gyro_bias_random_walk_noise_density > 0.0 &&
acc_noise_density > 0.0 && acc_bias_random_walk_noise_density > 0.0;
}
void operator=(const ImuSigmas& other) {
gyro_noise_density = other.gyro_noise_density;
gyro_bias_random_walk_noise_density =
other.gyro_bias_random_walk_noise_density;
acc_noise_density = other.acc_noise_density;
acc_bias_random_walk_noise_density =
other.acc_bias_random_walk_noise_density;
}
bool operator==(const ImuSigmas& other) const {
return isEqual(other, 1e-9);
}
bool isEqual(
const ImuSigmas& other, const double precision,
const bool verbose = false) const {
const bool is_equal =
std::abs(gyro_noise_density - other.gyro_noise_density) < precision &&
std::abs(
gyro_bias_random_walk_noise_density -
other.gyro_bias_random_walk_noise_density) < precision &&
std::abs(acc_noise_density - other.acc_noise_density) < precision &&
std::abs(
acc_bias_random_walk_noise_density -
other.acc_bias_random_walk_noise_density) < precision;
if (!is_equal) {
LOG_IF(WARNING, verbose)
<< "these imu sigmas: "
<< "\n gyro_noise_density: " << gyro_noise_density
<< "\n gyro_bias_random_walk_noise_density: "
<< gyro_bias_random_walk_noise_density
<< "\n acc_noise_density: " << acc_noise_density
<< "\n acc_bias_random_walk_noise_density: "
<< acc_bias_random_walk_noise_density;
LOG_IF(WARNING, verbose)
<< "other imu sigmas: "
<< "\n gyro_noise_density: " << other.gyro_noise_density
<< "\n gyro_bias_random_walk_noise_density: "
<< other.gyro_bias_random_walk_noise_density
<< "\n acc_noise_density: " << other.acc_noise_density
<< "\n acc_bias_random_walk_noise_density: "
<< other.acc_bias_random_walk_noise_density;
}
return is_equal;
}
bool loadFromYaml(const std::string& yaml_path);
bool saveToYaml(const std::string& yaml_path) const;
void setRandom();
};
class Imu final : public aslam::Sensor {
public:
MAPLAB_POINTER_TYPEDEFS(Imu);
Imu();
explicit Imu(const aslam::SensorId& sensor_id);
explicit Imu(const aslam::SensorId& sensor_id, const std::string& topic);
void operator=(const Imu& other) {
aslam::Sensor::operator=(other);
sigmas_ = other.sigmas_;
gravity_magnitude_ = other.gravity_magnitude_;
saturation_accel_max_ = other.saturation_accel_max_;
saturation_gyro_max_radps_ = other.saturation_gyro_max_radps_;
}
Sensor::Ptr cloneAsSensor() const {
return std::dynamic_pointer_cast<Sensor>(aligned_shared<Imu>(*this));
}
Imu* cloneWithNewIds() const {
Imu* cloned_imu = new Imu();
*cloned_imu = *this;
aslam::SensorId new_id;
aslam::generateId(&new_id);
cloned_imu->setId(new_id);
return cloned_imu;
}
uint8_t getSensorType() const override {
return SensorType::kImu;
}
std::string getSensorTypeString() const override {
return static_cast<std::string>(kImuIdentifier);
}
const ImuSigmas& getImuSigmas() const {
return sigmas_;
}
void setImuSigmas(const ImuSigmas& sigmas) {
sigmas_ = sigmas;
}
double getGravityMagnitudeMps2() const {
return gravity_magnitude_;
}
void setGravityMagnitude(const double gravity_magnitude) {
gravity_magnitude_ = gravity_magnitude;
CHECK_GE(gravity_magnitude_, kMinGravity);
CHECK_LE(gravity_magnitude_, kMaxGravity);
}
double getAccelerationSaturationMax() const {
return saturation_accel_max_;
}
double getGyroSaturationMaxRadps() const {
return saturation_gyro_max_radps_;
}
static constexpr double kMinGravity = 9.0;
static constexpr double kMaxGravity = 10.0;
static constexpr double kMinSaturationAccelMax = 0.0;
static constexpr double kMinSaturationGyroMax = 0.0;
private:
void initializeDefault();
bool loadFromYamlNodeImpl(const YAML::Node& sensor_node);
void saveToYamlNodeImpl(YAML::Node* sensor_node) const;
bool isValidImpl() const override {
return (
sigmas_.isValid() && gravity_magnitude_ >= kMinGravity &&
gravity_magnitude_ <= kMaxGravity &&
saturation_accel_max_ >= kMinSaturationAccelMax &&
saturation_gyro_max_radps_ >= kMinSaturationGyroMax);
}
void setRandomImpl() override;
bool isEqualImpl(const Sensor& other, const bool verbose) const override {
const Imu* other_imu = dynamic_cast<const Imu*>(&other);
if (other_imu == nullptr) {
LOG_IF(WARNING, verbose) << "Other sensor is not an IMU!";
return false;
}
const double kPrecision = 1e-6;
bool is_equal =
std::abs(gravity_magnitude_ - other_imu->gravity_magnitude_) <
kPrecision &&
std::abs(saturation_accel_max_ - other_imu->saturation_accel_max_) <
kPrecision &&
std::abs(
saturation_gyro_max_radps_ -
other_imu->saturation_gyro_max_radps_) < kPrecision;
if (!is_equal) {
LOG_IF(WARNING, verbose)
<< "this sensor: "
<< "\n gravity_magnitude_: " << gravity_magnitude_
<< "\n saturation_accel_max_: " << saturation_accel_max_
<< "\n saturation_gyro_max_radps_: " << saturation_gyro_max_radps_;
LOG_IF(WARNING, verbose)
<< "other sensor: "
<< "\n gravity_magnitude_: " << other_imu->gravity_magnitude_
<< "\n saturation_accel_max_: " << other_imu->saturation_accel_max_
<< "\n saturation_gyro_max_radps_: "
<< other_imu->saturation_gyro_max_radps_;
}
is_equal &= sigmas_.isEqual(other_imu->sigmas_, verbose);
return is_equal;
}
ImuSigmas sigmas_;
double gravity_magnitude_;
double saturation_accel_max_;
double saturation_gyro_max_radps_;
};
class ImuMeasurement final : public Measurement {
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
typedef Eigen::Matrix<double, 6, 1> CombinedImuData;
ImuMeasurement()
: I_accel_xyz_m_s2_gyro_xyz_rad_s_(CombinedImuData::Zero()) {}
explicit ImuMeasurement(
const aslam::SensorId& sensor_id, const int64_t timestamp_nanoseconds,
const CombinedImuData& I_accel_m_s2_gyro_rad_s)
: Measurement(sensor_id, timestamp_nanoseconds),
I_accel_xyz_m_s2_gyro_xyz_rad_s_(I_accel_m_s2_gyro_rad_s) {
CHECK(isValid());
}
explicit ImuMeasurement(
const aslam::SensorId& sensor_id, const int64_t timestamp_nanoseconds,
const Eigen::Vector3d& I_accel_xyz_m_s2,
const Eigen::Vector3d& I_gyro_xyz_rad_s)
: Measurement(sensor_id, timestamp_nanoseconds) {
I_accel_xyz_m_s2_gyro_xyz_rad_s_.topRows(3) = I_accel_xyz_m_s2;
I_accel_xyz_m_s2_gyro_xyz_rad_s_.bottomRows(3) = I_gyro_xyz_rad_s;
CHECK(isValid());
}
bool operator==(const ImuMeasurement& other) const {
return Measurement::operator==(other) &&
I_accel_xyz_m_s2_gyro_xyz_rad_s_ ==
other.get_I_Accel_m_s2_Gyro_rad_s();
}
const CombinedImuData& get_I_Accel_m_s2_Gyro_rad_s() const {
return I_accel_xyz_m_s2_gyro_xyz_rad_s_;
}
Eigen::Map<const Eigen::Vector3d> get_I_Accel_xyz_m_s2() const {
return Eigen::Map<const Eigen::Vector3d>(
I_accel_xyz_m_s2_gyro_xyz_rad_s_.data(), 3);
}
Eigen::Map<const Eigen::Vector3d> get_I_Gyro_xyz_rad_s() const {
return Eigen::Map<const Eigen::Vector3d>(
I_accel_xyz_m_s2_gyro_xyz_rad_s_.data() + 3, 3);
}
private:
explicit ImuMeasurement(const aslam::SensorId& sensor_id)
: Measurement(sensor_id),
I_accel_xyz_m_s2_gyro_xyz_rad_s_(CombinedImuData::Zero()) {}
bool isValidImpl() const override {
return true;
}
void setRandomImpl() override;
CombinedImuData I_accel_xyz_m_s2_gyro_xyz_rad_s_;
};
DEFINE_MEAUREMENT_CONTAINERS(ImuMeasurement)
} // namespace vi_map
DEFINE_MEASUREMENT_HASH(ImuMeasurement)
namespace YAML {
template <>
struct convert<vi_map::ImuSigmas> {
static bool decode(const Node& node, vi_map::ImuSigmas& camera); // NOLINT
static Node encode(const vi_map::ImuSigmas& camera);
};
} // namespace YAML
namespace common {
template <>
void linearInterpolation<int64_t, vi_map::ImuMeasurement>(
const int64_t t1, const vi_map::ImuMeasurement& x1, const int64_t t2,
const vi_map::ImuMeasurement& x2, const int64_t t_interpolated,
vi_map::ImuMeasurement* x_interpolated);
} // namespace common
#endif // SENSORS_IMU_H_