diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2018-07-09 07:18:25 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2018-07-09 07:18:25 +0200 |
commit | f5610a1ac847f17402415e4bf1080f84fd8d185f (patch) | |
tree | d8dda5864941a1d903a1fcf87ece585aa24d532b | |
parent | 793cea587159a0ba01fec6af28e899697ef4da79 (diff) |
tracker/tobii: add prototype support for accumulative mode
-rw-r--r-- | tracker-tobii-eyex/head-tracking.cpp | 89 | ||||
-rw-r--r-- | tracker-tobii-eyex/lang/nl_NL.ts | 45 | ||||
-rw-r--r-- | tracker-tobii-eyex/lang/ru_RU.ts | 45 | ||||
-rw-r--r-- | tracker-tobii-eyex/lang/stub.ts | 45 | ||||
-rw-r--r-- | tracker-tobii-eyex/lang/zh_CN.ts | 45 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-eyex-dialog.cpp | 5 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-eyex-dialog.ui | 449 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-eyex.cpp | 106 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-eyex.hpp | 57 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-settings.hpp | 11 |
10 files changed, 150 insertions, 747 deletions
diff --git a/tracker-tobii-eyex/head-tracking.cpp b/tracker-tobii-eyex/head-tracking.cpp new file mode 100644 index 00000000..8973293d --- /dev/null +++ b/tracker-tobii-eyex/head-tracking.cpp @@ -0,0 +1,89 @@ +#include "tobii-eyex.hpp" +#include "compat/math.hpp" +#include "compat/math-imports.hpp" + +real tobii_eyex_tracker::gain(real x) +{ + // simple sigmoid + x = clamp(x * 12 - 6, -6, 6); + x = 1 / (1 + exp(-x)); + x = x * 2 - 1; + return clamp(x, -1, 1); +} + +void tobii_eyex_tracker::data(double* data) +{ + real px, py, max_x, max_y; + bool fresh; + + { + QMutexLocker l(&global_state_mtx); + + if (!dev_state.is_valid()) + return; + + px = dev_state.px; + py = dev_state.py; + max_x = dev_state.display_res_x - 1; + max_y = dev_state.display_res_y - 1; + + fresh = dev_state.fresh; + dev_state.fresh = false; + } + + if (fresh) + { + real x = (2*px - max_x)/max_x; // (-1)->1 + real y = (2*py - max_y)/max_y; // idem + + data[TX] = x * 50; + data[TY] = y * -50; + + const double dt = t.elapsed_seconds(); + t.start(); + + const double max_yaw = *s.acc_max_yaw, max_pitch = *s.acc_max_pitch; + const double dz_ = *s.acc_dz; // closed set of 0->x, some arbitrary x < 1 + + for (auto* k_ : { &x, &y }) + { + real& k = *k_; + + if (std::fabs(k) < dz_) + k = 0; + else + { + // input has reduced dynamic range + k -= copysign(dz_, k); + k *= 1 + dz_; + } + } + + const double c = *s.acc_speed; + + // XXX check this for stability -sh 20180709 + const double yaw_delta = gain(x) * c * dt; + const double pitch_delta = gain(y) * c * dt; + + yaw += yaw_delta; + pitch += pitch_delta; + + yaw = clamp(yaw, -max_yaw, max_yaw); + pitch = clamp(pitch, -max_pitch, max_pitch); + } + + if (do_center) + { + do_center = false; + yaw = 0; + pitch = 0; + } + + data[Yaw] = yaw; + data[Pitch] = pitch; + data[Roll] = 0; + data[TZ] = 0; // XXX TODO + + // tan(x) in 0->.7 is almost linear. we don't need to adjust. + // .7 is 40 degrees which is already quite a lot from the monitor. +} diff --git a/tracker-tobii-eyex/lang/nl_NL.ts b/tracker-tobii-eyex/lang/nl_NL.ts index 35c7f98a..47076f04 100644 --- a/tracker-tobii-eyex/lang/nl_NL.ts +++ b/tracker-tobii-eyex/lang/nl_NL.ts @@ -7,51 +7,6 @@ <source>Tracker options</source> <translation type="unfinished"></translation> </message> - <message> - <source>Tracking settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode shifts the view toward a target that may be offscreen then fixes upon it. -On the other hand, the snap mode allows for a quick glance outside the field of vision.</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Screen edge length</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max yaw</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max pitch</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Position output</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Enabled</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Snap mode settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Tracking mode</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Speed</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>tobii_eyex_tracker</name> diff --git a/tracker-tobii-eyex/lang/ru_RU.ts b/tracker-tobii-eyex/lang/ru_RU.ts index 806c23b8..65ec8ca5 100644 --- a/tracker-tobii-eyex/lang/ru_RU.ts +++ b/tracker-tobii-eyex/lang/ru_RU.ts @@ -7,51 +7,6 @@ <source>Tracker options</source> <translation type="unfinished"></translation> </message> - <message> - <source>Tracking settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode shifts the view toward a target that may be offscreen then fixes upon it. -On the other hand, the snap mode allows for a quick glance outside the field of vision.</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Screen edge length</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max yaw</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max pitch</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Position output</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Enabled</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Snap mode settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Tracking mode</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Speed</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>tobii_eyex_tracker</name> diff --git a/tracker-tobii-eyex/lang/stub.ts b/tracker-tobii-eyex/lang/stub.ts index 26acccaa..6e4c7d1a 100644 --- a/tracker-tobii-eyex/lang/stub.ts +++ b/tracker-tobii-eyex/lang/stub.ts @@ -7,51 +7,6 @@ <source>Tracker options</source> <translation type="unfinished"></translation> </message> - <message> - <source>Tracking settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode shifts the view toward a target that may be offscreen then fixes upon it. -On the other hand, the snap mode allows for a quick glance outside the field of vision.</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Screen edge length</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max yaw</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max pitch</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Position output</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Enabled</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Snap mode settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Tracking mode</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Speed</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>tobii_eyex_tracker</name> diff --git a/tracker-tobii-eyex/lang/zh_CN.ts b/tracker-tobii-eyex/lang/zh_CN.ts index b7896059..6e4c7d1a 100644 --- a/tracker-tobii-eyex/lang/zh_CN.ts +++ b/tracker-tobii-eyex/lang/zh_CN.ts @@ -7,51 +7,6 @@ <source>Tracker options</source> <translation type="unfinished"></translation> </message> - <message> - <source>Tracking settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode shifts the view toward a target that may be offscreen then fixes upon it. -On the other hand, the snap mode allows for a quick glance outside the field of vision.</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Tracking mode</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Accumulative mode settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Screen edge length</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Speed</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max yaw</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Max pitch</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Position output</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Enabled</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Snap mode settings</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>tobii_eyex_tracker</name> diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.cpp b/tracker-tobii-eyex/tobii-eyex-dialog.cpp index 807542e1..6ab916be 100644 --- a/tracker-tobii-eyex/tobii-eyex-dialog.cpp +++ b/tracker-tobii-eyex/tobii-eyex-dialog.cpp @@ -7,10 +7,7 @@ tobii_eyex_dialog::tobii_eyex_dialog() connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &tobii_eyex_dialog::do_ok); connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &tobii_eyex_dialog::do_cancel); - ui.tracking_mode->addItem("Snap", tobii_snap); - ui.tracking_mode->addItem("Accumulative", tobii_acc); - - tie_setting(s.mode, ui.tracking_mode); + //tie_setting(s.mode, ui.tracking_mode); } void tobii_eyex_dialog::do_ok() diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.ui b/tracker-tobii-eyex/tobii-eyex-dialog.ui index a6aecafb..37451f06 100644 --- a/tracker-tobii-eyex/tobii-eyex-dialog.ui +++ b/tracker-tobii-eyex/tobii-eyex-dialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>659</width> - <height>471</height> + <width>184</width> + <height>35</height> </rect> </property> <property name="windowTitle"> @@ -22,447 +22,6 @@ <number>4</number> </property> <item row="0" column="0"> - <widget class="QGroupBox" name="groupBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Tracking settings</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="label_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>617</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Accumulative mode shifts the view toward a target that may be offscreen then fixes upon it. -On the other hand, the snap mode allows for a quick glance outside the field of vision.</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QFrame" name="frame"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QGridLayout" name="gridLayout"> - <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>9</number> - </property> - <property name="verticalSpacing"> - <number>4</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Tracking mode</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="tracking_mode"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>10</width> - <height>0</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="0"> - <widget class="QGroupBox" name="groupBox_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Accumulative mode settings</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <widget class="QLabel" name="label_3"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Screen edge length</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSlider" name="acc_inv_deadzone_slider"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>9</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>20</number> - </property> - <property name="pageStep"> - <number>1</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="acc_inv_deadzone_label"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>10</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Speed</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_6"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Max yaw</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSlider" name="acc_speed_slider"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>9</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="pageStep"> - <number>1</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_7"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Max pitch</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="acc_max_yaw"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QComboBox" name="acc_max_pitch"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_11"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Position output</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QCheckBox" name="acc_pos_output"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Enabled</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="2" column="0"> - <widget class="QGroupBox" name="groupBox_3"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Snap mode settings</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="2" column="1" rowspan="2"> - <widget class="QComboBox" name="snap_max_yaw"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="3" column="0" rowspan="2"> - <widget class="QLabel" name="label_10"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Max pitch</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_9"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Max yaw</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_8"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Speed</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSlider" name="snap_inv_deazone_slider"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>8</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>20</number> - </property> - <property name="pageStep"> - <number>1</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QComboBox" name="snap_max_pitch"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="snap_inv_deadzone_label"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>10</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSlider" name="snap_speed_slider"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>8</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="pageStep"> - <number>1</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_5"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Screen edge length</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QCheckBox" name="snap_pos_output"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Enabled</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_12"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Position output</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="3" column="0"> <widget class="QDialogButtonBox" name="buttonBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> @@ -479,6 +38,10 @@ On the other hand, the snap mode allows for a quick glance outside the field of </widget> <resources> <include location="tobii-eyex-res.qrc"/> + <include location="tobii-eyex-res.qrc"/> + <include location="tobii-eyex-res.qrc"/> + <include location="tobii-eyex-res.qrc"/> + <include location="tobii-eyex-res.qrc"/> </resources> <connections/> </ui> diff --git a/tracker-tobii-eyex/tobii-eyex.cpp b/tracker-tobii-eyex/tobii-eyex.cpp index 8f2edd62..af0d0c05 100644 --- a/tracker-tobii-eyex/tobii-eyex.cpp +++ b/tracker-tobii-eyex/tobii-eyex.cpp @@ -1,6 +1,7 @@ #include "tobii-eyex.hpp" #include "compat/math-imports.hpp" +#include <tuple> #include <cstdlib> #include <cstdio> @@ -32,17 +33,7 @@ static inline tobii_eyex_tracker& to_self(TX_USERPARAM param) return *reinterpret_cast<tobii_eyex_tracker*>(param); } -tobii_eyex_tracker::tobii_eyex_tracker() : - dev_ctx(TX_EMPTY_HANDLE), - conn_state_changed_ticket(TX_INVALID_TICKET), - event_handler_ticket(TX_INVALID_TICKET), - state_snapshot(TX_EMPTY_HANDLE), - display_state(TX_EMPTY_HANDLE), - yaw(0), - pitch(0), - do_center(false) -{ -} +tobii_eyex_tracker::tobii_eyex_tracker() = default; void tobii_eyex_tracker::call_tx_deinit() { @@ -54,12 +45,12 @@ tobii_eyex_tracker::~tobii_eyex_tracker() { dbg_verbose("dtor"); - (void) txDisableConnection(dev_ctx); + (void) txDisableConnection(ctx); (void) txReleaseObject(&state_snapshot); bool status = true; - status &= txShutdownContext(dev_ctx, TX_CLEANUPTIMEOUT_FORCEIMMEDIATE, TX_FALSE) == TX_RESULT_OK; - status &= txReleaseContext(&dev_ctx) == TX_RESULT_OK; + status &= txShutdownContext(ctx, TX_CLEANUPTIMEOUT_FORCEIMMEDIATE, TX_FALSE) == TX_RESULT_OK; + status &= txReleaseContext(&ctx) == TX_RESULT_OK; // the API cleanup function needs to be called exactly once over image lifetime. // client software communicates with a service and a desktop program. @@ -129,7 +120,7 @@ void tobii_eyex_tracker::snapshot_committed_handler(TX_CONSTHANDLE async_data_ha dbg_notice("snapshot bad result code") << result; } -void tobii_eyex_tracker::connection_state_change_handler(TX_CONNECTIONSTATE state, TX_USERPARAM param) +void tobii_eyex_tracker::state_change_handler(TX_CONNECTIONSTATE state, TX_USERPARAM param) { tobii_eyex_tracker& self = to_self(param); @@ -142,7 +133,7 @@ void tobii_eyex_tracker::connection_state_change_handler(TX_CONNECTIONSTATE stat dbg_notice("connected but failed to initialize data stream"); else { - txGetStateAsync(self.dev_ctx, TX_STATEPATH_EYETRACKINGSCREENBOUNDS, display_state_handler, param); + txGetStateAsync(self.ctx, TX_STATEPATH_EYETRACKINGSCREENBOUNDS, display_state_handler, param); dbg_notice("connected, data stream ok"); } } @@ -222,11 +213,11 @@ module_status tobii_eyex_tracker::start_tracker(QFrame*) bool status = true; status &= txInitializeEyeX(TX_EYEXCOMPONENTOVERRIDEFLAG_NONE, nullptr, nullptr, nullptr, nullptr) == TX_RESULT_OK; - status &= txCreateContext(&dev_ctx, TX_FALSE) == TX_RESULT_OK; - status &= register_state_snapshot(dev_ctx, &state_snapshot); - status &= txRegisterConnectionStateChangedHandler(dev_ctx, &conn_state_changed_ticket, connection_state_change_handler, reinterpret_cast<TX_USERPARAM>(this)) == TX_RESULT_OK; - status &= txRegisterEventHandler(dev_ctx, &event_handler_ticket, event_handler, reinterpret_cast<TX_USERPARAM>(this)) == TX_RESULT_OK; - status &= txEnableConnection(dev_ctx) == TX_RESULT_OK; + status &= txCreateContext(&ctx, TX_FALSE) == TX_RESULT_OK; + status &= register_state_snapshot(ctx, &state_snapshot); + status &= txRegisterConnectionStateChangedHandler(ctx, &state_changed_ticket, state_change_handler, (TX_USERPARAM)this) == TX_RESULT_OK; + status &= txRegisterEventHandler(ctx, &event_handler_ticket, event_handler, (TX_USERPARAM)this) == TX_RESULT_OK; + status &= txEnableConnection(ctx) == TX_RESULT_OK; if (!status) return error(tr("Connection can't be established. device missing?")); @@ -234,78 +225,15 @@ module_status tobii_eyex_tracker::start_tracker(QFrame*) return status_ok(); } -tobii_eyex_tracker::num tobii_eyex_tracker::gain(num x) +bool tobii_eyex_tracker::center() { - return 1; + do_center = true; + return true; } -static inline double signum(double x) -{ - return !(x < 0) - (x < 0); -} - -void tobii_eyex_tracker::data(double* data) -{ - TX_REAL px, py, dw, dh, x_, y_; - bool fresh; - - { - QMutexLocker l(&global_state_mtx); - - if (!dev_state.is_valid()) - return; - - px = dev_state.px; - py = dev_state.py; - dw = dev_state.display_res_x; - dh = dev_state.display_res_y; - - fresh = dev_state.fresh; - dev_state.fresh = false; - } - - x_ = (px-dw/2.) / (dw/2.); - y_ = (py-dh/2.) / (dh/2.); +settings::settings() : opts("tobii-eyex") {} - data[TX] = x_ * 50; - data[TY] = y_ * -50; - - if (fresh) - { - const double dt = t.elapsed_seconds(); - t.start(); - - using std::fabs; - - constexpr double max_yaw = 45, max_pitch = 30; - constexpr double c_yaw = 3; - constexpr double c_pitch = c_yaw * max_pitch / max_yaw; - - const double yaw_delta = gain(fabs(x_)) * signum(x_) * c_yaw * dt; - const double pitch_delta = gain(fabs(y_)) * signum(y_) * c_pitch * dt; - - yaw += yaw_delta; - pitch += pitch_delta; - - yaw = clamp(yaw, -max_yaw, max_yaw); - pitch = clamp(pitch, -max_pitch, max_pitch); - } - - if (do_center) - { - do_center = false; - yaw = 0; - pitch = 0; - } - - data[Yaw] = yaw; - data[Pitch] = pitch; - data[Roll] = 0; - data[TZ] = 0; // XXX TODO - - // tan(x) in 0->.7 is almost linear. we don't need to adjust. - // .7 is 40 degrees which is already quite a lot from the monitor. -} +state::state() = default; #include "tobii-eyex-dialog.hpp" diff --git a/tracker-tobii-eyex/tobii-eyex.hpp b/tracker-tobii-eyex/tobii-eyex.hpp index 84407930..def2ea2e 100644 --- a/tracker-tobii-eyex/tobii-eyex.hpp +++ b/tracker-tobii-eyex/tobii-eyex.hpp @@ -23,6 +23,20 @@ using namespace options; #include <QObject> #include <QMutex> +//using real = TX_REAL; +using real = double; + +struct state +{ + real display_res_x = -1, display_res_y = -1; + real px = -1, py = -1; + real last_timestamp = -1; + bool fresh = false; + + state(); + bool is_valid() const { return !(display_res_x < 0 || px < 0); } +}; + class tobii_eyex_tracker : public TR, public ITracker { Q_OBJECT @@ -30,13 +44,9 @@ class tobii_eyex_tracker : public TR, public ITracker public: tobii_eyex_tracker(); ~tobii_eyex_tracker() override; - module_status start_tracker(QFrame *) override; + module_status start_tracker(QFrame*) override; void data(double *data) override; - bool center() override - { - do_center = true; - return true; - } + bool center() override; private: static constexpr inline const char* const client_id = "opentrack-tobii-eyex"; @@ -44,47 +54,36 @@ private: static bool register_state_snapshot(TX_CONTEXTHANDLE ctx, TX_HANDLE* state_snapshot_ptr); static std::atomic_flag atexit_done; - static void TX_CALLCONVENTION connection_state_change_handler(TX_CONNECTIONSTATE state, TX_USERPARAM param); + static void TX_CALLCONVENTION state_change_handler(TX_CONNECTIONSTATE state, TX_USERPARAM param); static void TX_CALLCONVENTION event_handler(TX_CONSTHANDLE async_data_handle, TX_USERPARAM param); void gaze_data_handler(TX_HANDLE gaze_data_handle); static void TX_CALLCONVENTION snapshot_committed_handler(TX_CONSTHANDLE async_data_handle, TX_USERPARAM param); static void TX_CALLCONVENTION display_state_handler(TX_CONSTHANDLE async_data_handle, TX_USERPARAM param); void process_display_state(TX_HANDLE display_state_handle); - using num = double; + real gain(real x); - num gain(num x); + state dev_state; + real yaw = 0, pitch = 0; - TX_CONTEXTHANDLE dev_ctx; - TX_TICKET conn_state_changed_ticket; - TX_TICKET event_handler_ticket; - TX_HANDLE state_snapshot; - TX_HANDLE display_state; + TX_CONTEXTHANDLE ctx = TX_EMPTY_HANDLE; + TX_TICKET state_changed_ticket = TX_INVALID_TICKET; + TX_TICKET event_handler_ticket = TX_INVALID_TICKET; + TX_HANDLE state_snapshot = TX_EMPTY_HANDLE; + TX_HANDLE display_state = TX_EMPTY_HANDLE; QMutex global_state_mtx; settings s; Timer t; - struct state - { - TX_REAL display_res_x, display_res_y; - TX_REAL px, py; - TX_REAL last_timestamp; - bool fresh; - - state() : display_res_x(-1), display_res_y(-1), px(-1), py(-1), last_timestamp(0), fresh(false) {} - bool is_valid() const { return !(display_res_x < 0 || px < 0); } - } dev_state; - - double yaw, pitch; - std::atomic<bool> do_center; + std::atomic<bool> do_center = false; }; class tobii_eyex_metadata : public Metadata { Q_OBJECT - QString name() { return QString("Tobii EyeX"); } - QIcon icon() { return QIcon(":/images/tobii-eyex-logo.png"); } + QString name() override { return QString("Tobii EyeX"); } + QIcon icon() override { return QIcon(":/images/tobii-eyex-logo.png"); } }; diff --git a/tracker-tobii-eyex/tobii-settings.hpp b/tracker-tobii-eyex/tobii-settings.hpp index 49b9cae8..6101a28f 100644 --- a/tracker-tobii-eyex/tobii-settings.hpp +++ b/tracker-tobii-eyex/tobii-settings.hpp @@ -21,6 +21,7 @@ enum max_pitch struct settings final : public opts { +#if 0 value<tobii_mode> mode { b, "mode", tobii_snap }; value<slider_value> snap_speed {b, "snap-speed", { .1, .05, 1 }}, @@ -28,9 +29,15 @@ struct settings final : public opts value<slider_value> acc_speed {b, "acc-speed", { .1, .05, 1 }}, acc_dz_len {b, "acc-screen-edge-length", { .1, .1, 1 }}; value<max_yaw> snap_yaw {b, "snap-max-yaw", y20}, - acc_yaw {b, "acc-max-yaw", y20}; value<max_pitch> snap_pitch {b, "snap-max-pitch", p15}, acc_pitch {b, "acc-max-pitch", p15}; + acc_yaw {b, "acc-max-yaw", y20}; +#endif + value<slider_value> acc_speed { b, "acc-max-speed-deg", { 3, 1, 10 } }; + value<slider_value> acc_dz { b, "acc-deadzone", { .15, .0, .3 } }; - settings() : opts("tobii-eyex") {} + value<slider_value> acc_max_yaw { b, "acc-max-yaw", { 30, 15, 45} }, + acc_max_pitch { b, "acc-max-pitch", { 30, 15, 45 } }; + + settings(); }; |