Calico
A visual-inertial calibration library designed for rapid problem construction and debugging.
accelerometer_models.h
1 #ifndef CALICO_SENSORS_ACCELEROMETER_MODELS_H_
2 #define CALICO_SENSORS_ACCELEROMETER_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 AccelerometerIntrinsicsModel : int {
18  kNone,
25 };
26 
29  public:
30  virtual ~AccelerometerModel() = default;
31 
34  template <typename T>
35  absl::StatusOr<Eigen::Vector3<T>> Project(
36  const Eigen::VectorX<T>& intrinsics,
37  const Eigen::Vector3<T>& p_sensor_world_sensor) 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 
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<AccelerometerModel> Create(
59  AccelerometerIntrinsicsModel accelerometer_model);
60 };
61 
65  public:
66  static constexpr int kNumberOfParameters = 1;
67  static constexpr AccelerometerIntrinsicsModel kModelType =
69 
70  AccelerometerScaleOnlyModel() = default;
71  ~AccelerometerScaleOnlyModel() override = default;
72  AccelerometerScaleOnlyModel& operator=(
73  const AccelerometerScaleOnlyModel&) = default;
74 
79  template <typename T>
80  static absl::StatusOr<Eigen::Vector3<T>> Project(
81  const Eigen::VectorX<T>& intrinsics,
82  const Eigen::Vector3<T>& p_sensor_world_sensor) {
83  const T& scale = intrinsics(0);
84  return scale * p_sensor_world_sensor;
85  }
86 
92  template <typename T>
93  static absl::StatusOr<Eigen::Vector3<T>> Unproject(
94  const Eigen::VectorX<T>& intrinsics,
95  const Eigen::Vector3<T>& measurement) {
96  const T& inv_scale = static_cast<T>(1.0) / intrinsics(0);
97  return inv_scale * measurement;
98  }
99 
101  return kModelType;
102  }
103 
104  int NumberOfParameters() const final {
105  return kNumberOfParameters;
106  }
107 };
108 
113  public:
114  static constexpr int kNumberOfParameters = 4;
115  static constexpr AccelerometerIntrinsicsModel kModelType =
117 
118  AccelerometerScaleAndBiasModel() = default;
119  ~AccelerometerScaleAndBiasModel() override = default;
121  const AccelerometerScaleAndBiasModel&) = default;
122 
128  template <typename T>
129  static absl::StatusOr<Eigen::Vector3<T>> Project(
130  const Eigen::VectorX<T>& intrinsics,
131  const Eigen::Vector3<T>& p_sensor_world_sensor) {
132  if (intrinsics.size() != kNumberOfParameters) {
133  return absl::InvalidArgumentError(absl::StrCat(
134  "Invalid accelerometer intrinsics size. Expected ",
135  kNumberOfParameters, ", got ", intrinsics.size()));
136  }
137  const T& scale = intrinsics(0);
138  const Eigen::Ref<const Eigen::Vector3<T>> bias =
139  intrinsics.segment(1, 3);
140  return scale * p_sensor_world_sensor + bias;
141  }
142 
149  template <typename T>
150  static absl::StatusOr<Eigen::Vector3<T>> Unproject(
151  const Eigen::VectorX<T>& intrinsics,
152  const Eigen::Vector3<T>& measurement) {
153  if (intrinsics.size() != kNumberOfParameters) {
154  return absl::InvalidArgumentError(absl::StrCat(
155  "Invalid accelerometer intrinsics size. Expected ",
156  kNumberOfParameters, ", got ", intrinsics.size()));
157  }
158  const T& inv_scale = static_cast<T>(1.0) / intrinsics(0);
159  const Eigen::Ref<const Eigen::Vector3<T>> bias =
160  intrinsics.segment(1, 3);
161  return inv_scale * (measurement - bias);
162  }
163 
165  return kModelType;
166  }
167 
168  int NumberOfParameters() const final {
169  return kNumberOfParameters;
170  }
171 };
172 
173 
174 
181  public:
182  static constexpr int kNumberOfParameters = 12;
184 
185  AccelerometerVectorNavModel() = default;
186  ~AccelerometerVectorNavModel() override = default;
187  AccelerometerVectorNavModel& operator=(
188  const AccelerometerVectorNavModel&) = 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>& p_sensor_world_sensor) {
211  if (intrinsics.size() != kNumberOfParameters) {
212  return absl::InvalidArgumentError(absl::StrCat(
213  "Invalid accelerometer intrinsics size. Expected ",
214  kNumberOfParameters, ", 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 = p_sensor_world_sensor.x();
229  const T& wy = p_sensor_world_sensor.y();
230  const T& wz = p_sensor_world_sensor.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 accelerometer 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 template <typename T>
302 absl::StatusOr<Eigen::Vector3<T>> AccelerometerModel::Project(
303  const Eigen::VectorX<T>& intrinsics,
304  const Eigen::Vector3<T>& p_sensor_world_sensor) const {
305  if (const auto derived =
306  dynamic_cast<const AccelerometerScaleOnlyModel*>(this)) {
307  return derived->Project(intrinsics, p_sensor_world_sensor);
308  }
309  if (const auto derived =
310  dynamic_cast<const AccelerometerScaleAndBiasModel*>(this)) {
311  return derived->Project(intrinsics, p_sensor_world_sensor);
312  }
313  if (const auto derived =
314  dynamic_cast<const AccelerometerVectorNavModel*>(this)) {
315  return derived->Project(intrinsics, p_sensor_world_sensor);
316  }
317  return absl::InvalidArgumentError(absl::StrCat(
318  "Project for accelerometer model ", this->GetType(), " not supported."));
319 }
320 
321 template <typename T>
322 absl::StatusOr<Eigen::Vector3<T>> AccelerometerModel::Unproject(
323  const Eigen::VectorX<T>& intrinsics,
324  const Eigen::Vector3<T>& measurement) const {
325  if (const auto derived =
326  dynamic_cast<const AccelerometerScaleOnlyModel*>(this)) {
327  return derived->Unproject(intrinsics, measurement);
328  }
329  if (const auto derived =
330  dynamic_cast<const AccelerometerScaleAndBiasModel*>(this)) {
331  return derived->Unproject(intrinsics, measurement);
332  }
333  if (const auto derived =
334  dynamic_cast<const AccelerometerVectorNavModel*>(this)) {
335  return derived->Unproject(intrinsics, measurement);
336  }
337  return absl::InvalidArgumentError(absl::StrCat(
338  "Unproject for accelerometer model ", this->GetType(), " not supported."));
339 }
340 
341 } // namespace calico::sensors
342 
343 #endif // CALICO_SENSORS_ACCELEROMETER_MODELS_H_
Base class for accelerometer models.
Definition: accelerometer_models.h:28
absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &p_sensor_world_sensor) const
Definition: accelerometer_models.h:302
virtual AccelerometerIntrinsicsModel GetType() const =0
Getter for accelerometer model type.
static std::unique_ptr< AccelerometerModel > Create(AccelerometerIntrinsicsModel accelerometer_model)
Definition: accelerometer_models.cpp:5
absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement) const
Definition: accelerometer_models.h:322
virtual int NumberOfParameters() const =0
Getter for the number of parameters for this model.
Definition: accelerometer_models.h:112
AccelerometerIntrinsicsModel GetType() const final
Getter for accelerometer model type.
Definition: accelerometer_models.h:164
int NumberOfParameters() const final
Getter for the number of parameters for this model.
Definition: accelerometer_models.h:168
static absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement)
Definition: accelerometer_models.h:150
static absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &p_sensor_world_sensor)
Definition: accelerometer_models.h:129
Definition: accelerometer_models.h:64
static absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &p_sensor_world_sensor)
Definition: accelerometer_models.h:80
AccelerometerIntrinsicsModel GetType() const final
Getter for accelerometer model type.
Definition: accelerometer_models.h:100
static absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement)
Definition: accelerometer_models.h:93
int NumberOfParameters() const final
Getter for the number of parameters for this model.
Definition: accelerometer_models.h:104
Definition: accelerometer_models.h:180
static absl::StatusOr< Eigen::Vector3< T > > Unproject(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &measurement)
Definition: accelerometer_models.h:256
AccelerometerIntrinsicsModel GetType() const final
Getter for accelerometer model type.
Definition: accelerometer_models.h:292
int NumberOfParameters() const final
Getter for the number of parameters for this model.
Definition: accelerometer_models.h:296
static absl::StatusOr< Eigen::Vector3< T > > Project(const Eigen::VectorX< T > &intrinsics, const Eigen::Vector3< T > &p_sensor_world_sensor)
Definition: accelerometer_models.h:208
Sensors namespace.
Definition: accelerometer.cpp:8
AccelerometerIntrinsicsModel
Accelerometer model types.
Definition: accelerometer_models.h:16
@ kAccelerometerScaleOnly
Isotropic scale without bias.
@ kAccelerometerScaleAndBias
Isotropic scale with bias.