Calico
A visual-inertial calibration library designed for rapid problem construction and debugging.
gyroscope_models.h
1 #ifndef CALICO_SENSORS_GYROSCOPE_MODELS_H_
2 #define CALICO_SENSORS_GYROSCOPE_MODELS_H_
3 
4 #include "calico/typedefs.h"
5 
6 #include <memory>
7 
8 #include "absl/status/statusor.h"
9 #include "absl/strings/str_cat.h"
10 #include "Eigen/Dense"
11 
12 
13 namespace calico::sensors {
14 
16 enum class GyroscopeIntrinsicsModel : int {
18  kNone,
25 };
26 
29  public:
30  virtual ~GyroscopeModel() = default;
31 
34  template <typename T>
35  absl::StatusOr<Eigen::Vector3<T>> Project(
36  const Eigen::VectorX<T>& intrinsics,
37  const Eigen::Vector3<T>& omega_sensor_world) const;
38 
41  template <typename T>
42  absl::StatusOr<Eigen::Vector3<T>> Unproject(
43  const Eigen::VectorX<T>& intrinsics,
44  const Eigen::Vector3<T>& measurement) const;
45 
47  virtual GyroscopeIntrinsicsModel GetType() const = 0;
48 
50  virtual int NumberOfParameters() const = 0;
51 
52  // TODO(yangjames): This method should return an absl::StatusOr. Figure out
53  // how to support this using unique_ptr's, or find macros that already
54  // implement this feature (i.e. ASSIGN_OR_RETURN).
58  static std::unique_ptr<GyroscopeModel> Create(
59  GyroscopeIntrinsicsModel gyroscope_model);
60 };
61 
62 
66  public:
67  static constexpr int kNumberOfParameters = 1;
69 
70  GyroscopeScaleOnlyModel() = default;
71  ~GyroscopeScaleOnlyModel() override = default;
72  GyroscopeScaleOnlyModel& operator=(const GyroscopeScaleOnlyModel&) = default;
73 
81  template <typename T>
82  static absl::StatusOr<Eigen::Vector3<T>> Project(
83  const Eigen::VectorX<T>& intrinsics,
84  const Eigen::Vector3<T>& omega_sensor_world) {
85  const T& scale = intrinsics(0);
86  return scale * omega_sensor_world;
87  }
88 
94  template <typename T>
95  static absl::StatusOr<Eigen::Vector3<T>> Unproject(
96  const Eigen::VectorX<T>& intrinsics,
97  const Eigen::Vector3<T>& measurement) {
98  const T& inv_scale = static_cast<T>(1.0) / intrinsics(0);
99  return inv_scale * measurement;
100  }
101 
103  return kModelType;
104  }
105 
106  int NumberOfParameters() const final {
107  return kNumberOfParameters;
108  }
109 };
110 
115  public:
116  static constexpr int kNumberOfParameters = 4;
118 
119  GyroscopeScaleAndBiasModel() = default;
120  ~GyroscopeScaleAndBiasModel() override = default;
121  GyroscopeScaleAndBiasModel& operator=(
122  const GyroscopeScaleAndBiasModel&) = default;
123 
129  template <typename T>
130  static absl::StatusOr<Eigen::Vector3<T>> Project(
131  const Eigen::VectorX<T>& intrinsics,
132  const Eigen::Vector3<T>& omega_sensor_world) {
133  if (intrinsics.size() != kNumberOfParameters) {
134  return absl::InvalidArgumentError(absl::StrCat(
135  "Invalid gyroscope intrinsics size. Expected ", kNumberOfParameters,
136  ", got ", intrinsics.size()));
137  }
138  const T& scale = intrinsics(0);
139  const Eigen::Ref<const Eigen::Vector3<T>> bias =
140  intrinsics.segment(1, 3);
141  return scale * omega_sensor_world + bias;
142  }
143 
150  template <typename T>
151  static absl::StatusOr<Eigen::Vector3<T>> Unproject(
152  const Eigen::VectorX<T>& intrinsics,
153  const Eigen::Vector3<T>& measurement) {
154  if (intrinsics.size() != kNumberOfParameters) {
155  return absl::InvalidArgumentError(absl::StrCat(
156  "Invalid gyroscope intrinsics size. Expected ", kNumberOfParameters,
157  ", got ", intrinsics.size()));
158  }
159  const T& inv_scale = static_cast<T>(1.0) / intrinsics(0);
160  const Eigen::Ref<const Eigen::Vector3<T>> bias =
161  intrinsics.segment(1, 3);
162  return inv_scale * (measurement - bias);
163  }
164 
166  return kModelType;
167  }
168 
169  int NumberOfParameters() const final {
170  return kNumberOfParameters;
171  }
172 };
173 
174 
181  public:
182  static constexpr int kNumberOfParameters = 12;
184 
185  GyroscopeVectorNavModel() = default;
186  ~GyroscopeVectorNavModel() override = default;
187  GyroscopeVectorNavModel& operator=(
188  const GyroscopeVectorNavModel&) = default;
189 
207  template <typename T>
208  static absl::StatusOr<Eigen::Vector3<T>> Project(
209  const Eigen::VectorX<T>& intrinsics,
210  const Eigen::Vector3<T>& omega_sensor_world) {
211  if (intrinsics.size() != kNumberOfParameters) {
212  return absl::InvalidArgumentError(absl::StrCat(
213  "Invalid gyroscope intrinsics size. Expected ", kNumberOfParameters,
214  ", got ", intrinsics.size()));
215  }
216  const T& sx = intrinsics(0);
217  const T& sy = intrinsics(1);
218  const T& sz = intrinsics(2);
219  const T& a1 = intrinsics(3);
220  const T& a2 = intrinsics(4);
221  const T& a3 = intrinsics(5);
222  const T& a4 = intrinsics(6);
223  const T& a5 = intrinsics(7);
224  const T& a6 = intrinsics(8);
225  const T& bx = intrinsics(9);
226  const T& by = intrinsics(10);
227  const T& bz = intrinsics(11);
228  const T& wx = omega_sensor_world.x();
229  const T& wy = omega_sensor_world.y();
230  const T& wz = omega_sensor_world.z();
231  const T fx = bx + sx * (wx + a1 * wy + a2 * wz);
232  const T fy = by + sy * (wy + a3 * wx + a4 * wz);
233  const T fz = bz + sz * (wz + a5 * wx + a6 * wy);
234  return Eigen::Vector3<T>(fx, fy, fz);
235  }
236 
255  template <typename T>
256  static absl::StatusOr<Eigen::Vector3<T>> Unproject(
257  const Eigen::VectorX<T>& intrinsics,
258  const Eigen::Vector3<T>& measurement) {
259  if (intrinsics.size() != kNumberOfParameters) {
260  return absl::InvalidArgumentError(absl::StrCat(
261  "Invalid gyroscope intrinsics size. Expected ", kNumberOfParameters,
262  ", got ", intrinsics.size()));
263  }
264  const T& sx = intrinsics(0);
265  const T& sy = intrinsics(1);
266  const T& sz = intrinsics(2);
267  const T& a1 = intrinsics(3);
268  const T& a2 = intrinsics(4);
269  const T& a3 = intrinsics(5);
270  const T& a4 = intrinsics(6);
271  const T& a5 = intrinsics(7);
272  const T& a6 = intrinsics(8);
273  const T& fx = measurement.x();
274  const T& fy = measurement.y();
275  const T& fz = measurement.z();
276  const Eigen::Vector3<T> bias(intrinsics(9), intrinsics(10), intrinsics(11));
277  const Eigen::Vector3<T> d = bias - measurement;
278  const T det_A =
279  1.0 - a1*a3 - a2*a5 - a4*a6 + a1*a4*a5 + a2*a3*a6;
280  const T dx_inv_sx_detA = d.x() / (sx * det_A);
281  const T dy_inv_sy_detA = d.y() / (sy * det_A);
282  const T dz_inv_sz_detA = d.z() / (sz * det_A);
283  const T wx = (a4*a6 - 1) * dx_inv_sx_detA + (a1 - a2*a6) * dy_inv_sy_detA +
284  (a2 - a1*a4) * dz_inv_sz_detA;
285  const T wy = (a2*a5 - 1) * dy_inv_sy_detA + (a3 - a4*a5) * dx_inv_sx_detA +
286  (a4 - a2*a3) * dz_inv_sz_detA;
287  const T wz = (a1*a3 - 1) * dz_inv_sz_detA + (a5 - a3*a6) * dx_inv_sx_detA +
288  (a6 - a1*a5) * dy_inv_sy_detA;
289  return Eigen::Vector3<T>(wx, wy, wz);
290  }
291 
293  return kModelType;
294  }
295 
296  int NumberOfParameters() const final {
297  return kNumberOfParameters;
298  }
299 };
300 
301 
302 
303 template <typename T>
304 absl::StatusOr<Eigen::Vector3<T>> GyroscopeModel::Project(
305  const Eigen::VectorX<T>& intrinsics,
306  const Eigen::Vector3<T>& omega_sensor_world) const {
307  if (const auto derived = dynamic_cast<const GyroscopeScaleOnlyModel*>(this)) {
308  return derived->Project(intrinsics, omega_sensor_world);
309  }
310  if (const auto derived =
311  dynamic_cast<const GyroscopeScaleAndBiasModel*>(this)) {
312  return derived->Project(intrinsics, omega_sensor_world);
313  }
314  if (const auto derived =
315  dynamic_cast<const GyroscopeVectorNavModel*>(this)) {
316  return derived->Project(intrinsics, omega_sensor_world);
317  }
318  return absl::InvalidArgumentError(absl::StrCat(
319  "Project for gyroscope model ", this->GetType(), " not supported."));
320 }
321 
322 template <typename T>
323 absl::StatusOr<Eigen::Vector3<T>> GyroscopeModel::Unproject(
324  const Eigen::VectorX<T>& intrinsics,
325  const Eigen::Vector3<T>& measurement) const {
326  if (const auto derived = dynamic_cast<const GyroscopeScaleOnlyModel*>(this)) {
327  return derived->Unproject(intrinsics, measurement);
328  }
329  if (const auto derived =
330  dynamic_cast<const GyroscopeScaleAndBiasModel*>(this)) {
331  return derived->Unproject(intrinsics, measurement);
332  }
333  if (const auto derived =
334  dynamic_cast<const GyroscopeVectorNavModel*>(this)) {
335  return derived->Unproject(intrinsics, measurement);
336  }
337  return absl::InvalidArgumentError(absl::StrCat(
338  "Unproject for gyroscope model ", this->GetType(), " not supported."));
339 }
340 
341 } // namespace calico::sensors
342 
343 #endif // CALICO_SENSORS_GYROSCOPE_MODELS_H_
Base class for gyroscope models.
Definition: gyroscope_models.h:28
absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &omega_sensor_world) const
Definition: gyroscope_models.h:304
virtual int NumberOfParameters() const =0
Getter for the number of parameters for this model.
absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement) const
Definition: gyroscope_models.h:323
virtual GyroscopeIntrinsicsModel GetType() const =0
Getter for gyroscope model type.
static std::unique_ptr< GyroscopeModel > Create(GyroscopeIntrinsicsModel gyroscope_model)
Definition: gyroscope_models.cpp:5
Definition: gyroscope_models.h:114
static absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &omega_sensor_world)
Definition: gyroscope_models.h:130
GyroscopeIntrinsicsModel GetType() const final
Getter for gyroscope model type.
Definition: gyroscope_models.h:165
static absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement)
Definition: gyroscope_models.h:151
int NumberOfParameters() const final
Getter for the number of parameters for this model.
Definition: gyroscope_models.h:169
Definition: gyroscope_models.h:65
GyroscopeIntrinsicsModel GetType() const final
Getter for gyroscope model type.
Definition: gyroscope_models.h:102
static absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &omega_sensor_world)
Definition: gyroscope_models.h:82
int NumberOfParameters() const final
Getter for the number of parameters for this model.
Definition: gyroscope_models.h:106
static absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement)
Definition: gyroscope_models.h:95
Definition: gyroscope_models.h:180
static absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement)
Definition: gyroscope_models.h:256
GyroscopeIntrinsicsModel GetType() const final
Getter for gyroscope model type.
Definition: gyroscope_models.h:292
int NumberOfParameters() const final
Getter for the number of parameters for this model.
Definition: gyroscope_models.h:296
static absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &omega_sensor_world)
Definition: gyroscope_models.h:208
Sensors namespace.
Definition: accelerometer.cpp:8
GyroscopeIntrinsicsModel
Gyroscope model types.
Definition: gyroscope_models.h:16
@ kGyroscopeScaleOnly
Isotropic scale without bias.
@ kGyroscopeScaleAndBias
Isotropic scale with bias.