Skip to content
Snippets Groups Projects
main.cpp 6.62 KiB
Newer Older
/*
 * Copyright 2019 Nicolas Pope. All rights reserved.
 *
 * See LICENSE.
 */

Nicolas Pope's avatar
Nicolas Pope committed
#define LOGURU_WITH_STREAMS 1
#include <loguru.hpp>
#include <ftl/configuration.hpp>
Nicolas Pope's avatar
Nicolas Pope committed
#include <ftl/depth_camera.hpp>
#include <ftl/scene_rep_hash_sdf.hpp>
Nicolas Pope's avatar
Nicolas Pope committed
#include <ftl/rgbd.hpp>
Nicolas Pope's avatar
Nicolas Pope committed
#include <ftl/virtual_source.hpp>
#include <ftl/rgbd/streamer.hpp>
Sebastian Hahta's avatar
Sebastian Hahta committed

Nicolas Pope's avatar
Nicolas Pope committed
// #include <zlib.h>

#include <string>
#include <vector>
#include <thread>
#include <chrono>
#include <mutex>

#include <opencv2/opencv.hpp>
#include <ftl/net/universe.hpp>
Nicolas Pope's avatar
Nicolas Pope committed
#include <ftl/rgbd_display.hpp>
Nicolas Pope's avatar
Nicolas Pope committed
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/utility.hpp>

#include <ftl/utility/opencv_to_pcl.hpp>
#include <ftl/registration.hpp>
Nicolas Pope's avatar
Nicolas Pope committed
#ifdef HAVE_PCL
#include <pcl/point_cloud.h>
#include <pcl/common/transforms.h>
#include <pcl/filters/uniform_sampling.h>
#endif
Sebastian Hahta's avatar
Sebastian Hahta committed

Nicolas Pope's avatar
Nicolas Pope committed
using ftl::rgbd::Display;
using ftl::rgbd::Source;
Nicolas Pope's avatar
Nicolas Pope committed
using ftl::config::json_t;
Sebastian Hahta's avatar
Sebastian Hahta committed

using json = nlohmann::json;
using std::this_thread::sleep_for;
using std::chrono::milliseconds;
using std::mutex;
using std::unique_lock;

Nicolas Pope's avatar
Nicolas Pope committed
using std::vector;

using cv::Mat;
Sebastian Hahta's avatar
Sebastian Hahta committed

using ftl::registration::loadTransformations;
using ftl::registration::saveTransformations;
Nicolas Pope's avatar
Nicolas Pope committed
struct Cameras {
	Source *source;
Nicolas Pope's avatar
Nicolas Pope committed
	DepthCameraData gpu;
	DepthCameraParams params;
};

