···66 * @author Mateo de Mayo <mateo.demayo@collabora.com>
77 * @ingroup aux_tracking
88 *
99- * This header file contains the declaration of the @ref slam_tracker class to
1010- * implement a SLAM system for usage in Monado.
1111- *
1212- * A copy of this file is present in both Monado and any SLAM system that
1313- * intends to be used by Monado. The SLAM system should provide the
1414- * `slam_tracker` implementation so that Monado can use it.
1515- *
1616- * This file also declares additional data types to be used between Monado and
99+ * This file contains the declaration of the @ref slam_tracker class. This
1010+ * header is intended to appear in both Monado and an external SLAM system. The
1111+ * implementation of `slam_tracker` is provided by the external system.
1212+ * Additional data types are declared for the communication between Monado and
1713 * the system.
1814 *
1919- * @todo The interface is preliminary and should be improved to avoid
2020- * unnecessary copies.
2115 */
22162317#pragma once
24182519#include <opencv2/core/mat.hpp>
2020+2121+#include <cstdint>
2222+#include <memory>
2323+#include <string>
2424+#include <vector>
26252726namespace xrt::auxiliary::tracking::slam {
2827···4140 * @brief IMU Sample type to pass around between programs
4241 */
4342struct imu_sample {
4444- std::int64_t timestamp; // In nanoseconds
4545- double ax, ay, az; // In meters per second squared (m / s^2)
4646- double wx, wy, wz; // In radians per second (rad / s)
4343+ std::int64_t timestamp; //!< In nanoseconds
4444+ double ax, ay, az; //!< Accel in meters per second squared (m / s^2)
4545+ double wx, wy, wz; //!< Gyro in radians per second (rad / s)
4746 imu_sample() = default;
4847 imu_sample(std::int64_t timestamp, double ax, double ay, double az, double wx,
4948 double wy, double wz)
···5958 cv::Mat img;
6059 bool is_left;
6160 img_sample() = default;
6262- img_sample(std::int64_t timestamp, cv::Mat img, bool is_left)
6161+ img_sample(std::int64_t timestamp, const cv::Mat &img, bool is_left)
6362 : timestamp(timestamp), img(img), is_left(is_left) {}
6463};
6564···7978 * them up. Therefore, this constructor receives a path to a
8079 * implementation-specific configuration file.
8180 */
8282- slam_tracker(std::string config_file);
8181+ slam_tracker(const std::string &config_file);
8382 ~slam_tracker();
84838584 slam_tracker(const slam_tracker &) = delete;
8685 slam_tracker &operator=(const slam_tracker &) = delete;
87868787+ void initialize();
8888 void start();
8989- void stop();
9089 bool is_running();
9090+ void stop();
9191+ void finalize();
91929292- //! There must be a single producer thread pushing samples.
9393- //! Samples must have monotonically increasing timestamps.
9494- //! The implementation must be non-blocking.
9595- //! A separate consumer thread should process the samples.
9696- void push_imu_sample(imu_sample sample);
9393+ /*!
9494+ * @brief Push an IMU sample into the tracker.
9595+ *
9696+ * There must be a single producer thread pushing samples.
9797+ * Samples must have monotonically increasing timestamps.
9898+ * The implementation must be non-blocking.
9999+ * Thus, a separate consumer thread should process the samples.
100100+ */
101101+ void push_imu_sample(const imu_sample &sample);
971029898- //! Same conditions as `push_imu_sample` apply.
9999- //! When using stereo frames, they must be pushed in a left-right order.
100100- //! The consecutive left-right pair must have the same timestamps.
101101- void push_frame(img_sample sample);
103103+ /*!
104104+ * @brief Push an image sample into the tracker.
105105+ *
106106+ * Same conditions as @ref push_imu_sample apply.
107107+ * When using stereo frames, they must be pushed in a left-right order.
108108+ * The consecutive left-right pair must have the same timestamps.
109109+ */
110110+ void push_frame(const img_sample &sample);
102111103103- //! There must be a single thread accessing the tracked pose.
104104- bool try_dequeue_pose(pose &pose);
112112+ /*!
113113+ * @brief Get the latest tracked pose from the SLAM system.
114114+ *
115115+ * There must be a single thread consuming this method.
116116+ *
117117+ * @param[out] out_pose Dequeued pose.
118118+ * @return true If a new pose was dequeued into @p out_pose.
119119+ * @return false If there was no pose to dequeue.
120120+ */
121121+ bool try_dequeue_pose(pose &out_pose);
122122+123123+ //! Asks the SLAM system whether it supports a specific feature.
124124+ bool supports_feature(int feature_id);
125125+126126+ /*!
127127+ * @brief Use a special feature of the SLAM tracker.
128128+ *
129129+ * This method uses heap allocated objects for passing parameters and
130130+ * obtaining the results. Use `std::static_pointer_cast` to shared pointers to
131131+ * the expected types.
132132+ *
133133+ * @param feature_id Id of the special feature.
134134+ * @param params Pointer to the parameter object for this feature.
135135+ * @param result Pointer to the result produced by the feature call.
136136+ * @return false if the feature was not supported, true otherwise.
137137+ */
138138+ bool use_feature(int feature_id, const std::shared_ptr<void> ¶ms,
139139+ std::shared_ptr<void> &result);
105140106106- private:
141141+private:
107142 struct implementation;
108108- implementation *impl;
143143+ std::unique_ptr<implementation> impl;
144144+};
145145+146146+/*
147147+ * Special features
148148+ *
149149+ * A special feature is comprised of an ID, a PARAMS type and a RESULT type. It
150150+ * can be defined using DEFINE_FEATURE. Once defined, the definition should not
151151+ * suffer future changes.
152152+ *
153153+ * One of the main concerns in the features interface is the ability to add new
154154+ * features without being required to update the SLAM systems that are not
155155+ * interested in implementing the feature.
156156+ *
157157+ */
158158+159159+#define DEFINE_FEATURE(NAME, SHORT_NAME, ID, PARAMS_TYPE, RESULT_TYPE) \
160160+ using FPARAMS_##SHORT_NAME = PARAMS_TYPE; \
161161+ using FRESULT_##SHORT_NAME = RESULT_TYPE; \
162162+ constexpr int FID_##SHORT_NAME = ID; \
163163+ constexpr int F_##NAME = ID;
164164+165165+struct cam_calibration {
166166+ enum class cam_model { pinhole, fisheye };
167167+168168+ int cam_index; //!< For multi-camera setups. For stereo 0 ~ left, 1 ~ right.
169169+ int width, height; //<! Resolution
170170+ double frequency; //<! Frames per second
171171+ double fx, fy; //<! Focal point
172172+ double cx, cy; //<! Principal point
173173+ cam_model model;
174174+ std::vector<double> model_params;
175175+ cv::Matx<double, 4, 4> T_cam_imu; //!< Transformation from camera to imu space
176176+};
177177+178178+struct inertial_calibration {
179179+ // Calibration intrinsics to apply to each raw measurement.
180180+181181+ //! This transform will be applied to raw measurements.
182182+ cv::Matx<double, 3, 3> transform;
183183+184184+ //! Offset to apply to raw measurements to; called bias in other contexts.
185185+ cv::Matx<double, 3, 1> offset;
186186+187187+ // Parameters for the random processes that model this IMU. See section "2.1
188188+ // Gyro Noise Model" of N. Trawny and S. I. Roumeliotis, "Indirect Kalman
189189+ // Filter for 3D Attitude Estimation". Analogous for accelerometers.
190190+ // http://mars.cs.umn.edu/tr/reports/Trawny05b.pdf#page=15
191191+192192+ //! IMU internal bias ~ wiener process with steps N(0, σ²); this field is σ;
193193+ //! [σ] = U / sqrt(sec³) with U = rad if gyroscope, U = m/s if accelerometer.
194194+ cv::Matx<double, 3, 1> bias_std;
195195+196196+ //! IMU measurement noise ~ N(0, σ²); this field is σ.
197197+ //! [σ] = U / sqrt(sec) with U = rad if gyroscope, U = m/s if accelerometer.
198198+ cv::Matx<double, 3, 1> noise_std;
199199+200200+ inertial_calibration() : transform(cv::Matx<double, 3, 3>::eye()) {}
201201+};
202202+203203+struct imu_calibration {
204204+ int imu_index; //!< For multi-imu setups. Usually just 0.
205205+ double frequency; //!< Samples per second
206206+ inertial_calibration accel;
207207+ inertial_calibration gyro;
109208};
110209111111-} // namespace xrt::auxiliary::tracking::slam
210210+/*!
211211+ * Feature ADD_CAMERA_CALIBRATION
212212+ *
213213+ * Use it after constructor but before `start()` to write or overwrite camera
214214+ * calibration data that might come from the system-specific config file.
215215+ */
216216+DEFINE_FEATURE(ADD_CAMERA_CALIBRATION, ACC, 1, cam_calibration, void)
217217+218218+/*!
219219+ * Feature ADD_IMU_CALIBRATION
220220+ *
221221+ * Use it after constructor but before `start()` to write or overwrite IMU
222222+ * calibration data that might come from the system-specific config file.
223223+ */
224224+DEFINE_FEATURE(ADD_IMU_CALIBRATION, AIC, 2, imu_calibration, void)
225225+226226+} // namespace xrt::auxiliary::tracking::slam