summaryrefslogtreecommitdiffhomepage
path: root/tracker-tobii-eyex/head-tracking.cpp
blob: 77394f118371fca63f138cf934dfc8575fd43e7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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 * 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.
}