diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp index 18ed5db3cefd62b2414552b68b4dccf22b015fd1..619e586555d2fff34b2d1b3a0b9137aeb6346f81 100644 --- a/applications/reconstruct/src/main.cpp +++ b/applications/reconstruct/src/main.cpp @@ -46,10 +46,10 @@ using ftl::net::Universe; using ftl::rgbd::Display; -using ftl::config; using std::string; using std::vector; using ftl::rgbd::RGBDSource; +using ftl::config::json_t; using json = nlohmann::json; using std::this_thread::sleep_for; @@ -229,22 +229,22 @@ struct Cameras { }; template <template<class> class Container> -std::map<string, Eigen::Matrix4f> runRegistration(ftl::net::Universe &net, Container<Cameras> &inputs) { +std::map<string, Eigen::Matrix4f> runRegistration(ftl::Configurable *root, ftl::net::Universe &net, Container<Cameras> &inputs) { std::map<string, Eigen::Matrix4f> registration; // NOTE: uses config["registration"] - if (!config["registration"].is_object()) { + if (!root->getConfig()["registration"].is_object()) { LOG(FATAL) << "Configuration missing \"registration\" entry!"; return registration; } - int iter = (int) config["registration"]["calibration"]["iterations"]; - int delay = (int) config["registration"]["calibration"]["delay"]; - float max_error = (int) config["registration"]["calibration"]["max_error"]; - string ref_uri = (string) config["registration"]["reference-source"]; - cv::Size pattern_size( (int) config["registration"]["calibration"]["patternsize"][0], - (int) config["registration"]["calibration"]["patternsize"][1]); + int iter = (int) root->getConfig()["registration"]["calibration"]["iterations"]; + int delay = (int) root->getConfig()["registration"]["calibration"]["delay"]; + float max_error = (int) root->getConfig()["registration"]["calibration"]["max_error"]; + string ref_uri = (string) root->getConfig()["registration"]["reference-source"]; + cv::Size pattern_size( (int) root->getConfig()["registration"]["calibration"]["patternsize"][0], + (int) root->getConfig()["registration"]["calibration"]["patternsize"][1]); // config["registration"] done @@ -313,23 +313,25 @@ std::map<string, Eigen::Matrix4f> runRegistration(ftl::net::Universe &net, Conta } #endif -static void run() { - Universe net(config["net"]); +static void run(ftl::Configurable *root) { + Universe *net = ftl::create<Universe>(root, "net"); // Make sure connections are complete - sleep_for(milliseconds(500)); + //sleep_for(milliseconds(500)); + net->waitConnections(); - if (!config["sources"].is_array()) { + std::vector<Cameras> inputs; + auto sources = root->get<vector<json_t>>("sources"); + + if (!sources) { LOG(ERROR) << "No sources configured!"; return; } - - std::vector<Cameras> inputs; //std::vector<Display> displays; // TODO Allow for non-net source types - for (auto &src : config["sources"]) { - RGBDSource *in = ftl::rgbd::RGBDSource::create(src, &net); //new ftl::rgbd::NetSource(src, &net); + for (auto &src : *sources) { + RGBDSource *in = ftl::rgbd::RGBDSource::create(src, net); //new ftl::rgbd::NetSource(src, &net); if (!in) { LOG(ERROR) << "Unrecognised source: " << src; } else { @@ -355,8 +357,8 @@ static void run() { // load point cloud transformations std::map<string, Eigen::Matrix4f> registration; - if (config["registration"]["calibration"]["run"]) { - registration = runRegistration(net, inputs); + if (root->getConfig()["registration"]["calibration"]["run"]) { + registration = runRegistration(root, *net, inputs); } else { LOG(INFO) << "LOAD REG"; @@ -367,7 +369,7 @@ static void run() { // (registration includes every camera) bool valid_registration = true; - string ref_input = config["registration"]["reference-source"]; + string ref_input = root->getConfig()["registration"]["reference-source"]; // check every camera is included in registration for (auto &input : inputs) { @@ -417,28 +419,28 @@ static void run() { for (auto &input : inputs) { LOG(INFO) << " " + (string) input.source->getConfig()["uri"]; } //vector<PointCloud<PointXYZRGB>::Ptr> clouds(inputs.size()); - ftl::rgbd::Display display(config["display"]); // todo - ftl::rgbd::VirtualSource *virt = new ftl::rgbd::VirtualSource(config["virtual"], &net); - ftl::voxhash::SceneRep scene(config["voxelhash"]); - virt->setScene(&scene); - display.setSource(virt); + ftl::rgbd::Display *display = ftl::create<ftl::rgbd::Display>(root, "display"); + ftl::rgbd::VirtualSource *virt = ftl::create<ftl::rgbd::VirtualSource>(root, "virtual", net); + ftl::voxhash::SceneRep *scene = ftl::create<ftl::voxhash::SceneRep>(root, "voxelhash"); + virt->setScene(scene); + display->setSource(virt); unsigned char frameCount = 0; bool paused = false; // Keyboard camera controls - display.onKey([&paused](int key) { + display->onKey([&paused](int key) { if (key == 32) paused = !paused; }); int active = inputs.size(); - while (active > 0 && display.active()) { + while (active > 0 && display->active()) { active = 0; if (!paused) { //net.broadcast("grab"); // To sync cameras - scene.nextFrame(); + scene->nextFrame(); for (size_t i = 0; i < inputs.size(); i++) { // Get the RGB-Depth frame from input @@ -460,7 +462,7 @@ static void run() { // Send to GPU and merge view into scene inputs[i].gpu.updateParams(inputs[i].params); inputs[i].gpu.updateData(depth, rgba); - scene.integrate(inputs[i].source->getPose(), inputs[i].gpu, inputs[i].params, nullptr); + scene->integrate(inputs[i].source->getPose(), inputs[i].gpu, inputs[i].params, nullptr); } } else { active = 1; @@ -468,11 +470,10 @@ static void run() { frameCount++; - display.update(); + display->update(); } } int main(int argc, char **argv) { - ftl::configure(argc, argv, "reconstruction"); - run(); + run(ftl::configure(argc, argv, "reconstruction_default")); } diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp index 99c6937725e5d418802f59fa0b4134ab0f406da0..e9bcc690f11440596727a53f9b6f97e02e86261e 100644 --- a/applications/vision/src/main.cpp +++ b/applications/vision/src/main.cpp @@ -50,7 +50,6 @@ using std::mutex; using std::unique_lock; using cv::Mat; using json = nlohmann::json; -using ftl::config; namespace ftl { void disparityToDepth(const cv::Mat &disparity, cv::Mat &depth, const cv::Mat &q) { @@ -78,44 +77,51 @@ void disparityToDepth(const cv::Mat &disparity, cv::Mat &depth, const cv::Mat &q }; -static void run(const string &file) { - ctpl::thread_pool pool(2); - Universe net(config["net"]); +static void run(ftl::Configurable *root) { + Universe *net = ftl::create<Universe>(root, "net"); LOG(INFO) << "Net started."; + auto paths = root->get<vector<string>>("paths"); + string file = ""; + if (paths && (*paths).size() > 0) file = (*paths)[0]; + StereoVideoSource *source = nullptr; - source = new StereoVideoSource(config, file); + source = ftl::create<StereoVideoSource>(root, "source", file); - Display display(config["display"], "local"); + Display *display = ftl::create<Display>(root, "display", "local"); - Streamer stream(config["stream"], &net); - stream.add(source); - stream.run(); + Streamer *stream = ftl::create<Streamer>(root, "stream", net); + stream->add(source); + stream->run(); - while (display.active()) { + while (display->active()) { cv::Mat rgb, depth; source->getRGBD(rgb, depth); - if (!rgb.empty()) display.render(rgb, depth, source->getParameters()); - display.wait(10); + if (!rgb.empty()) display->render(rgb, depth, source->getParameters()); + display->wait(10); } - stream.stop(); + stream->stop(); LOG(INFO) << "Finished."; + delete stream; + delete display; + delete source; + delete net; } int main(int argc, char **argv) { std::cout << "FTL Vision Node " << FTL_VERSION_LONG << std::endl; - auto paths = ftl::configure(argc, argv, "vision"); + auto root = ftl::configure(argc, argv, "vision_default"); - config["paths"] = paths; + //config["ftl://vision/default"]["paths"] = paths; // Choose normal or middlebury modes - if (config["middlebury"]["dataset"] == "") { + //if (config["middlebury"]["dataset"] == "") { std::cout << "Loading..." << std::endl; - run((paths.size() > 0) ? paths[0] : ""); - } else { - ftl::middlebury::test(config); - } + run(root); + //} else { + // ftl::middlebury::test(config); + //} } diff --git a/components/common/cpp/CMakeLists.txt b/components/common/cpp/CMakeLists.txt index dac189bb61df6d19f1a8d0d8b1ed299c608c6054..56a74f2664127f3ad18390d1fbfc47d581d4e95b 100644 --- a/components/common/cpp/CMakeLists.txt +++ b/components/common/cpp/CMakeLists.txt @@ -1,10 +1,13 @@ set(COMMONSRC src/config.cpp + src/uri.cpp src/configuration.cpp src/configurable.cpp src/opencv_to_pcl.cpp ) +check_function_exists(uriParseSingleUriA HAVE_URIPARSESINGLE) + add_library(ftlcommon ${COMMONSRC}) target_compile_options(ftlcommon PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-fPIC>) @@ -14,7 +17,7 @@ target_include_directories(ftlcommon PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include> PRIVATE src) -target_link_libraries(ftlcommon glog::glog ${OpenCV_LIBS} ${PCL_LIBRARIES}) +target_link_libraries(ftlcommon glog::glog ${OpenCV_LIBS} ${PCL_LIBRARIES} ${URIPARSER_LIBRARIES}) add_subdirectory(test) diff --git a/components/common/cpp/include/ftl/configurable.hpp b/components/common/cpp/include/ftl/configurable.hpp index 7008c9b1edddf412c6d05130522977186f9d9cee..c1f903b61df4004e458c54f243fd0014c69ff96f 100644 --- a/components/common/cpp/include/ftl/configurable.hpp +++ b/components/common/cpp/include/ftl/configurable.hpp @@ -27,27 +27,17 @@ namespace ftl { */ class Configurable { public: - Configurable() {} + Configurable(); explicit Configurable(nlohmann::json &config) : config_(config) { if (config["uri"].is_string()) __changeURI(config["uri"].get<std::string>(), this); } + virtual ~Configurable() {} /** * 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) { - bool diderror = false; - for (auto i : r) { - auto [name, desc, type] = i; - if (config_[name].type_name() != type) { - LOG(ERROR) << "Missing required option in \"" << f << "\": \"" << name << "\" - " << desc; - LOG(ERROR) << " Got type " << config_[name].type_name() << " but expected " << type; - diderror = true; - } - } - if (diderror) LOG(FATAL) << "Cannot continue without required option"; - } + void required(const char *f, const std::vector<std::tuple<std::string, std::string, std::string>> &r); nlohmann::json &getConfig() { return config_; } @@ -57,12 +47,15 @@ class Configurable { * the requested type. */ template <typename T> - std::optional<T> get(const std::string &name) { - try { - return config_[name].get<T>(); - } catch (...) { - return {}; - } + std::optional<T> get(const std::string &name); + + /** + * Get a configuration property, but return a default if not found. + */ + template <typename T> + T value(const std::string &name, T def) { + auto r = get<T>(name); + return (r) ? *r : def; } /** @@ -102,4 +95,33 @@ void Configurable::set<const std::string&>(const std::string &name, const std::s } +#include <ftl/configuration.hpp> + +template <typename T> +std::optional<T> ftl::Configurable::get(const std::string &name) { + if (!config_[name].is_null()) { + try { + return config_[name].get<T>(); + } catch (...) { + return {}; + } + } else if (config_["$ref"].is_string()) { + // TODO(Nick) Add # if missing + // TODO(Nick) Cache result of ref loopkup + std::string res_uri = config_["$ref"].get<std::string>()+"/"+name; + auto &r = ftl::config::resolve(res_uri); + + LOG(INFO) << "GET Resolve: " << res_uri << " = " << r; + + try { + return r.get<T>(); + } catch (...) { + LOG(ERROR) << "Missing: " << config_["$id"].get<std::string>()+"/"+name; + return {}; + } + } else { + return {}; + } +} + #endif // _FTL_CONFIGURABLE_HPP_ diff --git a/components/common/cpp/include/ftl/configuration.hpp b/components/common/cpp/include/ftl/configuration.hpp index 685c9b4ba30e08268d4a48c2b50ad852e84cf7b8..9f8c6e0fda3033f0102b2ac1de95e7cb3afe3790 100644 --- a/components/common/cpp/include/ftl/configuration.hpp +++ b/components/common/cpp/include/ftl/configuration.hpp @@ -1,26 +1,125 @@ +#pragma once #ifndef _FTL_COMMON_CONFIGURATION_HPP_ #define _FTL_COMMON_CONFIGURATION_HPP_ #include <nlohmann/json.hpp> +//#include <ftl/configurable.hpp> #include <string> #include <vector> #include <optional> namespace ftl { -extern nlohmann::json config; +class Configurable; bool is_directory(const std::string &path); bool is_file(const std::string &path); bool create_directory(const std::string &path); - bool is_video(const std::string &file); +namespace config { + +typedef nlohmann::json json_t; + std::optional<std::string> locateFile(const std::string &name); -std::vector<std::string> configure(int argc, char **argv, const std::string &app); +Configurable *configure(int argc, char **argv, const std::string &root); + +/** + * Resolve a JSON schema reference, but do not wait for a remote reference + * if it is not available. A null entity is returned if not resolved. + */ +json_t &resolve(const std::string &); + +/** + * Resolve a reference object, or if not a reference object it simply returns + * the original object. A reference object with additional properties other + * than $ref will result in a new merged object. + */ +json_t &resolve(json_t &ref); + +/** + * Resolve a JSON schema reference and block until such a reference can be + * resolved correctly. + */ +json_t &resolveWait(const std::string &); + +/** + * Using a JSON schema reference, find an existing instance of a Configurable + * object for that reference. Or return nullptr if not found. + */ +Configurable *find(const std::string &uri); + +/** + * Adds a Configurable instance to the database of instances so that it can + * then be resolved using find(). + */ +void registerConfigurable(Configurable *cfg); + +template <typename T, typename... ARGS> +T *create(json_t &link, ARGS ...args); + +template <typename T, typename... ARGS> +T *create(ftl::Configurable *parent, const std::string &name, ARGS ...args); + +void set(const std::string &uri, const nlohmann::json &); + +} // namespace config + +// Deprecated +using config::create; +using config::locateFile; +using config::configure; + +} // namespace ftl + +#include <ftl/configurable.hpp> + +template <typename T, typename... ARGS> +T *ftl::config::create(json_t &link, ARGS ...args) { + auto &r = link; // = ftl::config::resolve(link); + + if (!r["$id"].is_string()) { + LOG(FATAL) << "Entity does not have $id or parent: " << r; + return nullptr; + } + + ftl::Configurable *cfg = ftl::config::find(r["$id"].get<std::string>()); + if (!cfg) { + // try { + cfg = new T(r, args...); + //} catch(...) { + // LOG(FATAL) << "Could not construct " << link; + //} + } + + try { + return dynamic_cast<T*>(cfg); + } catch(...) { + LOG(FATAL) << "Configuration URI object is of wrong type: " << link; + return nullptr; + } +} + +template <typename T, typename... ARGS> +T *ftl::config::create(ftl::Configurable *parent, const std::string &name, ARGS ...args) { + nlohmann::json &entity = ftl::config::resolve(parent->getConfig()[name]); + + if (entity.is_object()) { + if (!entity["$id"].is_string()) { + // TODO(Nick) Check for # in URI + entity["$id"] = *parent->get<std::string>("$id") + std::string("/") + name; + } + } /*else { + nlohmann::json &res = resolve(entity); + if (!res["uri"].is_string()) { + res["uri"] = *parent->get<std::string>("uri") + std::string("/") + name; + LOG(WARNING) << "Creating false URI!!! - " << res["uri"].get<std::string>(); + } + }*/ -}; + return create<T>(entity, args...); +} #endif // _FTL_COMMON_CONFIGURATION_HPP_ diff --git a/components/net/cpp/include/ftl/uri.hpp b/components/common/cpp/include/ftl/uri.hpp similarity index 84% rename from components/net/cpp/include/ftl/uri.hpp rename to components/common/cpp/include/ftl/uri.hpp index 1931c8196c5e73acea16390c2dee8613a5324f2d..be6b7fd3e52f27d9a0769e180a994bd781c7e85e 100644 --- a/components/net/cpp/include/ftl/uri.hpp +++ b/components/common/cpp/include/ftl/uri.hpp @@ -39,9 +39,17 @@ namespace ftl { scheme_t getProtocol() const { return m_proto; }; scheme_t getScheme() const { return m_proto; }; const std::string &getPath() const { return m_path; }; + const std::string &getFragment() const { return m_frag; } std::string getQuery() const; const std::string &getBaseURI() const { return m_base; }; - const std::string &getPathSegment(int n) const { return m_pathseg[n]; }; + + /** + * Get the URI without query parameters, and limit path to length N. + * If N is negative then it is taken from full path length. + */ + std::string getBaseURI(int n); + + std::string getPathSegment(int n) const; void setAttribute(const std::string &key, const std::string &value); void setAttribute(const std::string &key, int value); @@ -60,10 +68,12 @@ namespace ftl { bool m_valid; std::string m_host; std::string m_path; + std::string m_frag; std::string m_base; std::vector<std::string> m_pathseg; int m_port; scheme_t m_proto; + std::string m_protostr; // std::string m_query; std::map<std::string, std::string> m_qmap; }; diff --git a/components/common/cpp/include/nlohmann/json.hpp b/components/common/cpp/include/nlohmann/json.hpp index c9af0bed36d6852de735b8d0b5d034614aef0e54..68b715f045b97286b0d4849c67a9a747cac8f88b 100644 --- a/components/common/cpp/include/nlohmann/json.hpp +++ b/components/common/cpp/include/nlohmann/json.hpp @@ -3977,12 +3977,24 @@ scan_number_done: return token_type::parse_error; } + bool incomment = false; + // read next character and ignore whitespace do { get(); - } - while (current == ' ' or current == '\t' or current == '\n' or current == '\r'); + + // Nick: Add support for inline comments + if (!incomment && current == '/') { + get(); + if (current != '/') { + error_message = "missing / for inline comment"; + return token_type::parse_error; + } + incomment = true; + } else if (incomment && (current == '\n' || current == '\r')) incomment = false; + } + while (incomment or current == ' ' or current == '\t' or current == '\n' or current == '\r'); switch (current) { diff --git a/components/common/cpp/src/configurable.cpp b/components/common/cpp/src/configurable.cpp index c4520b12e9957f8d8cd11118865b935f0cfa2975..d770ae6e7003a21bc4a9d15d9c523cb0f0339f84 100644 --- a/components/common/cpp/src/configurable.cpp +++ b/components/common/cpp/src/configurable.cpp @@ -5,6 +5,25 @@ using std::string; using std::map; using std::list; using std::function; +using ftl::config::json_t; + +extern nlohmann::json null_json; + +Configurable::Configurable() : config_(null_json) {} + +void Configurable::required(const char *f, const std::vector<std::tuple<std::string, std::string, std::string>> &r) { + bool diderror = false; + for (auto i : r) { + auto [name, desc, type] = i; + auto ent = get<json_t>(name); + if (!ent || (*ent).type_name() != type) { + LOG(ERROR) << "Missing required option in \"" << f << "\": \"" << name << "\" - " << desc; + //LOG(ERROR) << " Got type " << (*ent).type_name() << " but expected " << type; + diderror = true; + } + } + if (diderror) LOG(FATAL) << "Cannot continue without required option"; +} void Configurable::_trigger(const string &name) { auto ix = observers_.find(name); diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp index a302d606bc32d8d2cd1ee8cc18b66387beab54bf..07fad52d1021b8146d63722f36b157262b199148 100644 --- a/components/common/cpp/src/configuration.cpp +++ b/components/common/cpp/src/configuration.cpp @@ -11,13 +11,15 @@ #include <nlohmann/json.hpp> #include <ftl/configuration.hpp> +#include <ftl/configurable.hpp> +#include <ftl/uri.hpp> #include <fstream> #include <string> #include <map> #include <iostream> -using nlohmann::json; +using ftl::config::json_t; using std::ifstream; using std::string; using std::map; @@ -25,13 +27,20 @@ using std::vector; using std::optional; using ftl::is_file; using ftl::is_directory; +using ftl::Configurable; // Store loaded configuration namespace ftl { -json config; +namespace config { +json_t config; +//json_t root_config; }; +}; + +using ftl::config::config; +//using ftl::config::root_config; -using ftl::config; +static Configurable *rootCFG = nullptr; bool ftl::is_directory(const std::string &path) { #ifdef WIN32 @@ -85,11 +94,14 @@ bool ftl::create_directory(const std::string &path) { #endif } -optional<string> ftl::locateFile(const string &name) { - auto paths = config["paths"]; +optional<string> ftl::config::locateFile(const string &name) { + if (is_file(name)) return name; + + auto paths = rootCFG->getConfig()["paths"]; - if (!paths.is_null()) { - for (string p : paths) { + if (paths.is_array()) { + vector<string> vpaths = paths.get<vector<string>>(); + for (string p : vpaths) { if (is_directory(p)) { if (is_file(p+"/"+name)) { return p+"/"+name; @@ -116,11 +128,11 @@ static bool mergeConfig(const string path) { //i.open(path); if (i.is_open()) { try { - json t; + nlohmann::json t; i >> t; config.merge_patch(t); return true; - } catch (json::parse_error& e) { + } catch (nlohmann::json::parse_error& e) { LOG(ERROR) << "Parse error in loading config: " << e.what(); return false; } catch (...) { @@ -131,11 +143,128 @@ static bool mergeConfig(const string path) { } } +static std::map<std::string, json_t*> config_index; +static std::map<std::string, ftl::Configurable*> config_instance; + +/* + * Recursively URI index the JSON structure. + */ +static void _indexConfig(json_t &cfg) { + if (cfg.is_object()) { + auto id = cfg["$id"]; + if (id.is_string()) { + LOG(INFO) << "Indexing: " << id.get<string>(); + config_index[id.get<string>()] = &cfg; + } + + for (auto i : cfg.items()) { + if (i.value().is_structured()) { + _indexConfig(cfg[i.key()]); + } + } + } // TODO(Nick) Arrays.... +} + +ftl::Configurable *ftl::config::find(const std::string &uri) { + auto ix = config_instance.find(uri); + if (ix == config_instance.end()) return nullptr; + else return (*ix).second; +} + +void ftl::config::registerConfigurable(ftl::Configurable *cfg) { + auto uri = cfg->get<string>("$id"); + if (!uri) { + LOG(FATAL) << "Configurable object is missing $id property"; + return; + } + auto ix = config_instance.find(*uri); + if (ix == config_instance.end()) { + LOG(FATAL) << "Attempting to create a duplicate object: " << *uri; + } else { + config_instance[*uri] = cfg; + } +} + +json_t null_json; + +json_t &ftl::config::resolve(const std::string &puri) { + string uri_str = puri; + + // TODO(Nick) Must support alternative root (last $id) + if (uri_str.at(0) == '#') { + uri_str = config["$id"].get<string>() + uri_str; + } + + ftl::URI uri(uri_str); + if (uri.isValid()) { + std::string u = uri.getBaseURI(); + LOG(INFO) << "Resolve URI: " << u; + auto ix = config_index.find(u); + if (ix == config_index.end()) { + LOG(FATAL) << "Cannot find resource: " << u; + } + + auto ptr = nlohmann::json::json_pointer("/"+uri.getFragment()); + try { + return resolve((*ix).second->at(ptr)); + } catch(...) { + return null_json; + } + //} +/* + + int n = 0; + while (u.size() != 0) { + LOG(INFO) << "Resolve URI: " << u; + auto ix = config_index.find(u); + if (ix == config_index.end()) { + u = uri.getBaseURI(--n); + continue; + } + //LOG(INFO) << "FOUND URI " << *(*ix).second; + + if (n == 0) { + return *(*ix).second; + } else { + // Must apply path segments again... + nlohmann::json *c = (*ix).second; + while (n < 0) { + auto seg = uri.getPathSegment(n++); + c = &(*c)[seg]; + + // Recursive resolve... + if ((*c).is_string()) { + c = &resolve(*c); + } + } + + // Give it the correct URI + if (!(*c)["$id"].is_string()) { + (*c)["$id"] = uri.getBaseURI(); + } + + return *c; + } + } + LOG(FATAL) << "Unresolvable configuration URI: " << uri.getBaseURI(); + return null_json;*/ + } else { + return null_json; + } +} + +json_t &ftl::config::resolve(json_t &j) { + if (j.is_object() && j["$ref"].is_string()) { + return resolve(j["$ref"].get<string>()); + } else { + return j; + } +} + /** * Find and load a JSON configuration file */ -static bool findConfiguration(const string &file, const vector<string> &paths, - const std::string &app) { +static bool findConfiguration(const string &file, const vector<string> &paths) { bool f = false; bool found = false; @@ -169,7 +298,7 @@ static bool findConfiguration(const string &file, const vector<string> &paths, } if (found) { - config = config[app]; + _indexConfig(config); return true; } else { return false; @@ -214,9 +343,10 @@ static map<string, string> read_options(char ***argv, int *argc) { * Put command line options into json config. If config element does not exist * or is of a different type then report an error. */ -static void process_options(const map<string, string> &opts) { +static void process_options(Configurable *root, const map<string, string> &opts) { for (auto opt : opts) { if (opt.first == "config") continue; + if (opt.first == "root") continue; if (opt.first == "version") { std::cout << "Future-Tech Lab - v" << FTL_VERSION << std::endl; @@ -225,21 +355,22 @@ static void process_options(const map<string, string> &opts) { } try { - auto ptr = json::json_pointer("/"+opt.first); + auto ptr = nlohmann::json::json_pointer("/"+opt.first); // TODO(nick) Allow strings without quotes - auto v = json::parse(opt.second); - if (v.type() != config.at(ptr).type()) { - LOG(ERROR) << "Incorrect type for argument " << opt.first; + auto v = nlohmann::json::parse(opt.second); + std::string type = root->getConfig().at(ptr).type_name(); + if (type != "null" && v.type_name() != type) { + LOG(ERROR) << "Incorrect type for argument " << opt.first << " - expected '" << type << "', got '" << v.type_name() << "'"; continue; } - config.at(ptr) = v; + root->getConfig().at(ptr) = v; } catch(...) { - LOG(ERROR) << "Unrecognised option: " << opt.first; + LOG(ERROR) << "Unrecognised option: " << *root->get<string>("$id") << "#" << opt.first; } } } -vector<string> ftl::configure(int argc, char **argv, const std::string &app) { +Configurable *ftl::config::configure(int argc, char **argv, const std::string &root) { argc--; argv++; @@ -251,11 +382,22 @@ vector<string> ftl::configure(int argc, char **argv, const std::string &app) { paths.push_back(argv[0]); } - if (!findConfiguration(options["config"], paths, app)) { + if (!findConfiguration(options["config"], paths)) { LOG(FATAL) << "Could not find any configuration!"; } - process_options(options); - return paths; + string root_str = (options.find("root") != options.end()) ? nlohmann::json::parse(options["root"]).get<string>() : root; + + Configurable *rootcfg = create<Configurable>(config); + if (root_str.size() > 0) { + LOG(INFO) << "Setting root to " << root_str; + rootcfg = create<Configurable>(rootcfg, root_str); + } + + //root_config = rootcfg->getConfig(); + rootCFG = rootcfg; + rootcfg->set("paths", paths); + process_options(rootcfg, options); + return rootcfg; } diff --git a/components/net/cpp/src/uri.cpp b/components/common/cpp/src/uri.cpp similarity index 72% rename from components/net/cpp/src/uri.cpp rename to components/common/cpp/src/uri.cpp index e23435246d42fc72adc2e18dca2ce199ce486688..2fcbd86d1d3c824627641474720067015fb8debd 100644 --- a/components/net/cpp/src/uri.cpp +++ b/components/common/cpp/src/uri.cpp @@ -21,6 +21,7 @@ URI::URI(const URI &c) { m_pathseg = c.m_pathseg; m_qmap = c.m_qmap; m_base = c.m_base; + m_frag = c.m_frag; } void URI::_parse(uri_t puri) { @@ -39,6 +40,7 @@ void URI::_parse(uri_t puri) { m_port = -1; m_proto = SCHEME_NONE; m_path = ""; + m_frag = ""; } else { m_host = std::string(uri.hostText.first, uri.hostText.afterLast - uri.hostText.first); @@ -50,6 +52,7 @@ void URI::_parse(uri_t puri) { else if (prototext == "ws") m_proto = SCHEME_WS; else if (prototext == "ipc") m_proto = SCHEME_IPC; else m_proto = SCHEME_OTHER; + m_protostr = prototext; std::string porttext = std::string(uri.portText.first, uri.portText.afterLast - uri.portText.first); m_port = atoi(porttext.c_str()); @@ -83,10 +86,16 @@ void URI::_parse(uri_t puri) { uriFreeUriMembersA(&uri); + auto fraglast = (uri.query.first != NULL) ? uri.query.first : uri.fragment.afterLast; + if (uri.fragment.first != NULL && fraglast - uri.fragment.first > 0) { + m_frag = std::string(uri.fragment.first, fraglast - uri.fragment.first); + } + m_valid = m_proto != SCHEME_NONE && m_host.size() > 0; if (m_valid) { if (m_qmap.size() > 0) m_base = std::string(uri.scheme.first, uri.query.first - uri.scheme.first - 1); + else if (uri.fragment.first != NULL) m_base = std::string(uri.scheme.first, uri.fragment.first - uri.scheme.first - 1); else m_base = std::string(uri.scheme.first); } } @@ -96,6 +105,34 @@ string URI::to_string() const { return (m_qmap.size() > 0) ? m_base + "?" + getQuery() : m_base; } +string URI::getPathSegment(int n) const { + int N = (n < 0) ? m_pathseg.size()+n : n; + if (N < 0 || N >= m_pathseg.size()) return ""; + else return m_pathseg[N]; +} + +string URI::getBaseURI(int n) { + if (n >= (int)m_pathseg.size()) return m_base; + if (n >= 0) { + string r = m_protostr + string("://") + m_host + ((m_port != 0) ? string(":") + std::to_string(m_port) : ""); + for (int i=0; i<n; i++) { + r += "/"; + r += getPathSegment(i); + } + + return r; + } else if (m_pathseg.size()+n >= 0) { + string r = m_protostr + string("://") + m_host + ((m_port != 0) ? string(":") + std::to_string(m_port) : ""); + int N = m_pathseg.size()+n; + for (int i=0; i<N; i++) { + r += "/"; + r += getPathSegment(i); + } + + return r; + } else return ""; +} + string URI::getQuery() const { string q; for (auto x : m_qmap) { diff --git a/components/common/cpp/test/CMakeLists.txt b/components/common/cpp/test/CMakeLists.txt index 67d8918396271c81fb2befdb5e19030bad29e0c7..c49d192bacfe66df7034612713dbc7e752291cb7 100644 --- a/components/common/cpp/test/CMakeLists.txt +++ b/components/common/cpp/test/CMakeLists.txt @@ -2,6 +2,9 @@ add_executable(configurable_unit ./tests.cpp ../src/configurable.cpp + ../src/uri.cpp + ../src/config.cpp + ../src/configuration.cpp ./configurable_unit.cpp ) target_include_directories(configurable_unit PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include") @@ -9,8 +12,18 @@ target_link_libraries(configurable_unit ${URIPARSER_LIBRARIES} glog::glog) +### URI ######################################################################## +add_executable(uri_unit + ./tests.cpp + ../src/uri.cpp + ./uri_unit.cpp) +target_include_directories(uri_unit PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include") +target_link_libraries(uri_unit + ${URIPARSER_LIBRARIES}) + add_test(ConfigurableUnitTest configurable_unit) +add_test(URIUnitTest uri_unit) diff --git a/components/net/cpp/test/uri_unit.cpp b/components/common/cpp/test/uri_unit.cpp similarity index 52% rename from components/net/cpp/test/uri_unit.cpp rename to components/common/cpp/test/uri_unit.cpp index a9fde4e8080ef98732c15149e6bd824dd1b31723..be94d76c12c6eee26af890b8178def8fd5914b4b 100644 --- a/components/net/cpp/test/uri_unit.cpp +++ b/components/common/cpp/test/uri_unit.cpp @@ -25,6 +25,53 @@ SCENARIO( "URI() can parse valid URIs", "[utility]" ) { REQUIRE( uri.getPath() == "/test/case.html" ); } + GIVEN( "a valid fragment" ) { + URI uri("http://localhost:8080/test/case.html#frag"); + + REQUIRE( uri.isValid() ); + REQUIRE( uri.getScheme() == URI::SCHEME_HTTP ); + REQUIRE( uri.getHost() == "localhost" ); + REQUIRE( (uri.getPort() == 8080) ); + REQUIRE( uri.getPath() == "/test/case.html" ); + REQUIRE( uri.getFragment() == "frag"); + } + + GIVEN( "a multipart valid fragment" ) { + URI uri("http://localhost:8080/test/case.html#frag/second"); + + REQUIRE( uri.isValid() ); + REQUIRE( uri.getScheme() == URI::SCHEME_HTTP ); + REQUIRE( uri.getHost() == "localhost" ); + REQUIRE( (uri.getPort() == 8080) ); + REQUIRE( uri.getPath() == "/test/case.html" ); + REQUIRE( uri.getFragment() == "frag/second"); + REQUIRE( uri.getBaseURI() == "http://localhost:8080/test/case.html"); + } + + GIVEN( "an empty fragment" ) { + URI uri("http://localhost:8080/test/case.html#"); + + REQUIRE( uri.isValid() ); + REQUIRE( uri.getScheme() == URI::SCHEME_HTTP ); + REQUIRE( uri.getHost() == "localhost" ); + REQUIRE( (uri.getPort() == 8080) ); + REQUIRE( uri.getPath() == "/test/case.html" ); + REQUIRE( uri.getFragment() == ""); + REQUIRE( uri.getBaseURI() == "http://localhost:8080/test/case.html"); + } + + /*GIVEN( "a valid fragment with query" ) { + URI uri("http://localhost:8080/test/case.html#frag?q=4"); + + REQUIRE( uri.isValid() ); + REQUIRE( uri.getScheme() == URI::SCHEME_HTTP ); + REQUIRE( uri.getHost() == "localhost" ); + REQUIRE( (uri.getPort() == 8080) ); + REQUIRE( uri.getPath() == "/test/case.html" ); + REQUIRE( uri.getQuery() == "q=4" ); + REQUIRE( uri.getFragment() == "frag"); + }*/ + GIVEN( "a valid scheme with path and query" ) { URI uri("ftl://utu.fi/test/case.html?v=1"); @@ -89,3 +136,25 @@ SCENARIO( "URI::getAttribute() from query" ) { } } +SCENARIO( "URI::getBaseURI(N)" ) { + GIVEN( "an N of 0" ) { + URI uri("http://localhost:1000/hello/world"); + REQUIRE( uri.getBaseURI(0) == "http://localhost:1000" ); + } + + GIVEN( "an N of -1" ) { + URI uri("http://localhost:1000/hello/world"); + REQUIRE( uri.getBaseURI(-1) == "http://localhost:1000/hello" ); + } + + GIVEN( "an N of 1" ) { + URI uri("http://localhost:1000/hello/world"); + REQUIRE( uri.getBaseURI(1) == "http://localhost:1000/hello" ); + } + + GIVEN( "an N of 2" ) { + URI uri("http://localhost:1000/hello/world"); + REQUIRE( uri.getBaseURI(2) == "http://localhost:1000/hello/world" ); + } +} + diff --git a/components/net/cpp/CMakeLists.txt b/components/net/cpp/CMakeLists.txt index d1e06de139d3bc5604cc68b95dc3d53b6a2d6937..c7e8bb34119a6b2f70b5a34b6e4b7e4911fe465f 100644 --- a/components/net/cpp/CMakeLists.txt +++ b/components/net/cpp/CMakeLists.txt @@ -4,7 +4,6 @@ add_library(ftlnet - src/uri.cpp src/listener.cpp src/peer.cpp src/dispatcher.cpp @@ -12,13 +11,11 @@ add_library(ftlnet src/ws_internal.cpp ) -check_function_exists(uriParseSingleUriA HAVE_URIPARSESINGLE) - target_include_directories(ftlnet PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include> PRIVATE src) -target_link_libraries(ftlnet ftlcommon Threads::Threads glog::glog ${UUID_LIBRARIES} ${URIPARSER_LIBRARIES}) +target_link_libraries(ftlnet ftlcommon Threads::Threads glog::glog ${UUID_LIBRARIES}) install(TARGETS ftlnet EXPORT ftlnet-config ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -27,7 +24,7 @@ install(TARGETS ftlnet EXPORT ftlnet-config install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) add_executable(net-cli src/main.cpp) -target_link_libraries(net-cli ftlnet ftlcommon glog::glog ${URIPARSER_LIBRARIES} Threads::Threads ${READLINE_LIBRARY} ${UUID_LIBRARIES}) +target_link_libraries(net-cli ftlnet ftlcommon glog::glog Threads::Threads ${READLINE_LIBRARY} ${UUID_LIBRARIES}) add_dependencies(net-cli ftlnet) ADD_SUBDIRECTORY(test) diff --git a/components/net/cpp/src/universe.cpp b/components/net/cpp/src/universe.cpp index 290993394cee4b68a9a46ba06add7364a0ff5ee9..55ab9b0a50ca43401e92c09eb69c1e9a395deeaa 100644 --- a/components/net/cpp/src/universe.cpp +++ b/components/net/cpp/src/universe.cpp @@ -21,6 +21,7 @@ using ftl::UUID; using std::optional; using std::unique_lock; using std::mutex; +using ftl::config::json_t; Universe::Universe() : Configurable(), active_(true), this_peer(ftl::net::this_peer), thread_(Universe::__start, this) { _installBindings(); @@ -28,17 +29,21 @@ Universe::Universe() : Configurable(), active_(true), this_peer(ftl::net::this_p Universe::Universe(nlohmann::json &config) : Configurable(config), active_(true), this_peer(ftl::net::this_peer), thread_(Universe::__start, this) { - if (config["listen"].is_array()) { - for (auto &l : config["listen"]) { - listen(l); + + auto l = get<json_t>("listen"); + + if (l && (*l).is_array()) { + for (auto &ll : *l) { + listen(ll); } - } else if (config["listen"].is_string()) { - listen(config["listen"]); + } else if (l && (*l).is_string()) { + listen((*l).get<string>()); } - if (config["peers"].is_array()) { - for (auto &p : config["peers"]) { - connect(p); + auto p = get<json_t>("peers"); + if (p && (*p).is_array()) { + for (auto &pp : *p) { + connect(pp); } } diff --git a/components/net/cpp/test/CMakeLists.txt b/components/net/cpp/test/CMakeLists.txt index e81a89721fb6022c7f2fb7c286a588efd5fc0d92..38c453171754d47786c1d12b0497f560bbbca3fb 100644 --- a/components/net/cpp/test/CMakeLists.txt +++ b/components/net/cpp/test/CMakeLists.txt @@ -3,26 +3,16 @@ add_executable(peer_unit ./tests.cpp ../src/ws_internal.cpp ../src/dispatcher.cpp - ../src/uri.cpp ./peer_unit.cpp ../../../common/cpp/src/config.cpp ) target_include_directories(peer_unit PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include" "${CMAKE_CURRENT_SOURCE_DIR}/../../../common/cpp/include") target_link_libraries(peer_unit - ${URIPARSER_LIBRARIES} + ftlcommon glog::glog Threads::Threads ${UUID_LIBRARIES}) -### URI ######################################################################## -add_executable(uri_unit - ./tests.cpp - ../src/uri.cpp - ./uri_unit.cpp) -target_include_directories(uri_unit PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include") -target_link_libraries(uri_unit - ${URIPARSER_LIBRARIES}) - ### P2P Base Unit ############################################################## # TODO(nick) Actually make this a unit test @@ -45,16 +35,13 @@ add_dependencies(net_integration ftlnet) target_include_directories(net_integration PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}../include") target_link_libraries(net_integration ftlnet - ${URIPARSER_LIBRARIES} + ftlcommon glog::glog Threads::Threads ${UUID_LIBRARIES}) - - -add_test(URIUnitTest uri_unit) #add_test(ProtocolUnitTest protocol_unit) add_test(PeerUnitTest peer_unit) add_test(NetIntegrationTest net_integration) diff --git a/components/renderers/cpp/include/ftl/display.hpp b/components/renderers/cpp/include/ftl/display.hpp index 7856c3ee924d009f547009dc48613afced465c2f..2c2e8b8d5b80a1f3355e27462798d0fe6f698f12 100644 --- a/components/renderers/cpp/include/ftl/display.hpp +++ b/components/renderers/cpp/include/ftl/display.hpp @@ -6,6 +6,7 @@ #define _FTL_DISPLAY_HPP_ #include <ftl/config.h> +#include <ftl/configurable.hpp> #include "../../../rgbd-sources/include/ftl/camera_params.hpp" #include <nlohmann/json.hpp> @@ -22,7 +23,7 @@ namespace ftl { /** * Multiple local display options for disparity or point clouds. */ -class Display { +class Display : public ftl::Configurable { private: std::string name_; public: @@ -48,8 +49,6 @@ class Display { void onKey(std::function<void(int)> h) { key_handlers_.push_back(h); } private: - nlohmann::json config_; - #if defined HAVE_VIZ cv::viz::Viz3d *window_; #endif // HAVE_VIZ diff --git a/components/renderers/cpp/src/display.cpp b/components/renderers/cpp/src/display.cpp index 092872a58608d6514fdff2d1005b16beceec51c5..23288289b01ef181f262f56d6d5cda501cfe146b 100644 --- a/components/renderers/cpp/src/display.cpp +++ b/components/renderers/cpp/src/display.cpp @@ -11,7 +11,7 @@ using ftl::Display; using cv::Mat; using cv::Vec3f; -Display::Display(nlohmann::json &config, std::string name) : config_(config) { +Display::Display(nlohmann::json &config, std::string name) : ftl::Configurable(config) { name_ = name; #if defined HAVE_VIZ window_ = new cv::viz::Viz3d("FTL: " + name); diff --git a/components/rgbd-sources/include/ftl/rgbd_source.hpp b/components/rgbd-sources/include/ftl/rgbd_source.hpp index ca7dec6ac18d54716d5a07c1f924b4b097b91548..e6ca35418f80368e5f62adc622203ce09d5962a6 100644 --- a/components/rgbd-sources/include/ftl/rgbd_source.hpp +++ b/components/rgbd-sources/include/ftl/rgbd_source.hpp @@ -29,7 +29,7 @@ class RGBDSource : public ftl::Configurable { void getRGBD(cv::Mat &rgb, cv::Mat &depth); const CameraParameters &getParameters() { return params_; }; - std::string getURI() const { return config_["uri"].get<std::string>(); } + std::string getURI() const { return config_["$id"].get<std::string>(); } virtual void setPose(const Eigen::Matrix4f &pose) { pose_ = pose; }; const Eigen::Matrix4f &getPose() { return pose_; }; diff --git a/components/rgbd-sources/src/algorithms/elas.hpp b/components/rgbd-sources/src/algorithms/elas.hpp index 02f72e3e20b3cf1b94de6fdbc8a55283ba90f3da..29b76cd9ef219013d8a47042a9e2a8529da08ba3 100644 --- a/components/rgbd-sources/src/algorithms/elas.hpp +++ b/components/rgbd-sources/src/algorithms/elas.hpp @@ -9,6 +9,7 @@ #include <opencv2/opencv.hpp> #include <elas.h> #include <ftl/disparity.hpp> +#include <ftl/configuration.hpp> namespace ftl { namespace algorithms { @@ -24,8 +25,8 @@ class ELAS : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); /* Factory creator */ - static inline Disparity *create(nlohmann::json &config) { - return new ELAS(config); + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<ELAS>(p, name); } private: diff --git a/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp b/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp index 4f78280f4e09b6f709c40c0d52285b8f2e09d659..a17ca1bbfdfddb82981ede823c6e878bc1d9c723 100644 --- a/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp +++ b/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp @@ -10,6 +10,7 @@ #include <libsgm.h> #include "../disparity.hpp" #include <opencv2/cudastereo.hpp> +#include <ftl/configuration.hpp> namespace ftl { namespace algorithms { @@ -29,8 +30,8 @@ class FixstarsSGM : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp, const cv::Mat &mask_l) override; /* Factory creator */ - static inline Disparity *create(nlohmann::json &config) { - return new FixstarsSGM(config); + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<FixstarsSGM>(p, name); } private: diff --git a/components/rgbd-sources/src/algorithms/nick.hpp b/components/rgbd-sources/src/algorithms/nick.hpp index ee18f77019ce600d745023084f1fd059258ca9e9..1b5c71ccf07a2757e321845cbd7d423e8e88ff75 100644 --- a/components/rgbd-sources/src/algorithms/nick.hpp +++ b/components/rgbd-sources/src/algorithms/nick.hpp @@ -5,6 +5,7 @@ #include <opencv2/opencv.hpp> #include <opencv2/cudastereo.hpp> #include "../disparity.hpp" +#include <ftl/configuration.hpp> namespace ftl { namespace algorithms { @@ -14,7 +15,9 @@ class NickCuda : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); - static inline Disparity *create(nlohmann::json &config) { return new NickCuda(config); } + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<NickCuda>(p, name); + } private: cv::cuda::GpuMat disp_; diff --git a/components/rgbd-sources/src/algorithms/opencv_bm.hpp b/components/rgbd-sources/src/algorithms/opencv_bm.hpp index b890c1b450ebb8263a5f821cdec21c9d707152cb..4a6b5af0c5442acbc45c1662a3f7a7270b84b714 100644 --- a/components/rgbd-sources/src/algorithms/opencv_bm.hpp +++ b/components/rgbd-sources/src/algorithms/opencv_bm.hpp @@ -10,6 +10,7 @@ #include "opencv2/ximgproc.hpp" #include <opencv2/calib3d.hpp> #include "../disparity.hpp" +#include <ftl/configuration.hpp> namespace ftl { namespace algorithms { @@ -23,8 +24,8 @@ class OpenCVBM : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); - static inline Disparity *create(nlohmann::json &config) { - return new OpenCVBM(config); + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<OpenCVBM>(p, name); } private: diff --git a/components/rgbd-sources/src/algorithms/opencv_cuda_bm.hpp b/components/rgbd-sources/src/algorithms/opencv_cuda_bm.hpp index 3542c8dd5f3da6f8a8e0f39cf34e7ada4dd05d04..13c88ccd55380e4ef2f0fd74f3a1e668602d29af 100644 --- a/components/rgbd-sources/src/algorithms/opencv_cuda_bm.hpp +++ b/components/rgbd-sources/src/algorithms/opencv_cuda_bm.hpp @@ -9,6 +9,7 @@ #include <opencv2/opencv.hpp> #include <opencv2/cudastereo.hpp> #include "../disparity.hpp" +#include <ftl/configuration.hpp> namespace ftl { namespace algorithms { @@ -22,8 +23,8 @@ class OpenCVCudaBM : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); - static inline Disparity *create(nlohmann::json &config) { - return new OpenCVCudaBM(config); + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<OpenCVCudaBM>(p, name); } private: diff --git a/components/rgbd-sources/src/algorithms/opencv_cuda_bp.hpp b/components/rgbd-sources/src/algorithms/opencv_cuda_bp.hpp index 4a096ed30bf753835dd3587b827d5204ce5a4652..3a498552d09ac828863d37c8dff1388e730aef1c 100644 --- a/components/rgbd-sources/src/algorithms/opencv_cuda_bp.hpp +++ b/components/rgbd-sources/src/algorithms/opencv_cuda_bp.hpp @@ -9,6 +9,7 @@ #include <opencv2/opencv.hpp> #include <opencv2/cudastereo.hpp> #include "../disparity.hpp" +#include <ftl/configuration.hpp> namespace ftl { namespace algorithms { @@ -22,8 +23,8 @@ class OpenCVCudaBP : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); - static inline Disparity *create(nlohmann::json &config) { - return new OpenCVCudaBP(config); + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<OpenCVCudaBP>(p, name); } private: diff --git a/components/rgbd-sources/src/algorithms/opencv_sgbm.hpp b/components/rgbd-sources/src/algorithms/opencv_sgbm.hpp index 052b331aebd73cf5042223f92b0b489c5c5d1319..4e6437b0fa75093a4ef2a1d0f3fb1dc8130ae16d 100644 --- a/components/rgbd-sources/src/algorithms/opencv_sgbm.hpp +++ b/components/rgbd-sources/src/algorithms/opencv_sgbm.hpp @@ -10,6 +10,7 @@ #include "opencv2/ximgproc.hpp" #include <opencv2/calib3d.hpp> #include "../disparity.hpp" +#include <ftl/configuration.hpp> namespace ftl { namespace algorithms { @@ -23,7 +24,9 @@ class OpenCVSGBM : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); - static inline Disparity *create(nlohmann::json &config) { return new OpenCVSGBM(config); } + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<OpenCVSGBM>(p, name); + } private: cv::Ptr<cv::StereoSGBM> left_matcher_; diff --git a/components/rgbd-sources/src/algorithms/rtcensus.hpp b/components/rgbd-sources/src/algorithms/rtcensus.hpp index f4a7d9c26b29c98c831d386ca71c9512d2ad1bfc..0a31a49b108b42ff319a3c61f5f138612160e171 100644 --- a/components/rgbd-sources/src/algorithms/rtcensus.hpp +++ b/components/rgbd-sources/src/algorithms/rtcensus.hpp @@ -11,6 +11,7 @@ #include <nlohmann/json.hpp> #include <ftl/config.h> +#include <ftl/configuration.hpp> #if defined HAVE_CUDA #include <opencv2/core/cuda.hpp> @@ -31,8 +32,8 @@ class RTCensus : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); - static inline Disparity *create(nlohmann::json &config) { - return new RTCensus(config); + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<RTCensus>(p, name); } private: diff --git a/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp b/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp index c62c21ca8549333c53f836b4090b3b736b125cc3..015c67b08cc4211aee4522d9be5746882a2f6060 100644 --- a/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp +++ b/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp @@ -9,6 +9,7 @@ #include <opencv2/opencv.hpp> #include "../disparity.hpp" #include <nlohmann/json.hpp> +#include <ftl/configuration.hpp> #if defined HAVE_CUDA #include <opencv2/core/cuda.hpp> @@ -29,8 +30,8 @@ class RTCensusSGM : public ftl::Disparity { void compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp); - static inline Disparity *create(nlohmann::json &config) { - return new RTCensusSGM(config); + static inline Disparity *create(ftl::Configurable *p, const std::string &name) { + return ftl::create<RTCensusSGM>(p, name); } private: diff --git a/components/rgbd-sources/src/calibrate.cpp b/components/rgbd-sources/src/calibrate.cpp index c4bcda7a1dffe9809b8a33c54f9808a472267cdb..3439fe5df9bb08074a28d5b2cc486b1d8168b107 100644 --- a/components/rgbd-sources/src/calibrate.cpp +++ b/components/rgbd-sources/src/calibrate.cpp @@ -75,22 +75,22 @@ void Calibrate::Settings::write(FileStorage& fs) const { << "}"; } -void Calibrate::Settings::read(const nlohmann::json& node) { - boardSize.width = node["board_size"][0]; - boardSize.height = node["board_size"][1]; - squareSize = node["square_size"]; - nrFrames = node["num_frames"]; - aspectRatio = node["fix_aspect_ratio"]; - calibZeroTangentDist = node["assume_zero_tangential_distortion"]; - calibFixPrincipalPoint = node["fix_principal_point_at_center"]; - useFisheye = node["use_fisheye_model"]; - flipVertical = node["flip_vertical"]; - delay = node["frame_delay"]; - fixK1 = node["fix_k1"]; - fixK2 = node["fix_k2"]; - fixK3 = node["fix_k3"]; - fixK4 = node["fix_k4"]; - fixK5 = node["fix_k5"]; +void Calibrate::Settings::read(ftl::Configurable *node) { + boardSize.width = node->value<vector<int>>("board_size", {10,10})[0]; + boardSize.height = node->value<vector<int>>("board_size", {10,10})[1]; + squareSize = node->value("square_size", 50); + nrFrames = node->value("num_frames", 20); + aspectRatio = node->value("fix_aspect_ratio", false); + calibZeroTangentDist = node->value("assume_zero_tangential_distortion", false); + calibFixPrincipalPoint = node->value("fix_principal_point_at_center", false); + useFisheye = node->value("use_fisheye_model", false); + flipVertical = node->value("flip_vertical", false); + delay = node->value("frame_delay", 1.0f); + fixK1 = node->value("fix_k1", false); + fixK2 = node->value("fix_k2", false); + fixK3 = node->value("fix_k3", false); + fixK4 = node->value("fix_k4", true); + fixK5 = node->value("fix_k5", true); validate(); } @@ -181,7 +181,7 @@ bool runCalibration(const Calibrate::Settings& s, Size imageSize, bool release_object); -Calibrate::Calibrate(ftl::LocalSource *s, nlohmann::json &config) : local_(s) { +Calibrate::Calibrate(nlohmann::json &config, ftl::LocalSource *s) : ftl::Configurable(config), local_(s) { /*FileStorage fs(cal, FileStorage::READ); // Read the settings if (!fs.isOpened()) { @@ -189,7 +189,7 @@ Calibrate::Calibrate(ftl::LocalSource *s, nlohmann::json &config) : local_(s) { return; }*/ // fs["Settings"] >> settings_; - settings_.read(config); + settings_.read(this); // fs.release(); if (!settings_.goodInput) { diff --git a/components/rgbd-sources/src/calibrate.hpp b/components/rgbd-sources/src/calibrate.hpp index 0e6a5d81fc0834816c76914b52db4d900d6cf4df..08c0525ea333c25b77f07788f40c0c55a5b77021 100644 --- a/components/rgbd-sources/src/calibrate.hpp +++ b/components/rgbd-sources/src/calibrate.hpp @@ -23,7 +23,7 @@ namespace ftl { * load any existing cached camera calibration unless explicitely told to * redo the calibration. */ -class Calibrate { +class Calibrate : public ftl::Configurable { public: // TODO(nick) replace or remove this class. @@ -39,7 +39,7 @@ class Calibrate { enum InputType { INVALID, CAMERA, VIDEO_FILE, IMAGE_LIST }; void write(cv::FileStorage& fs) const; - void read(const nlohmann::json& node); + void read(ftl::Configurable *node); void validate(); //Mat nextImage(); @@ -83,7 +83,7 @@ class Calibrate { }; public: - Calibrate(ftl::LocalSource *s, nlohmann::json &config); + Calibrate(nlohmann::json &config, ftl::LocalSource *s); /** * Perform a new camera calibration. Ignore and replace any existing diff --git a/components/rgbd-sources/src/disparity.cpp b/components/rgbd-sources/src/disparity.cpp index 5141d438fd3eb299ae2f010373fdd6b46458f0a7..a6af11e7dab463d7b1ade286b024538f27172230 100644 --- a/components/rgbd-sources/src/disparity.cpp +++ b/components/rgbd-sources/src/disparity.cpp @@ -5,25 +5,34 @@ #include "disparity.hpp" #include <glog/logging.h> #include <ftl/config.h> +#include <ftl/configuration.hpp> using ftl::Disparity; -std::map<std::string, std::function<Disparity*(nlohmann::json&)>> +std::map<std::string, std::function<Disparity*(ftl::Configurable *, const std::string &)>> *Disparity::algorithms__ = nullptr; Disparity::Disparity(nlohmann::json &config) - : config_(config), - min_disp_(config["minimum"]), - max_disp_(config["maximum"]) {} + : ftl::Configurable(config), + min_disp_(value("minimum",0)), + max_disp_(value("maximum", 256)) {} -Disparity *Disparity::create(nlohmann::json &config) { - if (algorithms__->count(config["algorithm"]) != 1) return nullptr; - return (*algorithms__)[config["algorithm"]](config); +Disparity *Disparity::create(ftl::Configurable *parent, const std::string &name) { + nlohmann::json &config = ftl::config::resolve(parent->getConfig()[name]); + + //auto alg = parent->get<std::string>("algorithm"); + if (!config["algorithm"].is_string()) { + return nullptr; + } + std::string alg = config["algorithm"].get<std::string>(); + + if (algorithms__->count(alg) != 1) return nullptr; + return (*algorithms__)[alg](parent, name); } void Disparity::_register(const std::string &n, - std::function<Disparity*(nlohmann::json&)> f) { - if (!algorithms__) algorithms__ = new std::map<std::string, std::function<Disparity*(nlohmann::json&)>>; + std::function<Disparity*(ftl::Configurable *, const std::string &)> f) { + if (!algorithms__) algorithms__ = new std::map<std::string, std::function<Disparity*(ftl::Configurable *, const std::string &)>>; LOG(INFO) << "Register disparity algorithm: " << n; (*algorithms__)[n] = f; } diff --git a/components/rgbd-sources/src/disparity.hpp b/components/rgbd-sources/src/disparity.hpp index 33bf58481161a14f8f5d1721a1f600ffb2d9e658..ebe5b9b0849df4a0831679f86600d72a7b348c0b 100644 --- a/components/rgbd-sources/src/disparity.hpp +++ b/components/rgbd-sources/src/disparity.hpp @@ -7,6 +7,7 @@ #include <opencv2/opencv.hpp> #include <nlohmann/json.hpp> +#include <ftl/configurable.hpp> namespace ftl { @@ -16,7 +17,7 @@ namespace ftl { * interface, for this to work a static instance of the Register class must * be created in the algorithms cpp file. */ -class Disparity { +class Disparity : public ftl::Configurable { public: explicit Disparity(nlohmann::json &config); @@ -37,7 +38,7 @@ class Disparity { */ class Register { public: - Register(const std::string &n, std::function<Disparity*(nlohmann::json&)> f) { + Register(const std::string &n, std::function<Disparity*(ftl::Configurable *, const std::string &)> f) { Disparity::_register(n,f); }; }; @@ -46,18 +47,18 @@ class Disparity { * Factory instance creator where config contains an "algorithm" property * used as the instance name to construct. */ - static Disparity *create(nlohmann::json &config); + static Disparity *create(ftl::Configurable *, const std::string &); protected: - static void _register(const std::string &n, std::function<Disparity*(nlohmann::json&)> f); + static void _register(const std::string &n, std::function<Disparity*(ftl::Configurable *, const std::string &)> f); protected: - nlohmann::json &config_; + //nlohmann::json &config_; size_t min_disp_; size_t max_disp_; private: - static std::map<std::string,std::function<Disparity*(nlohmann::json&)>> *algorithms__; + static std::map<std::string,std::function<Disparity*(ftl::Configurable *, const std::string &)>> *algorithms__; }; }; diff --git a/components/rgbd-sources/src/local.cpp b/components/rgbd-sources/src/local.cpp index 80190115fda19bc7ad749ccafa6dfb743af035e8..f7ed7ebd20b8596c6d739ce238e8e8c65babc10f 100644 --- a/components/rgbd-sources/src/local.cpp +++ b/components/rgbd-sources/src/local.cpp @@ -36,10 +36,10 @@ LocalSource::LocalSource(nlohmann::json &config) {"scale","Change the input image or video scaling","number"} }); - flip_ = config["flip"].get<bool>(); - flip_v_ = config["flip_vert"].get<bool>(); - nostereo_ = config["nostereo"].get<bool>(); - downsize_ = config["scale"].get<float>(); + flip_ = value("flip", false); + flip_v_ = value("flip_vert", false); + nostereo_ = value("nostereo", false); + downsize_ = value("scale", 1.0f); // Use cameras camera_a_ = new VideoCapture; @@ -67,10 +67,10 @@ LocalSource::LocalSource(nlohmann::json &config) stereo_ = false; LOG(WARNING) << "Not able to find second camera for stereo"; } else { - camera_a_->set(cv::CAP_PROP_FRAME_WIDTH,(int)config["width"]); - camera_a_->set(cv::CAP_PROP_FRAME_HEIGHT,(int)config["height"]); - camera_b_->set(cv::CAP_PROP_FRAME_WIDTH,(int)config["width"]); - camera_b_->set(cv::CAP_PROP_FRAME_HEIGHT,(int)config["height"]); + camera_a_->set(cv::CAP_PROP_FRAME_WIDTH, value("width", 640)); + camera_a_->set(cv::CAP_PROP_FRAME_HEIGHT, value("height", 480)); + camera_b_->set(cv::CAP_PROP_FRAME_WIDTH, value("width", 640)); + camera_b_->set(cv::CAP_PROP_FRAME_HEIGHT, value("height", 480)); Mat frame; camera_a_->grab(); @@ -81,10 +81,10 @@ LocalSource::LocalSource(nlohmann::json &config) stereo_ = true; } - tps_ = 1.0 / (double)config["max_fps"]; + tps_ = 1.0 / value("max_fps", 25.0); } -LocalSource::LocalSource(const string &vid, nlohmann::json &config) +LocalSource::LocalSource(nlohmann::json &config, const string &vid) : Configurable(config), timestamp_(0.0) { REQUIRED({ @@ -97,10 +97,10 @@ LocalSource::LocalSource(const string &vid, nlohmann::json &config) {"scale","Change the input image or video scaling","number"} }); - flip_ = config["flip"].get<bool>(); - flip_v_ = config["flip_vert"].get<bool>(); - nostereo_ = config["nostereo"].get<bool>(); - downsize_ = config["scale"].get<float>(); + flip_ = value("flip", false); + flip_v_ = value("flip_vert", false); + nostereo_ = value("nostereo", false); + downsize_ = value("scale", 1.0f); if (vid == "") { LOG(FATAL) << "No video file specified"; @@ -137,7 +137,7 @@ LocalSource::LocalSource(const string &vid, nlohmann::json &config) stereo_ = false; } - tps_ = 1.0 / (double)config["max_fps"]; + tps_ = 1.0 / value("max_fps", 25.0); } bool LocalSource::left(cv::Mat &l) { diff --git a/components/rgbd-sources/src/local.hpp b/components/rgbd-sources/src/local.hpp index d483ea185cf0a6db28d9da09fd55c2f1e17822c2..d3286684b70528c7c1e375e21d2e805b93a29818 100644 --- a/components/rgbd-sources/src/local.hpp +++ b/components/rgbd-sources/src/local.hpp @@ -14,7 +14,7 @@ namespace ftl { class LocalSource : public Configurable { public: explicit LocalSource(nlohmann::json &config); - LocalSource(const std::string &vid, nlohmann::json &config); + LocalSource(nlohmann::json &config, const std::string &vid); bool left(cv::Mat &m); bool right(cv::Mat &m); diff --git a/components/rgbd-sources/src/net_source.cpp b/components/rgbd-sources/src/net_source.cpp index a4e3c9f0a7b9f9b1d3edcd0d8188c09b8ddb18a0..7a9d3cbe21835daed8a704204f238639c15c0203 100644 --- a/components/rgbd-sources/src/net_source.cpp +++ b/components/rgbd-sources/src/net_source.cpp @@ -42,16 +42,21 @@ NetSource::NetSource(nlohmann::json &config) : RGBDSource(config) { NetSource::NetSource(nlohmann::json &config, ftl::net::Universe *net) : RGBDSource(config, net) { - auto p = net->findOne<ftl::UUID>("find_stream", getURI()); + auto uri = get<string>("uri"); + if (!uri) { + LOG(ERROR) << "NetSource does not have a URI"; + return; + } + auto p = net->findOne<ftl::UUID>("find_stream", *uri); if (!p) { - LOG(ERROR) << "Could not find stream: " << getURI(); + LOG(ERROR) << "Could not find stream: " << *uri; return; } peer_ = *p; - has_calibration_ = _getCalibration(*net, peer_, getURI(), params_); + has_calibration_ = _getCalibration(*net, peer_, *uri, params_); - net->bind(getURI(), [this](const vector<unsigned char> &jpg, const vector<unsigned char> &d) { + net->bind(*uri, [this](const vector<unsigned char> &jpg, const vector<unsigned char> &d) { unique_lock<mutex> lk(mutex_); _recv(jpg, d); }); @@ -59,7 +64,7 @@ NetSource::NetSource(nlohmann::json &config, ftl::net::Universe *net) N_ = 10; // Initiate stream with request for first 10 frames - net->send(peer_, "get_stream", getURI(), 10, 0, net->id(), getURI()); + net->send(peer_, "get_stream", *uri, 10, 0, net->id(), *uri); } NetSource::~NetSource() { @@ -75,7 +80,7 @@ void NetSource::_recv(const vector<unsigned char> &jpg, const vector<unsigned ch N_--; if (N_ == 0) { N_ += 10; - net_->send(peer_, "get_stream", getURI(), 10, 0, net_->id(), getURI()); + net_->send(peer_, "get_stream", *get<string>("uri"), 10, 0, net_->id(), *get<string>("uri")); } } diff --git a/components/rgbd-sources/src/rgbd_streamer.cpp b/components/rgbd-sources/src/rgbd_streamer.cpp index b4e256169d598587a637e35624750d8ed3370f90..8cf1e8f96c919aef4c5eb8e118e11272aeab70b5 100644 --- a/components/rgbd-sources/src/rgbd_streamer.cpp +++ b/components/rgbd-sources/src/rgbd_streamer.cpp @@ -81,6 +81,8 @@ void Streamer::add(RGBDSource *src) { s->src = src; s->state = 0; sources_[src->getURI()] = s; + + LOG(INFO) << "Streaming: " << src->getURI(); } void Streamer::_addClient(const string &source, int N, int rate, const ftl::UUID &peer, const string &dest) { diff --git a/components/rgbd-sources/src/stereovideo_source.cpp b/components/rgbd-sources/src/stereovideo_source.cpp index e254099c728371b686566e97107f8f03cc38bcd7..6264caff28ee5458125c518e80ef56c8907ffffb 100644 --- a/components/rgbd-sources/src/stereovideo_source.cpp +++ b/components/rgbd-sources/src/stereovideo_source.cpp @@ -22,29 +22,34 @@ StereoVideoSource::StereoVideoSource(nlohmann::json &config, const string &file) : RGBDSource(config), ready_(false) { REQUIRED({ - {"source","Details on source video [object]","object"} + {"feed","Details on source video [object]","object"} }); if (ftl::is_video(file)) { // Load video file LOG(INFO) << "Using video file..."; - lsrc_ = new LocalSource(file, config["source"]); + //lsrc_ = new LocalSource(file, config["source"]); + lsrc_ = ftl::create<LocalSource>(this, "feed", file); } else if (file != "") { auto vid = ftl::locateFile("video.mp4"); if (!vid) { - LOG(FATAL) << "No video.mp4 file found in provided paths"; + LOG(FATAL) << "No video.mp4 file found in provided paths (" << file << ")"; } else { LOG(INFO) << "Using test directory..."; - lsrc_ = new LocalSource(*vid, config["source"]); + //lsrc_ = new LocalSource(*vid, config["source"]); + lsrc_ = ftl::create<LocalSource>(this, "feed", *vid); } } else { // Use cameras LOG(INFO) << "Using cameras..."; - lsrc_ = new LocalSource(config["source"]); + //lsrc_ = new LocalSource(config["source"]); + lsrc_ = ftl::create<LocalSource>(this, "feed"); } - calib_ = new Calibrate(lsrc_, config["calibration"]); - if (config["calibrate"]) calib_->recalibrate(); + //calib_ = new Calibrate(lsrc_, ftl::resolve(config["calibration"])); + calib_ = ftl::create<Calibrate>(this, "calibration", lsrc_); + + if (value("calibrate", false)) calib_->recalibrate(); if (!calib_->isCalibrated()) LOG(WARNING) << "Cameras are not calibrated!"; else LOG(INFO) << "Calibration initiated."; @@ -69,7 +74,7 @@ StereoVideoSource::StereoVideoSource(nlohmann::json &config, const string &file) calib_->rectifyStereo(mask_l, mask_r); mask_l_ = (mask_l == 0); - disp_ = Disparity::create(config["disparity"]); + disp_ = Disparity::create(this, "disparity"); if (!disp_) LOG(FATAL) << "Unknown disparity algorithm : " << config["disparity"]; LOG(INFO) << "StereoVideo source ready..."; diff --git a/config/config.json b/config/config.json deleted file mode 100644 index 4b8f8f75c3e55e51e1af9cfaea77dd1aefa026bb..0000000000000000000000000000000000000000 --- a/config/config.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "vision": { - "type": "stereovideo", - "uri": "ftl://utu.fi/dummy/rgb-d", - "middlebury": { - "dataset": "", - "threshold": 10.0, - "scale": 0.25 - }, - "source": { - "flip": false, - "nostereo": false, - "scale": 1.0, - "flip_vert": false, - "max_fps": 25, - "width": 640, - "height": 480, - "crosshair": false - }, - "calibrate": false, - "calibration": { - "board_size": [9,6], - "square_size": 50, - "frame_delay": 1.0, - "num_frames": 35, - "assume_zero_tangential_distortion": true, - "fix_aspect_ratio": true, - "fix_principal_point_at_center": true, - "use_fisheye_model": false, - "fix_k1": false, - "fix_k2": false, - "fix_k3": false, - "fix_k4": true, - "fix_k5": true, - "save": true, - "use_intrinsics": true, - "use_extrinsics": true, - "flip_vertical": false - }, - "camera": { - "name": "Panasonic Lumix DMC-FZ300", - "focal_length": 25, - "sensor_width": 6.17, - "base_line": 0.1 - }, - "disparity": { - "algorithm": "rtcensus", - "use_cuda": true, - "minimum": 0, - "maximum": 208, - "tau": 0.0, - "gamma": 0.0, - "window_size": 5, - "sigma": 1.5, - "lambda": 8000.0, - "use_filter": true, - "filter_radius": 20, - "filter_iter": 3 - }, - "display": { - "flip_vert": false, - "disparity": false, - "points": true, - "depth": false, - "left": false, - "right": false, - "crosshair": false - }, - "net": { - "listen": "tcp://*:9001", - "peers": [] - }, - "stream": { - "name": "dummy" - } - }, - "reconstruction": { - "net": { - "peers": ["tcp://localhost:9001"] - }, - "sources": [{"type": "net", "uri": "ftl://utu.fi/node1/rgb-d"}], - "display": { - "flip_vert": false, - "disparity": false, - "points": true, - "depth": false, - "left": false, - "right": false - }, - "registration": { - "reference-source" : "ftl://utu.fi/node1/rgb-d", - "calibration" : { - "run": false, - "iterations" : 10, - "delay" : 1000, - "patternsize" : [9, 6] - } - } - } -} - diff --git a/config/config.jsonc b/config/config.jsonc new file mode 100644 index 0000000000000000000000000000000000000000..f83dde531bf82ef348b3ea964c919e7c77a157cb --- /dev/null +++ b/config/config.jsonc @@ -0,0 +1,193 @@ +{ + "$id": "ftl://utu.fi", + "$schema": "", + "calibrations": { + "default": { + "board_size": [9,6], + "square_size": 50, + "frame_delay": 1.0, + "num_frames": 35, + "assume_zero_tangential_distortion": true, + "fix_aspect_ratio": true, + "fix_principal_point_at_center": true, + "use_fisheye_model": false, + "fix_k1": false, + "fix_k2": false, + "fix_k3": false, + "fix_k4": true, + "fix_k5": true, + "save": true, + "use_intrinsics": true, + "use_extrinsics": true, + "flip_vertical": false + } + }, + "disparity": { + "libsgm": { + "algorithm": "libsgm", + "use_cuda": true, + "minimum": 0, + "maximum": 256, + "tau": 0.0, + "gamma": 0.0, + "window_size": 5, + "sigma": 1.5, + "lambda": 8000.0 + } + }, + "sources": { + "stereocam": { + "type": "stereovideo", + "feed": { + "flip": false, + "nostereo": false, + "scale": 1.0, + "flip_vert": false, + "max_fps": 500, + "width": 640, + "height": 480, + "crosshair": false + }, + "calibrate": false, + "calibration": { "$ref": "#calibrations/default" }, + "disparity": { "$ref": "#disparity/libsgm" } + }, + "stereovid": {}, + "localhost": {} + + }, + // Listen to localhost + "net": { + "default_vision": { + "listen": "tcp://*:9001", + "peers": [] + }, + "default_reconstruct": { + "listen": "tcp://*:9002", + "peers": [] + } + }, + "displays": { + "none": { + "flip_vert": false, + "disparity": false, + "points": false, + "depth": false, + "left": false, + "right": false + }, + "left": { + "flip_vert": false, + "disparity": false, + "points": false, + "depth": false, + "left": true, + "right": false + } + }, + "middlebury": { + "none": { + "dataset": "", + "threshold": 10.0, + "scale": 0.25 + } + }, + "virtual_cams": { + "default": { + "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" + } + }, + "hash_conf": { + "default": { + "adapterWidth": 640, + "adapterHeight": 480, + "sensorDepthMax": 20.0, + "sensorDepthMin": 0.2, + "SDFRayIncrementFactor": 0.8, + "SDFRayThresSampleDistFactor": 50.5, + "SDFRayThresDistFactor": 50.0, + "SDFUseGradients": false, + "hashNumBuckets": 50000, + "hashMaxCollisionLinkedListSize": 7, + "hashNumSDFBlocks": 1000000, + "SDFVoxelSize": 0.005, + "SDFMaxIntegrationDistance": 12.0, + "SDFTruncation": 0.1, + "SDFTruncationScale": 0.05, + "SDFIntegrationWeightSample": 10, + "SDFIntegrationWeightMax": 255, + "hash_renderer": true + } + }, + + "vision_default": { + "source": { "$ref": "#sources/stereocam" }, + "middlebury": { "$ref": "#middlebury/none" }, + "display": { "$ref": "#displays/none" }, + "net": { "$ref": "#net/default_vision" }, + "stream": {} + }, + + "reconstruction_default": { + "net": { + "peers": ["tcp://localhost:9001"] + }, + "sources": [ + {"type": "net", "uri":"ftl://utu.fi/vision_default/source"} + ], + "display": { "$ref": "#displays/left" }, + "virtual": { "$ref": "#virtual_cams/default" }, + "voxelhash": { "$ref": "#hash_conf/default" }, + "registration": { + "reference-source" : "ftl://utu.fi/vision_default/source", + "calibration" : { + "max_error": 25, + "run": false, + "iterations" : 10, + "delay" : 500, + "patternsize" : [9, 6] + } + } + }, + + "reconstruction_lab": { + "net": { + "peers": ["tcp://ftl-node-4:9001"] + }, + "sources": [ + {"type": "net", "uri":"ftl://utu.fi/node4"} + ], + "display": { "$ref": "#displays/left" }, + "virtual": { "$ref": "#virtual_cams/default" }, + "voxelhash": { "$ref": "#hash_conf/default" }, + "registration": { + "reference-source" : "ftl://utu.fi/node4", + "calibration" : { + "max_error": 25, + "run": false, + "iterations" : 10, + "delay" : 500, + "patternsize" : [9, 6] + } + } + }, + + + "ftl://gui/default": { + "net": { + "peers": ["tcp://ftl-node-4:9001"] + }, + "sources": [{"type": "net", "uri": "ftl://utu.fi/node/rgb-d"}] + } +} diff --git a/config/config_nick.jsonc b/config/config_nick.jsonc new file mode 100644 index 0000000000000000000000000000000000000000..a34e849c69523877bc9785c147147b0b8429762b --- /dev/null +++ b/config/config_nick.jsonc @@ -0,0 +1,137 @@ +{ + "$id": "ftl://utu.fi", + "$schema": "", + "calibrations": { + "default": { + "board_size": [9,6], + "square_size": 50, + "frame_delay": 1.0, + "num_frames": 35, + "assume_zero_tangential_distortion": true, + "fix_aspect_ratio": true, + "fix_principal_point_at_center": true, + "use_fisheye_model": false, + "fix_k1": false, + "fix_k2": false, + "fix_k3": false, + "fix_k4": true, + "fix_k5": true, + "save": true, + "use_intrinsics": true, + "use_extrinsics": true, + "flip_vertical": false + } + }, + "disparity": { + "libsgm": { + "algorithm": "libsgm", + "use_cuda": true, + "minimum": 0, + "maximum": 256, + "tau": 0.0, + "gamma": 0.0, + "window_size": 5, + "sigma": 1.5, + "lambda": 8000.0 + } + }, + "sources": { + "stereocam": {}, + "stereovid": {}, + "localhost": {} + + }, + // Listen to localhost + "net": { + "default": { + "listen": "tcp://*:9001", + "peers": [] + } + }, + "vision_default": { + "source": { + "type": "stereovideo", + "feed": { + "flip": false, + "nostereo": false, + "scale": 1.0, + "flip_vert": false, + "max_fps": 500, + "width": 640, + "height": 480, + "crosshair": false + }, + "calibrate": false, + "calibration": { "$ref": "#calibrations/default" }, + "disparity": { "$ref": "#disparity/libsgm" } + }, + "middlebury": { + "dataset": "", + "threshold": 10.0, + "scale": 0.25 + }, + "display": { + "flip_vert": false, + "disparity": false, + "points": false, + "depth": false, + "left": false, + "right": false + }, + "net": { "$ref": "#net/default" }, + "stream": { + } + }, + "ftl://reconstruction/default": { + "net": { + "peers": ["tcp://ftl-node-5:9001"] + }, + "sources": [ + {"type": "net", "uri":"ftl://utu.fi/node5/rgb-d"} + ], + "display": { + "flip_vert": false, + "disparity": false, + "points": false, + "depth": false, + "left": true, + "right": false + }, + "voxelhash": { + "adapterWidth": 640, + "adapterHeight": 480, + "sensorDepthMax": 20.0, + "sensorDepthMin": 0.2, + "SDFRayIncrementFactor": 0.8, + "SDFRayThresSampleDistFactor": 50.5, + "SDFRayThresDistFactor": 50.0, + "SDFUseGradients": false, + "hashNumBuckets": 50000, + "hashMaxCollisionLinkedListSize": 7, + "hashNumSDFBlocks": 1000000, + "SDFVoxelSize": 0.005, + "SDFMaxIntegrationDistance": 12.0, + "SDFTruncation": 0.1, + "SDFTruncationScale": 0.05, + "SDFIntegrationWeightSample": 10, + "SDFIntegrationWeightMax": 255, + "hash_renderer": true + }, + "registration": { + "reference-source" : "ftl://utu.fi/node5/rgb-d", + "calibration" : { + "max_error": 25, + "run": false, + "iterations" : 10, + "delay" : 500, + "patternsize" : [9, 6] + } + } + }, + "ftl://gui/default": { + "net": { + "peers": ["tcp://ftl-node-4:9001"] + }, + "sources": [{"type": "net", "uri": "ftl://utu.fi/node/rgb-d"}] + } +} diff --git a/config/config_node.jsonc b/config/config_node.jsonc new file mode 100644 index 0000000000000000000000000000000000000000..2e8923444d302d5e0c91b8e681e9b372478e4fb2 --- /dev/null +++ b/config/config_node.jsonc @@ -0,0 +1,11 @@ +{ + "$id": "ftl://utu.fi/node1", + "$schema": "http://json-schema.org/draft-07/schema", + "title": "Node 1", + "description": "Dev lab camera node 1", + "net": { + "peers": [], + "listen": ["tcp://*:9001"] + }, + "sources": { "$ref": "ftl://utu.fi/dev_lab#sources" } +} \ No newline at end of file