Nicolas Pope's avatar
Nicolas Pope committed
static void run(ftl::Configurable *root) {
	Universe *net = ftl::create<Universe>(root, "net");
Sebastian Hahta's avatar
Sebastian Hahta committed
	
	net->start();
	//net->waitConnections();
Sebastian Hahta's avatar
Sebastian Hahta committed
	
Nicolas Pope's avatar
Nicolas Pope committed
	std::vector<Cameras> inputs;
	auto sources = ftl::createArray<Source>(root, "sources", net); //root->get<vector<json_t>>("sources");
	if (sources.size() == 0) {
Sebastian Hahta's avatar
Sebastian Hahta committed
		LOG(ERROR) << "No sources configured!";
		return;
	}
	for (int i=0; i<sources.size(); i++) {
		Source *in = sources[i];
		auto &cam = inputs.emplace_back();
		cam.source = in;
		cam.params.m_imageWidth = 0;

	// TODO	move this block in its own method and add automated tests
	//		for error cases
	std::optional<json_t> merge = root->get<json_t>("merge");
	if (!merge) {
		LOG(WARNING) << "Input merging not configured, using only first input in configuration";
		inputs = { inputs[0] };
		inputs[0].source->setPose(Eigen::Matrix4f::Identity());

	if (inputs.size() > 1) {
		std::map<std::string, Eigen::Matrix4f> transformations;

		if ((*merge)["register"]) {
			LOG(INFO) << "Registration requested";

			ftl::registration::Registration *reg = ftl::registration::ChessboardRegistration::create(*merge);
			for (auto &input : inputs) { 
				while(!input.source->isReady()) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); }
				reg->addSource(input.source);
			}
			
			reg->run();
			if (reg->findTransformations(transformations)) {
				if (!saveTransformations(string(FTL_LOCAL_CONFIG_ROOT) + "/registration.json", transformations)) {
					LOG(ERROR) << "Error saving new registration";
				};
			else {
				LOG(ERROR) << "Registration failed";
			}

			free(reg);
		else {
			if (loadTransformations(string(FTL_LOCAL_CONFIG_ROOT) + "/registration.json", transformations)) {
				LOG(INFO) << "Loaded camera trasformations from file";
			}
			else {
				LOG(ERROR) << "Error loading camera transformations from file";
			}
		for (auto &input : inputs) {
			string uri = input.source->getURI();
			auto T = transformations.find(uri);
			if (T == transformations.end()) {
				LOG(ERROR) << "Camera pose for " + uri + " not found in transformations";
				LOG(WARNING) << "Using only first configured source";
				// TODO: use target source if configured and found
				inputs = { inputs[0] };
				inputs[0].source->setPose(Eigen::Matrix4f::Identity());
				break;
			}
			input.source->setPose(T->second);

	// Displays and Inputs configured
	for (auto &input : inputs) { LOG(INFO) << "    " + (string) input.source->getURI(); }
Nicolas Pope's avatar
Nicolas Pope committed
	ftl::rgbd::Display *display = ftl::create<ftl::rgbd::Display>(root, "display");
	ftl::rgbd::Source *virt = ftl::create<ftl::rgbd::Source>(root, "virtual", net);

	auto virtimpl = new ftl::rgbd::VirtualSource(virt);
	virt->customImplementation(virtimpl);

Nicolas Pope's avatar
Nicolas Pope committed
	ftl::voxhash::SceneRep *scene = ftl::create<ftl::voxhash::SceneRep>(root, "voxelhash");
	virtimpl->setScene(scene);
Nicolas Pope's avatar
Nicolas Pope committed
	display->setSource(virt);
Nicolas Pope's avatar
Nicolas Pope committed

	ftl::rgbd::Streamer *stream = ftl::create<ftl::rgbd::Streamer>(root, "stream", net);
	stream->add(virt);
	// Also proxy all inputs
	for (auto &in : inputs) {
		stream->add(in.source);
	}

Nicolas Pope's avatar
Nicolas Pope committed
	unsigned char frameCount = 0;
	bool paused = false;

	// Keyboard camera controls
Nicolas Pope's avatar
Nicolas Pope committed
	display->onKey([&paused](int key) {
Nicolas Pope's avatar
Nicolas Pope committed
		if (key == 32) paused = !paused;
	});

	int active = inputs.size();
	while (ftl::running && display->active()) {
		if (active == 0) {
			LOG(INFO) << "Waiting for sources...";
			sleep_for(milliseconds(1000));
		}

Sebastian Hahta's avatar
Sebastian Hahta committed
		active = 0;
Nicolas Pope's avatar
Nicolas Pope committed
		if (!paused) {
			//net.broadcast("grab");  // To sync cameras
Nicolas Pope's avatar
Nicolas Pope committed
			scene->nextFrame();
Nicolas Pope's avatar
Nicolas Pope committed
			for (size_t i = 0; i < inputs.size(); i++) {
				if (!inputs[i].source->isReady()) {
					inputs[i].params.m_imageWidth = 0;
					// TODO(Nick) : Free gpu allocs if was ready before
					continue;
				} else {
					auto &cam = inputs[i];
					auto in = inputs[i].source;
					if (cam.params.m_imageWidth == 0) {
						LOG(INFO) << "SETTING UP CAM PARAMS: " << in->parameters().fx;
						cam.params.fx = in->parameters().fx;
						cam.params.fy = in->parameters().fy;
						cam.params.mx = -in->parameters().cx;
						cam.params.my = -in->parameters().cy;
						cam.params.m_imageWidth = in->parameters().width;
						cam.params.m_imageHeight = in->parameters().height;
						cam.params.m_sensorDepthWorldMax = in->parameters().maxDepth;
						cam.params.m_sensorDepthWorldMin = in->parameters().minDepth;
						cam.gpu.alloc(cam.params);
					}
					
					//LOG(INFO) << in->getURI() << " loaded " << cam.params.fx;
				}

Nicolas Pope's avatar
Nicolas Pope committed
				// Get the RGB-Depth frame from input
				Source *input = inputs[i].source;
Nicolas Pope's avatar
Nicolas Pope committed
				Mat rgb, depth;
				input->grab();
				input->getFrames(rgb,depth);
Nicolas Pope's avatar
Nicolas Pope committed
				
				active += 1;

				if (depth.cols == 0) continue;

Nicolas Pope's avatar
Nicolas Pope committed
				// Must be in RGBA for GPU
Nicolas Pope's avatar
Nicolas Pope committed
				Mat rgba;
				cv::cvtColor(rgb,rgba, cv::COLOR_BGR2BGRA);

				inputs[i].params.flags = frameCount;

				// Send to GPU and merge view into scene
				inputs[i].gpu.updateParams(inputs[i].params);
				inputs[i].gpu.updateData(depth, rgba);
Nicolas Pope's avatar
Nicolas Pope committed
				scene->integrate(inputs[i].source->getPose(), inputs[i].gpu, inputs[i].params, nullptr);
Nicolas Pope's avatar
Nicolas Pope committed
			}
		} else {
			active = 1;
Nicolas Pope's avatar
Nicolas Pope committed
		}
Nicolas Pope's avatar
Nicolas Pope committed

		frameCount++;

		stream->poll();
Nicolas Pope's avatar
Nicolas Pope committed
		display->update();
		//sleep_for(milliseconds(10));
Nicolas Pope's avatar
Nicolas Pope committed
	run(ftl::configure(argc, argv, "reconstruction_default"));
Nicolas Pope's avatar
Nicolas Pope committed
}