Skip to content

Commit 91207c1

Browse files
authored
Add default recording directory to recording tools (#16)
* Add default recording directory to recording tools * Create timestamp based subfolders automatically if output is not set
1 parent 253cb25 commit 91207c1

File tree

7 files changed

+115
-47
lines changed

7 files changed

+115
-47
lines changed

cpp/k4a/CMakeLists.txt

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,25 @@ if(MSVC)
22
# Windows build uses newer features
33
cmake_minimum_required(VERSION 3.21)
44
else()
5-
cmake_minimum_required(VERSION 3.3)
5+
cmake_minimum_required(VERSION 3.12)
66
endif()
77

88
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
99

1010
project(spectacularAI_k4a_tools)
1111

12-
if(MSVC)
13-
set(CMAKE_CXX_STANDARD 20)
14-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
15-
else()
16-
set(CMAKE_CXX_STANDARD 14)
17-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
18-
endif()
19-
2012
find_package(Threads REQUIRED)
2113
find_package(spectacularAI_k4aPlugin REQUIRED)
2214

23-
if(MSVC) # Must be after project() is called
15+
if(MSVC)
2416
set(CMAKE_CXX_STANDARD 20)
17+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
2518
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Gy")
2619
# ./cmake/Findk4a.cmake is only tested on Windows and ideally we would rely on system dependency
2720
find_package(k4a MODULE REQUIRED)
2821
else()
29-
set(CMAKE_CXX_STANDARD 14)
22+
set(CMAKE_CXX_STANDARD 17)
23+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
3024
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
3125
find_package(k4a REQUIRED PATHS "${k4a_DIR}")
3226
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs=ALL")

cpp/k4a/record.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
#include <iostream>
33
#include <thread>
44
#include <vector>
5+
#include <sstream>
6+
#include <iomanip>
7+
#include <chrono>
8+
#include <filesystem>
59
#include <k4a/k4a.h>
610
#include <k4a/k4atypes.h>
711
#include <spectacularAI/k4a/plugin.hpp>
812

913
void showUsage() {
1014
std::cout << "Supported arguments:" << std::endl
1115
<< " -h, --help Help" << std::endl
12-
<< " --output <recording_folder>, recorded output" << std::endl
16+
<< " --output <recording_folder>, otherwise recording is saved to current working directory" << std::endl
17+
<< " --auto_subfolders, create timestamp-named subfolders for each recording" << std::endl
1318
<< " --recording_only, disables Vio" << std::endl
1419
<< " --color_res <720p, 1080p, 1440p, 1536p, 2160p, 3070p>" << std::endl
1520
<< " --depth_mode <1 (NVOF_2X2BINNED), 2 (NVOF_UNBINNED), 3 (WFOV_2X2BINNED), 4 (WFOV_UNBINNED)>" << std::endl
@@ -26,6 +31,18 @@ void showUsage() {
2631
<< std::endl;
2732
}
2833

34+
void setAutoSubfolder(std::string &recordingFolder) {
35+
auto now = std::chrono::system_clock::now();
36+
auto timePoint = std::chrono::system_clock::to_time_t(now);
37+
std::tm localTime = *std::localtime(&timePoint);
38+
std::ostringstream oss;
39+
oss << std::put_time(&localTime, "%Y-%m-%d_%H-%M-%S");
40+
std::filesystem::path basePath = recordingFolder;
41+
std::filesystem::path filename = oss.str();
42+
std::filesystem::path combinedPath = basePath / filename;
43+
recordingFolder = combinedPath.string();
44+
}
45+
2946
int main(int argc, char *argv[]) {
3047
std::vector<std::string> arguments(argv, argv + argc);
3148
std::string colorResolution = "720p";
@@ -37,11 +54,14 @@ int main(int argc, char *argv[]) {
3754
int32_t brightness = -1;
3855
spectacularAI::k4aPlugin::Configuration config;
3956
bool print = false;
57+
bool autoSubfolders = false;
4058

4159
for (size_t i = 1; i < arguments.size(); ++i) {
4260
const std::string &argument = arguments.at(i);
4361
if (argument == "--output")
4462
config.recordingFolder = arguments.at(++i);
63+
else if (argument == "--auto_subfolders")
64+
autoSubfolders = true;
4565
else if (argument == "--recording_only")
4666
config.recordingOnly = true;
4767
else if (argument == "--color_res")
@@ -78,12 +98,15 @@ int main(int argc, char *argv[]) {
7898
}
7999
}
80100

81-
// Require recording folder when using recording only mode.
82-
if (config.recordingOnly && config.recordingFolder.empty()) {
83-
std::cerr << "Record only but recording folder is not set!" << std::endl;
84-
return EXIT_FAILURE;
101+
// Set default recording folder if user didn't specify output
102+
if (config.recordingFolder.empty()) {
103+
autoSubfolders = true;
104+
config.recordingFolder = "data";
85105
}
86106

107+
// Create timestamp-named subfolders for each recording
108+
if (autoSubfolders) setAutoSubfolder(config.recordingFolder);
109+
87110
// In monocular mode, disable depth camera.
88111
if (!config.useStereo) depthMode = K4A_DEPTH_MODE_OFF;
89112

@@ -171,6 +194,7 @@ int main(int argc, char *argv[]) {
171194

172195
std::atomic<bool> shouldQuit(false);
173196
std::thread inputThread([&]() {
197+
std::cout << "Recording to '" << config.recordingFolder << "'" << std::endl;
174198
std::cout << "Press Enter to quit." << std::endl << std::endl;
175199
getchar();
176200
shouldQuit = true;

cpp/orbbec/CMakeLists.txt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ if(MSVC)
22
# Windows build uses newer features
33
cmake_minimum_required(VERSION 3.21)
44
else()
5-
cmake_minimum_required(VERSION 3.3)
5+
cmake_minimum_required(VERSION 3.12)
66
endif()
77

88
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
@@ -11,25 +11,18 @@ project(spectacularAI_orbbec_tools)
1111

1212
if(MSVC)
1313
set(CMAKE_CXX_STANDARD 20)
14+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1415
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
1516
else()
16-
set(CMAKE_CXX_STANDARD 14)
17+
set(CMAKE_CXX_STANDARD 17)
18+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1719
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
1820
endif()
1921

2022
find_package(Threads REQUIRED)
2123
find_package(spectacularAI_orbbecPlugin REQUIRED)
2224
find_package(OrbbecSDK REQUIRED PATHS "${OrbbecSDK_DIR}")
2325

24-
if(MSVC) # Must be after project() is called
25-
set(CMAKE_CXX_STANDARD 20)
26-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Gy")
27-
else()
28-
set(CMAKE_CXX_STANDARD 14)
29-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
30-
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs=ALL")
31-
endif()
32-
3326
set(TOOL_LIBS
3427
Threads::Threads
3528
spectacularAI::orbbecPlugin

cpp/orbbec/record.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
#include <atomic>
22
#include <iostream>
3-
#include <sstream>
43
#include <memory>
54
#include <thread>
65
#include <vector>
6+
#include <sstream>
7+
#include <iomanip>
8+
#include <chrono>
9+
#include <filesystem>
710
#include <libobsensor/ObSensor.hpp>
811
#include <spectacularAI/orbbec/plugin.hpp>
912

1013
void showUsage() {
1114
std::cout << "Supported arguments:" << std::endl
1215
<< " -h, --help Help" << std::endl
13-
<< " --output <recording_folder>, recorded output" << std::endl
16+
<< " --output <recording_folder>, otherwise recording is saved to current working directory" << std::endl
17+
<< " --auto_subfolders, create timestamp-named subfolders for each recording" << std::endl
1418
<< " --recording_only, disables Vio" << std::endl
1519
<< " --color_res <width,height>" << std::endl
1620
<< " --depth_res <width,height>" << std::endl
@@ -81,6 +85,18 @@ std::pair<int, int> tryParseResolution(const std::string &s) {
8185
}
8286
}
8387

88+
void setAutoSubfolder(std::string &recordingFolder) {
89+
auto now = std::chrono::system_clock::now();
90+
auto timePoint = std::chrono::system_clock::to_time_t(now);
91+
std::tm localTime = *std::localtime(&timePoint);
92+
std::ostringstream oss;
93+
oss << std::put_time(&localTime, "%Y-%m-%d_%H-%M-%S");
94+
std::filesystem::path basePath = recordingFolder;
95+
std::filesystem::path filename = oss.str();
96+
std::filesystem::path combinedPath = basePath / filename;
97+
recordingFolder = combinedPath.string();
98+
}
99+
84100
int main(int argc, char *argv[]) {
85101
std::vector<std::string> arguments(argv, argv + argc);
86102
ob::Context::setLoggerSeverity(OB_LOG_SEVERITY_OFF);
@@ -102,10 +118,14 @@ int main(int argc, char *argv[]) {
102118
int gain = -1;
103119
int brightness = -1;
104120
bool print = false;
121+
bool autoSubfolders = false;
122+
105123
for (size_t i = 1; i < arguments.size(); ++i) {
106124
const std::string &argument = arguments.at(i);
107125
if (argument == "--output")
108126
config.recordingFolder = arguments.at(++i);
127+
else if (argument == "--auto_subfolders")
128+
autoSubfolders = true;
109129
else if (argument == "--recording_only")
110130
config.recordingOnly = true;
111131
else if (argument == "--color_res")
@@ -136,12 +156,15 @@ int main(int argc, char *argv[]) {
136156
}
137157
}
138158

139-
// Require recording folder when using recording only mode.
140-
if (config.recordingOnly && config.recordingFolder.empty()) {
141-
std::cerr << "Record only but recording folder is not set!" << std::endl;
142-
return EXIT_FAILURE;
159+
// Set default recording folder if user didn't specify output
160+
if (config.recordingFolder.empty()) {
161+
autoSubfolders = true;
162+
config.recordingFolder = "data";
143163
}
144164

165+
// Create timestamp-named subfolders for each recording
166+
if (autoSubfolders) setAutoSubfolder(config.recordingFolder);
167+
145168
// Create vio pipeline using the config & setup orbbec pipeline
146169
spectacularAI::orbbecPlugin::Pipeline vioPipeline(*obPipeline, config);
147170

@@ -170,6 +193,7 @@ int main(int argc, char *argv[]) {
170193

171194
std::atomic<bool> shouldQuit(false);
172195
std::thread inputThread([&]() {
196+
std::cout << "Recording to '" << config.recordingFolder << "'" << std::endl;
173197
std::cout << "Press Enter to quit." << std::endl << std::endl;
174198
getchar();
175199
shouldQuit = true;

cpp/realsense/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ if(MSVC)
22
# Windows build uses newer features
33
cmake_minimum_required(VERSION 3.21)
44
else()
5-
cmake_minimum_required(VERSION 3.3)
5+
cmake_minimum_required(VERSION 3.12)
66
endif()
77

88
project(spectacularAI_realsense_tools)
99

1010
if(MSVC)
1111
set(CMAKE_CXX_STANDARD 20)
12+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1213
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
1314
else()
14-
set(CMAKE_CXX_STANDARD 14)
15+
set(CMAKE_CXX_STANDARD 17)
16+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1517
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
1618
endif()
1719

cpp/realsense/record.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22
#include <thread>
33
#include <vector>
44
#include <iostream>
5+
#include <sstream>
6+
#include <iomanip>
7+
#include <chrono>
8+
#include <filesystem>
59
#include <librealsense2/rs.hpp>
610
#include <spectacularAI/realsense/plugin.hpp>
711

812
void showUsage() {
913
std::cout << "Supported arguments:" << std::endl
1014
<< " -h, --help Help" << std::endl
11-
<< " --output <recording_folder>, recorded output" << std::endl
15+
<< " --output <recording_folder>, otherwise recording is saved to current working directory" << std::endl
16+
<< " --auto_subfolders, create timestamp-named subfolders for each recording" << std::endl
1217
<< " --recording_only, disables Vio" << std::endl
1318
<< " --resolution <value>, 400p or 800p" << std::endl
1419
<< " --brightness <value>" << std::endl
@@ -24,6 +29,18 @@ void showUsage() {
2429
<< std::endl;
2530
}
2631

32+
void setAutoSubfolder(std::string &recordingFolder) {
33+
auto now = std::chrono::system_clock::now();
34+
auto timePoint = std::chrono::system_clock::to_time_t(now);
35+
std::tm localTime = *std::localtime(&timePoint);
36+
std::ostringstream oss;
37+
oss << std::put_time(&localTime, "%Y-%m-%d_%H-%M-%S");
38+
std::filesystem::path basePath = recordingFolder;
39+
std::filesystem::path filename = oss.str();
40+
std::filesystem::path combinedPath = basePath / filename;
41+
recordingFolder = combinedPath.string();
42+
}
43+
2744
struct ColorCameraConfig {
2845
int brightness = -1;
2946
int contrast = -1;
@@ -40,12 +57,15 @@ int main(int argc, char** argv) {
4057
spectacularAI::rsPlugin::Configuration config;
4158
ColorCameraConfig colorConfig;
4259
bool print = false;
60+
bool autoSubfolders = false;
4361

4462
std::vector<std::string> arguments(argv, argv + argc);
4563
for (size_t i = 1; i < arguments.size(); ++i) {
4664
const std::string &argument = arguments.at(i);
4765
if (argument == "--output")
4866
config.recordingFolder = arguments.at(++i);
67+
else if (argument == "--auto_subfolders")
68+
autoSubfolders = true;
4969
else if (argument == "--recording_only")
5070
config.recordingOnly = true;
5171
else if (argument == "--resolution")
@@ -80,11 +100,15 @@ int main(int argc, char** argv) {
80100
}
81101
}
82102

103+
// Set default recording folder if user didn't specify output
83104
if (config.recordingFolder.empty()) {
84-
std::cerr << " You must provide output folder with --output <folder> argument." << std::endl;;
85-
return EXIT_FAILURE;
105+
autoSubfolders = true;
106+
config.recordingFolder = "data";
86107
}
87108

109+
// Create timestamp-named subfolders for each recording
110+
if (autoSubfolders) setAutoSubfolder(config.recordingFolder);
111+
88112
spectacularAI::rsPlugin::Pipeline vioPipeline(config);
89113

90114
{
@@ -123,6 +147,7 @@ int main(int argc, char** argv) {
123147

124148
std::atomic<bool> shouldQuit(false);
125149
std::thread inputThread([&]() {
150+
std::cout << "Recording to '" << config.recordingFolder << "'" << std::endl;
126151
std::cout << "Press Enter to quit." << std::endl << std::endl;
127152
getchar();
128153
shouldQuit = true;

python/cli/record/oak.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@
3131
# script and as a subcommand in sai-cli.
3232

3333
def define_args(p):
34-
p.add_argument("--output", help="Recording output folder", default="data")
35-
p.add_argument('--auto_subfolders', action='store_true',
36-
help='Create timestamp-named subfolders for each recording')
34+
p.add_argument("--output", help="Recording output folder, otherwise recording is saved to current working directory")
35+
p.add_argument('--auto_subfolders', action='store_true', help='Create timestamp-named subfolders for each recording')
3736
p.add_argument("--use_rgb", help="Use RGB data for tracking (OAK-D S2)", action="store_true")
3837
p.add_argument("--mono", help="Use a single camera (not stereo)", action="store_true")
3938
p.add_argument("--no_rgb", help="Disable recording RGB video feed", action="store_true")
@@ -73,6 +72,13 @@ def define_subparser(subparsers):
7372
sub.set_defaults(func=record)
7473
return define_args(sub)
7574

75+
def auto_subfolder(outputFolder):
76+
import datetime
77+
import os
78+
autoFolderName = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
79+
outputFolder = os.path.join(outputFolder, autoFolderName)
80+
return outputFolder
81+
7682
def record(args):
7783
import depthai
7884
import spectacularAI
@@ -87,11 +93,11 @@ def record(args):
8793

8894
config.useSlam = True
8995
config.inputResolution = args.resolution
90-
outputFolder = args.output
91-
if args.auto_subfolders:
92-
import datetime
93-
autoFolderName = datetime.datetime.now().strftime("%Y%m%dT%H%M%S")
94-
outputFolder = os.path.join(outputFolder, autoFolderName)
96+
if args.output:
97+
outputFolder = args.output
98+
if args.auto_subfolders: outputFolder = auto_subfolder(outputFolder)
99+
else:
100+
outputFolder = auto_subfolder("data")
95101

96102
internalParameters = {}
97103

@@ -189,7 +195,7 @@ def open_gray_video(name):
189195
videoFile = open(outputFolder + "/rgb_video.h265", "wb")
190196
rgbQueue = device.getOutputQueue(name="h265-rgb", maxSize=30, blocking=False)
191197

192-
print("Recording!")
198+
print("Recording to '{0}'".format(config.recordingFolder))
193199
print("")
194200
if plotter is not None:
195201
print("Close the visualization window to stop recording")

0 commit comments

Comments
 (0)