diff options
| author | Tom Brazier <tom_github@firstsolo.net> | 2023-05-30 14:18:40 +0100 | 
|---|---|---|
| committer | Tom Brazier <tom_github@firstsolo.net> | 2023-07-23 14:00:50 +0100 | 
| commit | 9d9620d2820eb9064fe7b75c509f3209f4ca3b9e (patch) | |
| tree | cf50f533d2075921d1fa8e232f621f900cddec2e | |
| parent | 53bc18790411d7bcd1aae9b5684aa8241666f21e (diff) | |
Added a filter based on natural body movements, which reduces higher frequency noise and cancels low speed position drift
| -rw-r--r-- | filter-tom/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | filter-tom/filter_tom.cpp | 48 | ||||
| -rw-r--r-- | filter-tom/filter_tom.h | 93 | ||||
| -rw-r--r-- | filter-tom/filter_tom_dialog.cpp | 88 | ||||
| -rw-r--r-- | filter-tom/lang/nl_NL.ts | 78 | ||||
| -rw-r--r-- | filter-tom/lang/ru_RU.ts | 78 | ||||
| -rw-r--r-- | filter-tom/lang/stub.ts | 78 | ||||
| -rw-r--r-- | filter-tom/lang/zh_CN.ts | 78 | ||||
| -rw-r--r-- | filter-tom/tom_filtercontrols.ui | 610 | 
9 files changed, 1152 insertions, 0 deletions
| diff --git a/filter-tom/CMakeLists.txt b/filter-tom/CMakeLists.txt new file mode 100644 index 00000000..d98e90e2 --- /dev/null +++ b/filter-tom/CMakeLists.txt @@ -0,0 +1 @@ +otr_module(filter-tom) diff --git a/filter-tom/filter_tom.cpp b/filter-tom/filter_tom.cpp new file mode 100644 index 00000000..6bcfeae0 --- /dev/null +++ b/filter-tom/filter_tom.cpp @@ -0,0 +1,48 @@ +/* Copyright (c) 2023 Tom Brazier <tom_github@firstsolo.net> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#include "filter_tom.h" +#include "compat/math-imports.hpp" +#include "compat/macros.h" + +#include "api/plugin-api.hpp" +#include "opentrack/defs.hpp" + +#include <algorithm> + +tom::tom() +{ +} + +void tom::filter(const double* input, double* output) +{ +    // order of axes: x, y, z, yaw, pitch, roll +    if (unlikely(first_run)) +    { +        first_run = false; +        t.start(); + +        std::fill(speeds, speeds + 6, 0.0); +        std::copy(input, input + 6, filtered_output); +    } +    else +    { +        const double dt = t.elapsed_seconds(); +        t.start(); + +        for (int i = 0; i < 6; i++) +        { +            double speed = (input[i] - last_input[i]) / dt; +            speeds[i] += dt * (double)s.responsiveness[i] * (speed - speeds[i]); +            filtered_output[i] += dt * (double)s.responsiveness[i] * min(1.0, abs(speeds[i]) / (double)s.drift_speeds[i]) * (input[i] - filtered_output[i]); +        } +      } + +    std::copy(input, input + 6, last_input); +    std::copy(filtered_output, filtered_output + 6, output); +} + +OPENTRACK_DECLARE_FILTER(tom, dialog_tom, tomDll) diff --git a/filter-tom/filter_tom.h b/filter-tom/filter_tom.h new file mode 100644 index 00000000..0f6d07c2 --- /dev/null +++ b/filter-tom/filter_tom.h @@ -0,0 +1,93 @@ +/* Copyright (c) 2023 Tom Brazier <tom_github@firstsolo.net> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#pragma once + +#include "ui_tom_filtercontrols.h" + +#include "api/plugin-api.hpp" +#include "compat/timer.hpp" +#include "options/options.hpp" + +using namespace options; + +struct settings_tom : opts +{ +    value<slider_value> responsiveness[6]; +    value<slider_value> drift_speeds[6]; + +    settings_tom() : +        opts("tom-filter"), +          responsiveness{ value<slider_value>(b, "x-responsiveness",        { 10.0, .0, 20.0 }), +                          value<slider_value>(b, "y-responsiveness",        { 10.0, .0, 20.0 }), +                          value<slider_value>(b, "z-responsiveness",        { 10.0, .0, 20.0 }), +                          value<slider_value>(b, "yaw-responsiveness",      { 10.0, .0, 20.0 }), +                          value<slider_value>(b, "pitch-responsiveness",    { 10.0, .0, 20.0 }), +                          value<slider_value>(b, "roll-responsiveness",     { 10.0, .0, 20.0 }) }, +          drift_speeds{ value<slider_value>(b, "x-drift-speed",     { 50.0, 1.0, 200.0 }), +                        value<slider_value>(b, "y-drift-speed",     { 50.0, 1.0, 200.0 }), +                        value<slider_value>(b, "z-drift-speed",     { 50.0, 1.0, 200.0 }), +                        value<slider_value>(b, "yaw-drift-speed",   { 100.0, 1.0, 400.0 }), +                        value<slider_value>(b, "pitch-drift-speed", { 100.0, 1.0, 400.0 }), +                        value<slider_value>(b, "roll-drift-speed",  { 100.0, 1.0, 400.0 }) } +    { +    } + +    /*    value<slider_value> kMinSmoothing, kMaxSmoothing, kSmoothingScaleCurve; +    settings() +        : opts("ewma-filter"), +          kMinSmoothing(b, "min-smoothing", { .02, .01, 1 }), +          kMaxSmoothing(b, "max-smoothing", { .7, .01, 1 }), +          kSmoothingScaleCurve(b, "smoothing-scale-curve", { .8, .1, 5 }) +    { +    } +*/ +}; + +struct tom : IFilter +{ +    tom(); +    void filter(const double* input, double* output) override; +    void center() override { first_run = true; } +    module_status initialize() override { return status_ok(); } + +private: +    double last_input[6]{}; +    double speeds[6]{}; +    double filtered_output[6]{}; +    Timer t; +    settings_tom s; +    bool first_run = true; +}; + +class dialog_tom : public IFilterDialog +{ +    Q_OBJECT +public: +    dialog_tom(); +    void register_filter(IFilter*) override {} +    void unregister_filter() override {} +    void save() override; +    void reload() override; +    bool embeddable() noexcept override { return true; } +    void set_buttons_visible(bool x) override; + +private: +    Ui::UICdialog_tom ui; +    settings_tom s; + +private slots: +    void doOK(); +    void doCancel(); +}; + +class tomDll : public Metadata +{ +    Q_OBJECT + +    QString name() override { return tr("Tom"); } +    QIcon icon() override { return QIcon(":/images/filter-16.png"); } +}; diff --git a/filter-tom/filter_tom_dialog.cpp b/filter-tom/filter_tom_dialog.cpp new file mode 100644 index 00000000..5a6ad3a4 --- /dev/null +++ b/filter-tom/filter_tom_dialog.cpp @@ -0,0 +1,88 @@ +/* Copyright (c) 2023 Tom Brazier <tom_github@firstsolo.net> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#include "filter_tom.h" + +using namespace options; + +dialog_tom::dialog_tom() +{ +    ui.setupUi(this); + +    tie_setting(s.responsiveness[0], ui.x_responsiveness_slider); +    tie_setting(s.responsiveness[0], ui.x_responsiveness, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.responsiveness[1], ui.y_responsiveness_slider); +    tie_setting(s.responsiveness[1], ui.y_responsiveness, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.responsiveness[2], ui.z_responsiveness_slider); +    tie_setting(s.responsiveness[2], ui.z_responsiveness, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.responsiveness[3], ui.yaw_responsiveness_slider); +    tie_setting(s.responsiveness[3], ui.yaw_responsiveness, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.responsiveness[4], ui.pitch_responsiveness_slider); +    tie_setting(s.responsiveness[4], ui.pitch_responsiveness, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.responsiveness[5], ui.roll_responsiveness_slider); +    tie_setting(s.responsiveness[5], ui.roll_responsiveness, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.drift_speeds[0], ui.x_drift_speed_slider); +    tie_setting(s.drift_speeds[0], ui.x_drift_speed, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.drift_speeds[1], ui.y_drift_speed_slider); +    tie_setting(s.drift_speeds[1], ui.y_drift_speed, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.drift_speeds[2], ui.z_drift_speed_slider); +    tie_setting(s.drift_speeds[2], ui.z_drift_speed, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.drift_speeds[3], ui.yaw_drift_speed_slider); +    tie_setting(s.drift_speeds[3], ui.yaw_drift_speed, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.drift_speeds[4], ui.pitch_drift_speed_slider); +    tie_setting(s.drift_speeds[4], ui.pitch_drift_speed, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); + +    tie_setting(s.drift_speeds[5], ui.roll_drift_speed_slider); +    tie_setting(s.drift_speeds[5], ui.roll_drift_speed, [](double x) +        { return QStringLiteral("%1").arg(x, 0, 'f', 2); }); +} + +void dialog_tom::doOK() +{ +    save(); +    close(); +} + +void dialog_tom::doCancel() +{ +    close(); +} + +void dialog_tom::save() +{ +    s.b->save(); +} + +void dialog_tom::reload() +{ +    s.b->reload(); +} + +void dialog_tom::set_buttons_visible(bool x) +{ +    ui.buttonBox->setVisible(x); +} diff --git a/filter-tom/lang/nl_NL.ts b/filter-tom/lang/nl_NL.ts new file mode 100644 index 00000000..ce0aefe3 --- /dev/null +++ b/filter-tom/lang/nl_NL.ts @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> +    <name>UICdialog_tom</name> +    <message> +        <source>Dialog</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>X</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>Yaw</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Pitch</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Roll</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>°/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>mm/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Responsiveness</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>10.0</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Drift speeds</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>50</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>100</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still.</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Instructions: Set all sliders to minimum. Then on an axis by axis basis: First, increase responsiveness until the filter only just cancels jerkiness for faster head movements. Second, increase drift speed until the filter only just cancels drift movement when your head is still.</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>tomDll</name> +    <message> +        <source>Tom</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> diff --git a/filter-tom/lang/ru_RU.ts b/filter-tom/lang/ru_RU.ts new file mode 100644 index 00000000..b72d73ad --- /dev/null +++ b/filter-tom/lang/ru_RU.ts @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> +    <name>UICdialog_tom</name> +    <message> +        <source>Dialog</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>X</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>Yaw</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Pitch</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Roll</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>°/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>mm/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Responsiveness</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>10.0</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Drift speeds</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>50</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>100</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still.</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Instructions: Set all sliders to minimum. Then on an axis by axis basis: First, increase responsiveness until the filter only just cancels jerkiness for faster head movements. Second, increase drift speed until the filter only just cancels drift movement when your head is still.</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>tomDll</name> +    <message> +        <source>Tom</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> diff --git a/filter-tom/lang/stub.ts b/filter-tom/lang/stub.ts new file mode 100644 index 00000000..f212040f --- /dev/null +++ b/filter-tom/lang/stub.ts @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="stub"> +<context> +    <name>UICdialog_tom</name> +    <message> +        <source>Dialog</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>X</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>Yaw</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Pitch</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Roll</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>°/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>mm/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Responsiveness</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>10.0</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Drift speeds</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>50</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>100</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still.</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Instructions: Set all sliders to minimum. Then on an axis by axis basis: First, increase responsiveness until the filter only just cancels jerkiness for faster head movements. Second, increase drift speed until the filter only just cancels drift movement when your head is still.</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>tomDll</name> +    <message> +        <source>Tom</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> diff --git a/filter-tom/lang/zh_CN.ts b/filter-tom/lang/zh_CN.ts new file mode 100644 index 00000000..5a322913 --- /dev/null +++ b/filter-tom/lang/zh_CN.ts @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_CN"> +<context> +    <name>UICdialog_tom</name> +    <message> +        <source>Dialog</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>X</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>Yaw</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Pitch</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Roll</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>°/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>mm/s</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Responsiveness</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>10.0</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Drift speeds</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>50</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>100</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still.</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Instructions: Set all sliders to minimum. Then on an axis by axis basis: First, increase responsiveness until the filter only just cancels jerkiness for faster head movements. Second, increase drift speed until the filter only just cancels drift movement when your head is still.</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>tomDll</name> +    <message> +        <source>Tom</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> diff --git a/filter-tom/tom_filtercontrols.ui b/filter-tom/tom_filtercontrols.ui new file mode 100644 index 00000000..1a135c1e --- /dev/null +++ b/filter-tom/tom_filtercontrols.ui @@ -0,0 +1,610 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UICdialog_tom</class> + <widget class="QDialog" name="UICdialog_tom"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>438</width> +    <height>559</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Dialog</string> +  </property> +  <layout class="QGridLayout" name="gridLayout_2"> +   <item row="0" column="0"> +    <widget class="QGroupBox" name="groupBox"> +     <property name="title"> +      <string>Responsiveness</string> +     </property> +     <layout class="QGridLayout" name="gridLayout"> +      <item row="0" column="0"> +       <widget class="QLabel" name="label"> +        <property name="text"> +         <string>X</string> +        </property> +       </widget> +      </item> +      <item row="0" column="1"> +       <widget class="QLabel" name="x_responsiveness"> +        <property name="sizePolicy"> +         <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> +          <horstretch>0</horstretch> +          <verstretch>0</verstretch> +         </sizepolicy> +        </property> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>10.0</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="0" column="2"> +       <widget class="QSlider" name="x_responsiveness_slider"> +        <property name="sizePolicy"> +         <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> +          <horstretch>0</horstretch> +          <verstretch>0</verstretch> +         </sizepolicy> +        </property> +        <property name="maximum"> +         <number>40</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="1" column="0"> +       <widget class="QLabel" name="label_3"> +        <property name="text"> +         <string>Y</string> +        </property> +       </widget> +      </item> +      <item row="1" column="1"> +       <widget class="QLabel" name="y_responsiveness"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>10.0</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="1" column="2"> +       <widget class="QSlider" name="y_responsiveness_slider"> +        <property name="maximum"> +         <number>40</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="2" column="0"> +       <widget class="QLabel" name="label_5"> +        <property name="text"> +         <string>Z</string> +        </property> +       </widget> +      </item> +      <item row="2" column="1"> +       <widget class="QLabel" name="z_responsiveness"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>10.0</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="2" column="2"> +       <widget class="QSlider" name="z_responsiveness_slider"> +        <property name="maximum"> +         <number>40</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="text"> +         <string>Yaw</string> +        </property> +       </widget> +      </item> +      <item row="3" column="1"> +       <widget class="QLabel" name="yaw_responsiveness"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>10.0</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="3" column="2"> +       <widget class="QSlider" name="yaw_responsiveness_slider"> +        <property name="maximum"> +         <number>40</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="4" column="0"> +       <widget class="QLabel" name="label_9"> +        <property name="text"> +         <string>Pitch</string> +        </property> +       </widget> +      </item> +      <item row="4" column="1"> +       <widget class="QLabel" name="pitch_responsiveness"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>10.0</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="4" column="2"> +       <widget class="QSlider" name="pitch_responsiveness_slider"> +        <property name="maximum"> +         <number>40</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="5" column="0"> +       <widget class="QLabel" name="label_11"> +        <property name="text"> +         <string>Roll</string> +        </property> +       </widget> +      </item> +      <item row="5" column="1"> +       <widget class="QLabel" name="roll_responsiveness"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>10.0</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="5" column="2"> +       <widget class="QSlider" name="roll_responsiveness_slider"> +        <property name="maximum"> +         <number>40</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +     </layout> +    </widget> +   </item> +   <item row="2" column="0"> +    <widget class="QLabel" name="label_2"> +     <property name="minimumSize"> +      <size> +       <width>0</width> +       <height>0</height> +      </size> +     </property> +     <property name="text"> +      <string>Natural movement filter by Tom Brazier: Cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still.</string> +     </property> +     <property name="textFormat"> +      <enum>Qt::PlainText</enum> +     </property> +     <property name="alignment"> +      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> +     </property> +     <property name="wordWrap"> +      <bool>true</bool> +     </property> +    </widget> +   </item> +   <item row="1" column="0"> +    <widget class="QGroupBox" name="groupBox_2"> +     <property name="title"> +      <string>Drift speeds</string> +     </property> +     <layout class="QGridLayout" name="gridLayout_3"> +      <item row="4" column="0"> +       <widget class="QLabel" name="label_6"> +        <property name="text"> +         <string>Z</string> +        </property> +       </widget> +      </item> +      <item row="2" column="3"> +       <widget class="QSlider" name="y_drift_speed_slider"> +        <property name="minimum"> +         <number>1</number> +        </property> +        <property name="maximum"> +         <number>200</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="11" column="0"> +       <widget class="QLabel" name="label_12"> +        <property name="text"> +         <string>Roll</string> +        </property> +       </widget> +      </item> +      <item row="2" column="1"> +       <widget class="QLabel" name="y_drift_speed"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>50</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="6" column="2"> +       <widget class="QLabel" name="label_24"> +        <property name="text"> +         <string>°/s</string> +        </property> +       </widget> +      </item> +      <item row="4" column="2"> +       <widget class="QLabel" name="label_23"> +        <property name="text"> +         <string>mm/s</string> +        </property> +       </widget> +      </item> +      <item row="9" column="2"> +       <widget class="QLabel" name="label_25"> +        <property name="text"> +         <string>°/s</string> +        </property> +       </widget> +      </item> +      <item row="4" column="3"> +       <widget class="QSlider" name="z_drift_speed_slider"> +        <property name="minimum"> +         <number>1</number> +        </property> +        <property name="maximum"> +         <number>200</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="4" column="1"> +       <widget class="QLabel" name="z_drift_speed"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>50</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="11" column="1"> +       <widget class="QLabel" name="roll_drift_speed"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>100</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="2" column="0"> +       <widget class="QLabel" name="label_13"> +        <property name="text"> +         <string>Y</string> +        </property> +       </widget> +      </item> +      <item row="9" column="1"> +       <widget class="QLabel" name="pitch_drift_speed"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>100</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="9" column="0"> +       <widget class="QLabel" name="label_10"> +        <property name="text"> +         <string>Pitch</string> +        </property> +       </widget> +      </item> +      <item row="9" column="3"> +       <widget class="QSlider" name="pitch_drift_speed_slider"> +        <property name="minimum"> +         <number>1</number> +        </property> +        <property name="maximum"> +         <number>400</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="0" column="0"> +       <widget class="QLabel" name="label_4"> +        <property name="text"> +         <string>X</string> +        </property> +       </widget> +      </item> +      <item row="6" column="1"> +       <widget class="QLabel" name="yaw_drift_speed"> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>100</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +      <item row="0" column="2"> +       <widget class="QLabel" name="label_14"> +        <property name="text"> +         <string>mm/s</string> +        </property> +       </widget> +      </item> +      <item row="2" column="2"> +       <widget class="QLabel" name="label_22"> +        <property name="text"> +         <string>mm/s</string> +        </property> +       </widget> +      </item> +      <item row="6" column="0"> +       <widget class="QLabel" name="label_8"> +        <property name="text"> +         <string>Yaw</string> +        </property> +       </widget> +      </item> +      <item row="0" column="3"> +       <widget class="QSlider" name="x_drift_speed_slider"> +        <property name="sizePolicy"> +         <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> +          <horstretch>0</horstretch> +          <verstretch>0</verstretch> +         </sizepolicy> +        </property> +        <property name="minimum"> +         <number>1</number> +        </property> +        <property name="maximum"> +         <number>200</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="11" column="2"> +       <widget class="QLabel" name="label_26"> +        <property name="text"> +         <string>°/s</string> +        </property> +       </widget> +      </item> +      <item row="6" column="3"> +       <widget class="QSlider" name="yaw_drift_speed_slider"> +        <property name="minimum"> +         <number>1</number> +        </property> +        <property name="maximum"> +         <number>400</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="11" column="3"> +       <widget class="QSlider" name="roll_drift_speed_slider"> +        <property name="minimum"> +         <number>1</number> +        </property> +        <property name="maximum"> +         <number>400</number> +        </property> +        <property name="orientation"> +         <enum>Qt::Horizontal</enum> +        </property> +       </widget> +      </item> +      <item row="0" column="1"> +       <widget class="QLabel" name="x_drift_speed"> +        <property name="sizePolicy"> +         <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> +          <horstretch>0</horstretch> +          <verstretch>0</verstretch> +         </sizepolicy> +        </property> +        <property name="minimumSize"> +         <size> +          <width>30</width> +          <height>0</height> +         </size> +        </property> +        <property name="text"> +         <string>50</string> +        </property> +        <property name="alignment"> +         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> +        </property> +       </widget> +      </item> +     </layout> +    </widget> +   </item> +   <item row="6" column="0"> +    <widget class="QDialogButtonBox" name="buttonBox"> +     <property name="orientation"> +      <enum>Qt::Horizontal</enum> +     </property> +     <property name="standardButtons"> +      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> +     </property> +    </widget> +   </item> +   <item row="4" column="0"> +    <widget class="QLabel" name="label_15"> +     <property name="text"> +      <string>Instructions: Set all sliders to minimum. Then on an axis by axis basis: First, increase responsiveness until the filter only just cancels jerkiness for faster head movements. Second, increase drift speed until the filter only just cancels drift movement when your head is still.</string> +     </property> +     <property name="alignment"> +      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> +     </property> +     <property name="wordWrap"> +      <bool>true</bool> +     </property> +    </widget> +   </item> +   <item row="5" column="0"> +    <spacer name="verticalSpacer"> +     <property name="orientation"> +      <enum>Qt::Vertical</enum> +     </property> +     <property name="sizeHint" stdset="0"> +      <size> +       <width>20</width> +       <height>40</height> +      </size> +     </property> +    </spacer> +   </item> +  </layout> + </widget> + <resources/> + <connections> +  <connection> +   <sender>buttonBox</sender> +   <signal>accepted()</signal> +   <receiver>UICdialog_tom</receiver> +   <slot>accept()</slot> +   <hints> +    <hint type="sourcelabel"> +     <x>248</x> +     <y>254</y> +    </hint> +    <hint type="destinationlabel"> +     <x>157</x> +     <y>274</y> +    </hint> +   </hints> +  </connection> +  <connection> +   <sender>buttonBox</sender> +   <signal>rejected()</signal> +   <receiver>UICdialog_tom</receiver> +   <slot>reject()</slot> +   <hints> +    <hint type="sourcelabel"> +     <x>316</x> +     <y>260</y> +    </hint> +    <hint type="destinationlabel"> +     <x>286</x> +     <y>274</y> +    </hint> +   </hints> +  </connection> + </connections> +</ui> | 
