summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2020-06-28 13:52:05 +0000
committerGitHub <noreply@github.com>2020-06-28 13:52:05 +0000
commit6374957a07590667f5eaa88184697505db77618a (patch)
tree98ff061fff66e67aba268eefa3b297c62761e049
parent4b858387c31f3d2778ff86789b4271d67343a7e3 (diff)
parent1f280196bd4807ac33c4e8d939db09c8fdd7c6a4 (diff)
Merge pull request #1108 from GO63-samara/unstable
Add a new Hamilton filter
-rw-r--r--filter-hamilton/CMakeLists.txt1
-rw-r--r--filter-hamilton/ReadMe.txt13
-rw-r--r--filter-hamilton/ftnoir_filter_hamilton.cpp75
-rw-r--r--filter-hamilton/ftnoir_filter_hamilton.h74
-rw-r--r--filter-hamilton/ftnoir_filter_hamilton_dialog.cpp64
-rw-r--r--filter-hamilton/ftnoir_hamilton_filtercontrols.ui940
-rw-r--r--filter-hamilton/hamilton-tools.cpp137
-rw-r--r--filter-hamilton/hamilton-tools.h27
-rw-r--r--filter-hamilton/lang/nl_NL.ts74
-rw-r--r--filter-hamilton/lang/ru_RU.ts74
-rw-r--r--filter-hamilton/lang/stub.ts74
-rw-r--r--filter-hamilton/lang/zh_CN.ts74
12 files changed, 1627 insertions, 0 deletions
diff --git a/filter-hamilton/CMakeLists.txt b/filter-hamilton/CMakeLists.txt
new file mode 100644
index 00000000..8d4d71b0
--- /dev/null
+++ b/filter-hamilton/CMakeLists.txt
@@ -0,0 +1 @@
+otr_module(filter-hamilton)
diff --git a/filter-hamilton/ReadMe.txt b/filter-hamilton/ReadMe.txt
new file mode 100644
index 00000000..bdd476da
--- /dev/null
+++ b/filter-hamilton/ReadMe.txt
@@ -0,0 +1,13 @@
+Add a new Hamilton filter.
+
+Hamilton Filter Key Features:
+- Instead of square, round (spherical) floating dead zones and smoothing areas are applied. Due to this, the angular size of these zones does not change when the Pitch angle changes. Diagonally rotations is as easy as moving along the Yaw and Pitch axes.
+- Rotations are not filtered by independent coordinates, but comprehensively, in 3D space. Rotations and movements are more natural. There are no view jumps at the borders of +/- 180 degrees.
+- The possibility of increasing the smoothing of rotations when zooming (when the head is approaching the monitor, that is, when increasing the -Z coordinate) is introduced. This makes it possible to more accurately aim and monitor remote targets.
+
+A full description of the Hamilton filter is available in Russian here:
+https://sites.google.com/site/diyheadtracking/home/opentrack/opentrack-hamilton-filter
+
+The Hamilton filter was tested by the Russian community, received positive reviews:
+https://forum.il2sturmovik.ru/topic/5061-opentrack-актуальная-информация-по-проекту-решение-проблем-вопросы/page/24/
+https://forums.eagle.ru/showthread.php?t=23280&page=249
diff --git a/filter-hamilton/ftnoir_filter_hamilton.cpp b/filter-hamilton/ftnoir_filter_hamilton.cpp
new file mode 100644
index 00000000..be3faa7f
--- /dev/null
+++ b/filter-hamilton/ftnoir_filter_hamilton.cpp
@@ -0,0 +1,75 @@
+/* Copyright (c) 2020, GO63-samara <go1@list.ru>
+ *
+ * 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 "ftnoir_filter_hamilton.h"
+#include <cmath>
+#include <QMutexLocker>
+#include "api/plugin-api.hpp"
+#include "hamilton-tools.h"
+
+hamilton::hamilton() = default;
+
+void hamilton::filter(const double *input, double *output)
+{
+ tQuat quat_input = QuatFromYPR( &input[Yaw] );
+
+ if (first_run)
+ {
+ first_run = false;
+ quat_last = quat_input;
+ pos_last = {input[TX], input[TY], input[TZ]};
+ for (int i=0; i<6; i++) output[i] = input[i];
+ return;
+ }
+
+ // positions:
+ const double pos_max {s.kMaxDist};
+ const double pos_deadzone{s.kDeadZoneDist};
+ const double pos_pow {s.kPowDist};
+
+ double dist = VectorDistance( &input[TX], pos_last);
+
+ double alpha = (dist - pos_deadzone) / (pos_max + pos_deadzone + EPSILON);
+ alpha = fmin(alpha, 1.0);
+ alpha = fmax(alpha, 0.0);
+ alpha = pow (alpha, pos_pow);
+ alpha = alpha * (dist - pos_deadzone) / (dist + EPSILON);
+
+ pos_last = Lerp(pos_last, input, alpha);
+
+ output[TX] = pos_last.v[0];
+ output[TY] = pos_last.v[1];
+ output[TZ] = pos_last.v[2];
+
+ // zoom smoothing:
+ const double pow_zoom {s.kPowZoom};
+ const double max_z {s.kMaxZ};
+ double rot_zoom = pow_zoom;
+
+ if (output[TZ] > 0) rot_zoom = 0;
+ else rot_zoom *= -output[TZ] / (max_z + EPSILON);
+ rot_zoom = fmin( rot_zoom, pow_zoom );
+
+ // rotations:
+ const double rot_max {s.kMaxRot};
+ const double rot_pow {s.kPowRot};
+ const double rot_deadzone{s.kDeadZoneRot};
+
+ double angle = AngleBetween(quat_input, quat_last);
+
+ alpha = (angle - rot_deadzone) / (rot_max + rot_deadzone + EPSILON);
+ alpha = fmin(alpha, 1.0);
+ alpha = fmax(alpha, 0.0);
+ alpha = pow (alpha, rot_pow + rot_zoom);
+ alpha = alpha * (angle - rot_deadzone) / (angle + EPSILON);
+
+ quat_last = Slerp(quat_last, quat_input, alpha);
+
+ QuatToYPR(quat_last, &output[Yaw] );
+}
+
+OPENTRACK_DECLARE_FILTER(hamilton, dialog_hamilton, hamiltonDll)
diff --git a/filter-hamilton/ftnoir_filter_hamilton.h b/filter-hamilton/ftnoir_filter_hamilton.h
new file mode 100644
index 00000000..0756c216
--- /dev/null
+++ b/filter-hamilton/ftnoir_filter_hamilton.h
@@ -0,0 +1,74 @@
+/* Copyright (c) 2020, GO63-samara <go1@list.ru>
+ *
+ * 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 "api/plugin-api.hpp"
+#include "ui_ftnoir_hamilton_filtercontrols.h"
+#include <QWidget>
+#include <QMutex>
+#include "options/options.hpp"
+//#include "compat/timer.hpp"
+#include "hamilton-tools.h"
+
+using namespace options;
+
+struct settings : opts {
+ value<slider_value> kMaxRot, kPowRot, kDeadZoneRot,
+ kMaxDist, kPowDist, kDeadZoneDist,
+ kPowZoom, kMaxZ;
+ settings() :
+ opts ("hamilton-filter"),
+ kMaxRot (b, "max-radius-smoothing", { .01, .001, 25.0 }),
+ kPowRot (b, "smoothing-power-rot", { .01, .001, 4.0 }),
+ kDeadZoneRot (b, "dead-zone-radius-rot", { .01, .001, 0.5 }),
+ kMaxDist (b, "max-distance-smoothing",{ .01, .001, 20.0 }),
+ kPowDist (b, "smoothing-power-dist", { .01, .001, 4.0 }),
+ kDeadZoneDist(b, "dead-zone-radius-dist", { .01, .001, 0.5 }),
+ kPowZoom (b, "smoothing-power-zoom", { .01, .001, 4.0 }),
+ kMaxZ (b, "max-z", { .01, .001, 100.0 })
+ {}
+};
+
+class hamilton : public IFilter
+{
+public:
+ hamilton();
+ void filter(const double *input, double *output) override;
+ void center() override { first_run = true; }
+ module_status initialize() override { return status_ok(); }
+private:
+ tQuat quat_last;
+ tVector pos_last;
+ settings s;
+ bool first_run = true;
+};
+
+class dialog_hamilton: public IFilterDialog
+{
+ Q_OBJECT
+public:
+ dialog_hamilton();
+ void register_filter(IFilter*) override {}
+ void unregister_filter() override {}
+
+private:
+ Ui::UICdialog_hamilton ui;
+ settings s;
+
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+class hamiltonDll : public Metadata
+{
+ Q_OBJECT
+
+ QString name() { return tr("Hamilton"); }
+ QIcon icon() { return QIcon(":/images/filter-16.png"); }
+};
diff --git a/filter-hamilton/ftnoir_filter_hamilton_dialog.cpp b/filter-hamilton/ftnoir_filter_hamilton_dialog.cpp
new file mode 100644
index 00000000..11f4c067
--- /dev/null
+++ b/filter-hamilton/ftnoir_filter_hamilton_dialog.cpp
@@ -0,0 +1,64 @@
+/* Copyright (c) 2020, GO63-samara <go1@list.ru>
+ *
+ * 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 "ftnoir_filter_hamilton.h"
+#include <cmath>
+#include <QDebug>
+#include <QString>
+#include "api/plugin-api.hpp"
+#include "ui_ftnoir_hamilton_filtercontrols.h"
+
+dialog_hamilton::dialog_hamilton()
+{
+ ui.setupUi(this);
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+
+ tie_setting(s.kMaxRot, ui.maxRot);
+ tie_setting(s.kMaxRot, ui.lbMaxRot, [](double x)
+ { return QStringLiteral("%1\xB0").arg(x, 0, 'f', 2);});
+
+ tie_setting(s.kPowRot, ui.powRot);
+ tie_setting(s.kPowRot, ui.lbPowRot, [](double x)
+ { return QStringLiteral("%1").arg(x, 0, 'f', 2);});
+
+ tie_setting(s.kDeadZoneRot, ui.dzRot);
+ tie_setting(s.kDeadZoneRot, ui.lbDZRot, [](double x)
+ { return QStringLiteral("%1\xB0").arg(x, 0, 'f', 2);});
+
+ tie_setting(s.kPowZoom, ui.powZoom);
+ tie_setting(s.kPowZoom, ui.lbPowZoom, [](double x)
+ { return QStringLiteral("%1").arg(x, 0, 'f', 2);});
+
+ tie_setting(s.kMaxZ, ui.maxZ);
+ tie_setting(s.kMaxZ, ui.lbMaxZ, [](double x)
+ { return QStringLiteral("%1").arg(x, 0, 'f', 2);});
+
+ tie_setting(s.kMaxDist, ui.maxDist);
+ tie_setting(s.kMaxDist, ui.lbMaxDist, [](double x)
+ { return QStringLiteral("%1cm").arg(x, 0, 'f', 2);});
+
+ tie_setting(s.kPowDist, ui.powDist);
+ tie_setting(s.kPowDist, ui.lbPowDist, [](double x)
+ { return QStringLiteral("%1").arg(x, 0, 'f', 2);});
+
+ tie_setting(s.kDeadZoneDist, ui.dzDist);
+ tie_setting(s.kDeadZoneDist, ui.lbDZDist, [](double x)
+ { return QStringLiteral("%1cm").arg(x, 0, 'f', 2);});
+}
+
+void dialog_hamilton::doOK()
+{
+ s.b->save();
+ close();
+}
+
+void dialog_hamilton::doCancel()
+{
+ close();
+}
diff --git a/filter-hamilton/ftnoir_hamilton_filtercontrols.ui b/filter-hamilton/ftnoir_hamilton_filtercontrols.ui
new file mode 100644
index 00000000..71cdb6da
--- /dev/null
+++ b/filter-hamilton/ftnoir_hamilton_filtercontrols.ui
@@ -0,0 +1,940 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UICdialog_hamilton</class>
+ <widget class="QWidget" name="UICdialog_hamilton">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>514</width>
+ <height>491</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>485</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="windowTitle">
+ <string>Hamilton filter settings</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../gui/opentrack-res.qrc">
+ <normaloff>:/images/filter-16.png</normaloff>:/images/filter-16.png</iconset>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>496</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>8</pointsize>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="title">
+ <string>Rotations: </string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <widget class="QSlider" name="maxRot">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>30</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>250</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>50</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbRmax">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>30</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string> Max distance:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbMaxRot">
+ <property name="geometry">
+ <rect>
+ <x>424</x>
+ <y>30</y>
+ <width>61</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>10,00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbRdz">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>110</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string> Dead Zone:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QSlider" name="dzRot">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>110</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>50</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbDZRot">
+ <property name="geometry">
+ <rect>
+ <x>424</x>
+ <y>110</y>
+ <width>61</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>0,01</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QSlider" name="powRot">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>70</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>400</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>200</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbPowRot">
+ <property name="geometry">
+ <rect>
+ <x>430</x>
+ <y>70</y>
+ <width>45</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>2,00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbRpow">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>70</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string> Smoothing:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Positions: </string>
+ </property>
+ <widget class="QSlider" name="maxDist">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>30</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>200</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>50</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbRpow_3">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>70</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string> Smoothing:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QSlider" name="powDist">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>70</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>400</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbRdz_3">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>110</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string> Dead Zone:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbPowDist">
+ <property name="geometry">
+ <rect>
+ <x>430</x>
+ <y>70</y>
+ <width>51</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>1,00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbDmax">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>30</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string> Max distance:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QSlider" name="dzDist">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>110</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>50</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>10</number>
+ </property>
+ <property name="value">
+ <number>2</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbMaxDist">
+ <property name="geometry">
+ <rect>
+ <x>420</x>
+ <y>30</y>
+ <width>71</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>10,00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbDZDist">
+ <property name="geometry">
+ <rect>
+ <x>420</x>
+ <y>110</y>
+ <width>71</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0,02</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Zoom smoothing: </string>
+ </property>
+ <widget class="QLabel" name="lbPowZoom">
+ <property name="geometry">
+ <rect>
+ <x>434</x>
+ <y>30</y>
+ <width>45</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>2,00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QSlider" name="powZoom">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>30</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>400</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>200</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbZpow">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>30</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string> Smoothing :</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QSlider" name="maxZ">
+ <property name="geometry">
+ <rect>
+ <x>103</x>
+ <y>60</y>
+ <width>311</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>1000</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>150</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBothSides</enum>
+ </property>
+ <property name="tickInterval">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbZpow_2">
+ <property name="geometry">
+ <rect>
+ <x>7</x>
+ <y>60</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Max Z:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="lbMaxZ">
+ <property name="geometry">
+ <rect>
+ <x>434</x>
+ <y>60</y>
+ <width>45</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>45</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>15,00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ <property name="centerButtons">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../gui/opentrack-res.qrc"/>
+ </resources>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/filter-hamilton/hamilton-tools.cpp b/filter-hamilton/hamilton-tools.cpp
new file mode 100644
index 00000000..4f9ad046
--- /dev/null
+++ b/filter-hamilton/hamilton-tools.cpp
@@ -0,0 +1,137 @@
+#pragma once
+
+#include "hamilton-tools.h"
+#include <cmath>
+
+double VectorLength(const tVector v)
+{
+ return(sqrt(v.v[0]*v.v[0] + v.v[1]*v.v[1] + v.v[2]*v.v[2]));
+}
+
+double sqr(const double v) { return(v*v); }
+
+double VectorDistance(const double v1[], const tVector v2)
+{
+ return(sqrt(sqr(v2.v[0]-v1[0])+sqr(v2.v[1]-v1[1])+sqr(v2.v[2]-v1[2])));
+}
+
+tVector Lerp(const tVector s, const double d[], const double alpha)
+{
+ tVector V;
+ V.v[0] = s.v[0] + (d[0] - s.v[0]) * alpha;
+ V.v[1] = s.v[1] + (d[1] - s.v[1]) * alpha;
+ V.v[2] = s.v[2] + (d[2] - s.v[2]) * alpha;
+ return(V);
+}
+
+tQuat QuatFromAngleAxe(const double angle, const tVector axe)
+{
+ double a = TO_RAD * 0.5 * angle;
+ double d = sin(a) / VectorLength(axe);
+ return ( tQuat (
+ axe.v[0] * d,
+ axe.v[1] * d,
+ axe.v[2] * d,
+ cos(a)
+ )
+ );
+}
+
+tQuat QuatMultiply(const tQuat qL, const tQuat qR)
+{
+ tQuat Q;
+ Q.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y;
+ Q.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z;
+ Q.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y - qL.y*qR.x;
+ Q.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z;
+ return(Q);
+}
+
+double AngleBetween(const tQuat S, const tQuat D)
+{
+ return( TO_DEG * 2*acos(fabs(S.x*D.x + S.y*D.y + S.z*D.z + S.w*D.w)) );
+}
+
+tQuat QuatFromYPR(const double YPR[])
+{
+ tQuat Q, Qp, Qy;
+ Q = QuatFromAngleAxe( -YPR[2], {0, 0, 1} ); //Roll, Z axe
+ Qp = QuatFromAngleAxe( -YPR[1], {1, 0, 0} ); //Pitch, X axe
+ Qy = QuatFromAngleAxe( -YPR[0], {0, 1, 0} ); //Yaw, Y axe
+
+ Q = QuatMultiply(Qp, Q);
+ return(QuatMultiply(Qy, Q));
+}
+
+void Normalize(tQuat Q)
+{
+ double m = sqrt(Q.x*Q.x + Q.y*Q.y + Q.z*Q.z + Q.w*Q.w);
+ if (m > EPSILON)
+ {
+ m = 1 / m;
+ Q.x = Q.x * m;
+ Q.y = Q.y * m;
+ Q.z = Q.z * m;
+ Q.w = Q.w * m;
+ }
+ else Q = tQuat(0, 0, 0, 1);
+}
+
+tQuat Slerp(const tQuat S, const tQuat D, const double alpha)
+{
+ // calc cosine of half angle
+ double cosin = S.x*D.x + S.y*D.y + S.z*D.z + S.w*D.w;
+
+ // select nearest rotation direction
+ tQuat Q;
+ if (cosin < 0)
+ {
+ cosin = - cosin;
+ Q.x = - D.x;
+ Q.y = - D.y;
+ Q.z = - D.z;
+ Q.w = - D.w;
+ }
+ else Q = D;
+
+ // calculate coefficients
+ double scale0, scale1;
+ if ((1.0 - cosin) > EPSILON)
+ {
+ double omega = acos(cosin);
+ double sinus = 1 / sin(omega);
+ scale0 = sin((1.0 - alpha) * omega) * sinus;
+ scale1 = sin(alpha * omega)* sinus;
+ }
+ else
+ {
+ scale0 = 1.0 - alpha;
+ scale1 = alpha;
+ }
+
+ Q.x = scale0 * S.x + scale1 * Q.x;
+ Q.y = scale0 * S.y + scale1 * Q.y;
+ Q.z = scale0 * S.z + scale1 * Q.z;
+ Q.w = scale0 * S.w + scale1 * Q.w;
+
+ Normalize(Q);
+
+ return( Q );
+}
+
+void QuatToYPR(const tQuat Q, double YPR[])
+{
+ const double xx = Q.x * Q.x;
+ const double xy = Q.x * Q.y;
+ const double xz = Q.x * Q.z;
+ const double xw = Q.x * Q.w;
+ const double yy = Q.y * Q.y;
+ const double yz = Q.y * Q.z;
+ const double yw = Q.y * Q.w;
+ const double zz = Q.z * Q.z;
+ const double zw = Q.z * Q.w;
+
+ YPR[0] = TO_DEG * ( -atan2( 2 * ( xz + yw ), 1 - 2 * ( xx + yy ) ));
+ YPR[1] = TO_DEG * ( asin ( 2 * ( yz - xw ) ));
+ YPR[2] = TO_DEG * ( -atan2( 2 * ( xy + zw ), 1 - 2 * ( xx + zz ) ));
+}
diff --git a/filter-hamilton/hamilton-tools.h b/filter-hamilton/hamilton-tools.h
new file mode 100644
index 00000000..2e288225
--- /dev/null
+++ b/filter-hamilton/hamilton-tools.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "compat/math.hpp"
+constexpr double TO_RAD = (M_PI / 180);
+constexpr double TO_DEG = (180 / M_PI);
+constexpr double EPSILON = 1e-30;
+
+struct tVector
+{
+ double v[3];
+ tVector(double X = 0, double Y = 0, double Z = 0) {v[0]=X; v[1]=Y; v[2]=Z;}
+ tVector(double V[]) {v[0]=V[0]; v[1]=V[1]; v[2]=V[2];}
+};
+
+struct tQuat
+{
+ double x, y, z, w;
+ tQuat(double X = 0, double Y = 0, double Z = 0, double W = 1)
+ {x = X; y = Y; z = Z; w = W;}
+};
+
+double VectorDistance(const double v1[], const tVector v2);
+tVector Lerp (const tVector s, const double d[], const double alpha);
+tQuat QuatFromYPR (const double YPR[]);
+double AngleBetween (const tQuat S, const tQuat D);
+tQuat Slerp (const tQuat S, const tQuat D, const double alpha);
+void QuatToYPR (const tQuat Q, double YPR[]);
diff --git a/filter-hamilton/lang/nl_NL.ts b/filter-hamilton/lang/nl_NL.ts
new file mode 100644
index 00000000..b03e4c0b
--- /dev/null
+++ b/filter-hamilton/lang/nl_NL.ts
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="nl_NL">
+<context>
+ <name>UICdialog_hamilton</name>
+ <message>
+ <source>Rotations: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing :</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Positions: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Max distance:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Zoom smoothing: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hamilton filter settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>10,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,01</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>2,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>1,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,02</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Dead Zone:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>15,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>hamiltonDll</name>
+ <message>
+ <source>Hamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/filter-hamilton/lang/ru_RU.ts b/filter-hamilton/lang/ru_RU.ts
new file mode 100644
index 00000000..dfbb2268
--- /dev/null
+++ b/filter-hamilton/lang/ru_RU.ts
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+ <name>UICdialog_hamilton</name>
+ <message>
+ <source>Rotations: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing :</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Positions: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Max distance:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Zoom smoothing: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hamilton filter settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>10,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,01</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>2,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>1,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,02</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Dead Zone:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>15,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>hamiltonDll</name>
+ <message>
+ <source>Hamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/filter-hamilton/lang/stub.ts b/filter-hamilton/lang/stub.ts
new file mode 100644
index 00000000..a8af9f98
--- /dev/null
+++ b/filter-hamilton/lang/stub.ts
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+ <name>UICdialog_hamilton</name>
+ <message>
+ <source>Rotations: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing :</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Positions: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Max distance:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Zoom smoothing: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hamilton filter settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>10,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,01</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>2,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>1,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,02</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Dead Zone:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>15,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>hamiltonDll</name>
+ <message>
+ <source>Hamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/filter-hamilton/lang/zh_CN.ts b/filter-hamilton/lang/zh_CN.ts
new file mode 100644
index 00000000..a8af9f98
--- /dev/null
+++ b/filter-hamilton/lang/zh_CN.ts
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+ <name>UICdialog_hamilton</name>
+ <message>
+ <source>Rotations: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing :</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Positions: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Max distance:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Zoom smoothing: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hamilton filter settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>10,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,01</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>2,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>1,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0,02</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Dead Zone:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source> Smoothing:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>15,00</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>hamiltonDll</name>
+ <message>
+ <source>Hamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>