Skip to content
Snippets Groups Projects
Commit 1a338ed3 authored by Nicolas Pope's avatar Nicolas Pope
Browse files

Merge branch 'master' into feature/gui

parents 76b2a4e0 40be6d53
No related branches found
No related tags found
1 merge request!23Feature/gui implements #53
set(COMMONSRC set(COMMONSRC
src/config.cpp src/config.cpp
src/configuration.cpp src/configuration.cpp
src/configurable.cpp
src/opencv_to_pcl.cpp src/opencv_to_pcl.cpp
) )
...@@ -15,3 +16,5 @@ target_include_directories(ftlcommon PUBLIC ...@@ -15,3 +16,5 @@ target_include_directories(ftlcommon PUBLIC
PRIVATE src) PRIVATE src)
target_link_libraries(ftlcommon glog::glog ${OpenCV_LIBS} ${PCL_LIBRARIES}) target_link_libraries(ftlcommon glog::glog ${OpenCV_LIBS} ${PCL_LIBRARIES})
add_subdirectory(test)
...@@ -6,18 +6,36 @@ ...@@ -6,18 +6,36 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <map>
#include <list>
#include <functional>
#include <optional>
#define REQUIRED(...) required(__func__, __VA_ARGS__) #define REQUIRED(...) required(__func__, __VA_ARGS__)
namespace ftl { namespace ftl {
/**
* The Configurable class should be inherited by any entity that is to be
* configured using json objects. Additionally, any such object can then be
* reconfigured through changes to that underlying json object with event
* callbacks being triggered when specific changes occur.
*
* Configurables may also optionally have a URI that enables static methods
* of getting and setting configuration options. These static methods are used
* by network RPCs to enable remote reconfiguration.
*/
class Configurable { class Configurable {
public: public:
Configurable() {} Configurable() {}
explicit Configurable(nlohmann::json &config) : config_(config) { explicit Configurable(nlohmann::json &config) : config_(config) {
if (config["uri"].is_string()) __changeURI(config["uri"].get<std::string>(), this);
} }
/**
* Force the JSON object to have specific properties with a specific type.
* If not, emit errors and terminate the application.
*/
void required(const char *f, const std::vector<std::tuple<std::string, std::string, std::string>> &r) { void required(const char *f, const std::vector<std::tuple<std::string, std::string, std::string>> &r) {
bool diderror = false; bool diderror = false;
for (auto i : r) { for (auto i : r) {
...@@ -33,10 +51,55 @@ class Configurable { ...@@ -33,10 +51,55 @@ class Configurable {
nlohmann::json &getConfig() { return config_; } nlohmann::json &getConfig() { return config_; }
/**
* Get a configuration property from the json object. Returns an optional
* result which will be empty if the property does not exist or is not of
* the requested type.
*/
template <typename T>
std::optional<T> get(const std::string &name) {
try {
return config_[name].get<T>();
} catch (...) {
return {};
}
}
/**
* Change a configuration property and trigger any listening event handlers
* for that property. Also triggers the global listeners.
*/
template <typename T>
void set(const std::string &name, T value) {
config_[name] = value;
_trigger(name);
}
/**
* Add callback for whenever a specified property changes value.
* @param prop Name of property to watch
* @param callback A function object that will be called on change.
*/
void on(const std::string &prop, std::function<void(Configurable*, const std::string&)>);
protected: protected:
nlohmann::json config_; nlohmann::json config_;
private:
std::map<std::string, std::list<std::function<void(Configurable*, const std::string&)>>> observers_;
void _trigger(const std::string &name);
static void __changeURI(const std::string &uri, Configurable *cfg);
}; };
/*template <>
void Configurable::set<const std::string&>(const std::string &name, const std::string &value) {
config_[name] = value;
if (name == "uri") __changeURI(value, this);
_trigger(name);
}*/
} }
#endif // _FTL_CONFIGURABLE_HPP_ #endif // _FTL_CONFIGURABLE_HPP_
#include <ftl/configurable.hpp>
using ftl::Configurable;
using std::string;
using std::map;
using std::list;
using std::function;
void Configurable::_trigger(const string &name) {
auto ix = observers_.find(name);
if (ix != observers_.end()) {
for (auto &f : (*ix).second) {
try {
f(this, name);
} catch(...) {
LOG(ERROR) << "Exception in event handler for '" << name << "'";
}
}
}
}
void Configurable::on(const string &prop, function<void(Configurable*, const string&)> f) {
auto ix = observers_.find(prop);
if (ix == observers_.end()) {
observers_[prop] = {f};
} else {
(*ix).second.push_back(f);
}
}
void Configurable::__changeURI(const string &uri, Configurable *cfg) {
}
\ No newline at end of file
### Configurable Unit ################################################################
add_executable(configurable_unit
./tests.cpp
../src/configurable.cpp
./configurable_unit.cpp
)
target_include_directories(configurable_unit PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include")
target_link_libraries(configurable_unit
${URIPARSER_LIBRARIES}
glog::glog)
add_test(ConfigurableUnitTest configurable_unit)
This diff is collapsed.
#include "catch.hpp"
#include <ftl/configurable.hpp>
using ftl::Configurable;
using std::string;
SCENARIO( "Configurable::get()" ) {
GIVEN( "a non-existent property" ) {
nlohmann::json json = {{"test",5}};
Configurable cfg(json);
auto r = cfg.get<int>("test2");
REQUIRE( !r );
}
GIVEN( "a valid property" ) {
nlohmann::json json = {{"test",5}};
Configurable cfg(json);
auto r = cfg.get<int>("test");
REQUIRE( r );
REQUIRE( *r == 5 );
}
}
SCENARIO( "Configurable::on()" ) {
GIVEN( "a changed property with no handlers" ) {
nlohmann::json json = {{"test",5}};
Configurable cfg(json);
cfg.set("test", 55);
REQUIRE( *(cfg.get<int>("test")) == 55 );
}
GIVEN( "a changed property one handler" ) {
nlohmann::json json = {{"test",5}};
Configurable cfg(json);
bool trig = false;
cfg.on("test", [&trig](Configurable *c, const string &n) {
trig = true;
});
cfg.set("test", 55);
REQUIRE( trig );
}
GIVEN( "a changed property two handlers" ) {
nlohmann::json json = {{"test",5}};
Configurable cfg(json);
bool trig1 = false;
bool trig2 = false;
cfg.on("test", [&trig1](Configurable *c, const string &n) {
trig1 = true;
});
cfg.on("test", [&trig2](Configurable *c, const string &n) {
trig2 = true;
});
cfg.set("test", 55);
REQUIRE( (trig1 && trig2) );
}
}
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
{ {
"vision": { "vision": {
"type": "stereovideo", "type": "stereovideo",
"uri": "ftl://utu.fi/dummy/rgb-d",
"middlebury": { "middlebury": {
"dataset": "", "dataset": "",
"threshold": 10.0, "threshold": 10.0,
......
{ {
"vision": { "vision": {
"type": "stereovideo", "type": "stereovideo",
"uri": "ftl://utu.fi/dummy/rgb-d",
"middlebury": { "middlebury": {
"dataset": "", "dataset": "",
"threshold": 2.0, "threshold": 2.0,
...@@ -52,7 +53,10 @@ ...@@ -52,7 +53,10 @@
"window_size": 5, "window_size": 5,
"sigma": 1.5, "sigma": 1.5,
"lambda": 8000.0, "lambda": 8000.0,
"filter": true "filter": true,
"use_filter": false,
"filter_radius": 7,
"filter_iter": 3
}, },
"display": { "display": {
"flip_vert": false, "flip_vert": false,
...@@ -72,6 +76,7 @@ ...@@ -72,6 +76,7 @@
}, },
"reconstruction": { "reconstruction": {
"net": { "net": {
"listen": "tcp://*:9002",
"peers": ["tcp://localhost:9001"] "peers": ["tcp://localhost:9001"]
}, },
"sources": [{"type": "net", "uri": "ftl://utu.fi/dummy/rgb-d"}], "sources": [{"type": "net", "uri": "ftl://utu.fi/dummy/rgb-d"}],
...@@ -83,6 +88,40 @@ ...@@ -83,6 +88,40 @@
"left": false, "left": false,
"right": false "right": false
}, },
"virtual": {
"hash_renderer": true,
"SDFRayIncrementFactor": 0.8,
"SDFTruncation": 0.1,
"SDFRayThresSampleDistFactor": 50.5,
"SDFRayThresDistFactor": 50.0,
"focal": 400,
"width": 640,
"height": 480,
"max_depth": 10.0,
"min_depth": 0.1,
"SDFUseGradients": false,
"uri": "ftl://utu.fi/virt1/rgb-d"
},
"voxelhash": {
"adapterWidth": 852,
"adapterHeight": 480,
"sensorDepthMax": 8.0,
"sensorDepthMin": 1.0,
"SDFRayIncrementFactor": 0.8,
"SDFRayThresSampleDistFactor": 50.5,
"SDFRayThresDistFactor": 50.0,
"SDFUseGradients": false,
"hashNumBuckets": 500000,
"hashMaxCollisionLinkedListSize": 7,
"hashNumSDFBlocks": 300000,
"SDFVoxelSize": 0.01,
"SDFMaxIntegrationDistance": 15.0,
"SDFTruncation": 0.1,
"SDFTruncationScale": 0.05,
"SDFIntegrationWeightSample": 10,
"SDFIntegrationWeightMax": 255,
"hash_renderer": true
},
"registration": { "registration": {
"reference-source" : "ftl://utu.fi/dummy/rgb-d", "reference-source" : "ftl://utu.fi/dummy/rgb-d",
"calibration" : { "calibration" : {
...@@ -91,6 +130,12 @@ ...@@ -91,6 +130,12 @@
"delay" : 1000, "delay" : 1000,
"patternsize" : [9, 6] "patternsize" : [9, 6]
} }
},
"gui": {
"net": {
"peers": ["tcp://localhost:9002"]
},
"sources": [{"type": "net", "uri": "ftl://utu.fi/virt1/rgb-d"}]
} }
} }
} }
......
{ {
"vision": { "vision": {
"type": "stereovideo", "type": "stereovideo",
"uri": "ftl://utu.fi/dummy/rgb-d",
"middlebury": { "middlebury": {
"dataset": "", "dataset": "",
"threshold": 2.0, "threshold": 2.0,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment