From 14c1ecc96ebe7423cba266e98895b652b794f754 Mon Sep 17 00:00:00 2001 From: Mateo de Mayo Date: Wed, 23 Aug 2023 13:46:17 -0300 Subject: [PATCH] t/euroc: Allow euroc recorder to start and stop recordings in the same session --- .../auxiliary/tracking/t_euroc_recorder.cpp | 89 ++++++++++++------- src/xrt/auxiliary/tracking/t_euroc_recorder.h | 21 ++++- 2 files changed, 76 insertions(+), 34 deletions(-) diff --git a/src/xrt/auxiliary/tracking/t_euroc_recorder.cpp b/src/xrt/auxiliary/tracking/t_euroc_recorder.cpp index 825ab21fa..7e460b3bb 100644 --- a/src/xrt/auxiliary/tracking/t_euroc_recorder.cpp +++ b/src/xrt/auxiliary/tracking/t_euroc_recorder.cpp @@ -42,11 +42,11 @@ using std::filesystem::create_directories; struct euroc_recorder { struct xrt_frame_node node; - string path; //!< Destination path for the dataset + string path_prefix; //!< Path for the dataset without datetime suffix + string path; //!< Full path of the current dataset being recorded or empty string if none int cam_count = -1; bool recording; //!< Whether samples are being recorded - bool files_created; //!< Whether the dataset directory structure has been created struct u_var_button recording_btn; //!< UI button to start/stop `recording` bool use_jpg; //! Whether or not we should save images as .jpg files @@ -84,14 +84,8 @@ struct euroc_recorder */ static void -euroc_recorder_try_mkfiles(struct euroc_recorder *er) +euroc_recorder_mkfiles(struct euroc_recorder *er) { - // Create directory structure and files only once - if (er->files_created) { - return; - } - er->files_created = true; - string path = er->path; create_directories(path + "/mav0/imu0"); @@ -348,30 +342,15 @@ euroc_recorder_create(struct xrt_frame_context *xfctx, const char *record_path, { struct euroc_recorder *er = new euroc_recorder{}; - er->recording = record_from_start; er->cam_count = cam_count; + er->path_prefix = record_path == nullptr ? "euroc_recording" : record_path; + er->path = record_path == nullptr ? "" : record_path; struct xrt_frame_node *xfn = &er->node; xfn->break_apart = euroc_recorder_node_break_apart; xfn->destroy = euroc_recorder_node_destroy; xrt_frame_context_add(xfctx, xfn); - // Determine dataset path - if (record_path != nullptr) { - er->path = record_path; - } else { - time_t seconds = os_realtime_get_ns() / U_1_000_000_000; - constexpr size_t size = sizeof("YYYYMMDDHHmmss"); - char datetime[size] = {0}; - (void)strftime(datetime, size, "%Y%m%d%H%M%S", localtime(&seconds)); - string default_path = string{"euroc_recording_"} + datetime; - er->path = default_path; - } - - if (record_from_start) { - euroc_recorder_try_mkfiles(er); - } - er->use_jpg = debug_get_bool_option_euroc_recorder_use_jpg(); // Setup sink pipeline @@ -408,23 +387,69 @@ euroc_recorder_create(struct xrt_frame_context *xfctx, const char *record_path, er->writer_gt_sink.push_pose = euroc_recorder_save_gt; xrt_slam_sinks *public_sinks = &er->cloner_queues; + + if (record_from_start) { + euroc_recorder_start(public_sinks); + } + return public_sinks; } +extern "C" void +euroc_recorder_start(struct xrt_slam_sinks *er_sinks) +{ + euroc_recorder *er = container_of(er_sinks, euroc_recorder, cloner_queues); + + if (er->recording) { + U_LOG_W("We are already recording; unable to start."); + return; + } + + // Create dataset directories with current datetime suffix + time_t seconds = os_realtime_get_ns() / U_1_000_000_000; + constexpr size_t size = sizeof("YYYYMMDDHHmmss"); + char datetime[size] = {0}; + (void)strftime(datetime, size, "%Y%m%d%H%M%S", localtime(&seconds)); + string default_path = er->path_prefix + "_" + datetime; + er->path = default_path; + + euroc_recorder_mkfiles(er); + er->recording = true; +} + +extern "C" void +euroc_recorder_stop(struct xrt_slam_sinks *er_sinks) +{ + euroc_recorder *er = container_of(er_sinks, euroc_recorder, cloner_queues); + + if (!er->recording) { + U_LOG_W("We are already not recording; unable to stop."); + return; + } + + er->path = ""; + er->recording = false; + euroc_recorder_flush(er); +} + static void euroc_recorder_btn_cb(void *ptr) { euroc_recorder *er = (euroc_recorder *)ptr; - euroc_recorder_try_mkfiles(er); - er->recording = !er->recording; - (void)snprintf(er->recording_btn.label, sizeof(er->recording_btn.label), - er->recording ? "Stop recording" : "Record EuRoC dataset"); + + if (er->recording) { + euroc_recorder_stop(&er->cloner_queues); + (void)snprintf(er->recording_btn.label, sizeof(er->recording_btn.label), "Record EuRoC dataset"); + } else { + euroc_recorder_start(&er->cloner_queues); + (void)snprintf(er->recording_btn.label, sizeof(er->recording_btn.label), "Stop recording"); + } } extern "C" void -euroc_recorder_add_ui(struct xrt_slam_sinks *public_sinks, void *root, const char *prefix) +euroc_recorder_add_ui(struct xrt_slam_sinks *er_sinks, void *root, const char *prefix) { - euroc_recorder *er = container_of(public_sinks, euroc_recorder, cloner_queues); + euroc_recorder *er = container_of(er_sinks, euroc_recorder, cloner_queues); er->recording_btn.cb = euroc_recorder_btn_cb; er->recording_btn.ptr = er; diff --git a/src/xrt/auxiliary/tracking/t_euroc_recorder.h b/src/xrt/auxiliary/tracking/t_euroc_recorder.h index d5f541683..3a86b0638 100644 --- a/src/xrt/auxiliary/tracking/t_euroc_recorder.h +++ b/src/xrt/auxiliary/tracking/t_euroc_recorder.h @@ -20,7 +20,7 @@ extern "C" { #endif /*! - * @brief Create SLAM sinks to record samples in EuRoC format. + * Create SLAM sinks to record samples in EuRoC format. * * @param xfctx Frame context for the sinks. * @param record_path Directory name to save the dataset or NULL for a default based on the current datetime. @@ -33,6 +33,23 @@ extern "C" { struct xrt_slam_sinks * euroc_recorder_create(struct xrt_frame_context *xfctx, const char *record_path, int cam_count, bool record_from_start); +/*! + * Start recording samples sent to the recorder sinks. + * + * @param er The recorder sinks returned by @ref euroc_recorder_create + */ +void +euroc_recorder_start(struct xrt_slam_sinks *er_sinks); + +/*! + * Stop recording samples sent to the recorder sinks. You can start and + * stop as many times as you like. + * + * @param er The recorder sinks returned by @ref euroc_recorder_create + */ +void +euroc_recorder_stop(struct xrt_slam_sinks *er_sinks); + /*! * Add EuRoC recorder UI button to start recording after creation. * @@ -41,7 +58,7 @@ euroc_recorder_create(struct xrt_frame_context *xfctx, const char *record_path, * @param prefix Prefix in case you have multiple recorders, otherwise pass an empty string */ void -euroc_recorder_add_ui(struct xrt_slam_sinks *er, void *root, const char *prefix); +euroc_recorder_add_ui(struct xrt_slam_sinks *er_sinks, void *root, const char *prefix); #ifdef __cplusplus }