#include <dv-processing/core/stereo_event_stream_slicer.hpp>
#include <dv-processing/io/stereo_camera_writer.hpp>
#include <dv-processing/io/stereo_capture.hpp>
#include <dv-processing/io/camera_capture.hpp>
#include <dv-processing/core/utils.hpp>
#include <functions.hpp>
#include <CLI/CLI.hpp>
#include <map>
#include <csignal>
#include <chrono>
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <structs.hpp>
#include <filehandler.hpp>
#include <tinyfiledialogs/tinyfiledialogs.h>
#include <visualization.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/video.hpp>
#include <opencv2/optflow.hpp>
#include <opencv2/features2d.hpp>
#include <thread>
#include <atomic>
#include <csignal>
#include <chrono>
#include <iostream>
#include <filesystem>
#include <yaml-cpp/yaml.h>
#include <structs.hpp>
#include <filters.hpp>
#include <visualization.hpp>
static std::atomic<bool> keepRunning(true);
static std::atomic<bool> signalReceived(false);
// Signal handler that sets flags instead of performing the cleanup directly
void handleShutdown(int) {
keepRunning.store(false);
signalReceived.store(true);
}
int main(int ac, char **av) {
using namespace std::chrono_literals;
std::signal(SIGINT, handleShutdown);
std::signal(SIGTERM, handleShutdown);
std::string configFile = "../configs/record_aedat4.yaml"; // Default configuration file
bool first = true;
camera cam;
VIS_params visualizationPar;
ACC_params accumulatorPar;
CLI::App app{"Event based camera recorder.\n Default configuration file : \"config_cam_recording.yaml\""};
app.add_option("-c,--configuration", configFile, "Path for the .yaml configuration file")
->check(CLI::ExistingFile);
try {
app.parse(ac, av);
} catch (const CLI::ParseError &e) {
return app.exit(e);
}
// Load configuration from YAML
std::cout << "Reading configuration file : " << configFile << " .. " << std::endl;
YAML::Node config = YAML::LoadFile(configFile);
std::string directory = config["file"]["directory"].as<std::string>();
//check if directory exists
if (!std::filesystem::exists(directory))
{
std::cerr << "Error: Directory does not exist" << std::endl;
std::exit(1);
}
std::string aedat4FileStr = config["file"]["fileName"].as<std::string>();
extractCameraParameters(config, cam);
//remove .aedat4 from the string if present
if (aedat4FileStr.find(".aedat4") != std::string::npos)
{
aedat4FileStr.erase(aedat4FileStr.find(".aedat4"), 7);
}
//attach data of the camera onto the name
aedat4FileStr += "_efps" + std::to_string(cam.efps) + "_sensitivity" + std::to_string(cam.sensitivity);
//add the .aedat4 extension
aedat4FileStr += ".aedat4";
//check if no other files have the same exact name. in that case, check if there is already a (n) on the name, then increase the n
int n = 0;
while (std::filesystem::exists(directory + aedat4FileStr))
{
n++;
aedat4FileStr = aedat4FileStr.substr(0, aedat4FileStr.size() - 7); //remove the .aedat4
aedat4FileStr += "(" + std::to_string(n) + ").aedat4";
}
// Open the camera; the camera name can empty as well
dv::io::CameraCapture capture;
// Provide the opened camera name; Especially useful when no camera name is provided in the arguments.
std::cout << "Camera [" << capture.getCameraName() << "] has been opened!" << std::endl;
//getting EFPS setting
dv::io::CameraCapture::DVXeFPS efpsSetting = intToDVXeFPS(cam.efps);
dv::io::CameraCapture::BiasSensitivity sensitivity = intToBiasSensitivity(cam.sensitivity);
//EFPS
capture.setDVXplorerEFPS(efpsSetting);
//BIAS SENSITIVITY
capture.setDVSBiasSensitivity(sensitivity);
// Create the file writer instance
dv::io::MonoCameraWriter writer(directory + aedat4FileStr, capture);
//LOOPING UNTIL THE END
while (keepRunning && capture.isRunning()) {
//WRITING EVENT stream
if (const auto &events = capture.getNextEventBatch(); events.has_value()) {
//const auto events_copy = events;
if(first)
{
std::cout << "Starting the recording!" << std::endl;
first = false;
}
writer.writeEvents(*events);
}
//WRITING IMU data stream
if(cam.saveIMU)
{
if (const auto &imu = capture.getNextImuBatch(); imu.has_value()) {
writer.writeImuPacket(*imu);
}
}
else {
// No events available yet, short sleep
std::this_thread::sleep_for(100us);
continue;
}
}
// The recording required a tailing data table which is going to be written when MonoCameraWriter
// goes out of scope.
std::cout << "Finalizing the recording!" << std::endl;
return EXIT_SUCCESS;
}