My Project 1.0
Holistic Fusion: A Generic Framework for Multimodal Sensor Fusion
Loading...
Searching...
No Matches
GmsfUnaryExpressionLocalVelocity3.h
Go to the documentation of this file.
1/*
2Copyright 2024 by Julian Nubert, Robotic Systems Lab, ETH Zurich.
3All rights reserved.
4This file is released under the "BSD-3-Clause License".
5Please see the LICENSE file that has been included as part of this package.
6 */
7
8#ifndef GMSF_UNARY_EXPRESSION_VELOCITY3_LOCAL_H
9#define GMSF_UNARY_EXPRESSION_VELOCITY3_LOCAL_H
10
11// GTSAM
12#include <gtsam/base/types.h>
13#include <gtsam/inference/Symbol.h>
14#include <gtsam/navigation/ImuBias.h>
15#include <gtsam/slam/expressions.h>
16
17// Workspace
21
22namespace holistic_fusion {
23
24class GmsfUnaryExpressionLocalVelocity3 final : public GmsfUnaryExpressionLocal<gtsam::Point3, 'd'> {
25 public:
26 // Constructor
27 GmsfUnaryExpressionLocalVelocity3(const std::shared_ptr<UnaryMeasurementXD<Eigen::Vector3d, 3>>& velocityUnaryMeasurementPtr,
28 const std::string& imuFrameName, const Eigen::Isometry3d& T_I_sensorFrame,
29 const std::shared_ptr<holistic_fusion::ImuBuffer> imuBufferPtr)
30 : GmsfUnaryExpressionLocal(velocityUnaryMeasurementPtr, imuFrameName, T_I_sensorFrame),
31 velocityUnaryMeasurementPtr_(velocityUnaryMeasurementPtr),
32 exp_sensorFrame_v_fixedFrame_sensorFrame_(gtsam::Point3::Zero()),
33 exp_R_fixedFrame_I_(gtsam::Rot3::Identity()),
34 exp_I_w_W_I_(gtsam::Point3(gtsam::Point3::Zero())) {
35 // Find Angular Velocity in IMU Buffer which is closest to the measurement time
36 // Check whether we can find an IMU measurement corresponding to the velocity measurement
37 double imuTimestamp;
40 imuBufferPtr->getClosestImuMeasurement(imuTimestamp, imuMeasurement, 0.1, velocityUnaryMeasurementPtr->timeK()); // previously 0.02
42 REGULAR_COUT << RED_START << " No IMU Measurement (in time interval) found, assuming 0 angular velocity for the factor." << COLOR_END
43 << std::endl;
44 }
45
46 // Angular Velocity
47 angularVelocity_ = imuMeasurement.angularVelocity;
48 }
49
50 // Constructor with explicitly provided angular velocity (IMU frame), for callers that already hold
51 // the IMU sample consistent with the measurement (e.g. from a synchronized sensor tuple). Skips the
52 // IMU buffer lookup; the lever-arm term is always corrected by the estimated gyroscope bias.
53 GmsfUnaryExpressionLocalVelocity3(const std::shared_ptr<UnaryMeasurementXD<Eigen::Vector3d, 3>>& velocityUnaryMeasurementPtr,
54 const std::string& imuFrameName, const Eigen::Isometry3d& T_I_sensorFrame,
55 const Eigen::Vector3d& angularVelocity)
56 : GmsfUnaryExpressionLocal(velocityUnaryMeasurementPtr, imuFrameName, T_I_sensorFrame),
57 velocityUnaryMeasurementPtr_(velocityUnaryMeasurementPtr),
58 angularVelocity_(angularVelocity),
60 exp_sensorFrame_v_fixedFrame_sensorFrame_(gtsam::Point3::Zero()),
61 exp_R_fixedFrame_I_(gtsam::Rot3::Identity()),
62 exp_I_w_W_I_(gtsam::Point3(gtsam::Point3::Zero())) {}
63
64 // Destructor
66
67 // Noise as GTSAM Datatype
68 [[nodiscard]] const gtsam::Vector getNoiseDensity() const override {
69 return velocityUnaryMeasurementPtr_->unaryMeasurementNoiseDensity();
70 }
71
72 // Return Measurement as GTSAM Datatype
73 [[nodiscard]] const gtsam::Point3 getGtsamMeasurementValue() const override {
74 return gtsam::Point3(velocityUnaryMeasurementPtr_->unaryMeasurement().matrix());
75 }
76
77 protected:
78 // i) Generate Expression for Basic IMU State in World Frame at Key
79 void generateImuStateInWorldFrameAtKey(const gtsam::Key& closestGeneralKey) override {
80 // Translation (core part)
81 gtsam::Point3_ exp_fixedFrame_v_fixedFrame_sensorFrame_ =
82 gtsam::Expression<gtsam::Vector3>(gtsam::symbol_shorthand::V(closestGeneralKey)); // W_v_W_I at this point
83
84 // Rotation (needed for the transformation to the sensor frame)
86 gtsam::rotation(gtsam::Expression<gtsam::Pose3>(gtsam::symbol_shorthand::X(closestGeneralKey))); // R_W_I at this point
87
88 // Express velocity in sensor frame
90 gtsam::rotate(inverseRot3(exp_R_fixedFrame_I_), exp_fixedFrame_v_fixedFrame_sensorFrame_); // I_v_W_I at this point
91
92 // Angular velocity corrected by the estimated gyroscope bias --> makes the bias observable
93 // through the lever-arm term in transformImuStateToSensorFrameState()
95 const gtsam::Expression<gtsam::imuBias::ConstantBias> exp_imuBias(gtsam::symbol_shorthand::B(closestGeneralKey));
96 exp_I_w_W_I_ = gtsam::Point3_(exp_imuBias, &gtsam::imuBias::ConstantBias::correctGyroscope, gtsam::Point3_(angularVelocity_));
97 } else {
98 // No gyro sample --> keep the assumed zero angular velocity; subtracting the bias from it
99 // would inject a spurious -bias x leverArm term
100 exp_I_w_W_I_ = gtsam::Point3_(angularVelocity_);
101 }
102 }
103
104 // iii) Transform Measurement to Core Imu Frame
106 // Get relative translation
107 Eigen::Vector3d I_t_I_sensorFrame = T_I_sensorFrameInit_.translation();
108
109 // Compute Velocity of the Sensor Frame with (bias-corrected) Angular Velocity
111 exp_sensorFrame_v_fixedFrame_sensorFrame_ + gtsam::cross(exp_I_w_W_I_, I_t_I_sensorFrame); // I_v_W_sensorFrame at this point
112
113 // Get Rotation from Sensor Frame to Inertial Frame
114 gtsam::Rot3 R_sensorFrame_I = gtsam::Rot3(T_I_sensorFrameInit_.rotation().inverse());
115
116 // Convert to Sensor Frame
118 gtsam::rotate(R_sensorFrame_I, exp_sensorFrame_v_fixedFrame_sensorFrame_); // sensorFrame_v_fixedFrame_sensorFrame
119 }
120
121 // iv) Extrinsic Calibration
122 void applyExtrinsicCalibrationCorrection(const gtsam::Point3_& exp_correction) final {
123 // TODO: Implement
124 // REGULAR_COUT << RED_START << "GmsfUnaryExpressionVelocity3SensorFrame: Extrinsic Calibration not implemented yet." << COLOR_END
125 // << std::endl;
126 }
127
128 gtsam::Pose3 convertToPose3(const gtsam::Point3& measurement) final { return gtsam::Pose3(gtsam::Rot3::Identity(), measurement); }
129
130 gtsam::Point3 convertFromPose3(const gtsam::Pose3& pose) final { return pose.translation(); }
131
132 // Return Expression
133 [[nodiscard]] const gtsam::Expression<gtsam::Point3> getGtsamExpression() const override {
135 }
136
137 private:
138 // Full Measurement Type
139 std::shared_ptr<UnaryMeasurementXD<Eigen::Vector3d, 3>> velocityUnaryMeasurementPtr_;
140
141 // Angular Velocity
142 gtsam::Point3 angularVelocity_; // Angular Velocity
144
145 // Expression
146 gtsam::Expression<gtsam::Point3> exp_sensorFrame_v_fixedFrame_sensorFrame_; // Translation
147 gtsam::Expression<gtsam::Rot3> exp_R_fixedFrame_I_; // Rotation
148 gtsam::Expression<gtsam::Point3> exp_I_w_W_I_; // Bias-corrected Angular Velocity
149};
150} // namespace holistic_fusion
151
152#endif // GMSF_UNARY_EXPRESSION_VELOCITY3_LOCAL_H
#define REGULAR_COUT
#define COLOR_END
#define RED_START
gtsam::Pose3 convertToPose3(const gtsam::Point3 &measurement) final
gtsam::Point3 convertFromPose3(const gtsam::Pose3 &pose) final
void applyExtrinsicCalibrationCorrection(const gtsam::Point3_ &exp_correction) final
const gtsam::Expression< gtsam::Point3 > getGtsamExpression() const override
std::shared_ptr< UnaryMeasurementXD< Eigen::Vector3d, 3 > > velocityUnaryMeasurementPtr_
GmsfUnaryExpressionLocalVelocity3(const std::shared_ptr< UnaryMeasurementXD< Eigen::Vector3d, 3 > > &velocityUnaryMeasurementPtr, const std::string &imuFrameName, const Eigen::Isometry3d &T_I_sensorFrame, const std::shared_ptr< holistic_fusion::ImuBuffer > imuBufferPtr)
void generateImuStateInWorldFrameAtKey(const gtsam::Key &closestGeneralKey) override
GmsfUnaryExpressionLocalVelocity3(const std::shared_ptr< UnaryMeasurementXD< Eigen::Vector3d, 3 > > &velocityUnaryMeasurementPtr, const std::string &imuFrameName, const Eigen::Isometry3d &T_I_sensorFrame, const Eigen::Vector3d &angularVelocity)
GmsfUnaryExpressionLocal(const std::shared_ptr< UnaryMeasurement > &baseUnaryAbsoluteMeasurementPtr, const std::string &imuFrameName, const Eigen::Isometry3d &T_I_sensorFrame)
Class to represent x-dimensional unary measurement in the graph.
gtsam::Rot3_ inverseRot3(const gtsam::Rot3_ &R)