From ae0b7aa2cab7c9b40c1e115ffef2d3afbd94e48e Mon Sep 17 00:00:00 2001
From: Nicolas Pope <nicolas.pope@utu.fi>
Date: Thu, 15 Oct 2020 09:21:43 +0300
Subject: [PATCH] Pylon properties from master machine

---
 applications/vision/src/main.cpp              |  1 +
 components/common/cpp/include/ftl/timer.hpp   |  7 +++
 .../{net => common}/cpp/include/ftl/uuid.hpp  |  0
 components/common/cpp/src/timer.cpp           | 12 ++++
 .../net/cpp/include/ftl/net/universe.hpp      |  3 +
 components/net/cpp/src/universe.cpp           |  4 ++
 .../src/sources/stereovideo/pylon.cpp         | 62 ++++++++++++++++++-
 7 files changed, 86 insertions(+), 3 deletions(-)
 rename components/{net => common}/cpp/include/ftl/uuid.hpp (100%)

diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp
index afbddb050..40531fa3a 100644
--- a/applications/vision/src/main.cpp
+++ b/applications/vision/src/main.cpp
@@ -88,6 +88,7 @@ static void run(ftl::Configurable *root) {
 	if (opt_time_master) {
 		time_peer = *opt_time_master;
 		LOG(INFO) << "Found a time master: " << time_peer.to_string();
+		ftl::timer::setTimeMaster(time_peer);
 	}
 	int sync_counter = 0;
 
diff --git a/components/common/cpp/include/ftl/timer.hpp b/components/common/cpp/include/ftl/timer.hpp
index 6530aeadd..1dd3ff76f 100644
--- a/components/common/cpp/include/ftl/timer.hpp
+++ b/components/common/cpp/include/ftl/timer.hpp
@@ -3,9 +3,12 @@
 
 #include <ftl/handle.hpp>
 #include <functional>
+#include <optional>
 
 namespace ftl {
 
+class UUID;
+
 /**
  * A single global timer mechanism to call functions with either high or low
  * precision timing accuracy. This is used to provide accurate frame timing for
@@ -114,6 +117,10 @@ size_t count(timerlevel_t);
  */
 void reset();
 
+void setTimeMaster(const ftl::UUID &m);
+
+std::optional<ftl::UUID> getTimeMaster();
+
 }
 }
 
diff --git a/components/net/cpp/include/ftl/uuid.hpp b/components/common/cpp/include/ftl/uuid.hpp
similarity index 100%
rename from components/net/cpp/include/ftl/uuid.hpp
rename to components/common/cpp/include/ftl/uuid.hpp
diff --git a/components/common/cpp/src/timer.cpp b/components/common/cpp/src/timer.cpp
index e49a955cf..e9587355e 100644
--- a/components/common/cpp/src/timer.cpp
+++ b/components/common/cpp/src/timer.cpp
@@ -1,5 +1,6 @@
 #include <ftl/timer.hpp>
 #include <ftl/threads.hpp>
+#include <ftl/uuid.hpp>
 #include <loguru.hpp>
 
 #include <vector>
@@ -28,6 +29,8 @@ static MUTEX mtx;
 static int last_id = 0;
 static bool clock_slave = true;
 static std::future<void> timer_future;
