diff --git a/applications/gui2/src/main.cpp b/applications/gui2/src/main.cpp index 2367bd03f151f0b48a7c11b05675d154838972c6..ee07557d2848599e4c2af85034bfb0fc887f4bd3 100644 --- a/applications/gui2/src/main.cpp +++ b/applications/gui2/src/main.cpp @@ -153,6 +153,8 @@ void FTLGui::mainloop() { // Process events once more glfwPollEvents(); + ftl::config::save(); + // Stop everything before deleting feed etc LOG(INFO) << "Stopping..."; ftl::timer::stop(true); diff --git a/applications/gui2/src/modules/camera.cpp b/applications/gui2/src/modules/camera.cpp index f527a4cc1db01603120e1c0d6f6537409aeed002..72d91779c45f46071defbbc5227ca692e0ae8588 100644 --- a/applications/gui2/src/modules/camera.cpp +++ b/applications/gui2/src/modules/camera.cpp @@ -8,6 +8,8 @@ #include <ftl/utility/matrix_conversion.hpp> #include <ftl/calibration/structures.hpp> #include <ftl/calibration/parameters.hpp> +#include <ftl/codecs/shapes.hpp> +#include <ftl/operators/poser.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/imgcodecs.hpp> @@ -427,7 +429,11 @@ bool Camera::hasFrame() { return false; } -Eigen::Matrix4d Camera::cursor() const { +const Eigen::Matrix4d &Camera::cursor() const { + return cursor_; +} + +Eigen::Matrix4d Camera::_cursor() const { if (cursor_normal_.norm() > 0.0f) return nanogui::lookAt(cursor_pos_, cursor_target_, cursor_normal_).cast<double>(); Eigen::Matrix4d ident; @@ -573,17 +579,19 @@ void Camera::setCursor(int x, int y) { cursor_target_[2] = CP.z; } } + + cursor_ = _cursor(); } void Camera::setOriginToCursor() { using ftl::calibration::transform::inverse; // Check for valid cursor - if (cursor_normal_.norm() == 0.0f) return; + /*if (cursor_normal_.norm() == 0.0f) return; float cursor_length = (cursor_target_ - cursor_pos_).norm(); float cursor_dist = cursor_pos_.norm(); if (cursor_length < 0.01f || cursor_length > 5.0f) return; - if (cursor_dist > 10.0f) return; + if (cursor_dist > 10.0f) return;*/ if (movable_) { auto *rend = io->feed()->getRenderer(frame_id_); @@ -612,12 +620,14 @@ void Camera::setOriginToCursor() { cursor_target_ = Eigen::Vector3f(0.0f,0.0f,0.0f); cursor_pos_ = Eigen::Vector3f(0.0f,0.0f,0.0f); cursor_normal_ = Eigen::Vector3f(0.0f,0.0f,0.0f); + cursor_ = _cursor(); } void Camera::resetOrigin() { cursor_target_ = Eigen::Vector3f(0.0f,0.0f,0.0f); cursor_pos_ = Eigen::Vector3f(0.0f,0.0f,0.0f); - cursor_normal_ = Eigen::Vector3f(0.0f,0.0f,0.0f); + cursor_normal_ = Eigen::Vector3f(0.0f,0.0f,0.0f); + cursor_ = _cursor(); if (movable_) { auto *rend = io->feed()->getRenderer(frame_id_); @@ -642,3 +652,45 @@ void Camera::resetOrigin() { } } } + +void Camera::saveCursorToPoser() { + ftl::codecs::Shape3D shape; + shape.type = ftl::codecs::Shape3DType::CURSOR; + shape.id = cursor_save_id_++; + shape.label = std::string("Cursor") + std::to_string(shape.id); + shape.pose = cursor().inverse().cast<float>(); + shape.size = Eigen::Vector3f(0.1f,0.1f,0.1f); + + ftl::operators::Poser::add(shape, frame_id_); +} + +Eigen::Matrix4d Camera::getActivePose() { + return cursor(); //.inverse(); +} + +nanogui::Vector2i Camera::getActivePoseScreenCoord() { + Eigen::Matrix4d pose = getActivePose().inverse(); + + auto ptr = std::atomic_load(&latest_); + if (ptr) { + const auto &frame = ptr->frames[frame_idx].cast<ftl::rgbd::Frame>(); + auto campose = frame.getPose().inverse() * pose; + float3 campos; + campos.x = campose(0,3); + campos.y = campose(1,3); + campos.z = campose(2,3); + + int2 spos = frame.getLeft().camToScreen<int2>(campos); + return nanogui::Vector2i(spos.x, spos.y); + } + + return nanogui::Vector2i(-1,-1); +} + +void Camera::transformActivePose(const Eigen::Matrix4d &pose) { + cursor_ = pose * cursor_; +} + +void Camera::setActivePose(const Eigen::Matrix4d &pose) { + cursor_ = pose; //.inverse(); +} diff --git a/applications/gui2/src/modules/camera.hpp b/applications/gui2/src/modules/camera.hpp index d314f0a7a8ba9873ed27c7cf6bf6913c9c46d457..21ed70dc34a986b034a28e246897fbcd55e4e384 100644 --- a/applications/gui2/src/modules/camera.hpp +++ b/applications/gui2/src/modules/camera.hpp @@ -71,17 +71,23 @@ public: void snapshot(const std::string &filename); - Eigen::Matrix4d cursor() const; + const Eigen::Matrix4d &cursor() const; - void setCursorPosition(const Eigen::Vector3f &pos) { cursor_pos_ = pos; } - void setCursorNormal(const Eigen::Vector3f &norm) { cursor_normal_ = norm; } - void setCursorTarget(const Eigen::Vector3f &targ) { cursor_target_ = targ; } + void setCursorPosition(const Eigen::Vector3f &pos) { cursor_pos_ = pos; cursor_ = _cursor(); } + void setCursorNormal(const Eigen::Vector3f &norm) { cursor_normal_ = norm; cursor_ = _cursor(); } + void setCursorTarget(const Eigen::Vector3f &targ) { cursor_target_ = targ; cursor_ = _cursor(); } void setCursor(int x, int y); const Eigen::Vector3f getCursorPosition() const { return cursor_pos_; } void setOriginToCursor(); void resetOrigin(); + void saveCursorToPoser(); + + Eigen::Matrix4d getActivePose(); + nanogui::Vector2i getActivePoseScreenCoord(); + void transformActivePose(const Eigen::Matrix4d &pose); + void setActivePose(const Eigen::Matrix4d &pose); private: int frame_idx = -1; @@ -102,6 +108,8 @@ private: Eigen::Vector3f cursor_pos_; Eigen::Vector3f cursor_target_; Eigen::Vector3f cursor_normal_; + int cursor_save_id_=0; + Eigen::Matrix4d cursor_; ftl::data::FrameSetPtr current_fs_; ftl::data::FrameSetPtr latest_; @@ -120,6 +128,7 @@ private: void initiate_(ftl::data::Frame &frame); void _updateCapabilities(ftl::data::Frame &frame); + Eigen::Matrix4d _cursor() const; }; } diff --git a/applications/gui2/src/modules/camera_tools.hpp b/applications/gui2/src/modules/camera_tools.hpp index 8e665b8421fa07d32f39bd1d43928cb5cb9a66e8..ebe8386f100fe6b7a624055f61262f03f9752967 100644 --- a/applications/gui2/src/modules/camera_tools.hpp +++ b/applications/gui2/src/modules/camera_tools.hpp @@ -24,6 +24,9 @@ enum class Tools { ROTATE_X, ROTATE_Y, ROTATE_Z, + TRANSLATE_X, + TRANSLATE_Y, + TRANSLATE_Z, INSPECT_POINT }; diff --git a/applications/gui2/src/screen.cpp b/applications/gui2/src/screen.cpp index 6fbd703b84bcb6784d5de302640fd05b6cdd6e4a..6925df289e3259f6236416a0fc55f942ad167f3a 100644 --- a/applications/gui2/src/screen.cpp +++ b/applications/gui2/src/screen.cpp @@ -25,7 +25,7 @@ using Eigen::Vector2i; using ftl::gui2::Screen; static const int toolbar_w = 50; -static const Vector2i wsize(1280+toolbar_w,720); +static const Vector2i wsize(1280,720); Screen::Screen() : nanogui::Screen(wsize, "FT-Lab Remote Presence"), @@ -40,6 +40,7 @@ Screen::Screen() : toolbar_->setPosition({0, 0}); toolbar_->setWidth(toolbar_w); toolbar_->setHeight(height()); + toolbar_->setTheme(getTheme("media")); setResizeCallback([this](const Vector2i &s) { toolbar_->setFixedSize({toolbar_->width(), s[1]}); @@ -98,7 +99,7 @@ void Screen::redraw() { } nanogui::Vector2i Screen::viewSize(const nanogui::Vector2i &ws) { - return {ws.x() - toolbar_->width(), ws.y()}; + return {ws.x(), ws.y()}; } nanogui::Vector2i Screen::viewSize() { @@ -119,7 +120,7 @@ void Screen::showError(const std::string&title, const std::string& msg) { void Screen::setView(ftl::gui2::View *view) { - view->setPosition({toolbar_->width(), 0}); + view->setPosition({0, 0}); view->setTheme(getTheme("view")); view->setVisible(true); diff --git a/applications/gui2/src/views/camera.cpp b/applications/gui2/src/views/camera.cpp index 451a032ee9f4aa450547594aeb8929c8b9252afb..016ce424c9c6849620be0ed7a57637645f638da7 100644 --- a/applications/gui2/src/views/camera.cpp +++ b/applications/gui2/src/views/camera.cpp @@ -397,7 +397,13 @@ ToolPanel::ToolPanel(nanogui::Widget *parent, ftl::gui2::Camera* ctrl, CameraVie Tools::PAN, Tools::INSPECT_POINT, Tools::ZOOM_IN, - Tools::ZOOM_OUT + Tools::ZOOM_OUT, + Tools::ROTATE_X, + Tools::ROTATE_Y, + Tools::ROTATE_Z, + Tools::TRANSLATE_X, + Tools::TRANSLATE_Y, + Tools::TRANSLATE_Z }); _addButton(mouse_group, Tools::SELECT_POINT, ENTYPO_ICON_MOUSE_POINTER, "Select Point"); _addButton(mouse_group, Tools::MOVEMENT, ENTYPO_ICON_MAN, "First Person Camera"); @@ -406,6 +412,17 @@ ToolPanel::ToolPanel(nanogui::Widget *parent, ftl::gui2::Camera* ctrl, CameraVie _addButton(mouse_group, Tools::INSPECT_POINT, ENTYPO_ICON_MAGNIFYING_GLASS, "Inspect Point"); _addButton(mouse_group, Tools::ZOOM_IN, ENTYPO_ICON_CIRCLE_WITH_PLUS, "Zoom In (+)"); _addButton(mouse_group, Tools::ZOOM_OUT, ENTYPO_ICON_CIRCLE_WITH_MINUS, "Zoom Out (-)"); + auto *trans_but = _addButton(mouse_group, { + Tools::ROTATE_X, + Tools::ROTATE_Y, + Tools::ROTATE_Z + }, ENTYPO_ICON_CYCLE, "Transform Pose"); + _addButton(trans_but, Tools::ROTATE_X, "Rotate X"); + _addButton(trans_but, Tools::ROTATE_Y, "Rotate Y"); + _addButton(trans_but, Tools::ROTATE_Z, "Rotate Z"); + _addButton(trans_but, Tools::TRANSLATE_X, "Translate X"); + _addButton(trans_but, Tools::TRANSLATE_Y, "Translate Y"); + _addButton(trans_but, Tools::TRANSLATE_Z, "Translate Z"); auto *view2d_group = _addGroup(ToolGroup::VIEW_2D_ACTIONS, Button::Flags::NormalButton, { Tools::CENTRE_VIEW, diff --git a/applications/gui2/src/views/camera3d.cpp b/applications/gui2/src/views/camera3d.cpp index 29bb0ae4d82b0599dfa0ddd44bee6bb0ac51d676..599fc88a9ae66c246efd319e0c9b3e5ad167651a 100644 --- a/applications/gui2/src/views/camera3d.cpp +++ b/applications/gui2/src/views/camera3d.cpp @@ -44,7 +44,13 @@ CameraView3D::CameraView3D(ftl::gui2::Screen *parent, ftl::gui2::Camera *ctrl) : Tools::MOVE_CURSOR, Tools::ORIGIN_TO_CURSOR, Tools::RESET_ORIGIN, - Tools::SAVE_CURSOR + Tools::SAVE_CURSOR, + Tools::ROTATE_X, + Tools::ROTATE_Y, + Tools::ROTATE_Z, + Tools::TRANSLATE_X, + Tools::TRANSLATE_Y, + Tools::TRANSLATE_Z }); setZoom(false); @@ -61,6 +67,15 @@ CameraView3D::CameraView3D(ftl::gui2::Screen *parent, ftl::gui2::Camera *ctrl) : ctrl_->resetOrigin(); tools_->setTool(Tools::MOVEMENT); return true; + } else if (tool == Tools::SAVE_CURSOR) { + ctrl_->saveCursorToPoser(); + tools_->setTool(Tools::MOVEMENT); + return true; + } else if (tool == Tools::ROTATE_X || tool == Tools::ROTATE_Y || tool == Tools::ROTATE_Z || + tool == Tools::TRANSLATE_X || tool == Tools::TRANSLATE_Y || tool == Tools::TRANSLATE_Z) { + LOG(INFO) << "Loading cache pose"; + cache_pose_ = ctrl_->getActivePose(); + cache_screen_ = ctrl_->getActivePoseScreenCoord(); } return false; }); @@ -103,6 +118,9 @@ bool CameraView3D::mouseButtonEvent(const Eigen::Vector2i &p, int button, bool d return true; } else if (tools_->isActive(Tools::ROTATE_CURSOR)) { tools_->setTool(Tools::MOVEMENT); + } else if (tools_->isActive(Tools::ROTATE_X) || tools_->isActive(Tools::ROTATE_Y) || tools_->isActive(Tools::ROTATE_Z) || + tools_->isActive(Tools::TRANSLATE_X) || tools_->isActive(Tools::TRANSLATE_Y) || tools_->isActive(Tools::TRANSLATE_Z)) { + tools_->setTool(Tools::MOVEMENT); } } @@ -126,6 +144,45 @@ bool CameraView3D::mouseMotionEvent(const Eigen::Vector2i &p, const Eigen::Vecto Eigen::Vector3f world = ctrl_->worldAt(pos.x(), pos.y()); ctrl_->setCursorTarget(world); return true; + } else if (tools_->isActive(Tools::ROTATE_X)) { + auto screen_origin = ctrl_->getActivePoseScreenCoord(); + double angle = atan2(float(screen_origin[1] - p[1]), float(screen_origin[0] - p[0])); + Eigen::Affine3d rx = Eigen::Affine3d(Eigen::AngleAxisd(angle, Eigen::Vector3d(1, 0, 0))); + ctrl_->setActivePose(rx.matrix() * cache_pose_); + } else if (tools_->isActive(Tools::ROTATE_Y)) { + auto screen_origin = ctrl_->getActivePoseScreenCoord(); + double angle = -atan2(float(screen_origin[1] - p[1]), float(screen_origin[0] - p[0])); + Eigen::Affine3d ry = Eigen::Affine3d(Eigen::AngleAxisd(angle, Eigen::Vector3d(0, 1, 0))); + ctrl_->setActivePose(ry.matrix() * cache_pose_); + } else if (tools_->isActive(Tools::ROTATE_Z)) { + auto screen_origin = ctrl_->getActivePoseScreenCoord(); + double angle = atan2(float(screen_origin[1] - p[1]), float(screen_origin[0] - p[0])); + Eigen::Affine3d rz = Eigen::Affine3d(Eigen::AngleAxisd(angle, Eigen::Vector3d(0, 0, 1))); + ctrl_->setActivePose(rz.matrix() * cache_pose_); + } else if (tools_->isActive(Tools::TRANSLATE_X)) { + auto mouse = screen()->mousePos(); + auto pos = imview_->imageCoordinateAt((mouse - mPos).cast<float>()); + double dx = pos[0] - double(cache_screen_[0]); + //double dy = pos[1] - double(cache_screen_[1]); + double dist = dx; //(std::abs(dx) > std::abs(dy)) ? dx : dy; + Eigen::Affine3d rx = Eigen::Affine3d(Eigen::Translation3d(dist*0.001, 0.0, 0.0)); + ctrl_->setActivePose(rx.matrix() * cache_pose_); + } else if (tools_->isActive(Tools::TRANSLATE_Y)) { + auto mouse = screen()->mousePos(); + auto pos = imview_->imageCoordinateAt((mouse - mPos).cast<float>()); + double dx = pos[0] - double(cache_screen_[0]); + //double dy = pos[1] - double(cache_screen_[1]); + double dist = dx; //(std::abs(dx) > std::abs(dy)) ? dx : dy; + Eigen::Affine3d rx = Eigen::Affine3d(Eigen::Translation3d(0.0, dist*0.001, 0.0)); + ctrl_->setActivePose(rx.matrix() * cache_pose_); + } else if (tools_->isActive(Tools::TRANSLATE_Z)) { + auto mouse = screen()->mousePos(); + auto pos = imview_->imageCoordinateAt((mouse - mPos).cast<float>()); + double dx = pos[0] - double(cache_screen_[0]); + //double dy = pos[1] - double(cache_screen_[1]); + double dist = dx; //(std::abs(dx) > std::abs(dy)) ? dx : dy; + Eigen::Affine3d rx = Eigen::Affine3d(Eigen::Translation3d(0.0, 0.0, dist*0.001)); + ctrl_->setActivePose(rx.matrix() * cache_pose_); } //LOG(INFO) << "New pose: \n" << getUpdatedPose(); diff --git a/applications/gui2/src/views/camera3d.hpp b/applications/gui2/src/views/camera3d.hpp index b5dda23c2efec1f9ba78a1ffdf6ed021b8a250bd..1d0771ca6e5b9bbb8dc0b26410dceca9f46814bd 100644 --- a/applications/gui2/src/views/camera3d.hpp +++ b/applications/gui2/src/views/camera3d.hpp @@ -28,6 +28,8 @@ protected: // current Eigen::Vector3d eye_; Eigen::Matrix4d rotmat_; + Eigen::Matrix4d cache_pose_; + Eigen::Vector2i cache_screen_; // updates from mouse double rx_; diff --git a/applications/reconstruct2/src/main.cpp b/applications/reconstruct2/src/main.cpp index 7aa75b51f90ca8ecee8a0b5705cb84aebc5287e4..07a0c258cc9ae248234c081e5927f77aea14c553 100644 --- a/applications/reconstruct2/src/main.cpp +++ b/applications/reconstruct2/src/main.cpp @@ -129,6 +129,8 @@ static void run(ftl::Configurable *root) { feed->stopRecording(); feed->removeFilter(filter); + ftl::config::save(); + net->shutdown(); LOG(INFO) << "Stopping..."; ftl::timer::stop(true); diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp index f74fb46daa7b0a7b2cae4a3217c27a4fbcc5b668..9c829d1cbfb2767580328202e793ffd547b102c3 100644 --- a/applications/vision/src/main.cpp +++ b/applications/vision/src/main.cpp @@ -164,6 +164,8 @@ static void run(ftl::Configurable *root) { // Send channels on flush auto flushhandle = pool.onFlushSet([sender,&encodable](ftl::data::FrameSet &fs, ftl::codecs::Channel c) { + if (!fs.test(ftl::data::FSFlag::AUTO_SEND)) return true; + // Always send data channels if ((int)c >= 32) sender->post(fs, c); else { @@ -212,19 +214,18 @@ static void run(ftl::Configurable *root) { if (encodable != previous_encodable) sender->resetEncoders(fs->frameset()); previous_encodable = encodable; - // Must touch the depth channel to indicate it should be waited for - //for (auto &f : fs->frames) f.touch(Channel::Depth); + if (busy.test_and_set()) { + LOG(WARNING) << "Depth pipeline drop: " << fs->timestamp(); + fs->firstFrame().message(ftl::data::Message::Warning_PIPELINE_DROP, "Depth pipeline drop"); + return true; + } + + fs->set(ftl::data::FSFlag::AUTO_SEND); // Do all processing in another thread... ftl::pool.push([sender,&stats_count,&latency,&frames,&stats_time,pipeline,&busy,fs](int id) mutable { - // Do pipeline here... if not still busy doing it - if (busy.test_and_set()) { - LOG(WARNING) << "Depth pipeline drop: " << fs->timestamp(); - fs->firstFrame().message(ftl::data::Message::Warning_PIPELINE_DROP, "Depth pipeline drop"); - return; - } + pipeline->apply(*fs, *fs); - busy.clear(); ++frames; latency += float(ftl::timer::get_time() - fs->timestamp()); @@ -232,6 +233,7 @@ static void run(ftl::Configurable *root) { // Destruct frameset as soon as possible to send the data... if (fs->hasAnyChanged(Channel::Depth)) fs->flush(Channel::Depth); const_cast<ftl::data::FrameSetPtr&>(fs).reset(); + busy.clear(); if (!quiet && --stats_count <= 0) { latency /= float(frames); @@ -266,6 +268,8 @@ static void run(ftl::Configurable *root) { ftl::timer::start(true); // Blocks LOG(INFO) << "Stopping..."; ctrl.stop(); + + ftl::config::save(); net->shutdown(); diff --git a/components/codecs/include/ftl/codecs/shapes.hpp b/components/codecs/include/ftl/codecs/shapes.hpp index 313381887bee18c8b70eec45127c4fd7c662352b..2368660e526a294a468e19bcd8ebf105a4fa9263 100644 --- a/components/codecs/include/ftl/codecs/shapes.hpp +++ b/components/codecs/include/ftl/codecs/shapes.hpp @@ -17,7 +17,8 @@ enum class Shape3DType { CLIPPING, CAMERA, FEATURE, - ARUCO + ARUCO, + CURSOR }; struct Shape3D { diff --git a/components/common/cpp/include/ftl/configuration.hpp b/components/common/cpp/include/ftl/configuration.hpp index d555d6dc5eecfa9eeb56137d56661f7affc5763d..3f9118947a003c722c66e0023e8ec20c6424c1e5 100644 --- a/components/common/cpp/include/ftl/configuration.hpp +++ b/components/common/cpp/include/ftl/configuration.hpp @@ -48,6 +48,8 @@ nlohmann::json &getDefault(const std::string &key); void cleanup(); +void save(); + void removeConfigurable(Configurable *cfg); /** diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp index f756d1d571927d9c8eb9e070e8b39761b007b962..0e327b539c284381d30834572814e6523b7ae992 100644 --- a/components/common/cpp/src/configuration.cpp +++ b/components/common/cpp/src/configuration.cpp @@ -685,6 +685,15 @@ static void stripJSON(nlohmann::json &j) { } } +void ftl::config::save() { + for (auto &f : config_instance) { + //LOG(INFO) << "Saving: " << f.second->getID(); + f.second->save(); + } + stripJSON(config_restore); + ftl::saveJSON(std::string(FTL_LOCAL_CONFIG_ROOT "/")+cfg_root_str+std::string("_session.json"), config_restore); +} + static std::atomic_bool doing_cleanup = false; void ftl::config::cleanup() { if (doing_cleanup) return; @@ -702,8 +711,7 @@ void ftl::config::cleanup() { } config_instance.clear(); - stripJSON(config_restore); - ftl::saveJSON(std::string(FTL_LOCAL_CONFIG_ROOT "/")+cfg_root_str+std::string("_session.json"), config_restore); + ftl::config::save(); doing_cleanup = false; } diff --git a/components/net/cpp/src/universe.cpp b/components/net/cpp/src/universe.cpp index 08e4820ff090d4cdf0b765c542a2cd6a2b61fcb8..84633c833ca937f897a26dd8381f593c5a02a99b 100644 --- a/components/net/cpp/src/universe.cpp +++ b/components/net/cpp/src/universe.cpp @@ -41,8 +41,8 @@ struct NetImplDetail { //#define TCP_SEND_BUFFER_SIZE (512*1024) //#define TCP_RECEIVE_BUFFER_SIZE (1024*1024*1) -#define TCP_SEND_BUFFER_SIZE (256*1024) -#define TCP_RECEIVE_BUFFER_SIZE (256*1024) +#define TCP_SEND_BUFFER_SIZE (52*1024) // Was 256 +#define TCP_RECEIVE_BUFFER_SIZE (52*1024) // Was 256 callback_t ftl::net::Universe::cbid__ = 0; diff --git a/components/operators/include/ftl/operators/poser.hpp b/components/operators/include/ftl/operators/poser.hpp index 732ee47ed90caf3fb9bc1ed3bcc889626edf4885..9c642e47730e3f6833087b1a484e1f16476e3017 100644 --- a/components/operators/include/ftl/operators/poser.hpp +++ b/components/operators/include/ftl/operators/poser.hpp @@ -22,19 +22,24 @@ class Poser : public ftl::operators::Operator { bool apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cudaStream_t stream) override; + bool apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t stream) override; + static bool get(const std::string &name, Eigen::Matrix4d &pose); - static bool set(const std::string &name, const Eigen::Matrix4d &pose); + static bool get(const std::string &name, ftl::codecs::Shape3D &shape); + static std::list<ftl::codecs::Shape3D*> getAll(int32_t fsid); + + //static bool set(const ftl::codecs::Shape3D &shape); + + static void add(const ftl::codecs::Shape3D &t, ftl::data::FrameID id); private: struct PoseState { - Eigen::Matrix4d pose; + ftl::codecs::Shape3D shape; bool locked; }; static std::unordered_map<std::string,PoseState> pose_db__; - - void add(const ftl::codecs::Shape3D &t, int frameset, int frame); - + static std::unordered_map<int,std::list<ftl::codecs::Shape3D*>> fs_shapes__; }; } diff --git a/components/operators/src/poser.cpp b/components/operators/src/poser.cpp index 2f8a166cff6c67979acf42d7ab375bad928b9b44..a03682767163c03b089ec985342ca1f846e19996 100644 --- a/components/operators/src/poser.cpp +++ b/components/operators/src/poser.cpp @@ -8,7 +8,9 @@ using ftl::codecs::Channel; using ftl::codecs::Shape3DType; using std::string; +static SHARED_MUTEX smtx; std::unordered_map<std::string,ftl::operators::Poser::PoseState> Poser::pose_db__; +std::unordered_map<int,std::list<ftl::codecs::Shape3D*>> Poser::fs_shapes__; Poser::Poser(ftl::Configurable *cfg) : ftl::operators::Operator(cfg) { @@ -18,36 +20,48 @@ Poser::~Poser() { } -void Poser::add(const ftl::codecs::Shape3D &t, int frameset, int frame) { +void Poser::add(const ftl::codecs::Shape3D &t, ftl::data::FrameID id) { std::string idstr; switch(t.type) { case Shape3DType::ARUCO : idstr = "aruco-"; break; case Shape3DType::CAMERA : idstr = "camera-"; break; + case Shape3DType::CURSOR : idstr = "cursor-"; break; default : idstr = "unk-"; break; } - idstr += std::to_string(frameset) + string("-") + std::to_string(frame) + string("-") + std::to_string(t.id); + idstr += std::to_string(id.frameset()) + string("-") + std::to_string(id.source()) + string("-") + std::to_string(t.id); - auto pose = t.pose.cast<double>(); // f.getPose() * + //auto pose = t.pose.cast<double>(); // f.getPose() * + UNIQUE_LOCK(smtx, lk); auto p = pose_db__.find(idstr); if (p == pose_db__.end()) { ftl::operators::Poser::PoseState ps; - ps.pose = pose; + ps.shape = t; ps.locked = false; pose_db__.emplace(std::make_pair(idstr,ps)); LOG(INFO) << "POSE ID: " << idstr; + fs_shapes__[id.frameset()].push_back(&pose_db__[idstr].shape); } else { // TODO: Merge poses - if (!(*p).second.locked) (*p).second.pose = pose; + if (!(*p).second.locked) (*p).second.shape = t; //LOG(INFO) << "POSE ID: " << idstr; } } +std::list<ftl::codecs::Shape3D*> Poser::getAll(int32_t fsid) { + SHARED_LOCK(smtx, lk); + if (fs_shapes__.count(fsid)) { + return fs_shapes__[fsid]; + } + return {}; +} + bool Poser::get(const std::string &name, Eigen::Matrix4d &pose) { + SHARED_LOCK(smtx, lk); auto p = pose_db__.find(name); if (p != pose_db__.end()) { - pose = (*p).second.pose; + pose = (*p).second.shape.pose.cast<double>(); return true; } else { LOG(WARNING) << "Pose not found: " << name; @@ -55,22 +69,6 @@ bool Poser::get(const std::string &name, Eigen::Matrix4d &pose) { } } -bool Poser::set(const std::string &name, const Eigen::Matrix4d &pose) { - auto p = pose_db__.find(name); - if (p == pose_db__.end()) { - ftl::operators::Poser::PoseState ps; - ps.pose = pose; - ps.locked = false; - pose_db__.emplace(std::make_pair(name,ps)); - LOG(INFO) << "POSE ID: " << name; - } else { - // TODO: Merge poses - if (!(*p).second.locked) (*p).second.pose = pose; - //LOG(INFO) << "POSE ID: " << idstr; - } - return true; -} - bool Poser::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cudaStream_t stream) { if (in.hasChannel(Channel::Shapes3D)) { const auto &transforms = in.get<std::list<ftl::codecs::Shape3D>>(Channel::Shapes3D); @@ -79,7 +77,7 @@ bool Poser::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cudaStream_ for (auto &t : transforms) { // LOG(INFO) << "Have FS transform: " << t.label; - add(t, in.frameset(), 255); + add(t, in.id()); } } @@ -93,7 +91,7 @@ bool Poser::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cudaStream_ //LOG(INFO) << "Found shapes 3D: " << (int)transforms.size(); for (auto &t : transforms) { - add(t, in.frameset(), i); + add(t, f.id()); } } @@ -103,21 +101,46 @@ bool Poser::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cudaStream_ cam.label = f.name(); cam.pose = f.getPose().cast<float>(); cam.type = ftl::codecs::Shape3DType::CAMERA; - add(cam, in.frameset(), i); + add(cam, f.id()); } //} } + SHARED_LOCK(smtx, lk); string pose_ident = config()->value("pose_ident",string("default")); if (pose_ident != "default") { auto p = pose_db__.find(pose_ident); if (p != pose_db__.end()) { (*p).second.locked = config()->value("locked",false); - in.cast<ftl::rgbd::Frame>().setPose() = (config()->value("inverse",false)) ? (*p).second.pose.inverse() : (*p).second.pose; + + Eigen::Matrix4d pose = (*p).second.shape.pose.cast<double>(); + in.cast<ftl::rgbd::Frame>().setPose() = (config()->value("inverse",false)) ? pose.inverse() : pose; } else { LOG(WARNING) << "Pose not found: " << pose_ident; } } + return true; +} + +bool Poser::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t stream) { + auto &f = in; + + if (f.hasChannel(Channel::Shapes3D)) { + const auto &transforms = f.get<std::list<ftl::codecs::Shape3D>>(Channel::Shapes3D); + + for (auto &t : transforms) { + add(t, f.id()); + } + } + + if (f.hasChannel(Channel::Pose)) { + ftl::codecs::Shape3D cam; + cam.id = 0; + cam.label = f.name(); + cam.pose = f.getPose().cast<float>(); + cam.type = ftl::codecs::Shape3DType::CAMERA; + add(cam, f.id()); + } return true; } \ No newline at end of file diff --git a/components/renderers/cpp/src/overlay.cpp b/components/renderers/cpp/src/overlay.cpp index 611e9737c2a5157d5ab1ff21174436d2e763d5c7..7562ffbf9272c72e90e409c03401c0f6f65072a6 100644 --- a/components/renderers/cpp/src/overlay.cpp +++ b/components/renderers/cpp/src/overlay.cpp @@ -5,6 +5,7 @@ #include <opencv2/imgproc.hpp> #include <ftl/codecs/shapes.hpp> +#include <ftl/operators/poser.hpp> #define LOGURU_REPLACE_GLOG 1 #include <loguru.hpp> @@ -365,40 +366,39 @@ void Overlay::draw(NVGcontext *ctx, ftl::data::FrameSet &fs, ftl::rgbd::Frame &f } }*/ - for (size_t i=0; i<fs.frames.size(); ++i) { - if (fs.frames[i].hasChannel(Channel::Shapes3D)) { - const auto &shapes = fs.frames[i].get<std::list<ftl::codecs::Shape3D>>(Channel::Shapes3D); + auto shapes = ftl::operators::Poser::getAll(fs.frameset()); - for (auto &s : shapes) { - auto pose = s.pose.cast<double>(); //.inverse() * state.getPose(); - //Eigen::Vector4d pos = pose.inverse() * Eigen::Vector4d(0,0,0,1); - //pos /= pos[3]; + for (auto *ps : shapes) { + auto &s = *ps; - Eigen::Vector3f scale(s.size[0]/2.0f, s.size[1]/2.0f, s.size[2]/2.0f); + auto pose = s.pose.cast<double>(); //.inverse() * state.getPose(); + //Eigen::Vector4d pos = pose.inverse() * Eigen::Vector4d(0,0,0,1); + //pos /= pos[3]; - auto tpose = frame.getPose().inverse() * pose; + Eigen::Vector3f scale(s.size[0]/2.0f, s.size[1]/2.0f, s.size[2]/2.0f); - switch (s.type) { - case ftl::codecs::Shape3DType::CAMERA: _drawOutlinedShape(Shape::CAMERA, tpose, scale, make_uchar4(255,0,0,80), make_uchar4(255,0,0,255)); break; - case ftl::codecs::Shape3DType::CLIPPING: _drawOutlinedShape(Shape::BOX, tpose, scale, make_uchar4(255,0,255,80), make_uchar4(255,0,255,255)); break; - case ftl::codecs::Shape3DType::ARUCO: _drawAxis(tpose, Eigen::Vector3f(0.2f, 0.2f, 0.2f)); break; - default: break; - } + auto tpose = frame.getPose().inverse() * pose; - if (s.label.size() > 0) { - float3 textpos; - textpos.x = tpose(0,3); - textpos.y = tpose(1,3); - textpos.z = tpose(2,3); + switch (s.type) { + case ftl::codecs::Shape3DType::CAMERA: _drawOutlinedShape(Shape::CAMERA, tpose, scale, make_uchar4(255,0,0,80), make_uchar4(255,0,0,255)); break; + case ftl::codecs::Shape3DType::CLIPPING: _drawOutlinedShape(Shape::BOX, tpose, scale, make_uchar4(255,0,255,80), make_uchar4(255,0,255,255)); break; + case ftl::codecs::Shape3DType::ARUCO: _drawAxis(tpose, Eigen::Vector3f(0.2f, 0.2f, 0.2f)); break; + case ftl::codecs::Shape3DType::CURSOR: _drawAxis(tpose, Eigen::Vector3f(0.2f, 0.2f, 0.2f)); break; + default: break; + } - float2 textscreen = frame.getLeft().camToScreen<float2>(textpos); - if (textpos.z > 0.1f) nvgText(ctx, textscreen.x, textscreen.y, s.label.c_str(), nullptr); - } + if (s.label.size() > 0) { + float3 textpos; + textpos.x = tpose(0,3); + textpos.y = tpose(1,3); + textpos.z = tpose(2,3); - //ftl::overlay::drawBox(state.getLeft(), out, over_depth_, pose, cv::Scalar(0,0,255,100), s.size.cast<double>()); - //ftl::overlay::drawText(state.getLeft(), out, over_depth_, s.label, pos, 0.5, cv::Scalar(0,0,255,100)); - } + float2 textscreen = frame.getLeft().camToScreen<float2>(textpos); + if (textpos.z > 0.1f) nvgText(ctx, textscreen.x, textscreen.y, s.label.c_str(), nullptr); } + + //ftl::overlay::drawBox(state.getLeft(), out, over_depth_, pose, cv::Scalar(0,0,255,100), s.size.cast<double>()); + //ftl::overlay::drawText(state.getLeft(), out, over_depth_, s.label, pos, 0.5, cv::Scalar(0,0,255,100)); } } diff --git a/components/streams/src/builder.cpp b/components/streams/src/builder.cpp index 33d19b9460f7f96e1da8e45f44c3e3600b99047f..58f2dd3c92b7e1ce1ce0f802dae91935ae465393 100644 --- a/components/streams/src/builder.cpp +++ b/components/streams/src/builder.cpp @@ -394,7 +394,7 @@ std::shared_ptr<ftl::data::FrameSet> ForeignBuilder::_getFrameset() { ftl::data::FrameSetPtr &f2 = framesets_.back(); if (f2.get() == f.get()) break; - LOG(WARNING) << "FrameSet discarded: " << f2->timestamp(); + LOG(WARNING) << "FrameSet discarded: " << f2->timestamp() << " (" << f->timestamp() << ")"; f2->set(ftl::data::FSFlag::DISCARD); { // Ensure frame processing is finished first diff --git a/components/streams/src/receiver.cpp b/components/streams/src/receiver.cpp index 9db6ee7929025c881f79eb5600db2e503d0a728e..aee169927ace489075499ec5738fd2fa246c6da1 100644 --- a/components/streams/src/receiver.cpp +++ b/components/streams/src/receiver.cpp @@ -319,6 +319,7 @@ void Receiver::_finishPacket(ftl::streams::LockedFrameSet &fs, size_t fix) { if (frame.packet_tx > 0 && frame.packet_tx == frame.packet_rx) { fs->completed(fix); + if (fs->isComplete()) timestamp_ = fs->timestamp(); frame.packet_tx = 0; frame.packet_rx = 0; } @@ -329,7 +330,6 @@ void Receiver::processPackets(const StreamPacket &spkt, const Packet &pkt) { if (spkt.channel == Channel::EndFrame) { auto fs = builder(spkt.streamID).get(spkt.timestamp, spkt.frame_number+pkt.frame_count-1); - timestamp_ = spkt.timestamp; fs->frames[spkt.frame_number].packet_tx = static_cast<int>(pkt.packet_count); _finishPacket(fs, spkt.frame_number); return; diff --git a/components/streams/src/renderers/screen_render.cpp b/components/streams/src/renderers/screen_render.cpp index 3df19e7a387d0aa48fd5a7abe5d07e61cc7819de..7b74511b9fd379a47548e562bbc22f303cf33c29 100644 --- a/components/streams/src/renderers/screen_render.cpp +++ b/components/streams/src/renderers/screen_render.cpp @@ -4,6 +4,7 @@ #include <ftl/rgbd/capabilities.hpp> #include <ftl/operators/antialiasing.hpp> #include <ftl/operators/gt_analysis.hpp> +#include <ftl/operators/poser.hpp> #include <ftl/utility/matrix_conversion.hpp> #include <ftl/codecs/shapes.hpp> @@ -213,6 +214,7 @@ bool ScreenRender::retrieve(ftl::data::Frame &frame_out) { if (!data_only) { if (!post_pipe_) { post_pipe_ = ftl::config::create<ftl::operators::Graph>(host(), "post_filters"); + post_pipe_->append<ftl::operators::Poser>("poser"); post_pipe_->append<ftl::operators::FXAA>("fxaa"); post_pipe_->append<ftl::operators::GTAnalysis>("gtanalyse"); } diff --git a/components/streams/src/sender.cpp b/components/streams/src/sender.cpp index 62e48bd0b34a62b8dcf7a1e445ff95c0eaea1df3..5e153f82ee5d145148c5d63d0b61fed5efc6f735 100644 --- a/components/streams/src/sender.cpp +++ b/components/streams/src/sender.cpp @@ -164,6 +164,11 @@ void Sender::post(ftl::data::FrameSet &fs, ftl::codecs::Channel c, bool noencode // Send quick message for this special channel. if (c == Channel::EndFrame) { + if (timestamp_ >= fs.timestamp()) { + LOG(WARNING) << "Sending old frame! " << fs.timestamp() << " vs " << timestamp_ << " (size = " << fs.frames[0].packet_tx+1 << ")"; + } + timestamp_ = fs.timestamp(); + StreamPacket spkt; spkt.version = 5; spkt.timestamp = fs.timestamp(); diff --git a/components/structures/include/ftl/data/new_frameset.hpp b/components/structures/include/ftl/data/new_frameset.hpp index c471eb5a04cfffd6cd2e235069c35d9151dc93ca..90be7f7bee9c9f646ea3eb7c8c4cfb78e55d532b 100644 --- a/components/structures/include/ftl/data/new_frameset.hpp +++ b/components/structures/include/ftl/data/new_frameset.hpp @@ -20,7 +20,8 @@ static const size_t kMaxFramesInSet = 32; enum class FSFlag : int { STALE = 0, PARTIAL = 1, - DISCARD = 4 + DISCARD = 4, + AUTO_SEND = 8 }; /** @@ -77,7 +78,7 @@ class FrameSet : public ftl::data::Frame { /** * Are all frames complete within this frameset? */ - inline bool isComplete() { return ftl::popcount(mask) == frames.size(); } + inline bool isComplete() { return mask != 0 && ftl::popcount(mask) == frames.size(); } /** * Check that a given frame is valid in this frameset. diff --git a/components/structures/src/frameset.cpp b/components/structures/src/frameset.cpp index f6c9ff4587491ca356820e856198b5ce33dcded8..81848289e21eca9b57688c107caf0c194a007d71 100644 --- a/components/structures/src/frameset.cpp +++ b/components/structures/src/frameset.cpp @@ -12,6 +12,7 @@ FrameSet::FrameSet(Pool *ppool, FrameID pid, int64_t ts, size_t psize) : FrameSet::~FrameSet() { if (status() == ftl::data::FrameStatus::CREATED) store(); if (status() == ftl::data::FrameStatus::STORED) flush(); + pool()->flush_fs_.trigger(*this, ftl::codecs::Channel::EndFrame); } void ftl::data::FrameSet::completed(size_t ix) { @@ -103,7 +104,6 @@ void FrameSet::flush() { for (auto c : unflushed) { pool()->flush_fs_.trigger(*this, c); } - pool()->flush_fs_.trigger(*this, ftl::codecs::Channel::EndFrame); } void FrameSet::flush(ftl::codecs::Channel c) {