Skip to content

Commit cb3b9e8

Browse files
authored
Add replay API example (SpectacularAI#37)
1 parent 13628fd commit cb3b9e8

File tree

4 files changed

+159
-3
lines changed

4 files changed

+159
-3
lines changed

cpp/offline/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# SpectacularAI offline example
1+
# Spectacular AI main API example
22

3-
This example shows how to run basic stereo VIO using offline data.
3+
This example shows how to run basic stereo VIO using offline data to mimic real-time use case. Functions in the main header `spectacularAI/vio.hpp` are used primarily.
44

5-
* Supported platform: Linux
5+
* Tested platforms: Linux
66
* Dependencies: CMake, FFmpeg (for video input)
77

88
## Setup
@@ -70,4 +70,5 @@ For the included libraries, see
7070
* [lodepng](https://lodev.org/lodepng/): `lodepng/LICENSE`
7171

7272
For access to the C++ SDK, contact us at <https://www.spectacularai.com/#contact>.
73+
7374
Available for multiple OSes and CPU architectures.

cpp/replay/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
cmake_minimum_required(VERSION 3.3)
2+
3+
project(spectacularAI_replay_example)
4+
5+
add_executable(replay replay.cpp)
6+
7+
find_package(spectacularAI REQUIRED)
8+
9+
target_link_libraries(replay PRIVATE spectacularAI::spectacularAI)
10+
target_include_directories(replay PRIVATE ".")

cpp/replay/README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Spectacular AI Replay API example
2+
3+
This example shows how to replay recordings created using Spectacular AI SDK. The header `spectacularAI/replay.hpp` is primarily used.
4+
5+
* Tested platforms: Linux
6+
* Dependencies: CMake, FFmpeg (for video input)
7+
8+
## Setup
9+
10+
* Install the Spectacular AI SDK
11+
* Build this example using CMake:
12+
13+
```
14+
mkdir target
15+
cd target
16+
cmake -DspectacularAI_DIR=<path/to/spectacularai-sdk/lib/cmake/spectacularAI> ..
17+
make
18+
```
19+
20+
The `-DspectacularAI_DIR` option is not needed is you have used `sudo make install` for the SDK.
21+
22+
## Usage
23+
24+
In the target folder, run `./replay -i path/to/data -o out.jsonl`, where
25+
26+
* `-i` specifies the input folder, see details below.
27+
* `-o` specifies output JSONL file.
28+
29+
See the source code for more options. Input data is read from a given folder with the following hierarchy:
30+
31+
```
32+
├── calibration.json
33+
├── vio_config.yaml
34+
├── data.jsonl
35+
├── data.mp4
36+
└── data2.mp4
37+
```
38+
39+
when using video files. And if instead using PNG images:
40+
41+
```
42+
├── calibration.json
43+
├── vio_config.yaml
44+
├── data.jsonl
45+
├── frames1
46+
│   ├── 00000000.png
47+
│   ├── 00000001.png
48+
│   ├── ...
49+
│   └── 00000600.png
50+
└── frames2
51+
├── 00000000.png
52+
├── 00000001.png
53+
├── ...
54+
└── 00000600.png
55+
```
56+
57+
## Copyright
58+
59+
For access to the C++ SDK, contact us at <https://www.spectacularai.com/#contact>.
60+
61+
Available for multiple OSes and CPU architectures.

cpp/replay/replay.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include <cassert>
2+
#include <chrono>
3+
#include <fstream>
4+
#include <iostream>
5+
#include <memory>
6+
#include <sstream>
7+
8+
#include <spectacularAI/vio.hpp>
9+
#include <spectacularAI/replay.hpp>
10+
11+
const std::string SEPARATOR = "/";
12+
13+
std::string readFileToString(const std::string &filename) {
14+
std::ifstream f(filename);
15+
std::ostringstream oss;
16+
oss << f.rdbuf();
17+
return oss.str();
18+
}
19+
20+
bool fileExists(const std::string &filePath) {
21+
std::ifstream dataFile(filePath);
22+
return dataFile.is_open();
23+
}
24+
25+
int main(int argc, char *argv[]) {
26+
std::vector<std::string> arguments(argv, argv + argc);
27+
std::unique_ptr<std::ofstream> outputFile;
28+
std::string inputFolder;
29+
std::string userConfigurationYaml;
30+
bool realtime = false;
31+
bool print = false;
32+
for (size_t i = 1; i < arguments.size(); ++i) {
33+
const std::string &argument = arguments.at(i);
34+
if (argument == "-o") {
35+
outputFile = std::make_unique<std::ofstream>(arguments.at(++i));
36+
assert(outputFile->is_open());
37+
}
38+
else if (argument == "-i") inputFolder = arguments.at(++i);
39+
else if (argument == "-c") userConfigurationYaml = readFileToString(arguments.at(++i));
40+
else if (argument == "--realtime") realtime = true;
41+
else if (argument == "--print") print = true;
42+
}
43+
if (inputFolder.empty()) {
44+
std::cout << "Please specify input directory using `-i`."<< std::endl;
45+
return 0;
46+
}
47+
48+
std::ostringstream configurationYaml;
49+
std::string dataConfigurationYamlPath = inputFolder + SEPARATOR + "vio_config.yaml";
50+
if (fileExists(dataConfigurationYamlPath)) {
51+
// Vio::Builder::setConfigurationYAML overwrites the configuration in the data
52+
// directory, but in most cases that configuration is needed for the best VIO
53+
// performance, so we concatenate our changes to it.
54+
configurationYaml << readFileToString(dataConfigurationYamlPath) << std::endl;
55+
}
56+
// The `processingQueueSize` option makes the data input wait for VIO to finish to
57+
// avoid dropping frames. It should not be used in real-time scenarios.
58+
configurationYaml << "processingQueueSize: 0\n";
59+
configurationYaml << userConfigurationYaml;
60+
61+
// The Replay API builder takes as input the main API builder as a way to share
62+
// configuration methods.
63+
spectacularAI::Vio::Builder vioBuilder = spectacularAI::Vio::builder()
64+
.setConfigurationYAML(configurationYaml.str());
65+
66+
std::unique_ptr<spectacularAI::Replay> replay
67+
= spectacularAI::Replay::builder(inputFolder, vioBuilder).build();
68+
replay->setPlaybackSpeed(realtime ? 1.0 : -1.0);
69+
70+
replay->setOutputCallback([&](spectacularAI::VioOutputPtr vioOutput) {
71+
if (outputFile) *outputFile << vioOutput->asJson().c_str() << std::endl;
72+
if (print) std::cout << vioOutput->asJson().c_str() << std::endl;
73+
});
74+
75+
const auto t0 = std::chrono::steady_clock::now();
76+
77+
replay->runReplay();
78+
79+
const auto time = std::chrono::duration<double, std::milli>(
80+
std::chrono::steady_clock::now() - t0).count();
81+
printf("Replay took %.2fs\n", 1e-3 * time);
82+
83+
return 0;
84+
}

0 commit comments

Comments
 (0)