The open source OpenXR runtime

t/euroc: Allow euroc recorder to start and stop recordings in the same session

authored by

Mateo de Mayo and committed by
Jakob Bornecrantz
14c1ecc9 cdcb4fbc

+76 -34
+57 -32
src/xrt/auxiliary/tracking/t_euroc_recorder.cpp
··· 42 42 struct euroc_recorder 43 43 { 44 44 struct xrt_frame_node node; 45 - string path; //!< Destination path for the dataset 45 + string path_prefix; //!< Path for the dataset without datetime suffix 46 + string path; //!< Full path of the current dataset being recorded or empty string if none 46 47 int cam_count = -1; 47 48 48 49 bool recording; //!< Whether samples are being recorded 49 - bool files_created; //!< Whether the dataset directory structure has been created 50 50 struct u_var_button recording_btn; //!< UI button to start/stop `recording` 51 51 52 52 bool use_jpg; //! Whether or not we should save images as .jpg files ··· 84 84 */ 85 85 86 86 static void 87 - euroc_recorder_try_mkfiles(struct euroc_recorder *er) 87 + euroc_recorder_mkfiles(struct euroc_recorder *er) 88 88 { 89 - // Create directory structure and files only once 90 - if (er->files_created) { 91 - return; 92 - } 93 - er->files_created = true; 94 - 95 89 string path = er->path; 96 90 97 91 create_directories(path + "/mav0/imu0"); ··· 348 342 { 349 343 struct euroc_recorder *er = new euroc_recorder{}; 350 344 351 - er->recording = record_from_start; 352 345 er->cam_count = cam_count; 346 + er->path_prefix = record_path == nullptr ? "euroc_recording" : record_path; 347 + er->path = record_path == nullptr ? "" : record_path; 353 348 354 349 struct xrt_frame_node *xfn = &er->node; 355 350 xfn->break_apart = euroc_recorder_node_break_apart; 356 351 xfn->destroy = euroc_recorder_node_destroy; 357 352 xrt_frame_context_add(xfctx, xfn); 358 - 359 - // Determine dataset path 360 - if (record_path != nullptr) { 361 - er->path = record_path; 362 - } else { 363 - time_t seconds = os_realtime_get_ns() / U_1_000_000_000; 364 - constexpr size_t size = sizeof("YYYYMMDDHHmmss"); 365 - char datetime[size] = {0}; 366 - (void)strftime(datetime, size, "%Y%m%d%H%M%S", localtime(&seconds)); 367 - string default_path = string{"euroc_recording_"} + datetime; 368 - er->path = default_path; 369 - } 370 - 371 - if (record_from_start) { 372 - euroc_recorder_try_mkfiles(er); 373 - } 374 353 375 354 er->use_jpg = debug_get_bool_option_euroc_recorder_use_jpg(); 376 355 ··· 408 387 er->writer_gt_sink.push_pose = euroc_recorder_save_gt; 409 388 410 389 xrt_slam_sinks *public_sinks = &er->cloner_queues; 390 + 391 + if (record_from_start) { 392 + euroc_recorder_start(public_sinks); 393 + } 394 + 411 395 return public_sinks; 412 396 } 413 397 398 + extern "C" void 399 + euroc_recorder_start(struct xrt_slam_sinks *er_sinks) 400 + { 401 + euroc_recorder *er = container_of(er_sinks, euroc_recorder, cloner_queues); 402 + 403 + if (er->recording) { 404 + U_LOG_W("We are already recording; unable to start."); 405 + return; 406 + } 407 + 408 + // Create dataset directories with current datetime suffix 409 + time_t seconds = os_realtime_get_ns() / U_1_000_000_000; 410 + constexpr size_t size = sizeof("YYYYMMDDHHmmss"); 411 + char datetime[size] = {0}; 412 + (void)strftime(datetime, size, "%Y%m%d%H%M%S", localtime(&seconds)); 413 + string default_path = er->path_prefix + "_" + datetime; 414 + er->path = default_path; 415 + 416 + euroc_recorder_mkfiles(er); 417 + er->recording = true; 418 + } 419 + 420 + extern "C" void 421 + euroc_recorder_stop(struct xrt_slam_sinks *er_sinks) 422 + { 423 + euroc_recorder *er = container_of(er_sinks, euroc_recorder, cloner_queues); 424 + 425 + if (!er->recording) { 426 + U_LOG_W("We are already not recording; unable to stop."); 427 + return; 428 + } 429 + 430 + er->path = ""; 431 + er->recording = false; 432 + euroc_recorder_flush(er); 433 + } 434 + 414 435 static void 415 436 euroc_recorder_btn_cb(void *ptr) 416 437 { 417 438 euroc_recorder *er = (euroc_recorder *)ptr; 418 - euroc_recorder_try_mkfiles(er); 419 - er->recording = !er->recording; 420 - (void)snprintf(er->recording_btn.label, sizeof(er->recording_btn.label), 421 - er->recording ? "Stop recording" : "Record EuRoC dataset"); 439 + 440 + if (er->recording) { 441 + euroc_recorder_stop(&er->cloner_queues); 442 + (void)snprintf(er->recording_btn.label, sizeof(er->recording_btn.label), "Record EuRoC dataset"); 443 + } else { 444 + euroc_recorder_start(&er->cloner_queues); 445 + (void)snprintf(er->recording_btn.label, sizeof(er->recording_btn.label), "Stop recording"); 446 + } 422 447 } 423 448 424 449 extern "C" void 425 - euroc_recorder_add_ui(struct xrt_slam_sinks *public_sinks, void *root, const char *prefix) 450 + euroc_recorder_add_ui(struct xrt_slam_sinks *er_sinks, void *root, const char *prefix) 426 451 { 427 - euroc_recorder *er = container_of(public_sinks, euroc_recorder, cloner_queues); 452 + euroc_recorder *er = container_of(er_sinks, euroc_recorder, cloner_queues); 428 453 er->recording_btn.cb = euroc_recorder_btn_cb; 429 454 er->recording_btn.ptr = er; 430 455
+19 -2
src/xrt/auxiliary/tracking/t_euroc_recorder.h
··· 20 20 #endif 21 21 22 22 /*! 23 - * @brief Create SLAM sinks to record samples in EuRoC format. 23 + * Create SLAM sinks to record samples in EuRoC format. 24 24 * 25 25 * @param xfctx Frame context for the sinks. 26 26 * @param record_path Directory name to save the dataset or NULL for a default based on the current datetime. ··· 34 34 euroc_recorder_create(struct xrt_frame_context *xfctx, const char *record_path, int cam_count, bool record_from_start); 35 35 36 36 /*! 37 + * Start recording samples sent to the recorder sinks. 38 + * 39 + * @param er The recorder sinks returned by @ref euroc_recorder_create 40 + */ 41 + void 42 + euroc_recorder_start(struct xrt_slam_sinks *er_sinks); 43 + 44 + /*! 45 + * Stop recording samples sent to the recorder sinks. You can start and 46 + * stop as many times as you like. 47 + * 48 + * @param er The recorder sinks returned by @ref euroc_recorder_create 49 + */ 50 + void 51 + euroc_recorder_stop(struct xrt_slam_sinks *er_sinks); 52 + 53 + /*! 37 54 * Add EuRoC recorder UI button to start recording after creation. 38 55 * 39 56 * @param er The sinks returned by @ref euroc_recorder_create ··· 41 58 * @param prefix Prefix in case you have multiple recorders, otherwise pass an empty string 42 59 */ 43 60 void 44 - euroc_recorder_add_ui(struct xrt_slam_sinks *er, void *root, const char *prefix); 61 + euroc_recorder_add_ui(struct xrt_slam_sinks *er_sinks, void *root, const char *prefix); 45 62 46 63 #ifdef __cplusplus 47 64 }