Skip to content

File pose_relay.hpp

File List > offload_rendering_server > pose_relay.hpp

Go to the documentation of this file

#pragma once

#ifndef ENABLE_MONADO
#    define ENABLE_MONADO
#endif

#define DOUBLE_INCLUDE
#ifdef USING_OPENXR
#    include "illixr/data_format/poses/combined_pose.hpp"
#else
#    include "illixr/data_format/poses/head_pose.hpp"
#endif

#include "illixr/data_format/pose_prediction.hpp"
#include "illixr/switchboard.hpp"
#include "illixr/threadloop.hpp"

#undef DOUBLE_INCLUDE

#include 

#ifdef USING_OPENXR
#    include "auxiliary/os/os_time.h"
#else
#    ifndef XrTime
typedef int64_t XrTime;
#    endif
#endif

namespace ILLIXR {

struct pose_map_entry {
    uint64_t  id{0}; 
    POSE_TYPE pose;
};

#ifdef USING_OPENXR
struct pose_point {
    XrTime             time;
    uint64_t           id; 
    xrt_space_relation pose;
};
#else
typedef ILLIXR::data_format::pose::fast_head_pose_type pose_point;
#endif

struct velocity_filter {
    static constexpr int MAX_WINDOW                  = 16;
    Eigen::Vector3f      linear_samples[MAX_WINDOW]  = {};
    Eigen::Vector3f      angular_samples[MAX_WINDOW] = {};
    int                  head                        = 0;
    int                  count                       = 0;
    bool                 initialized                 = false;
};

class MY_EXPORT_API pose_relay : public threadloop {
public:
    pose_relay(const std::string& name, phonebook* pb);

    POSE_TYPE get_pose() const;

    POSE_TYPE get_pose(POSE_TIME_TYPE future_time) const;

    bool fast_pose_reliable() const;

#ifdef USING_OPENXR
    uint64_t get_pose_id_for_time(XrTime at_time) const;

    uint64_t find_pose_id_by_orientation(const Eigen::Quaternionf& q) const;

    std::chrono::steady_clock::time_point get_pose_time(uint64_t id) const;
#endif

protected:
    threadloop::skip_option _p_should_skip() override;

    void _p_one_iteration() override;

private:
#ifdef USING_OPENXR
    void calibrate_monado_time_offset();
#endif
    std::shared_ptr<spdlog::logger> log_;
    std::shared_ptr<switchboard>    switchboard_;

#ifdef USING_OPENXR
    switchboard::reader<data_format::pose::combined_pose> combined_pose_;

    mutable switchboard::writer<data_format::pose::hand_joint_poses_pair>       hand_tracking_writer_;
    mutable switchboard::writer<data_format::pose::hand_interaction_poses_pair> hand_interaction_writer_;
    mutable switchboard::writer<data_format::pose::palm_poses_pair>             palm_pose_writer_;
#else
    switchboard::reader<POSE_TYPE> render_pose_;
#endif

    // Pipeline latency constants (will be replaced with measured values later)
    static constexpr double ENCODE_LATENCY_NS = 9.0 * 1'000'000.0;
    static constexpr double DECODE_LATENCY_NS = 5.0 * 1'000'000.0;
    static constexpr double UNITY_LATENCY_NS  = 5.0 * 1'000'000.0;

#ifdef USING_OPENXR
    std::vector<pose_point> current_poses_;
    uint64_t                last_pose_id_ = 0;
#else
    POSE_TYPE current_pose_;
#endif

    int64_t windows_epoch_offset_ns_  = 0;
    bool    monado_offset_calibrated_ = false;

    mutable std::map<XrTime, pose_map_entry> pose_map_;

    mutable std::mutex pose_mutex_;

    mutable std::atomic<double> smoothed_rtt_ns_{0.0};

    std::chrono::steady_clock::time_point                     last_offset_calibration_{};
    std::map<uint64_t, std::chrono::steady_clock::time_point> pose_time_{};
#ifdef USING_OPENXR
    bool use_hand_tracking_     = false;
    bool use_palm_poses_        = false;
    bool use_hand_interactions_ = false;
#endif
    bool            do_pose_prediction_{false};
    velocity_filter velocity_filter_;
    int             velocity_window_size_  = 8; // set from env in ctor
    float           velocity_deadband_lin_ = 0.05f;
    float           velocity_deadband_ang_ = 0.03f;
};

} // namespace ILLIXR