#pragma once #include "../tracker-pt/pt-api.hpp" #include "compat/timer.hpp" #include "options/options.hpp" #include #include #include #include #include enum model_type : int { model_cap = 1, model_clip_left, model_clip_right, model_mini_clip_left, model_mini_clip_right, model_mystery_meat, }; namespace trackhat_impl { using namespace options; TH_ErrorCode log_error(TH_ErrorCode error, const char* source, const char* file, int line, const char* function); #define th_check_(expr, expr2) ::trackhat_impl::log_error((expr), expr2) #define th_check(expr) ::trackhat_impl::log_error((expr), #expr, __FILE__, __LINE__, function_name) enum class led_mode : unsigned char { off, constant, dynamic, }; struct trackhat_settings : opts { static constexpr int min_gain = 1, max_gain = 47, min_exposure = 0x10, max_exposure = 0xff; static constexpr int num_exposure_steps = max_gain + max_exposure - min_gain - min_exposure; trackhat_settings(); value exposure{b, "exposure", {min_exposure + max_exposure*2/3, min_exposure, max_exposure}}; value gain{b, "gain", {min_gain + max_gain*2/3, min_gain, max_gain}}; //value threshold{b, "threshold", {0x97, 64, 0xfe}}; value model{b, "model", model_mini_clip_left}; value min_pt_size{b, "min-point-size", 10}; value max_pt_size{b, "max-point-size", 50}; value enable_point_filter{b, "enable-point-filter", true }; value point_filter_coefficient{b, "point-filter-coefficient", { 1.5, 1, 4 }}; value point_filter_limit { b, "point-filter-limit", { 0.1, 0.01, 1 }}; value point_filter_deadzone { b, "point-filter-deadzone", {0, 0, 1}}; value led { b, "led-mode", led_mode::dynamic }; }; class setting_receiver : public QObject { Q_OBJECT public: explicit setting_receiver(bool value); bool test_and_clear(); public slots: void settings_changed(); private: std::atomic changed{false}; }; enum class led_state : unsigned char { invalid, stopped, not_tracking, tracking, }; struct led_updater final { trackHat_SetLeds_t leds_ {TH_UNCHANGED, TH_UNCHANGED, TH_UNCHANGED}; std::optional timer_; led_state state_ = led_state::invalid; trackHat_SetLeds_t next_state(led_mode mode, led_state new_state); void update_(trackHat_Device_t* device, trackHat_SetLeds_t leds); void update(trackHat_Device_t* device, led_mode mode, led_state new_state); static constexpr int SWITCH_TIME_MS = 2000; static constexpr trackHat_SetLeds_t LED_idle = {TH_OFF, TH_SOLID, TH_OFF}, LED_off = {TH_OFF, TH_OFF, TH_OFF}, LED_tracking {TH_OFF, TH_SOLID, TH_SOLID}, LED_not_tracking {TH_SOLID, TH_OFF, TH_OFF}; }; } // ns trackhat_impl using trackhat_impl::trackhat_settings; using trackhat_impl::led_updater; struct trackhat_metadata final : pt_runtime_traits { pt_runtime_traits::pointer make_camera() const override; pt_runtime_traits::pointer make_point_extractor() const override; pt_runtime_traits::pointer make_frame() const override; pt_runtime_traits::pointer make_preview(int w, int h) const override; QString get_module_name() const override; OTR_DISABLE_MOVE_COPY(trackhat_metadata); trackhat_metadata() = default; ~trackhat_metadata() override = default; static const QString module_name; }; struct point { int brightness = 0, area, x, y, W, H; bool ok = false; }; struct camera_handle final { OTR_DISABLE_MOVE_COPY(camera_handle); trackHat_Device_t* operator->() { return &device_; } trackHat_Device_t& operator*() { return device_; } camera_handle() = default; ~camera_handle() = default; constexpr operator bool() const { return state_ >= st_streaming; } [[nodiscard]] bool ensure_connected(); [[nodiscard]] bool ensure_device_exists(); void disconnect(); private: trackHat_Device_t device_ = {}; enum state { st_stopped, st_detected, st_streaming, }; state state_ = st_stopped; }; struct trackhat_camera final : pt_camera { trackhat_camera(); ~trackhat_camera() override; OTR_DISABLE_MOVE_COPY(trackhat_camera); bool start(const pt_settings& s) override; void stop() override; pt_camera::result get_frame(pt_frame& frame) override; pt_camera::result get_info() const override; pt_camera_info get_desired() const override; QString get_desired_name() const override; QString get_active_name() const override; void set_fov(f value) override; void show_camera_settings() override; f deadzone_amount() const override { return 10; } static constexpr int sensor_size = 4096; static constexpr int sensor_fov = 52; static constexpr int point_count = TRACK_HAT_NUMBER_OF_POINTS; static constexpr bool debug_mode = true; private: trackhat_impl::setting_receiver sig{true}; [[nodiscard]] bool init_regs(); void set_pt_options(); camera_handle device; pt_settings s{trackhat_metadata::module_name}; trackhat_settings t; led_updater led; }; struct trackhat_frame final : pt_frame { void init_points(const trackHat_ExtendedPoints_t& points, double min_size, double max_size); trackhat_frame() = default; ~trackhat_frame() override = default; std::array points; }; struct trackhat_preview final : pt_preview { QImage get_bitmap() override; void draw_head_center(f x, f y) override; void set_last_frame(const pt_frame&) override; // NOLINT(misc-unconventional-assign-operator) trackhat_preview(int w, int h); ~trackhat_preview() override = default; void draw_points(); void draw_center(); OTR_DISABLE_MOVE_COPY(trackhat_preview); cv::Mat frame_bgr, frame_bgra; numeric_types::vec2 center{-1, -1}; std::array points; }; struct trackhat_extractor final : pt_point_extractor { void extract_points(const pt_frame& data, pt_preview&, bool, std::vector& points) override; OTR_DISABLE_MOVE_COPY(trackhat_extractor); trackhat_extractor() = default; ~trackhat_extractor() override = default; };