···991010#pragma once
11111212+#include "util/u_logging.h"
1213#include "xrt/xrt_frameserver.h"
13141415#ifdef __cplusplus
···2728 */
28292930/*!
3131+ * Playback configuration for the euroc player.
3232+ *
3333+ * @ingroup drv_euroc
3434+ */
3535+struct euroc_player_playback_config
3636+{
3737+ bool stereo; //!< Whether to stream both left and right sinks or only left
3838+ bool color; //!< If RGB available but this is false, images will be loaded in grayscale
3939+ bool gt; //!< Whether to send groundtruth data (if available) to the SLAM tracker
4040+ bool skip_perc; //!< Whether @ref skip_first represents percentage or seconds
4141+ float skip_first; //!< How much of the first dataset samples to skip, @see skip_perc
4242+ float scale; //!< Scale of each frame; e.g., 0.5 (half), 1.0 (avoids resize)
4343+ bool max_speed; //!< If true, push samples as fast as possible, other wise @see speed
4444+ double speed; //!< Intended reproduction speed if @ref max_speed is false
4545+ bool send_all_imus_first; //!< If enabled all imu samples will be sent before img samples
4646+ bool paused; //!< Whether to pause the playback
4747+ bool use_source_ts; //!< If true, use the original timestamps from the dataset
4848+ bool play_from_start; //!< If set, the euroc player does not wait for user input to start
4949+ bool print_progress; //!< Whether to print progress to stdout (useful for CLI runs)
5050+};
5151+5252+/*!
5353+ * Describes information about a particular EuRoC dataset residing in @ref path.
5454+ *
5555+ * @ingroup drv_euroc
5656+ */
5757+struct euroc_player_dataset_info
5858+{
5959+ char path[256];
6060+ bool is_stereo;
6161+ bool is_colored;
6262+ bool has_gt; //!< Whether this dataset has groundtruth data available
6363+ const char *gt_device_name;
6464+ uint32_t width;
6565+ uint32_t height;
6666+};
6767+6868+/*!
6969+ * Configuration for the euroc player.
7070+ *
7171+ * @ingroup drv_euroc
7272+ */
7373+struct euroc_player_config
7474+{
7575+ enum u_logging_level log_level;
7676+ struct euroc_player_dataset_info dataset;
7777+ struct euroc_player_playback_config playback;
7878+};
7979+8080+/*!
8181+ * Fills in an @ref euroc_player_config with defaults based on the provided dataset path.
8282+ *
8383+ * @ingroup drv_euroc
8484+ */
8585+void
8686+euroc_player_fill_default_config_for(struct euroc_player_config *config, const char *path);
8787+8888+/*!
3089 * Create an euroc player from a path to a dataset.
3190 *
3291 * @ingroup drv_euroc
3392 */
3493struct xrt_fs *
3535-euroc_player_create(struct xrt_frame_context *xfctx, const char *path);
9494+euroc_player_create(struct xrt_frame_context *xfctx, const char *path, struct euroc_player_config *config);
36953796/*!
3897 * Create a auto prober for the fake euroc device.
+114-94
src/xrt/drivers/euroc/euroc_player.cpp
···1919#include "math/m_filter_fifo.h"
20202121#include "euroc_driver.h"
2222+#include "euroc_interface.h"
22232324#include <algorithm>
2425#include <chrono>
2626+#include <cstring>
2527#include <stdio.h>
2628#include <fstream>
2729#include <future>
2830#include <thread>
29313030-DEBUG_GET_ONCE_OPTION(euroc_gt_device_name, "EUROC_GT_DEVICE_NAME", NULL)
3131-DEBUG_GET_ONCE_OPTION(euroc_skip_first, "EUROC_SKIP_FIRST", "0%")
3232-DEBUG_GET_ONCE_BOOL_OPTION(euroc_play_from_start, "EUROC_PLAY_FROM_START", false)
3333-DEBUG_GET_ONCE_BOOL_OPTION(euroc_use_source_ts, "EUROC_USE_SOURCE_TS", false)
3434-DEBUG_GET_ONCE_BOOL_OPTION(euroc_print_progress, "EUROC_PRINT_PROGRESS", false)
3535-DEBUG_GET_ONCE_BOOL_OPTION(euroc_max_speed, "EUROC_MAX_SPEED", false)
3636-DEBUG_GET_ONCE_FLOAT_OPTION(euroc_playback_speed, "EUROC_PLAYBACK_SPEED", 1.0)
3232+//! @see euroc_player_playback_config
3333+DEBUG_GET_ONCE_OPTION(gt_device_name, "EUROC_GT_DEVICE_NAME", nullptr)
3434+DEBUG_GET_ONCE_OPTION(stereo, "EUROC_STEREO", nullptr)
3535+DEBUG_GET_ONCE_OPTION(color, "EUROC_COLOR", nullptr)
3636+DEBUG_GET_ONCE_OPTION(gt, "EUROC_GT", nullptr)
3737+DEBUG_GET_ONCE_OPTION(skip_first, "EUROC_SKIP_FIRST", "0%")
3838+DEBUG_GET_ONCE_FLOAT_OPTION(scale, "EUROC_SCALE", 1.0f)
3939+DEBUG_GET_ONCE_BOOL_OPTION(max_speed, "EUROC_MAX_SPEED", false)
4040+DEBUG_GET_ONCE_FLOAT_OPTION(speed, "EUROC_SPEED", 1.0f)
4141+DEBUG_GET_ONCE_BOOL_OPTION(paused, "EUROC_PAUSED", false)
4242+DEBUG_GET_ONCE_BOOL_OPTION(send_all_imus_first, "EUROC_SEND_ALL_IMUS_FIRST", false)
4343+DEBUG_GET_ONCE_BOOL_OPTION(user_source_ts, "EUROC_USER_SOURCE_TS", false)
4444+DEBUG_GET_ONCE_BOOL_OPTION(play_from_start, "EUROC_PLAY_FROM_START", false)
4545+DEBUG_GET_ONCE_BOOL_OPTION(print_progress, "EUROC_PRINT_PROGRESS", false)
37463847#define EUROC_PLAYER_STR "Euroc Player"
3948#define CLAMP(X, A, B) (MIN(MAX((X), (A)), (B)))
···8291 struct xrt_slam_sinks in_sinks; //!< Pointers to intermediate sinks
8392 struct xrt_slam_sinks out_sinks; //!< Pointers to downstream sinks
84939494+ enum u_logging_level log_level; //!< Log messages with this priority and onwards
9595+ struct euroc_player_dataset_info dataset; //!< Contains information about the source dataset
9696+ struct euroc_player_playback_config playback; //!< Playback information. Prefer to fill it before stream start
9797+ struct xrt_fs_mode mode; //!< The only fs mode the euroc dataset provides
9898+ bool is_running; //!< Set only at start, stop and end of frameserver stream
9999+ timepoint_ns last_pause_ts; //!< Last time the stream was paused
85100 struct os_thread_helper play_thread;
8686- enum u_logging_level log_level;
8787- struct xrt_fs_mode mode; //!< The only fs mode the euroc dataset provides
8888- bool is_running; //!< Set only at start, stop and end of frameserver stream
8989-9090- //! Contains information about the source dataset; set only at start
9191- struct
9292- {
9393- char path[256];
9494- bool is_stereo;
9595- bool is_colored;
9696- bool has_gt; //!< Whether this dataset has groundtruth data available
9797- uint32_t width;
9898- uint32_t height;
9999- } dataset;
100101101102 //! Next frame number to use, index in `left_imgs` and `right_imgs`.
102103 //! Note that this expects that both cameras provide the same amount of frames.
···113114 timepoint_ns start_ts; //!< When did the dataset started to be played
114115 timepoint_ns offset_ts; //!< Amount of ns to offset start_ns (pauses, skips, etc)
115116116116- //! Playback information.
117117- //! Prefer to fill it before starting to push frames. Modifying them on
118118- //! runtime will work with the debug sinks but probably not elsewhere
119119- struct
120120- {
121121- bool stereo; //!< Whether to stream both left and right sinks or only left
122122- bool color; //!< If RGB available but this is false, images will be loaded in grayscale
123123- bool gt; //!< Whether to send groundtruth data (if available) to the SLAM tracker
124124- bool skip_perc; //!< Whether @ref skip_first represents percentage or seconds
125125- float skip_first; //!< How much of the first dataset samples to skip, @see skip_perc
126126- float scale; //!< Scale of each frame; e.g., 0.5 (half), 1.0 (avoids resize)
127127- bool max_speed; //!< If true, push samples as fast as possible, other wise @see speed
128128- double speed; //!< Intended reproduction speed if @ref max_speed is false
129129- bool send_all_imus_first; //!< If enabled all imu samples will be sent before img samples
130130- bool paused; //!< Whether to pause the playback
131131- bool use_source_ts; //!< If true, use the original timestamps from the dataset
132132- } playback;
133133- timepoint_ns last_pause_ts; //!< Last time the stream was paused
134134- bool play_from_start; //!< If set, the euroc player does not way for user input to start
135135- bool print_progress; //!< Whether to print progress to stdout (useful for CLI runs)
136136-137117 // UI related fields
138118 enum euroc_player_ui_state ui_state;
139119 struct u_var_button start_btn;
···187167 return true;
188168}
189169190190-//! Parse and load ground truth trajectory into `trajectory`.
191191-//! If read_n > 0, read at most that amount of samples
192192-//! Returns whether the appropriate data.csv file could be opened
193193-//! @note Groundtruth data can come from different devices so we use the first of:
194194-//! 1. vicon0: found in euroc "vicon room" datasets
195195-//! 2. mocap0: found in TUM-VI datasets with euroc format
196196-//! 3. state_groundtruth_estimate0: found in euroc as a postprocessed ground truth (we only use first 7 columns)
197197-//! 4. leica0: found in euroc "machine hall" datasets, only positional ground truth
198198-//! You can also add your own gt device name with the EUROC_GT_DEVICE_NAME environment variable.
170170+/*!
171171+ * Parse and load ground truth device name and trajectory into `gtdev` and
172172+ * `trajectory` respectively
173173+ *
174174+ * @param[in] dataset_path
175175+ * @param[in, out] gtdev The name of the groundtruth device found in the dataset if any or `nullptr`.
176176+ * Groundtruth data can come from different devices, so we use the first of:
177177+ * 1. The value prespecified in `gtdev`
178178+ * 2. vicon0: found in euroc "vicon room" datasets
179179+ * 3. mocap0: found in TUM-VI datasets with euroc format
180180+ * 4. state_groundtruth_estimate0: found in euroc as a postprocessed ground truth (we only use first 7 columns)
181181+ * 5. leica0: found in euroc "machine hall" datasets, only positional ground truth
182182+ * @param[out] trajectory The read trajectory
183183+ * @param[in] read_n If > 0, read at most that amount of gt poses
184184+ *
185185+ * @returns Whether the appropriate data.csv file could be opened
186186+ */
199187static bool
200200-euroc_player_preload_gt_data(const string &dataset_path, gt_trajectory *trajectory, int64_t read_n = -1)
188188+euroc_player_preload_gt_data(const string &dataset_path,
189189+ const char **gtdev,
190190+ gt_trajectory *trajectory,
191191+ int64_t read_n = -1)
201192{
202202- vector<string> gt_devices = {"vicon0", "mocap0", "state_groundtruth_estimate0", "leica0"};
203203- const char *user_gtdev = debug_get_option_euroc_gt_device_name();
204204- if (user_gtdev) {
205205- gt_devices.insert(gt_devices.begin(), user_gtdev);
193193+ vector<const char *> gt_devices = {"vicon0", "mocap0", "state_groundtruth_estimate0", "leica0"};
194194+ if (*gtdev != nullptr && !string(*gtdev).empty()) {
195195+ gt_devices.insert(gt_devices.begin(), *gtdev);
206196 }
207197208198 ifstream fin;
209209- for (const string &device : gt_devices) {
199199+ for (const char *device : gt_devices) {
210200 string csv_filename = dataset_path + "/mav0/" + device + "/data.csv";
211201 fin = ifstream{csv_filename};
212202 if (fin.is_open()) {
203203+ *gtdev = device;
213204 break;
214205 }
215206 }
···319310320311 if (ep->dataset.has_gt) {
321312 ep->gt->clear();
322322- euroc_player_preload_gt_data(ep->dataset.path, ep->gt);
313313+ euroc_player_preload_gt_data(ep->dataset.path, &ep->dataset.gt_device_name, ep->gt);
323314 }
324315}
325316···355346//! Determine and fill attributes of the dataset pointed by `path`
356347//! Assertion fails if `path` does not point to an euroc dataset
357348static void
358358-euroc_player_fill_dataset_info(struct euroc_player *ep, const char *path)
349349+euroc_player_fill_dataset_info(const char *path, euroc_player_dataset_info *dataset)
359350{
360360- const char *euroc_path = debug_get_option_euroc_path();
361361- EUROC_ASSERT(strcmp(euroc_path, path) == 0, "Unexpected path=%s differs from EUROC_PATH=%s", path, euroc_path);
362362-363363- snprintf(ep->dataset.path, sizeof(ep->dataset.path), "%s", path);
351351+ snprintf(dataset->path, sizeof(dataset->path), "%s", path);
364352 img_samples samples;
365353 imu_samples _1;
366354 gt_trajectory _2;
367367- bool has_right_camera = euroc_player_preload_img_data(ep->dataset.path, &samples, false, 0);
368368- bool has_left_camera = euroc_player_preload_img_data(ep->dataset.path, &samples, true, 1);
369369- bool has_imu = euroc_player_preload_imu_data(ep->dataset.path, &_1, 0);
370370- bool has_gt = euroc_player_preload_gt_data(ep->dataset.path, &_2, 0);
355355+ bool has_right_camera = euroc_player_preload_img_data(dataset->path, &samples, false, 0);
356356+ bool has_left_camera = euroc_player_preload_img_data(dataset->path, &samples, true, 1);
357357+ bool has_imu = euroc_player_preload_imu_data(dataset->path, &_1, 0);
358358+ bool has_gt = euroc_player_preload_gt_data(dataset->path, &dataset->gt_device_name, &_2, 0);
371359 bool is_valid_dataset = has_left_camera && has_imu;
372360 EUROC_ASSERT(is_valid_dataset, "Invalid dataset %s", path);
373361374362 cv::Mat first_left_img = cv::imread(samples[0].second, cv::IMREAD_ANYCOLOR);
375375- ep->dataset.is_stereo = has_right_camera;
376376- ep->dataset.is_colored = first_left_img.channels() == 3;
377377- ep->dataset.has_gt = has_gt;
378378- ep->dataset.width = first_left_img.cols;
379379- ep->dataset.height = first_left_img.rows;
380380- EUROC_INFO(ep, "dataset information\n\tpath: %s\n\tis_stereo: %d, is_colored: %d, width: %d, height: %d",
381381- ep->dataset.path, ep->dataset.is_stereo, ep->dataset.is_colored, ep->dataset.width,
382382- ep->dataset.height);
363363+ dataset->is_stereo = has_right_camera;
364364+ dataset->is_colored = first_left_img.channels() == 3;
365365+ dataset->has_gt = has_gt;
366366+ dataset->width = first_left_img.cols;
367367+ dataset->height = first_left_img.rows;
383368}
384369385370···488473 snprintf(ep->progress_text, sizeof(ep->progress_text), "Frames %lu/%lu - IMUs %lu/%lu", ep->img_seq,
489474 ep->left_imgs->size(), ep->imu_seq, ep->imus->size());
490475491491- if (ep->print_progress) {
476476+ if (ep->playback.print_progress) {
492477 printf("Playback %.2f%% - Frame %lu/%lu\r", float(ep->img_seq) / float(ep->left_imgs->size()) * 100,
493478 ep->img_seq, ep->left_imgs->size());
494479 fflush(stdout);
···731716 if (ep->out_sinks.left == NULL) {
732717 EUROC_WARN(ep, "No left sink provided, will keep running but tracking is unlikely to work");
733718 }
734734- if (ep->play_from_start) {
719719+ if (ep->playback.play_from_start) {
735720 euroc_player_start_btn_cb(ep);
736721 }
737722 } else if (xs != NULL && capture_type == XRT_FS_CAPTURE_TYPE_CALIBRATION) {
···910895 u_var_add_sink_debug(ep, &ep->ui_right_sink, "Right Camera");
911896}
912897898898+extern "C" void
899899+euroc_player_fill_default_config_for(struct euroc_player_config *config, const char *dataset_path)
900900+{
901901+ struct euroc_player_dataset_info dataset = {};
902902+ dataset.gt_device_name = debug_get_option_gt_device_name();
903903+ euroc_player_fill_dataset_info(dataset_path, &dataset);
904904+905905+ struct euroc_player_playback_config playback = {};
906906+ const char *stereo = debug_get_option_stereo();
907907+ const char *color = debug_get_option_color();
908908+ const char *gt = debug_get_option_gt();
909909+ const char *skip_option = debug_get_option_skip_first();
910910+ playback.stereo = stereo == nullptr ? dataset.is_stereo : debug_string_to_bool(stereo);
911911+ playback.color = color == nullptr ? dataset.is_colored : debug_string_to_bool(color);
912912+ playback.gt = gt == nullptr ? dataset.has_gt : debug_string_to_bool(gt);
913913+ playback.skip_perc = string(skip_option).back() == '%';
914914+ playback.skip_first = stof(skip_option);
915915+ playback.scale = debug_get_float_option_scale();
916916+ playback.max_speed = debug_get_bool_option_max_speed();
917917+ playback.speed = debug_get_float_option_speed();
918918+ playback.paused = debug_get_bool_option_paused();
919919+ playback.send_all_imus_first = debug_get_bool_option_send_all_imus_first();
920920+ playback.use_source_ts = debug_get_bool_option_user_source_ts();
921921+ playback.play_from_start = debug_get_bool_option_play_from_start();
922922+ playback.print_progress = debug_get_bool_option_print_progress();
923923+924924+ config->log_level = debug_get_log_option_euroc_log();
925925+ config->dataset = dataset;
926926+ config->playback = playback;
927927+}
928928+913929// Euroc driver creation
914930915915-struct xrt_fs *
916916-euroc_player_create(struct xrt_frame_context *xfctx, const char *path)
931931+extern "C" struct xrt_fs *
932932+euroc_player_create(struct xrt_frame_context *xfctx, const char *path, struct euroc_player_config *config)
917933{
918934 struct euroc_player *ep = U_TYPED_CALLOC(struct euroc_player);
919919- euroc_player_fill_dataset_info(ep, path);
935935+936936+ struct euroc_player_config *default_config = nullptr;
937937+ if (config == nullptr) {
938938+ default_config = U_TYPED_CALLOC(struct euroc_player_config);
939939+ euroc_player_fill_default_config_for(default_config, path);
940940+ config = default_config;
941941+ }
942942+943943+ ep->log_level = config->log_level;
944944+ ep->dataset = config->dataset;
945945+ ep->playback = config->playback;
946946+947947+ if (default_config != nullptr) {
948948+ free(default_config);
949949+ }
950950+920951 ep->mode = xrt_fs_mode{
921952 ep->dataset.width,
922953 ep->dataset.height,
···925956 // xrt_fs interface as it will be managed through two different sinks.
926957 XRT_STEREO_FORMAT_NONE,
927958 };
959959+ EUROC_INFO(ep, "dataset information\n\tpath: %s\n\tis_stereo: %d, is_colored: %d, width: %d, height: %d",
960960+ ep->dataset.path, ep->dataset.is_stereo, ep->dataset.is_colored, ep->dataset.width,
961961+ ep->dataset.height);
928962929963 // Using pointers to not mix vector with a C-compatible struct
930964 ep->gt = new gt_trajectory{};
···932966 ep->left_imgs = new img_samples{};
933967 ep->right_imgs = new img_samples{};
934968935935- ep->playback.stereo = ep->dataset.is_stereo;
936936- ep->playback.color = ep->dataset.is_colored;
937937- ep->playback.gt = ep->dataset.has_gt;
938938- ep->playback.skip_perc = string(debug_get_option_euroc_skip_first()).back() == '%';
939939- ep->playback.skip_first = stof(debug_get_option_euroc_skip_first());
940940- ep->playback.scale = 1.0;
941941- ep->playback.max_speed = debug_get_bool_option_euroc_max_speed();
942942- ep->playback.speed = debug_get_float_option_euroc_playback_speed();
943943- ep->playback.send_all_imus_first = false;
944944- ep->playback.use_source_ts = debug_get_bool_option_euroc_use_source_ts();
945945- ep->play_from_start = debug_get_bool_option_euroc_play_from_start();
946946-947947- ep->log_level = debug_get_log_option_euroc_log();
948948- ep->print_progress = debug_get_bool_option_euroc_print_progress();
949969 euroc_player_setup_gui(ep);
950970951971 ep->left_sink.push_frame = receive_left_frame;
+1-1
src/xrt/state_trackers/prober/p_prober.c
···10011001#if defined(XRT_BUILD_DRIVER_EUROC)
10021002 const char *euroc_path = debug_get_option_euroc_path();
10031003 if (euroc_path != NULL) {
10041004- *out_xfs = euroc_player_create(xfctx, euroc_path); // Euroc will exit if it can't be created
10041004+ *out_xfs = euroc_player_create(xfctx, euroc_path, NULL); // Euroc will exit if it can't be created
10051005 return 0;
10061006 }
10071007#endif