diff --git a/applications/gui2/src/modules/camera.cpp b/applications/gui2/src/modules/camera.cpp index 72d91779c45f46071defbbc5227ca692e0ae8588..5919db56fe206b0478e2d0ec819c4cc8f4eee754 100644 --- a/applications/gui2/src/modules/camera.cpp +++ b/applications/gui2/src/modules/camera.cpp @@ -1,6 +1,8 @@ #include "camera.hpp" #include "statistics.hpp" +#include <ftl/file.hpp> + #include "../views/camera3d.hpp" #include <ftl/rgbd/capabilities.hpp> #include <ftl/streams/renderer.hpp> @@ -18,6 +20,8 @@ #include <loguru.hpp> +// ==== Camera ================================================================= + using ftl::gui2::Camera; using ftl::codecs::Channel; using ftl::rgbd::Capability; @@ -31,6 +35,17 @@ void Camera::init() { overlay_ = std::unique_ptr<ftl::overlay::Overlay> (ftl::create<ftl::overlay::Overlay>(this, "overlay")); + + try { + ftl::file::unpack(file::config_dir() / "poses.bin", poses_); + for (const auto& pose : poses_) { + ftl::operators::Poser::add(pose, frame_id_); + } + LOG(INFO) << "Poses loaded from file (" << poses_.size() << " items)"; + } + catch (msgpack::insufficient_bytes&) { + LOG(INFO) << "No poses loaded from file"; + } } void Camera::update(double delta) { @@ -585,7 +600,7 @@ void Camera::setCursor(int x, int y) { void Camera::setOriginToCursor() { using ftl::calibration::transform::inverse; - + // Check for valid cursor /*if (cursor_normal_.norm() == 0.0f) return; float cursor_length = (cursor_target_ - cursor_pos_).norm(); @@ -617,17 +632,17 @@ void Camera::setOriginToCursor() { } } - cursor_target_ = Eigen::Vector3f(0.0f,0.0f,0.0f); + 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(); } void Camera::resetOrigin() { - cursor_target_ = Eigen::Vector3f(0.0f,0.0f,0.0f); + 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(); + cursor_ = _cursor(); if (movable_) { auto *rend = io->feed()->getRenderer(frame_id_); @@ -656,11 +671,14 @@ void Camera::resetOrigin() { void Camera::saveCursorToPoser() { ftl::codecs::Shape3D shape; shape.type = ftl::codecs::Shape3DType::CURSOR; - shape.id = cursor_save_id_++; + shape.id = poses_.size(); 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); + auto k = (*(io->feed()->getFrameSet(frame_id_.frameset())))[frame_id_.source()].name(); + poses_.push_back(shape); + ftl::file::pack(ftl::file::config_dir() / "poses.bin", poses_); ftl::operators::Poser::add(shape, frame_id_); } diff --git a/applications/gui2/src/modules/camera.hpp b/applications/gui2/src/modules/camera.hpp index 21ed70dc34a986b034a28e246897fbcd55e4e384..f35bb7e33cee7f6b8895b66e08605a7f980e3d98 100644 --- a/applications/gui2/src/modules/camera.hpp +++ b/applications/gui2/src/modules/camera.hpp @@ -4,6 +4,8 @@ #include "../screen.hpp" #include "../views/camera.hpp" +#include <ftl/codecs/shapes.hpp> + #include <ftl/render/colouriser.hpp> #include <ftl/render/overlay.hpp> #include <ftl/codecs/touch.hpp> @@ -94,7 +96,7 @@ private: ftl::data::FrameID frame_id_; ftl::codecs::Channel channel_ = ftl::codecs::Channel::Colour; ftl::stream::Feed::Filter *filter_ = nullptr; - std::atomic_bool paused_ = false; // TODO: implement in InputOutput + std::atomic_bool paused_ = false; bool has_seen_frame_ = false; ftl::codecs::Touch point_; bool live_=false; @@ -108,7 +110,6 @@ 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_; @@ -129,6 +130,11 @@ private: void initiate_(ftl::data::Frame &frame); void _updateCapabilities(ftl::data::Frame &frame); Eigen::Matrix4d _cursor() const; + + std::vector<ftl::codecs::Shape3D> poses_; + +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; } diff --git a/components/codecs/CMakeLists.txt b/components/codecs/CMakeLists.txt index 821a11ed93a11f2075bdd1517468a84e0a9ef9a3..5ecf43399a7ceb5ca41edccee26abed452a16c6e 100644 --- a/components/codecs/CMakeLists.txt +++ b/components/codecs/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(BaseCodec OBJECT src/reader.cpp src/channels.cpp src/depth_convert.cu + src/shapes.cpp ) target_include_directories(BaseCodec PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -16,7 +17,7 @@ target_include_directories(BaseCodec PUBLIC ) set_property(TARGET BaseCodec PROPERTY CUDA_ARCHITECTURES OFF) -add_library(OpenCVCodec OBJECT +add_library(OpenCVCodec OBJECT src/opencv_encoder.cpp src/opencv_decoder.cpp ) @@ -32,7 +33,7 @@ $<TARGET_OBJECTS:BaseCodec> $<TARGET_OBJECTS:OpenCVCodec> ) -add_library(NvidiaCodec OBJECT +add_library(NvidiaCodec OBJECT src/nvidia_encoder.cpp src/nvidia_decoder.cpp src/Video_Codec_SDK_9.1.23/Samples/NvCodec/NvDecoder/NvDecoder.cpp diff --git a/components/codecs/include/ftl/codecs/shapes.hpp b/components/codecs/include/ftl/codecs/shapes.hpp index 2368660e526a294a468e19bcd8ebf105a4fa9263..9e8f95637d3d8651eb9866a6fde81931eda033f6 100644 --- a/components/codecs/include/ftl/codecs/shapes.hpp +++ b/components/codecs/include/ftl/codecs/shapes.hpp @@ -2,12 +2,32 @@ #define _FTL_CODECS_SHAPES_HPP_ #include <opencv2/core/mat.hpp> - #include <ftl/utility/msgpack.hpp> namespace ftl { namespace codecs { +// ============================================================================= +// TODO: document which direction the pose transforma is + +class Pose { +public: + Pose(const Eigen::Matrix4d& pose); + Eigen::Vector3d rvec() const; + Eigen::Vector3d tvec() const; + Eigen::Matrix3d rmat() const; + Eigen::Matrix4d mat() const; + +private: + double rvec_[3] = {0.0}; + double tvec_[3] = {0.0}; + +public: + MSGPACK_DEFINE(rvec_, tvec_); +}; + +// ============================================================================= + enum class Shape3DType { UNKNOWN = 0, BOX, diff --git a/components/codecs/src/shapes.cpp b/components/codecs/src/shapes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a338431d6e9c0b38f1095362893f024e7a2cce6 --- /dev/null +++ b/components/codecs/src/shapes.cpp @@ -0,0 +1,42 @@ +#include <Eigen/Geometry> +#include "ftl/codecs/shapes.hpp" + +namespace ftl { +namespace codecs { + +Pose::Pose(const Eigen::Matrix4d& pose) { + const Eigen::Vector4d t = pose.col(3); + for (int i = 0; i < 3; i++) { tvec_[i] = t[i]; } + Eigen::AngleAxis<double> rot(Eigen::Matrix3d(pose.block(0, 0, 3, 3))); + Eigen::Vector3d r = rot.axis(); + for (int i = 0; i < 3; i++) { rvec_[i] = r[i]; } +} + +Eigen::Vector3d Pose::tvec() const { + Eigen::Vector3d v; + for (int i = 0; i < 3; i++) { v[i] = tvec_[i]; } + return v; +} + +Eigen::Vector3d Pose::rvec() const { + Eigen::Vector3d v; + for (int i = 0; i < 3; i++) { v[i] = rvec_[i]; } + return v; +} + +Eigen::Matrix3d Pose::rmat() const { + Eigen::AngleAxis<double> rot; + rot.axis() = rvec(); + return rot.toRotationMatrix(); +} + +Eigen::Matrix4d Pose::mat() const { + Eigen::Matrix4d T = Eigen::Matrix4d::Identity(); + T.block<3, 3>(0, 0) = rmat(); + T.block<1, 3>(0, 3) = tvec(); + return T; +} + +} + +} \ No newline at end of file diff --git a/components/common/cpp/include/ftl/file.hpp b/components/common/cpp/include/ftl/file.hpp index 765607974d520d270e67acf0b9d7a15f33c8fda1..0230604c5413129502d478221f64706cce0a8433 100644 --- a/components/common/cpp/include/ftl/file.hpp +++ b/components/common/cpp/include/ftl/file.hpp @@ -11,6 +11,10 @@ namespace filesystem = experimental::filesystem; #include <filesystem> #endif +#include <fstream> +#include <msgpack.hpp> +#include <ftl/utility/msgpack.hpp> + namespace ftl { namespace file { @@ -19,6 +23,24 @@ std::filesystem::path config_dir(); bool is_file(const std::filesystem::path &path); +// wrap msgpack to/from file +template<typename T> +void pack(const std::filesystem::path& path, const T& obj) { + std::ofstream ofs(path.string(), std::ios_base::trunc); + msgpack::pack(ofs, obj); + ofs.close(); +} + +template<typename T> +void unpack(const std::filesystem::path& path, T& obj) { + msgpack::object_handle oh; + std::stringstream buf; + std::ifstream ifs(path.string()); + buf << ifs.rdbuf(); + msgpack::unpack(oh, buf.str().data(), buf.str().size()); + oh.get().convert(obj); +} + } } diff --git a/components/streams/src/stream.cpp b/components/streams/src/stream.cpp index 72a8524e97d538ad1f407bcad15ebf76cf3b2517..f9d17d86edb0e9052c2a6842189f5fb8c595cea8 100644 --- a/components/streams/src/stream.cpp +++ b/components/streams/src/stream.cpp @@ -34,13 +34,15 @@ bool operator!=(const std::unordered_set<ftl::codecs::Channel> &a, const std::un const std::unordered_set<ftl::codecs::Channel> &Stream::available(int fs) const { SHARED_LOCK(mtx_, lk); - if (fs < 0 || static_cast<uint32_t>(fs) >= state_.size()) throw FTL_Error("Frameset index out-of-bounds: " << fs); + if (fs < 0 || static_cast<uint32_t>(fs) >= state_.size()) + throw FTL_Error("Frameset index out-of-bounds: " << fs); return state_[fs].available; } const std::unordered_set<ftl::codecs::Channel> &Stream::selected(int fs) const { SHARED_LOCK(mtx_, lk); - if (fs < 0 || static_cast<uint32_t>(fs) >= state_.size()) throw FTL_Error("Frameset index out-of-bounds: " << fs); + if (fs < 0 || static_cast<uint32_t>(fs) >= state_.size()) + throw FTL_Error("Frameset index out-of-bounds: " << fs); return state_[fs].selected; } @@ -56,7 +58,8 @@ void Stream::select(int fs, const std::unordered_set<ftl::codecs::Channel> &s, b if (fs == 255) return; UNIQUE_LOCK(mtx_, lk); - if (fs < 0 || (!make && static_cast<uint32_t>(fs) >= state_.size())) throw FTL_Error("Frameset index out-of-bounds: " << fs); + if (fs < 0 || (!make && static_cast<uint32_t>(fs) >= state_.size())) + throw FTL_Error("Frameset index out-of-bounds: " << fs); if (static_cast<uint32_t>(fs) >= state_.size()) state_.resize(fs+1); state_[fs].selected = s; }