+static ftl::UUID time_master(0);
+static bool has_time_master = false;
 
 struct TimerJob {
 	int id=0;
@@ -42,6 +45,15 @@ struct TimerJob {
 
 static list<TimerJob> jobs[kTimerMAXLEVEL];
 
+void ftl::timer::setTimeMaster(const ftl::UUID &m) {
+	has_time_master = true;
+	time_master = m;
+}
+
+std::optional<ftl::UUID> ftl::timer::getTimeMaster() {
+	return (has_time_master) ? time_master : std::optional<ftl::UUID>{};
+}
+
 int64_t ftl::timer::get_time() {
 	return time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count()+clock_adjust;
 }
diff --git a/components/net/cpp/include/ftl/net/universe.hpp b/components/net/cpp/include/ftl/net/universe.hpp
index 8ee642fe6..58f23053a 100644
--- a/components/net/cpp/include/ftl/net/universe.hpp
+++ b/components/net/cpp/include/ftl/net/universe.hpp
@@ -214,6 +214,8 @@ class Universe : public ftl::Configurable {
 
 	size_t getSendBufferSize(ftl::URI::scheme_t s);
 	size_t getRecvBufferSize(ftl::URI::scheme_t s);
+
+	static inline Universe *getInstance() { return instance_; }
 	
 	private:
 	void _run();
@@ -274,6 +276,7 @@ class Universe : public ftl::Configurable {
 	std::list<ErrHandler> on_error_;
 
 	static callback_t cbid__;
+	static Universe *instance_;
 
 	// std::map<std::string, std::vector<ftl::net::Peer*>> subscriptions_;
 };
diff --git a/components/net/cpp/src/universe.cpp b/components/net/cpp/src/universe.cpp
index ce1137ee0..3dbcd5887 100644
--- a/components/net/cpp/src/universe.cpp
+++ b/components/net/cpp/src/universe.cpp
@@ -47,6 +47,7 @@ struct NetImplDetail {
 #define WS_RECEIVE_BUFFER_SIZE	(62*1024)
 
 callback_t ftl::net::Universe::cbid__ = 0;
+Universe *Universe::instance_ = nullptr;
 
 Universe::Universe() :
 		Configurable(),
@@ -94,6 +95,9 @@ Universe::Universe(nlohmann::json &config) :
 		}
 		return true;
 	});
+
+	if (instance_ != nullptr) LOG(FATAL) << "Multiple net instances";
+	instance_ = this;
 }
 
 Universe::~Universe() {
diff --git a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
index 6901837f6..6281cdd51 100644
--- a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
+++ b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
@@ -81,6 +81,8 @@ PylonDevice::PylonDevice(nlohmann::json &config)
 		_configureCamera(lcam_);
 		if (rcam_) _configureCamera(rcam_);
 
+		value("gain", lcam_->Gain.GetValue());
+
 		lcam_->StartGrabbing( Pylon::GrabStrategy_OneByOne);
 		if (rcam_) rcam_->StartGrabbing( Pylon::GrabStrategy_OneByOne);
 
@@ -106,6 +108,11 @@ PylonDevice::PylonDevice(nlohmann::json &config)
 	//hres_hm_ = cv::cuda::HostMem(fullheight_, fullwidth_, CV_8UC4);
 	//rtmp_.create(fullheight_, fullwidth_, CV_8UC4);
 
+	//on("gain", [this]() {
+	//	lcam_->Gain.SetValue(value("gain",1.0));
+	//	rcam_->Gain.SetValue(value("gain",1.0));
+	//});
+
 	on("exposure", [this]() {
 		if (lcam_->GetDeviceInfo().GetModelName() != "Emulation") {
 			lcam_->ExposureTime.SetValue(value("exposure", 24000.0f));  // Exposure time in microseconds
@@ -138,6 +145,26 @@ PylonDevice::PylonDevice(nlohmann::json &config)
 
 		return true;
 	});
+
+	auto *net = ftl::net::Universe::getInstance();
+	if (!net->isBound("pylon_gain")) {
+		net->bind("pylon_gain", [this]() {
+			return (lcam_) ? lcam_->Gain.GetValue() : 0.0;
+		});
+		net->bind("pylon_exposure", [this]() {
+			return (lcam_) ? lcam_->ExposureTime.GetValue() : 0.0;
+		});
+		net->bind("pylon_white", [this]() {
+			cv::Vec3d wb;
+			lcam_->BalanceRatioSelector.SetValue(Basler_UniversalCameraParams::BalanceRatioSelector_Blue);
+			wb[0] = lcam_->BalanceRatio.GetValue();
+			lcam_->BalanceRatioSelector.SetValue(Basler_UniversalCameraParams::BalanceRatioSelector_Green);
+			wb[1] = lcam_->BalanceRatio.GetValue();
+			lcam_->BalanceRatioSelector.SetValue(Basler_UniversalCameraParams::BalanceRatioSelector_Red);
+			wb[2] = lcam_->BalanceRatio.GetValue();
+			return wb;
+		});
+	}
 }
 
 PylonDevice::~PylonDevice() {
@@ -200,13 +227,42 @@ void PylonDevice::_configureCamera(CBaslerUniversalInstantCamera *cam) {
 		LOG(WARNING) << "Could not change pixel format";
 	}
 
+	auto *net = ftl::net::Universe::getInstance();
+	auto tm = ftl::timer::getTimeMaster();
+
 	if (cam->GetDeviceInfo().GetModelName() != "Emulation") {
 		// Emulated device throws exception with these
-		cam->ExposureTime.SetValue(value("exposure", 24000.0f));  // Exposure time in microseconds
+		if (tm) {
+			double expo = net->call<double>(*tm, "pylon_exposure");
+			cam->ExposureTime.SetValue(expo);
+			LOG(INFO) << "Pylon exposure from master = " << expo;
+		} else {
+			cam->ExposureTime.SetValue(value("exposure", 24000.0f));  // Exposure time in microseconds
+		}
+
 		cam->AutoTargetBrightness.SetValue(0.3);
 		cam->LightSourcePreset.SetValue(Basler_UniversalCameraParams::LightSourcePreset_Tungsten2800K);  // White balance option
-		cam->BalanceWhiteAuto.SetValue(Basler_UniversalCameraParams::BalanceWhiteAuto_Once);
-		cam->GainAuto.SetValue(Basler_UniversalCameraParams::GainAuto_Once);
+
+		if (tm) {
+			cv::Vec3d white = net->call<cv::Vec3d>(*tm, "pylon_white");
+			cam->BalanceRatioSelector.SetValue(Basler_UniversalCameraParams::BalanceRatioSelector_Blue);
+			cam->BalanceRatio.SetValue(white[0]);
+			cam->BalanceRatioSelector.SetValue(Basler_UniversalCameraParams::BalanceRatioSelector_Green);
+			cam->BalanceRatio.SetValue(white[1]);
+			cam->BalanceRatioSelector.SetValue(Basler_UniversalCameraParams::BalanceRatioSelector_Red);
+			cam->BalanceRatio.SetValue(white[2]);
+			LOG(INFO) << "Pylon WB from master = " << white;
+		} else {
+			cam->BalanceWhiteAuto.SetValue(Basler_UniversalCameraParams::BalanceWhiteAuto_Once);
+		}
+
+		if (tm) {
+			double gain = net->call<double>(*tm, "pylon_gain");
+			cam->Gain.SetValue(gain);
+			LOG(INFO) << "Pylon Gain from master = " << gain;
+		} else {
+			cam->GainAuto.SetValue(Basler_UniversalCameraParams::GainAuto_Once);
+		}
 		cam->DeviceTemperatureSelector.SetValue(Basler_UniversalCameraParams::DeviceTemperatureSelector_Coreboard);
 	}
 }
-- 
GitLab