diff options
35 files changed, 2309 insertions, 1147 deletions
diff --git a/gui/images/opentrack.png b/gui/images/opentrack.png Binary files differindex 39359782..48cbe812 100644 --- a/gui/images/opentrack.png +++ b/gui/images/opentrack.png diff --git a/installer/trackhat-file-list.txt b/installer/trackhat-file-list.txt new file mode 100644 index 00000000..5a17b55f --- /dev/null +++ b/installer/trackhat-file-list.txt @@ -0,0 +1,64 @@ +./cleye.config +./doc/3rdparty-notices/ps3eyedriver +./doc/3rdparty-notices/EIGEN-COPYING.txt +./doc/3rdparty-notices/FACETRACKNOIR-COPYING.txt +./doc/3rdparty-notices/NFAILCLIENT-CREDIT.txt +./doc/3rdparty-notices/OPENCV-COPYING.txt +./doc/3rdparty-notices/QT5-COPYING.txt +./doc/3rdparty-notices/VJOYSTICK-COPYING.txt +./doc/AUTHORS.md +./doc/CONTRIBUTING.md +./doc/OPENTRACK-LICENSING.txt +./doc/README.md +./doc/settings/facetracknoir supported games.csv +./doc/WARRANTY.txt +#./i18n/nl_NL.qm +#./i18n/ru_RU.qm +#./i18n/stub.qm +#./i18n/zh_CN.qm +./modules/cleye.config +./modules/freetrackclient.dll +./modules/freetrackclient64.dll +./modules/NPClient.dll +./modules/NPClient64.dll +./modules/opencv_core455.dll +#./modules/opencv_imgcodecs455.dll +./modules/opencv_imgproc455.dll +#./modules/opencv_videoio455.dll +./modules/opentrack-filter-accela.dll +./modules/opentrack-filter-ewma.dll +./modules/opentrack-filter-hamilton.dll +./modules/opentrack-filter-kalman.dll +./modules/opentrack-proto-fgfs.dll +./modules/opentrack-proto-freetrack.dll +./modules/opentrack-proto-fsuipc.dll +./modules/opentrack-proto-simconnect.dll +./modules/opentrack-proto-udp.dll +./modules/opentrack-proto-vjoy.dll +./modules/opentrack-proto-win32-mouse.dll +./modules/opentrack-tracker-pt.dll +./modules/opentrack-tracker-test.dll +./modules/opentrack-tracker-trackhat.dll +./modules/opentrack-tracker-udp.dll +./modules/opentrack-video-opencv.dll +#./modules/opentrack-video-ps3eye.dll +./modules/ps3eye-subprocess.exe +./modules/TrackIR.exe +./modules/vJoyInterface.dll +./opentrack-api.dll +./opentrack-compat.dll +./opentrack-dinput.dll +./opentrack-logic.dll +./opentrack-migration.dll +./opentrack-options.dll +./opentrack-pose-widget.dll +./opentrack-spline.dll +./opentrack-user-interface.dll +./opentrack-video.dll +./opentrack.exe +./platforms/qwindows.dll +./qt.conf +./Qt5Core.dll +./Qt5Gui.dll +./Qt5Network.dll +./Qt5Widgets.dll diff --git a/opentrack/defs.hpp b/opentrack/defs.hpp index e3826474..f3522d50 100644 --- a/opentrack/defs.hpp +++ b/opentrack/defs.hpp @@ -1,14 +1,11 @@ #pragma once -//#define UI_FORCED_TRACKER "pt" -//#define UI_FORCED_FILTER "accela" - -//#define UI_NO_TRACKER_COMBOBOX -//#define UI_NO_FILTER_COMBOBOX - -//#define UI_NO_TRACKER_SETTINGS_BUTTON -//#define UI_NO_FILTER_SETTINGS_BUTTON - -//#define UI_NO_RAW_DATA -//#define UI_NO_GAME_DATA -//define UI_ACCELA_OLD_STAIRCASE +#define UI_FORCED_TRACKER "trackhat" +#define UI_FORCED_FILTER "accela" +#define UI_NO_TRACKER_COMBOBOX +#define UI_NO_FILTER_COMBOBOX +#define UI_NO_TRACKER_SETTINGS_BUTTON +#define UI_NO_FILTER_SETTINGS_BUTTON +#define UI_NO_RAW_DATA +#define UI_NO_GAME_DATA +#define UI_ACCELA_OLD_STAIRCASE diff --git a/opentrack/lang/nl_NL.ts b/opentrack/lang/nl_NL.ts index 7a465820..15acd701 100644 --- a/opentrack/lang/nl_NL.ts +++ b/opentrack/lang/nl_NL.ts @@ -15,38 +15,6 @@ <context> <name>main_window</name> <message> - <source>Raw tracker data</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Z</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Pitch</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Y</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>X</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Roll</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Yaw</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Game data</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Profile</source> <translation type="unfinished"></translation> </message> @@ -59,10 +27,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>Tracking</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Start</source> <translation type="unfinished"></translation> </message> @@ -71,10 +35,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>Input</source> - <translation type="unfinished"></translation> - </message> - <message> <source>🔨</source> <translation type="unfinished"></translation> </message> @@ -83,10 +43,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>Filter</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Running as root is bad</source> <translation type="unfinished"></translation> </message> diff --git a/opentrack/lang/ru_RU.ts b/opentrack/lang/ru_RU.ts index 684a8212..c869bae8 100644 --- a/opentrack/lang/ru_RU.ts +++ b/opentrack/lang/ru_RU.ts @@ -87,38 +87,6 @@ Exiting now.</source> <translation> :: </translation> </message> <message> - <source>Raw tracker data</source> - <translation>Исходные данные</translation> - </message> - <message> - <source>Z</source> - <translation>Z</translation> - </message> - <message> - <source>Pitch</source> - <translation>Pitch</translation> - </message> - <message> - <source>Y</source> - <translation>Y</translation> - </message> - <message> - <source>X</source> - <translation>X</translation> - </message> - <message> - <source>Roll</source> - <translation>Roll</translation> - </message> - <message> - <source>Yaw</source> - <translation>Yaw</translation> - </message> - <message> - <source>Game data</source> - <translation>Игровые данные</translation> - </message> - <message> <source>Profile</source> <translation>Профиль</translation> </message> @@ -127,10 +95,6 @@ Exiting now.</source> <translation> Кривые</translation> </message> <message> - <source>Tracking</source> - <translation>Статус работы трекера</translation> - </message> - <message> <source>Start</source> <translation>Запустить</translation> </message> @@ -139,10 +103,6 @@ Exiting now.</source> <translation>Остановить</translation> </message> <message> - <source>Input</source> - <translation>Источник данных</translation> - </message> - <message> <source>🔨</source> <translation></translation> </message> @@ -151,10 +111,6 @@ Exiting now.</source> <translation>Выходной интерфейс</translation> </message> <message> - <source>Filter</source> - <translation>Фильтрация/сглаживание</translation> - </message> - <message> <source>Running as root is bad</source> <translation type="unfinished"></translation> </message> diff --git a/opentrack/lang/stub.ts b/opentrack/lang/stub.ts index 04555dd0..66917925 100644 --- a/opentrack/lang/stub.ts +++ b/opentrack/lang/stub.ts @@ -15,38 +15,6 @@ <context> <name>main_window</name> <message> - <source>Raw tracker data</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Z</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Pitch</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Y</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>X</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Roll</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Yaw</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Game data</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Profile</source> <translation type="unfinished"></translation> </message> @@ -59,10 +27,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>Tracking</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Start</source> <translation type="unfinished"></translation> </message> @@ -71,10 +35,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>Input</source> - <translation type="unfinished"></translation> - </message> - <message> <source>🔨</source> <translation type="unfinished"></translation> </message> @@ -83,10 +43,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>Filter</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Running as root is bad</source> <translation type="unfinished"></translation> </message> diff --git a/opentrack/lang/zh_CN.ts b/opentrack/lang/zh_CN.ts index 15609d70..fd9ea20f 100644 --- a/opentrack/lang/zh_CN.ts +++ b/opentrack/lang/zh_CN.ts @@ -15,38 +15,6 @@ <context> <name>main_window</name> <message> - <source>Raw tracker data</source> - <translation>跟踪器原始数据</translation> - </message> - <message> - <source>Z</source> - <translation></translation> - </message> - <message> - <source>Pitch</source> - <translation>仰俯</translation> - </message> - <message> - <source>Y</source> - <translation></translation> - </message> - <message> - <source>X</source> - <translation></translation> - </message> - <message> - <source>Roll</source> - <translation>横滚</translation> - </message> - <message> - <source>Yaw</source> - <translation>偏航</translation> - </message> - <message> - <source>Game data</source> - <translation>游戏得到的数据</translation> - </message> - <message> <source>Profile</source> <translation>配置文件</translation> </message> @@ -59,10 +27,6 @@ <translation>映射</translation> </message> <message> - <source>Tracking</source> - <translation>跟踪</translation> - </message> - <message> <source>Start</source> <translation>开始</translation> </message> @@ -71,10 +35,6 @@ <translation>停止</translation> </message> <message> - <source>Input</source> - <translation>输入</translation> - </message> - <message> <source>🔨</source> <translation></translation> </message> @@ -83,10 +43,6 @@ <translation>输出</translation> </message> <message> - <source>Filter</source> - <translation>过滤器</translation> - </message> - <message> <source>Running as root is bad</source> <translation>以管理员运行不是什么好主意</translation> </message> diff --git a/opentrack/main-window.cpp b/opentrack/main-window.cpp index 1fded8e0..ed1db357 100644 --- a/opentrack/main-window.cpp +++ b/opentrack/main-window.cpp @@ -538,7 +538,7 @@ void main_window::show_pose_(const double* mapped, const double* raw) void main_window::set_title(const QString& game_title) { static const QString version{opentrack_version}; - static const QString sep { tr(" :: ") }; + static const QString sep { " PRE-RELEASE CONFIDENTIAL" + tr(" :: ") }; static const QString pat1{ version + sep + "%1" + sep + "%2" }; static const QString pat2{ version + sep + "%1" }; diff --git a/opentrack/main-window.ui b/opentrack/main-window.ui index 32c9f57a..7a1ee993 100644 --- a/opentrack/main-window.ui +++ b/opentrack/main-window.ui @@ -8,21 +8,15 @@ <x>0</x> <y>0</y> <width>655</width> - <height>502</height> + <height>349</height> </rect> </property> <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>500</height> - </size> - </property> <property name="windowIcon"> <iconset resource="../gui/opentrack-res.qrc"> <normaloff>:/images/opentrack.png</normaloff>:/images/opentrack.png</iconset> @@ -33,24 +27,18 @@ </property> <widget class="QWidget" name="content"> <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <layout class="QGridLayout" name="gridLayout_2"> + <layout class="QGridLayout" name="gridLayout"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> - <property name="rightMargin"> - <number>9</number> - </property> - <property name="bottomMargin"> - <number>9</number> - </property> <item row="0" column="0"> <widget class="QFrame" name="video_feed"> <property name="sizePolicy"> @@ -158,12 +146,6 @@ </item> <item row="0" column="1"> <widget class="pose_widget" name="pose_display" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> <property name="minimumSize"> <size> <width>320</width> @@ -173,673 +155,25 @@ </widget> </item> <item row="1" column="0"> - <widget class="QGroupBox" name="box_raw_headpose"> - <property name="minimumSize"> - <size> - <width>316</width> - <height>0</height> - </size> - </property> - <property name="title"> - <string>Raw tracker data</string> - </property> - <layout class="QGridLayout" name="gridLayout_12"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>0</number> - </property> - <item row="0" column="3"> - <widget class="QLCDNumber" name="raw_yaw"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="lblZ_4"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="autoFillBackground"> - <bool>false</bool> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Z</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLabel" name="lblRotY_4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Pitch</string> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QLCDNumber" name="raw_pitch"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="lblY_4"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="autoFillBackground"> - <bool>false</bool> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Y</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="lblX_4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>X</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLCDNumber" name="raw_x"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLabel" name="lblRotZ_4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Roll</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="lblRotX_4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Yaw</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLCDNumber" name="raw_y"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="QLCDNumber" name="raw_roll"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLCDNumber" name="raw_z"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="1"> - <widget class="QGroupBox" name="box_mapped_headpose"> - <property name="minimumSize"> - <size> - <width>316</width> - <height>0</height> - </size> - </property> - <property name="title"> - <string>Game data</string> - </property> - <layout class="QGridLayout" name="gridLayout_14"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>0</number> - </property> - <item row="1" column="3"> - <widget class="QLCDNumber" name="pose_pitch"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QLCDNumber" name="pose_yaw"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLCDNumber" name="pose_z"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="lblx"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>X</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="lblY_2"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="autoFillBackground"> - <bool>false</bool> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Y</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLCDNumber" name="pose_x"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLabel" name="lblRotY_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Pitch</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLabel" name="lblRotZ_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Roll</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="lblRotX_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Yaw</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="lblZ_2"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="autoFillBackground"> - <bool>false</bool> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Z</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLCDNumber" name="pose_y"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="QLCDNumber" name="pose_roll"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <stylestrategy>NoAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="smallDecimalPoint"> - <bool>true</bool> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="2" column="1"> - <widget class="QWidget" name="groupControls" native="true"> + <widget class="QWidget" name="widget_2" native="true"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> - <horstretch>4</horstretch> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> - <width>315</width> + <width>310</width> <height>0</height> </size> </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> + <layout class="QVBoxLayout" name="verticalLayout"> <property name="spacing"> - <number>4</number> + <number>3</number> </property> <property name="leftMargin"> - <number>0</number> + <number>6</number> </property> <property name="topMargin"> <number>0</number> @@ -851,143 +185,74 @@ <number>0</number> </property> <item> - <widget class="QWidget" name="groupProfile" native="true"> + <widget class="QGroupBox" name="groupGameProtocol"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="spacing"> - <number>0</number> - </property> + <property name="title"> + <string>Output</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> <property name="leftMargin"> <number>4</number> </property> <property name="topMargin"> - <number>0</number> + <number>4</number> </property> <property name="rightMargin"> <number>4</number> </property> <property name="bottomMargin"> + <number>4</number> + </property> + <property name="horizontalSpacing"> + <number>6</number> + </property> + <property name="verticalSpacing"> <number>0</number> </property> - <item> - <widget class="QToolButton" name="profile_button"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="text"> - <string>Profile</string> - </property> - <property name="popupMode"> - <enum>QToolButton::InstantPopup</enum> - </property> - <property name="toolButtonStyle"> - <enum>Qt::ToolButtonTextBesideIcon</enum> - </property> - <property name="autoRaise"> - <bool>true</bool> - </property> - <property name="arrowType"> - <enum>Qt::DownArrow</enum> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="iconcomboProfile"> + <item row="0" column="0"> + <widget class="QComboBox" name="iconcomboProtocol"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize"> - <size> - <width>245</width> - <height>0</height> - </size> - </property> <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="maxVisibleItems"> - <number>20</number> + <enum>Qt::TabFocus</enum> </property> </widget> </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="groupOptions" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <property name="leftMargin"> - <number>4</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>4</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QPushButton" name="btnShortcuts"> + <item row="0" column="1"> + <widget class="QToolButton" name="btnShowServerControls"> + <property name="enabled"> + <bool>true</bool> + </property> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string>Options</string> - </property> - <property name="icon"> - <iconset resource="../gui/opentrack-res.qrc"> - <normaloff>:/images/tools.png</normaloff>:/images/tools.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>80</width> - <height>24</height> - </size> + <property name="font"> + <font> + <family>DejaVu Sans</family> + <stylestrategy>PreferAntialias</stylestrategy> + <kerning>false</kerning> + </font> </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btnEditCurves"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <property name="focusPolicy"> + <enum>Qt::ClickFocus</enum> </property> <property name="text"> - <string>Mapping</string> - </property> - <property name="icon"> - <iconset resource="../gui/opentrack-res.qrc"> - <normaloff>:/images/curves.png</normaloff>:/images/curves.png</iconset> + <string>🔨</string> </property> - <property name="iconSize"> - <size> - <width>80</width> - <height>24</height> - </size> + <property name="flat" stdset="0"> + <bool>false</bool> </property> </widget> </item> @@ -995,9 +260,9 @@ </widget> </item> <item> - <widget class="QGroupBox" name="groupStartStop"> + <widget class="QWidget" name="groupStartStop" native="true"> <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> <horstretch>4</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -1008,12 +273,9 @@ <height>0</height> </size> </property> - <property name="title"> - <string>Tracking</string> - </property> <layout class="QHBoxLayout" name="horizontalLayout_4"> <property name="spacing"> - <number>7</number> + <number>6</number> </property> <property name="leftMargin"> <number>4</number> @@ -1025,12 +287,12 @@ <number>4</number> </property> <property name="bottomMargin"> - <number>4</number> + <number>0</number> </property> <item> <widget class="QToolButton" name="btnStartTracker"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -1058,7 +320,7 @@ <bool>false</bool> </property> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -1086,26 +348,26 @@ </layout> </widget> </item> - <item row="2" column="0"> - <widget class="QWidget" name="modules" native="true"> + <item row="1" column="1"> + <widget class="QWidget" name="groupWindows" native="true"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> + <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> + <horstretch>4</horstretch> + <verstretch>1</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> - <width>310</width> + <width>315</width> <height>0</height> </size> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_3"> <property name="spacing"> <number>4</number> </property> <property name="leftMargin"> - <number>4</number> + <number>0</number> </property> <property name="topMargin"> <number>0</number> @@ -1117,137 +379,73 @@ <number>0</number> </property> <item> - <widget class="QGroupBox" name="groupTracker"> - <property name="title"> - <string>Input</string> - </property> - <layout class="QGridLayout" name="gridLayout"> + <widget class="QWidget" name="groupProfile" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> <property name="leftMargin"> - <number>4</number> + <number>0</number> </property> <property name="topMargin"> - <number>4</number> + <number>0</number> </property> <property name="rightMargin"> - <number>4</number> + <number>0</number> </property> <property name="bottomMargin"> - <number>4</number> - </property> - <property name="horizontalSpacing"> - <number>6</number> - </property> - <property name="verticalSpacing"> <number>0</number> </property> - <item row="0" column="0"> - <widget class="QComboBox" name="iconcomboTrackerSource"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy"> - <enum>Qt::TabFocus</enum> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QToolButton" name="btnShowEngineControls"> + <item> + <widget class="QToolButton" name="profile_button"> <property name="enabled"> <bool>true</bool> </property> <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="font"> - <font> - <family>DejaVu Sans</family> - <stylestrategy>PreferAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> <property name="focusPolicy"> - <enum>Qt::ClickFocus</enum> + <enum>Qt::StrongFocus</enum> </property> <property name="text"> - <string>🔨</string> + <string>Profile</string> </property> - <property name="flat" stdset="0"> - <bool>false</bool> + <property name="popupMode"> + <enum>QToolButton::InstantPopup</enum> </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupProto"> - <property name="title"> - <string>Output</string> - </property> - <layout class="QGridLayout" name="gridLayout_4"> - <property name="leftMargin"> - <number>4</number> - </property> - <property name="topMargin"> - <number>4</number> - </property> - <property name="rightMargin"> - <number>4</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <property name="horizontalSpacing"> - <number>6</number> - </property> - <property name="verticalSpacing"> - <number>0</number> - </property> - <item row="0" column="0"> - <widget class="QComboBox" name="iconcomboProtocol"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> </property> - <property name="focusPolicy"> - <enum>Qt::TabFocus</enum> + <property name="autoRaise"> + <bool>true</bool> + </property> + <property name="arrowType"> + <enum>Qt::DownArrow</enum> </property> </widget> </item> - <item row="0" column="1"> - <widget class="QToolButton" name="btnShowServerControls"> - <property name="enabled"> - <bool>true</bool> - </property> + <item> + <widget class="QComboBox" name="iconcomboProfile"> <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="font"> - <font> - <family>DejaVu Sans</family> - <stylestrategy>PreferAntialias</stylestrategy> - <kerning>false</kerning> - </font> + <property name="minimumSize"> + <size> + <width>245</width> + <height>0</height> + </size> </property> <property name="focusPolicy"> - <enum>Qt::ClickFocus</enum> - </property> - <property name="text"> - <string>🔨</string> + <enum>Qt::StrongFocus</enum> </property> - <property name="flat" stdset="0"> - <bool>false</bool> + <property name="maxVisibleItems"> + <number>20</number> </property> </widget> </item> @@ -1255,72 +453,49 @@ </widget> </item> <item> - <widget class="QGroupBox" name="groupFilter"> - <property name="title"> - <string>Filter</string> + <widget class="QPushButton" name="btnShortcuts"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Options</string> + </property> + <property name="icon"> + <iconset resource="../gui/opentrack-res.qrc"> + <normaloff>:/images/tools.png</normaloff>:/images/tools.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>80</width> + <height>24</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnEditCurves"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Mapping</string> + </property> + <property name="icon"> + <iconset resource="../gui/opentrack-res.qrc"> + <normaloff>:/images/curves.png</normaloff>:/images/curves.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>80</width> + <height>24</height> + </size> </property> - <layout class="QGridLayout" name="gridLayout_3"> - <property name="leftMargin"> - <number>4</number> - </property> - <property name="topMargin"> - <number>4</number> - </property> - <property name="rightMargin"> - <number>4</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <property name="horizontalSpacing"> - <number>6</number> - </property> - <property name="verticalSpacing"> - <number>0</number> - </property> - <item row="0" column="0"> - <widget class="QComboBox" name="iconcomboFilter"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy"> - <enum>Qt::TabFocus</enum> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QToolButton" name="btnShowFilterControls"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <family>DejaVu Sans</family> - <stylestrategy>PreferAntialias</stylestrategy> - <kerning>false</kerning> - </font> - </property> - <property name="focusPolicy"> - <enum>Qt::ClickFocus</enum> - </property> - <property name="text"> - <string>🔨</string> - </property> - <property name="flat" stdset="0"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> </widget> </item> </layout> diff --git a/opentrack/opentrack.ico b/opentrack/opentrack.ico Binary files differindex 5cac8da1..03af36dc 100644 --- a/opentrack/opentrack.ico +++ b/opentrack/opentrack.ico diff --git a/pose-widget/images/side1.png b/pose-widget/images/side1.png Binary files differindex 2955bc01..4f17de81 100644 --- a/pose-widget/images/side1.png +++ b/pose-widget/images/side1.png diff --git a/pose-widget/images/side6.png b/pose-widget/images/side6.png Binary files differindex 3bae0e50..4f17de81 100644 --- a/pose-widget/images/side6.png +++ b/pose-widget/images/side6.png diff --git a/sdk-paths-sthalik@MSVC-windows.cmake b/sdk-paths-sthalik@MSVC-windows.cmake index db6e8b35..8e5b3fc3 100644 --- a/sdk-paths-sthalik@MSVC-windows.cmake +++ b/sdk-paths-sthalik@MSVC-windows.cmake @@ -36,6 +36,7 @@ setq(SDK_VJOYSTICK "vjoystick") setq(ONNXRuntime_INCLUDE_DIR "onnxruntime-1.10.0//include") setq(ONNXRuntime_LIBRARY "onnxruntime-1.10.0/lib/onnxruntime.lib") setq(ONNXRuntime_RUNTIME "onnxruntime-1.10.0/lib/onnxruntime.dll") +setq(SDK_TRACKHAT_SENSOR "../trackhat/trackhat-c-library-driver/build/install") setq(Qt5_DIR "../qt-5.15.0kde0/lib/cmake/Qt5") set(Qt5Core_DIR "${Qt5_DIR}Core" CACHE PATH "" FORCE) diff --git a/tracker-trackhat/CMakeLists.txt b/tracker-trackhat/CMakeLists.txt new file mode 100644 index 00000000..483bf4c9 --- /dev/null +++ b/tracker-trackhat/CMakeLists.txt @@ -0,0 +1,16 @@ +if(WIN32) + include(opentrack-opencv) + find_package(OpenCV QUIET) + if(OpenCV_FOUND) + foreach(k core imgproc) + otr_install_lib("opencv_${k}" "${opentrack-libexec}") + endforeach() + set(SDK_TRACKHAT_SENSOR CACHE PATH "") + if(SDK_TRACKHAT_SENSOR) + include_directories("${SDK_TRACKHAT_SENSOR}/include" ${OpenCV_INCLUDE_DIRS}) + link_directories("${SDK_TRACKHAT_SENSOR}/lib") + link_libraries(opencv_imgproc opencv_core opentrack-tracker-pt-base track-hat) + otr_module(tracker-trackhat) + endif() + endif() +endif() diff --git a/tracker-trackhat/camera.cpp b/tracker-trackhat/camera.cpp new file mode 100644 index 00000000..033fd532 --- /dev/null +++ b/tracker-trackhat/camera.cpp @@ -0,0 +1,126 @@ +#include "trackhat.hpp" +#include "compat/sleep.hpp" +#include <cstdio> + +namespace trackhat_impl { + +TH_ErrorCode log_error(TH_ErrorCode error, const char* source, + const char* file, int line, const char* function) +{ + if (error == TH_ERROR_DEVICE_ALREADY_OPEN) + error = TH_SUCCESS; + if (error) + { + auto logger = QMessageLogger(file, line, function).warning(); + logger << "tracker/trackhat: error" << (void*)-error << "in" << source; + } + return error; +} + +} // ns trackhat_impl + +pt_camera::result trackhat_camera::get_info() const +{ + return {true, get_desired() }; +} + +pt_camera_info trackhat_camera::get_desired() const +{ + pt_camera_info ret = {}; + + ret.fov = sensor_fov; + ret.fps = 250; + ret.res_x = sensor_size; + ret.res_y = sensor_size; + + return ret; +} + +QString trackhat_camera::get_desired_name() const +{ + return QStringLiteral("TrackHat sensor"); +} + +QString trackhat_camera::get_active_name() const +{ + return get_desired_name(); +} + +void trackhat_camera::set_fov(pt_camera::f) {} +void trackhat_camera::show_camera_settings() {} + +trackhat_camera::trackhat_camera() +{ + s.set_raii_dtor_state(false); + t.set_raii_dtor_state(false); + + for (auto* slider : { &t.exposure, &t.gain, &t.threshold, }) + { + QObject::connect(slider, options::value_::value_changed<options::slider_value>(), + &sig, &trackhat_impl::setting_receiver::settings_changed, + Qt::DirectConnection); + } +} + +trackhat_camera::~trackhat_camera() +{ + stop(); +} + +pt_camera::result trackhat_camera::get_frame(pt_frame& frame_) +{ + if (!device.ensure_connected()) + goto error; + + if (sig.test_and_clear() && !init_regs()) + goto error; + + set_pt_options(); + + { + trackHat_ExtendedPoints_t points; + if (!!th_check(trackHat_GetDetectedPointsExtended(&*device, &points))) + goto error; + auto& frame = *frame_.as<trackhat_frame>(); + frame.init_points(points, t.min_pt_size, t.max_pt_size); + } + + return {true, get_desired()}; + +error: + stop(); + return {false, {}}; +} + +static void log_handler(const char* file, int line, const char* function, char level, const char* str, size_t len) +{ + if (level != 'E') + return; + char file_[128]; + snprintf(file_, std::size(file_), "trackhat/%s", file); + auto logger = QMessageLogger(file_, line, function).debug(); + logger << "tracker/trackhat:"; + logger.noquote() << QLatin1String(str, (int)len); +} + +bool trackhat_camera::start(const pt_settings&) +{ + trackHat_SetDebugHandler(log_handler); + + if constexpr(debug_mode) + trackHat_EnableDebugMode(); + else + trackHat_DisableDebugMode(); + + if (!device.ensure_device_exists()) + return false; + + set_pt_options(); + + return true; +} + +void trackhat_camera::stop() +{ + device.disconnect(); +} diff --git a/tracker-trackhat/dialog.cpp b/tracker-trackhat/dialog.cpp new file mode 100644 index 00000000..2a7bf119 --- /dev/null +++ b/tracker-trackhat/dialog.cpp @@ -0,0 +1,143 @@ +#include "dialog.hpp" + +using namespace options; + +trackhat_dialog::trackhat_dialog() +{ + ui.setupUi(this); + poll_tracker_info(); + poll_timer.setInterval(100); + + const std::tuple<QString, model_type> model_types[] = { + { tr("Cap"), model_cap }, + { tr("Clip (left)"), model_clip_left }, + { tr("Clip (right)"), model_clip_right }, + { tr("Mini Clip (left)"), model_mini_clip_left }, + { tr("Mini Clip (right)"), model_mini_clip_right }, + { tr("Custom"), model_mystery_meat }, + }; + + ui.model_type->clear(); + + for (const auto& [name, type] : model_types) + ui.model_type->addItem(QIcon{}, name, (QVariant)(int)type); + + // model + + tie_setting(t.model, ui.model_type); + tie_setting(t.min_pt_size, ui.min_point_size); + tie_setting(t.max_pt_size, ui.max_point_size); + tie_setting(t.point_filter_limit, ui.point_filter_limit); + + // exposure + + tie_setting(t.exposure, ui.exposure_slider); + tie_setting(t.gain, ui.gain_slider); + ui.exposure_label->setValue((int)*t.exposure); + ui.gain_label->setValue((int)*t.gain); + ui.point_filter_limit_label->setValue(*t.point_filter_limit); + + connect(&t.exposure, value_::value_changed<slider_value>(), ui.exposure_label, + [this] { ui.exposure_label->setValue((int)*t.exposure); }, Qt::QueuedConnection); + connect(&t.gain, value_::value_changed<slider_value>(), ui.gain_label, + [this] { ui.gain_label->setValue((int)*t.gain); }, Qt::QueuedConnection); + connect(&t.point_filter_limit, value_::value_changed<slider_value>(), ui.point_filter_limit_label, + [this] { ui.point_filter_limit_label->setValue(*t.point_filter_limit); }, Qt::QueuedConnection); + + // threshold + + tie_setting(t.threshold, ui.threshold_slider); + + ui.threshold_label->setValue((int)*t.threshold); + + connect(&t.threshold, value_::value_changed<slider_value>(), ui.threshold_label, [=] { + ui.threshold_label->setValue((int)*t.threshold); + }, Qt::QueuedConnection); + + // point filter + + tie_setting(t.enable_point_filter, ui.enable_point_filter); + tie_setting(t.point_filter_coefficient, ui.point_filter_slider); + ui.point_filter_label->setValue(*t.point_filter_coefficient); + + connect(&t.point_filter_coefficient, value_::value_changed<slider_value>(), ui.point_filter_label, + [this] { ui.point_filter_label->setValue(*t.point_filter_coefficient); }, Qt::QueuedConnection); + + tie_setting(t.point_filter_deadzone, ui.point_filter_deadzone); + ui.point_filter_deadzone_label->setValue(*t.point_filter_deadzone); + + connect(&t.point_filter_deadzone, value_::value_changed<slider_value>(), ui.point_filter_deadzone_label, + [this] { ui.point_filter_deadzone_label->setValue(*t.point_filter_deadzone); }, Qt::QueuedConnection); + + // stuff + + connect(&poll_timer, &QTimer::timeout, this, &trackhat_dialog::poll_tracker_info); + connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &trackhat_dialog::doOK); + connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &trackhat_dialog::doCancel); +} + +void trackhat_dialog::register_tracker(ITracker* tracker_) +{ + tracker = static_cast<Tracker_PT*>(tracker_); + poll_tracker_info(); + poll_timer.start(); +} + +void trackhat_dialog::unregister_tracker() +{ + tracker = nullptr; + poll_tracker_info(); + poll_timer.stop(); + update_raw_data(); +} + +void trackhat_dialog::save() +{ + s.b->save(); + t.b->save(); +} + +void trackhat_dialog::reload() +{ + s.b->reload(); + t.b->reload(); +} + +void trackhat_dialog::doCancel() { reload(); close(); } +void trackhat_dialog::doOK() { save(); close(); } + +trackhat_dialog::~trackhat_dialog() +{ +} + +void trackhat_dialog::poll_tracker_info() +{ + if (!tracker) + ui.status_label->setText(tr("Status: Tracking stopped.")); + else if (tracker->get_n_points() == 3) + ui.status_label->setText(tr("Status: %1 points detected. Good!").arg(tracker->get_n_points())); + else + ui.status_label->setText(tr("Status: %1 points detected. BAD!").arg(tracker->get_n_points())); + update_raw_data(); +} + +void trackhat_dialog::set_buttons_visible(bool x) +{ + ui.buttonBox->setVisible(x); + adjustSize(); +} +void trackhat_dialog::update_raw_data() +{ + QLabel* labels[] = { ui.label_x, ui.label_y, ui.label_z, ui.label_yaw, ui.label_pitch, ui.label_roll }; + if (tracker) + { + QString str; str.reserve(16); + double data[6] {}; + tracker->data(data); + for (unsigned i = 0; i < std::size(labels); i++) + labels[i]->setText(str.sprintf("%.2f%s", data[i], i >= 3 ? "°" : " mm")); + } + else + for (QLabel* x : labels) + x->setText(QStringLiteral("-")); +} diff --git a/tracker-trackhat/dialog.hpp b/tracker-trackhat/dialog.hpp new file mode 100644 index 00000000..35ca866b --- /dev/null +++ b/tracker-trackhat/dialog.hpp @@ -0,0 +1,36 @@ +#pragma once +#include "trackhat.hpp" +#include "ui_dialog.h" +#include "tracker-pt/ftnoir_tracker_pt.h" +#include "api/plugin-api.hpp" +#include <QTimer> + +class trackhat_dialog final : public ITrackerDialog +{ + Q_OBJECT + +protected: + Ui_trackhat_dialog ui; + Tracker_PT* tracker = nullptr; + QTimer poll_timer{this}; + + pt_settings s{trackhat_metadata::module_name}; + trackhat_settings t; + + void set_buttons_visible(bool x) override; + void update_raw_data(); + +public: + trackhat_dialog(); + ~trackhat_dialog() override; + void register_tracker(ITracker *tracker) override; + void unregister_tracker() override; + bool embeddable() noexcept override { return true; } + void save() override; + void reload() override; + +public slots: + void doOK(); + void doCancel(); + void poll_tracker_info(); +}; diff --git a/tracker-trackhat/dialog.ui b/tracker-trackhat/dialog.ui new file mode 100644 index 00000000..6bb7f515 --- /dev/null +++ b/tracker-trackhat/dialog.ui @@ -0,0 +1,611 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>trackhat_dialog</class> + <widget class="QDialog" name="trackhat_dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>365</width> + <height>485</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>365</width> + <height>0</height> + </size> + </property> + <property name="windowTitle"> + <string>TrackHat</string> + </property> + <property name="windowIcon"> + <iconset resource="trackhat-res.qrc"> + <normaloff>:/images/trackhat-64x64.png</normaloff>:/images/trackhat-64x64.png</iconset> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Camera</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="1"> + <widget class="QSlider" name="gain_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>51</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSlider" name="exposure_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>239</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Threshold</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="threshold_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimum"> + <number>64</number> + </property> + <property name="maximum"> + <number>254</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Gain</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QSpinBox" name="threshold_label"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>999</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QSpinBox" name="gain_label"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>999</number> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QSpinBox" name="exposure_label"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>999</number> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Exposure</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Model</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>10</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Type</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="model_type"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>9</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Min point size</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Max point size</string> + </property> + </widget> + </item> + <item row="2" column="1" alignment="Qt::AlignRight"> + <widget class="QDoubleSpinBox" name="max_point_size"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="decimals"> + <number>1</number> + </property> + <property name="minimum"> + <double>1.000000000000000</double> + </property> + <property name="maximum"> + <double>999.000000000000000</double> + </property> + </widget> + </item> + <item row="1" column="1" alignment="Qt::AlignRight"> + <widget class="QDoubleSpinBox" name="min_point_size"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="decimals"> + <number>1</number> + </property> + <property name="minimum"> + <double>1.000000000000000</double> + </property> + <property name="maximum"> + <double>999.000000000000000</double> + </property> + <property name="value"> + <double>1.000000000000000</double> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Tracking</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QWidget" name="widget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item row="0" column="2"> + <widget class="QDoubleSpinBox" name="point_filter_label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="decimals"> + <number>2</number> + </property> + <property name="maximum"> + <double>300.000000000000000</double> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="point_filter_limit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>99</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Limit</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>Deadzone</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QCheckBox" name="enable_point_filter"> + <property name="text"> + <string>Point filter</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QDoubleSpinBox" name="point_filter_limit_label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="prefix"> + <string/> + </property> + <property name="suffix"> + <string/> + </property> + <property name="decimals"> + <number>2</number> + </property> + <property name="maximum"> + <double>1.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSlider" name="point_filter_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>300</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="point_filter_deadzone"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QDoubleSpinBox" name="point_filter_deadzone_label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="decimals"> + <number>2</number> + </property> + <property name="maximum"> + <double>300.000000000000000</double> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QLabel" name="status_label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Status</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_4"> + <property name="title"> + <string>Raw data</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>X</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_y"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_z"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>Yaw</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Roll</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Y</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_x"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>Z</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>Pitch</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLabel" name="label_yaw"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLabel" name="label_pitch"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QLabel" name="label_roll"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>exposure_slider</tabstop> + <tabstop>gain_slider</tabstop> + <tabstop>threshold_slider</tabstop> + <tabstop>model_type</tabstop> + <tabstop>min_point_size</tabstop> + <tabstop>max_point_size</tabstop> + <tabstop>enable_point_filter</tabstop> + <tabstop>point_filter_slider</tabstop> + <tabstop>point_filter_limit</tabstop> + </tabstops> + <resources> + <include location="trackhat-res.qrc"/> + </resources> + <connections/> +</ui> diff --git a/tracker-trackhat/extractor.cpp b/tracker-trackhat/extractor.cpp new file mode 100644 index 00000000..58b9fd05 --- /dev/null +++ b/tracker-trackhat/extractor.cpp @@ -0,0 +1,21 @@ +#include "trackhat.hpp" +#include <algorithm> +#include <iterator> + +void trackhat_extractor::extract_points(const pt_frame& data, + pt_preview&, bool, + std::vector<vec2>& points) +{ + points.clear(); + points.reserve(trackhat_camera::point_count); + const auto& copy = data.as_const<trackhat_frame>()->points; + + for (const auto& pt : copy) + { + if (!pt.ok) + continue; + constexpr int sz = trackhat_camera::sensor_size; + auto [ x, y ] = to_screen_pos(pt.x, pt.y, sz, sz); + points.push_back({x, y}); + } +} diff --git a/tracker-trackhat/frame.cpp b/tracker-trackhat/frame.cpp new file mode 100644 index 00000000..d8fae002 --- /dev/null +++ b/tracker-trackhat/frame.cpp @@ -0,0 +1,127 @@ +#include "trackhat.hpp" +#include <opencv2/imgproc.hpp> +#include "compat/math.hpp" + +trackhat_preview::trackhat_preview(int w, int h) +{ + frame_bgr.create(h, w, CV_8UC3); + frame_bgra.create(h, w, CV_8UC4); +} + +void trackhat_preview::set_last_frame(const pt_frame& frame_) +{ + center = {-1, -1}; + points = frame_.as_const<trackhat_frame>()->points; +} + +void trackhat_preview::draw_head_center(pt_pixel_pos_mixin::f x, pt_pixel_pos_mixin::f y) +{ + center = {x, y}; +} + +QImage trackhat_preview::get_bitmap() +{ + frame_bgr.setTo({0}); + + draw_points(); + draw_center(); + + cv::cvtColor(frame_bgr, frame_bgra, cv::COLOR_BGR2BGRA); + + return QImage((const unsigned char*) frame_bgra.data, + frame_bgra.cols, frame_bgra.rows, + (int)frame_bgra.step.p[0], + QImage::Format_ARGB32); +} + +void trackhat_preview::draw_center() +{ + if (center == numeric_types::vec2(-1, -1)) + return; + + auto [px_, py_] = to_pixel_pos(center[0], center[1], frame_bgr.cols, frame_bgr.rows); + int px = iround(px_), py = iround(py_); + + const f dpi = (f)frame_bgr.cols / f(320); + constexpr int len_ = 9; + int len = iround(len_ * dpi); + + static const cv::Scalar color(0, 255, 255); + cv::line(frame_bgr, + cv::Point(px - len, py), + cv::Point(px + len, py), + color, 1); + cv::line(frame_bgr, + cv::Point(px, py - len), + cv::Point(px, py + len), + color, 1); +} + +void trackhat_preview::draw_points() +{ + for (const auto& pt : points) + { + if (pt.brightness == 0) + continue; + + constexpr int sz = trackhat_camera::sensor_size; + constexpr f scaling_factor = 10; + const int x = pt.x * frame_bgr.cols / sz, y = pt.y * frame_bgr.rows / sz; + const f dpi = (f)frame_bgr.cols / f(320); + const int W = std::max(1, iround(pt.W * frame_bgr.cols * scaling_factor / sz)), + H = std::max(1, iround(pt.H * frame_bgr.rows * scaling_factor / sz)); + const auto point_color = progn(double c = pt.brightness; return cv::Scalar{c, c, c};); + const auto outline_color = pt.ok + ? cv::Scalar{255, 255, 0} + : cv::Scalar{192, 192, 192}; + + cv::ellipse(frame_bgr, {x, y}, {W, H}, + 0, 0, 360, point_color, -1, cv::LINE_AA); + cv::ellipse(frame_bgr, {x, y}, {iround(W + 2*dpi), iround(H + 2*dpi)}, + 0, 0, 360, outline_color, iround(dpi), cv::LINE_AA); + + char buf[16]; + std::snprintf(buf, sizeof(buf), "%dpx", pt.area); + auto text_color = pt.ok + ? cv::Scalar(0, 0, 255) + : cv::Scalar(160, 160, 160); + const int offx = iround(W + 9*dpi), offy = H*3/2; + + cv::putText(frame_bgr, buf, {x+offx, y+offy}, + cv::FONT_HERSHEY_PLAIN, iround(dpi), text_color, + 1); + } +} + +void trackhat_frame::init_points(const trackHat_ExtendedPoints_t& points_, double min_size, double max_size) +{ + trackHat_ExtendedPoints_t copy = points_; + points = {}; + + std::sort(std::begin(copy.m_point), std::end(copy.m_point), + [](trackHat_ExtendedPoint_t p1, trackHat_ExtendedPoint_t p2) { + return p1.m_averageBrightness > p2.m_averageBrightness; + }); + + unsigned i = 0; + + for (const trackHat_ExtendedPoint_t& pt : copy.m_point) + { + if (pt.m_averageBrightness == 0) + continue; + + point p = {}; + + if (pt.m_area >= min_size && pt.m_area <= max_size) + p.ok = true; + + p.brightness = pt.m_averageBrightness; + p.area = pt.m_area; + p.W = std::max(1, pt.m_boundryRigth - pt.m_boundryLeft); + p.H = std::max(1, pt.m_boundryDown - pt.m_boundryUp); + p.x = trackhat_camera::sensor_size-1-pt.m_coordinateX; + p.y = pt.m_coordinateY; + + points[i++] = p; + } +} diff --git a/tracker-trackhat/handle.cpp b/tracker-trackhat/handle.cpp new file mode 100644 index 00000000..42902e76 --- /dev/null +++ b/tracker-trackhat/handle.cpp @@ -0,0 +1,72 @@ +#undef NDEBUG +#include "trackhat.hpp" +#include "compat/sleep.hpp" +#include "compat/timer.hpp" +#include <cassert> + +bool camera_handle::ensure_connected() +{ + if (state_ >= st_streaming) + return true; + else if (state_ == st_stopped) + return false; + + Timer t; + + constexpr int max_attempts = 5; + + if (!ensure_device_exists()) + goto error; + + for (int i = 0; i < max_attempts; i++) + { + if (!th_check(trackHat_Connect(&device_, TH_FRAME_EXTENDED))) + { + state_ = st_streaming; + if (int ms = (int)t.elapsed_ms(); ms > 1000) + qDebug() << "tracker/trackhat: connecting took" << ms << "ms"; + return true; + } + + auto dbg = qDebug(); + dbg << "tracker/trackhat: connect failed, retry"; + dbg.space(); dbg.nospace(); + dbg << (i+1) << "/" << max_attempts; + portable::sleep(50); + } + +error: + disconnect(); + return false; +} + +bool camera_handle::ensure_device_exists() +{ + switch (state_) + { + case st_streaming: + return true; + case st_detected: + disconnect(); + [[fallthrough]]; + case st_stopped: + assert(!th_check(trackHat_Initialize(&device_)) && device_.m_pInternal); + if (auto error = th_check(trackHat_DetectDevice(&device_)); error) + { + disconnect(); + return false; + } + state_ = st_detected; + return true; + } +} + +void camera_handle::disconnect() +{ + state_ = st_stopped; + if (device_.m_pInternal) + { + (void)!th_check(trackHat_Disconnect(&device_)); + trackHat_Deinitialize(&device_); + } +} diff --git a/tracker-trackhat/images/trackhat-64x64.png b/tracker-trackhat/images/trackhat-64x64.png Binary files differnew file mode 100644 index 00000000..9e856c23 --- /dev/null +++ b/tracker-trackhat/images/trackhat-64x64.png diff --git a/tracker-trackhat/images/trackhat.ico b/tracker-trackhat/images/trackhat.ico Binary files differnew file mode 100644 index 00000000..b5f34db3 --- /dev/null +++ b/tracker-trackhat/images/trackhat.ico diff --git a/tracker-trackhat/images/trackhat.png b/tracker-trackhat/images/trackhat.png Binary files differnew file mode 100644 index 00000000..4f17de81 --- /dev/null +++ b/tracker-trackhat/images/trackhat.png diff --git a/tracker-trackhat/lang/nl_NL.ts b/tracker-trackhat/lang/nl_NL.ts new file mode 100644 index 00000000..50fdef30 --- /dev/null +++ b/tracker-trackhat/lang/nl_NL.ts @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> + <name>trackhat_dialog</name> + <message> + <source>Cap</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Custom</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: Tracking stopped.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. Good!</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. BAD!</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>TrackHat</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Threshold</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Model</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Type</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Min point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> px</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Tracking</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Point filter</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Limit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Raw data</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>TextLabel</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yaw</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Roll</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Pitch</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Deadzone</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>trackhat_module</name> + <message> + <source>TrackHat Point Tracker</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-trackhat/lang/ru_RU.ts b/tracker-trackhat/lang/ru_RU.ts new file mode 100644 index 00000000..23c14ed4 --- /dev/null +++ b/tracker-trackhat/lang/ru_RU.ts @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>trackhat_dialog</name> + <message> + <source>Cap</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Custom</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: Tracking stopped.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. Good!</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. BAD!</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>TrackHat</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Threshold</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Model</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Type</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Min point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> px</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Tracking</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Point filter</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Limit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Raw data</source> + <translation>Исходные данные</translation> + </message> + <message> + <source>X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>TextLabel</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yaw</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Roll</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Pitch</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Deadzone</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>trackhat_module</name> + <message> + <source>TrackHat Point Tracker</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-trackhat/lang/stub.ts b/tracker-trackhat/lang/stub.ts new file mode 100644 index 00000000..17ca6da6 --- /dev/null +++ b/tracker-trackhat/lang/stub.ts @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="stub"> +<context> + <name>trackhat_dialog</name> + <message> + <source>TrackHat</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Threshold</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Model</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Type</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Min point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> px</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Tracking</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Limit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Deadzone</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Point filter</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Raw data</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>TextLabel</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yaw</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Roll</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Pitch</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cap</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Custom</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: Tracking stopped.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. Good!</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. BAD!</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>trackhat_module</name> + <message> + <source>TrackHat Point Tracker</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-trackhat/lang/zh_CN.ts b/tracker-trackhat/lang/zh_CN.ts new file mode 100644 index 00000000..1c7f83ae --- /dev/null +++ b/tracker-trackhat/lang/zh_CN.ts @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_CN"> +<context> + <name>trackhat_dialog</name> + <message> + <source>Cap</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (left)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mini Clip (right)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Custom</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: Tracking stopped.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. Good!</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status: %1 points detected. BAD!</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>TrackHat</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Threshold</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Model</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Type</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Min point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max point size</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> px</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Tracking</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Point filter</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Limit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Status</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Raw data</source> + <translation>跟踪器原始数据</translation> + </message> + <message> + <source>X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>TextLabel</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yaw</source> + <translation>偏航</translation> + </message> + <message> + <source>Roll</source> + <translation>横滚</translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Pitch</source> + <translation>仰俯</translation> + </message> + <message> + <source>Deadzone</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>trackhat_module</name> + <message> + <source>TrackHat Point Tracker</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-trackhat/metadata.cpp b/tracker-trackhat/metadata.cpp new file mode 100644 index 00000000..8c6f4de0 --- /dev/null +++ b/tracker-trackhat/metadata.cpp @@ -0,0 +1,39 @@ +#include "metadata.hpp" +#include "api/plugin-api.hpp" +#include "trackhat.hpp" +#include "dialog.hpp" + +// XXX TODO +const QString trackhat_metadata::module_name = QStringLiteral("tracker-trackhat/pt"); + +pt_runtime_traits::pointer<pt_camera> trackhat_metadata::make_camera() const +{ + return std::make_shared<trackhat_camera>(); +} + +pt_runtime_traits::pointer<pt_point_extractor> trackhat_metadata::make_point_extractor() const +{ + return std::make_shared<trackhat_extractor>(); +} + +pt_runtime_traits::pointer<pt_frame> trackhat_metadata::make_frame() const +{ + return std::make_shared<trackhat_frame>(); +} + +pt_runtime_traits::pointer<pt_preview> trackhat_metadata::make_preview(int w, int h) const +{ + return std::make_shared<trackhat_preview>(w, h); +} + +QString trackhat_metadata::get_module_name() const +{ + return trackhat_metadata::module_name; +} + +trackhat_pt::trackhat_pt() : + Tracker_PT(pt_runtime_traits::pointer<pt_runtime_traits>(new trackhat_metadata)) +{ +} + +OPENTRACK_DECLARE_TRACKER(trackhat_pt, trackhat_dialog, trackhat_module) diff --git a/tracker-trackhat/metadata.hpp b/tracker-trackhat/metadata.hpp new file mode 100644 index 00000000..c0f7567c --- /dev/null +++ b/tracker-trackhat/metadata.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "trackhat.hpp" +#include "../tracker-pt/ftnoir_tracker_pt.h" + +class trackhat_pt final : public Tracker_PT +{ + Q_OBJECT + +public: + trackhat_pt(); +}; + +class trackhat_module final : public Metadata +{ + Q_OBJECT + +public: + QString name() override { return tr("TrackHat Point Tracker"); } + QIcon icon() override { return QIcon(":/images/trackhat-64x64.png"); } + static const QString module_name; +}; diff --git a/tracker-trackhat/settings.cpp b/tracker-trackhat/settings.cpp new file mode 100644 index 00000000..f9a866bf --- /dev/null +++ b/tracker-trackhat/settings.cpp @@ -0,0 +1,137 @@ +#include "trackhat.hpp" +#include "compat/sleep.hpp" +#include "compat/timer.hpp" + +namespace trackhat_impl { + +trackhat_settings::trackhat_settings() : opts{"tracker-trackhat"} +{ +} + +void setting_receiver::settings_changed() +{ + changed = true; +} + +bool setting_receiver::test_and_clear() +{ + bool x = true; + return changed.compare_exchange_strong(x, false); +} + +setting_receiver::setting_receiver(bool value) : changed{value} +{ +} + +} // ns trackhat_impl + +void trackhat_camera::set_pt_options() +{ + s.min_point_size = t.min_pt_size; + s.max_point_size = t.max_pt_size; + + switch (t.model) + { + default: + case model_cap: + s.t_MH_x = 0; s.t_MH_y = 0; s.t_MH_z = 0; + break; + case model_mystery_meat: + case model_clip_left: + case model_mini_clip_left: + s.t_MH_x = -135; s.t_MH_y = 0; s.t_MH_z = 0; + break; + case model_clip_right: + case model_mini_clip_right: + s.t_MH_x = 135; s.t_MH_y = 0; s.t_MH_z = 0; + break; + } + + switch (t.model) + { + default: + eval_once(qDebug() << "tracker/trackhat: unknown model"); + [[fallthrough]]; + case model_clip_left: + case model_clip_right: + s.clip_tz = 27; s.clip_ty = 43; s.clip_by = 62; s.clip_bz = 74; + break; + case model_mini_clip_left: + case model_mini_clip_right: + s.clip_tz = 13; s.clip_ty = 42; s.clip_by = 60; s.clip_bz = 38; + break; + case model_cap: + s.cap_x = 60; s.cap_y = 90; s.cap_z = 95; + break; + case model_mystery_meat: + break; + } + + s.dynamic_pose = t.model == model_cap; + s.init_phase_timeout = 500; + + s.camera_name = QStringLiteral("TrackHat Sensor (WIP)"); + + s.active_model_panel = t.model == model_cap ? 1 : 0; + s.enable_point_filter = t.enable_point_filter; + s.point_filter_coefficient = *t.point_filter_coefficient; + s.point_filter_deadzone = *t.point_filter_deadzone; +} + +bool trackhat_camera::init_regs() +{ + auto exp = (uint8_t)t.exposure; + auto exp2 = (uint8_t)(exp == 0xff ? 0xf0 : 0xff); + auto thres = (uint8_t)t.threshold; + auto thres2 = (uint8_t)3; + + auto gain = (uint8_t)((int)*t.gain); + auto gain_c = (uint8_t)(gain/0x10); + gain %= 0x10; gain_c %= 4; + + trackHat_SetRegisterGroup_t regs = { + { + { 0x0c, 0x0f, exp2 }, // exposure lo + { 0x0c, 0x10, exp }, // exposure hi + { 0x00, 0x0b, 0xff }, // blob area max size + { 0x00, 0x0c, 0x03 }, // blob area min size + { 0x0c, 0x08, gain }, // gain + { 0x0c, 0x0c, gain_c }, // gain multiplier + { 0x0c, 0x47, thres }, // min brightness + { 0x00, 0x0f, thres2 }, // brightness margin, formula is `thres >= px > thres - fuzz' + { 0x00, 0x01, 0x01 }, // bank0 sync + { 0x01, 0x01, 0x01 }, // bank1 sync + }, + 10 + }; + + Timer t; + + constexpr int max = 5; + int i = 0; + for (i = 0; i < max; i++) + { + auto status = th_check(trackHat_SetRegisterGroupValue(&*device, ®s)); + if (status == TH_SUCCESS) + break; + else if (status != TH_FAILED_TO_SET_REGISTER && + status != TH_ERROR_DEVICE_COMUNICATION_TIMEOUT) + return false; + else + { + auto dbg = qDebug(); + dbg << "tracker/trackhat: set register retry attempt"; + dbg.space(); dbg.nospace(); + dbg << i << "/" << max; + portable::sleep(50); + } + } + + if (i == max) + return false; + + if (int elapsed = (int)t.elapsed_ms(); elapsed > 100) + qDebug() << "tracker/trackhat: setting registers took" << elapsed << "ms"; + + return true; +} diff --git a/tracker-trackhat/tracker_trackhat.qrc b/tracker-trackhat/tracker_trackhat.qrc new file mode 100644 index 00000000..d54010a0 --- /dev/null +++ b/tracker-trackhat/tracker_trackhat.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>images/trackhat-64x64.png</file> + </qresource> +</RCC> diff --git a/tracker-trackhat/trackhat-res.qrc b/tracker-trackhat/trackhat-res.qrc new file mode 100644 index 00000000..9aeb8879 --- /dev/null +++ b/tracker-trackhat/trackhat-res.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource> + <file>images/trackhat-64x64.png</file> + </qresource> +</RCC> diff --git a/tracker-trackhat/trackhat.hpp b/tracker-trackhat/trackhat.hpp new file mode 100644 index 00000000..1e1857f5 --- /dev/null +++ b/tracker-trackhat/trackhat.hpp @@ -0,0 +1,174 @@ +#pragma once + +#include "../tracker-pt/pt-api.hpp" +#include "compat/macros.hpp" +#include "options/options.hpp" + +#include <track_hat_driver.h> + +#include <array> +#include <atomic> +#include <opencv2/core/mat.hpp> + +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) + +struct trackhat_settings : opts +{ + trackhat_settings(); + value<slider_value> exposure{b, "exposure", {0x80, 0x10, 0xff}}; + value<slider_value> gain{b, "gain", {16, 0, 47}}; + value<slider_value> threshold{b, "threshold", {0x97, 64, 0xfe}}; + value<model_type> model{b, "model", model_mini_clip_left}; + value<double> min_pt_size{b, "min-point-size", 10}; + value<double> max_pt_size{b, "max-point-size", 50}; + value<bool> enable_point_filter{b, "enable-point-filter", true }; + value<slider_value> point_filter_coefficient{b, "point-filter-coefficient", { 1.5, 1, 4 }}; + value<slider_value> point_filter_limit { b, "point-filter-limit", { 0.1, 0.01, 1 }}; + value<slider_value> point_filter_deadzone { b, "point-filter-deadzone", {0, 0, 1}}; +}; + +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<bool> changed{false}; +}; + +} // ns trackhat_impl + +using typename trackhat_impl::trackhat_settings; + +struct trackhat_metadata final : pt_runtime_traits +{ + pt_runtime_traits::pointer<pt_camera> make_camera() const override; + pt_runtime_traits::pointer<pt_point_extractor> make_point_extractor() const override; + pt_runtime_traits::pointer<pt_frame> make_frame() const override; + pt_runtime_traits::pointer<pt_preview> 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; + + [[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; + + static constexpr int sensor_size = 2940; + 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; +}; + +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<point, trackhat_camera::point_count> 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<point, trackhat_camera::point_count> points; +}; + +struct trackhat_extractor final : pt_point_extractor +{ + void extract_points(const pt_frame& data, pt_preview&, bool, std::vector<vec2>& points) override; + + OTR_DISABLE_MOVE_COPY(trackhat_extractor); + + trackhat_extractor() = default; + ~trackhat_extractor() override = default; +}; diff --git a/variant/default/_variant.cmake b/variant/default/_variant.cmake index ffa795d0..908ae9c5 100644 --- a/variant/default/_variant.cmake +++ b/variant/default/_variant.cmake @@ -1,6 +1,6 @@ function(otr_init_variant) set_property(GLOBAL PROPERTY opentrack-variant "default") - set_property(GLOBAL PROPERTY opentrack-ident "opentrack-2.3") + set_property(GLOBAL PROPERTY opentrack-ident "trackhat-2.3") set(subprojects "tracker-*" |
