summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMichael Welter <DaWelter@users.noreply.github.com>2024-05-14 19:50:04 +0200
committerGitHub <noreply@github.com>2024-05-14 19:50:04 +0200
commit9f4bc14bf6d5fbe4534953945a587c89a86a29f5 (patch)
treecf5bdd7e80107c19d87a8ab24e38a4c7debb4051
parentaa31de35da5e6a6f43d443aa17abd5a4dc78fbc8 (diff)
Add new filter: HamiltonAccela which is a combination of ideas from Accela and Hamilton filters (#1843)
-rw-r--r--filter-accela-hamilton/CMakeLists.txt2
-rw-r--r--filter-accela-hamilton/accela_hamilton.cpp120
-rw-r--r--filter-accela-hamilton/accela_hamilton.h69
-rw-r--r--filter-accela-hamilton/accela_hamilton_dialog.cpp99
-rw-r--r--filter-accela-hamilton/accela_hamilton_filtercontrols.ui485
-rw-r--r--filter-accela-hamilton/accela_hamilton_settings.hpp63
-rw-r--r--filter-accela-hamilton/lang/nl_NL.ts82
-rw-r--r--filter-accela-hamilton/lang/ru_RU.ts82
-rw-r--r--filter-accela-hamilton/lang/stub.ts82
-rw-r--r--filter-accela-hamilton/lang/zh_CN.ts82
10 files changed, 1166 insertions, 0 deletions
diff --git a/filter-accela-hamilton/CMakeLists.txt b/filter-accela-hamilton/CMakeLists.txt
new file mode 100644
index 00000000..825cef5e
--- /dev/null
+++ b/filter-accela-hamilton/CMakeLists.txt
@@ -0,0 +1,2 @@
+otr_module(filter-accela-hamilton)
+target_link_libraries(opentrack-filter-accela-hamilton opentrack-spline)
diff --git a/filter-accela-hamilton/accela_hamilton.cpp b/filter-accela-hamilton/accela_hamilton.cpp
new file mode 100644
index 00000000..5e7660a8
--- /dev/null
+++ b/filter-accela-hamilton/accela_hamilton.cpp
@@ -0,0 +1,120 @@
+/* Copyright (c) 2012-2015 Stanislaw Halik
+ * Copyright (c) 2023-2024 Michael Welter
+ *
+ * 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 "accela_hamilton.h"
+#include "compat/math.hpp"
+#include "api/plugin-api.hpp"
+#include "opentrack/defs.hpp"
+
+#include <algorithm>
+#include <QDebug>
+#include <QMutexLocker>
+
+#include "compat/math-imports.hpp"
+#include "compat/time.hpp"
+
+
+accela_hamilton::accela_hamilton()
+{
+ s.make_splines(spline_rot, spline_pos);
+}
+
+
+void accela_hamilton::filter(const double* input, double *output)
+{
+ constexpr float EPSILON = 1e-15F;
+
+ const QQuaternion current_rot = QQuaternion::fromEulerAngles(input[Pitch], input[Yaw], input[Roll]);
+ const QVector3D current_pos(input[TX], input[TY], input[TZ]);
+
+ if (unlikely(first_run))
+ {
+ first_run = false;
+ last_rotation = current_rot;
+ last_position = current_pos;
+ t.start();
+#if defined DEBUG_ACCELA
+ debug_max = 0;
+ debug_timer.start();
+#endif
+ return;
+ }
+
+ const float pos_thres{s.pos_smoothing};
+ const float pos_dz{ s.pos_deadzone};
+
+ const float dt = t.elapsed_seconds();
+ t.start();
+
+ // Position
+ {
+ const QVector3D delta = current_pos - last_position;
+ const float delta_len = delta.length();
+ QVector3D delta_normed = delta_len>0.F ? delta/delta_len : QVector3D(); // Zero vector when length was zero.
+ const float gain = dt*spline_pos.get_value_no_save(std::max(0.F, delta_len-pos_dz) / pos_thres);
+ const QVector3D output_pos = last_position + gain * delta_normed;
+ output[TX] = output_pos.x();
+ output[TY] = output_pos.y();
+ output[TZ] = output_pos.z();
+ last_position = output_pos;
+ }
+
+ // Zoom smoothing:
+ const float zoomed_smoothing = [this](float output_z) {
+ // Local copies because accessing settings involves thread synchronization
+ // and I don't like this in the middle of math.
+ const float max_zoomed_smoothing {s.max_zoomed_smoothing};
+ const float max_z {s.max_z};
+ // Movement toward the monitor is negative. Negate and clamp it to get a positive value
+ const float z = std::clamp(-output_z, 0.F, max_z);
+ return max_zoomed_smoothing * z / (max_z + EPSILON);
+ }(output[TZ]);
+
+ const float rot_dz{ s.rot_deadzone};
+ const float rot_thres = float{s.rot_smoothing} + zoomed_smoothing;
+
+ // Rotation
+ {
+ // Inter/extrapolates along the arc between the old and new orientation.
+ // It's basically a quaternion spherical linear interpolation, where the
+ // accela gain x dt is the blending parameter. Might actually overshoot
+ // the new orientation, but that's fine.
+
+ // Compute rotation angle and axis which brings the previous orientation to the current rotation
+ QVector3D axis;
+ float angle;
+ (last_rotation.conjugated() * current_rot).getAxisAndAngle(&axis, &angle);
+ // Apply the Accela gain magic. Also need to multiply with dt here.
+ angle = std::max(0.f, angle - std::copysign(rot_dz, angle)) / rot_thres;
+ const float gain_angle = dt*spline_rot.get_value_no_save(std::abs(angle)) * signum(angle);
+ // Rotate toward the measured orientation. We take the already computed axis. But the angle is now the accela gain.
+ const QQuaternion output_rot = last_rotation * QQuaternion::fromAxisAndAngle(axis, gain_angle);
+ // And back to Euler angles
+ const QVector3D output_euler = output_rot.toEulerAngles();
+ output[Pitch] = output_euler.x();
+ output[Yaw] = output_euler.y();
+ output[Roll] = output_euler.z();
+ last_rotation = output_rot;
+ }
+}
+
+namespace detail::accela_hamilton {
+
+void settings_accela_hamilton::make_splines(spline& rot, spline& pos)
+{
+ rot.clear(); pos.clear();
+
+ for (const auto& val : rot_gains)
+ rot.add_point({ val.x, val.y });
+
+ for (const auto& val : pos_gains)
+ pos.add_point({ val.x, val.y });
+}
+
+} // ns detail::accela_hamilton
+
+OPENTRACK_DECLARE_FILTER(accela_hamilton, dialog_accela_hamilton, accela_hamiltonDll)
diff --git a/filter-accela-hamilton/accela_hamilton.h b/filter-accela-hamilton/accela_hamilton.h
new file mode 100644
index 00000000..ccd74fbf
--- /dev/null
+++ b/filter-accela-hamilton/accela_hamilton.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2012-2015 Stanislaw Halik
+ * Copyright (c) 2023-2024 Michael Welter
+ *
+ * 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_accela_hamilton_filtercontrols.h"
+
+#include "accela_hamilton_settings.hpp"
+#include "api/plugin-api.hpp"
+#include "compat/timer.hpp"
+#include "compat/variance.hpp"
+
+#include <QMutex>
+#include <QTimer>
+#include <QQuaternion>
+#include <QVector3D>
+
+//#define DEBUG_ACCELA
+
+struct accela_hamilton : IFilter
+{
+ accela_hamilton();
+ void filter(const double* input, double *output) override;
+ void center() override { first_run = true; }
+ spline spline_rot, spline_pos;
+ module_status initialize() override { return status_ok(); }
+private:
+ settings_accela_hamilton s;
+ QVector3D last_position = {};
+ QQuaternion last_rotation = {};
+ Timer t;
+#if defined DEBUG_ACCELA
+ Timer debug_timer;
+ double debug_max;
+ variance var;
+#endif
+ bool first_run = true;
+};
+
+class dialog_accela_hamilton : public IFilterDialog
+{
+ Q_OBJECT
+public:
+ dialog_accela_hamilton();
+ 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::AccelaUICdialog_accela ui;
+ settings_accela_hamilton s;
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+class accela_hamiltonDll : public Metadata
+{
+ Q_OBJECT
+
+ QString name() override { return tr("AccelaHamilton"); }
+ QIcon icon() override { return QIcon(":/images/filter-16.png"); }
+};
diff --git a/filter-accela-hamilton/accela_hamilton_dialog.cpp b/filter-accela-hamilton/accela_hamilton_dialog.cpp
new file mode 100644
index 00000000..711535f8
--- /dev/null
+++ b/filter-accela-hamilton/accela_hamilton_dialog.cpp
@@ -0,0 +1,99 @@
+/* Copyright (c) 2012-2015 Stanislaw Halik
+ * Copyright (c) 2023-2024 Michael Welter
+ *
+ * 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 "accela_hamilton.h"
+#include <cmath>
+#include <QDebug>
+#include <algorithm>
+#include <QDoubleSpinBox>
+#include "api/plugin-api.hpp"
+#include "spline/spline-widget.hpp"
+#include <QDialog>
+
+using namespace options;
+
+dialog_accela_hamilton::dialog_accela_hamilton()
+{
+ ui.setupUi(this);
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+
+ tie_setting(s.rot_smoothing, ui.rotation_slider);
+ tie_setting(s.pos_smoothing, ui.translation_slider);
+ tie_setting(s.rot_deadzone, ui.rot_dz_slider);
+ tie_setting(s.pos_deadzone, ui.trans_dz_slider);
+
+ tie_setting(s.rot_smoothing, ui.rot_gain, [](const slider_value& s) { return tr("%1°").arg(s, 0, 'g', 4); });
+ tie_setting(s.pos_smoothing, ui.trans_gain, [](const slider_value& s) { return tr("%1mm").arg(s, 0, 'g', 4); });
+ tie_setting(s.rot_deadzone, ui.rot_dz, [](const slider_value& s) { return tr("%1°").arg(s, 0, 'g', 4); });
+ tie_setting(s.pos_deadzone, ui.trans_dz, [](const slider_value& s) { return tr("%1mm").arg(s); });
+
+ tie_setting(s.max_zoomed_smoothing, ui.max_zoomed_smoothing);
+ tie_setting(s.max_zoomed_smoothing, ui.lb_max_zoomed_smoothing, [](double x)
+ { return tr("%1°").arg(x, 0, 'g', 3);});
+
+ tie_setting(s.max_z, ui.max_z);
+ tie_setting(s.max_z, ui.lb_max_z, [](double x)
+ { return tr("%1mm").arg(x, 0, 'g', 3);});
+
+//#define SPLINE_ROT_DEBUG
+//#define SPLINE_TRANS_DEBUG
+
+#if defined SPLINE_ROT_DEBUG || defined SPLINE_TRANS_DEBUG
+ {
+ spline rot, pos;
+ s.make_splines(rot, pos);
+
+#ifdef SPLINE_ROT_DEBUG
+ QDialog dr;
+ spline_widget r(&dr);
+ dr.setWindowTitle("Accela rotation gain"); r.set_preview_only(true); r.setEnabled(true);
+ r.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); r.set_config(&rot);
+ r.setFixedSize(1024, 600);
+ dr.show();
+ dr.exec();
+#endif
+
+#ifdef SPLINE_TRANS_DEBUG
+ QDialog dt;
+ spline_widget t(&dt);
+ dt.setWindowTitle("Accela translation gain"); t.set_preview_only(true); t.setEnabled(true);
+ dt.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); t.set_config(&pos);
+ t.setFixedSize(1024, 600);
+ dt.show();
+ dt.exec();
+#endif
+ }
+#endif
+}
+
+void dialog_accela_hamilton::doOK()
+{
+ save();
+ close();
+}
+
+void dialog_accela_hamilton::doCancel()
+{
+ close();
+}
+
+void dialog_accela_hamilton::save()
+{
+ s.b->save();
+}
+
+void dialog_accela_hamilton::reload()
+{
+ s.b->reload();
+}
+
+void dialog_accela_hamilton::set_buttons_visible(bool x)
+{
+ ui.buttonBox->setVisible(x);
+}
diff --git a/filter-accela-hamilton/accela_hamilton_filtercontrols.ui b/filter-accela-hamilton/accela_hamilton_filtercontrols.ui
new file mode 100644
index 00000000..f6049444
--- /dev/null
+++ b/filter-accela-hamilton/accela_hamilton_filtercontrols.ui
@@ -0,0 +1,485 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AccelaUICdialog_accela</class>
+ <widget class="QWidget" name="AccelaUICdialog_accela">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>632</width>
+ <height>628</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>550</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>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>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <property name="topMargin">
+ <number>5</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QTextBrowser" name="textBrowser">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>130</height>
+ </size>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QAbstractScrollArea::AdjustToContents</enum>
+ </property>
+ <property name="html">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Accela + Hamilton Filter&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For both rotations and positions: No movement occurs within the dead zone.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For larger movements, rotation and translation occurs toward the new measurement. The strength is determined by the Smoothing setting and the builtin Accela gain curves.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;When you lean forward, smoothing is added up to the set maximum at the distance of Max Z.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>Rotation Smoothing (Added when zoomed)</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <property name="topMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>9</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="1" column="2">
+ <widget class="QSlider" name="max_z">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>25</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_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Max Added</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QSlider" name="max_zoomed_smoothing">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>49</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>40</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="lb_max_zoomed_smoothing">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0° </string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="lb_max_z">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0mm</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Max Z</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Position filtering (X, Y, Z - translation)</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="topMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>9</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="1" column="2">
+ <widget class="QSlider" name="trans_dz_slider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</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="0">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smoothing</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QSlider" name="translation_slider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>29</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>40</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="trans_gain">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0mm</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="trans_dz">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0mm</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Deadzone</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ <zorder>trans_dz_slider</zorder>
+ <zorder>translation_slider</zorder>
+ <zorder>trans_dz</zorder>
+ <zorder>label_6</zorder>
+ <zorder>trans_gain</zorder>
+ <zorder>label</zorder>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupBox44">
+ <property name="title">
+ <string>Rotation filtering (Yaw, pitch, and roll)</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="topMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>9</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="lblSensYaw_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smoothing</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="rot_gain">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0°</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QSlider" name="rotation_slider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>49</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Deadzone</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="rot_dz">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0°</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QSlider" name="rot_dz_slider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</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>
+ </layout>
+ </widget>
+ </item>
+ <item row="4" 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>
+ <tabstops>
+ <tabstop>rotation_slider</tabstop>
+ <tabstop>rot_dz_slider</tabstop>
+ <tabstop>translation_slider</tabstop>
+ <tabstop>trans_dz_slider</tabstop>
+ </tabstops>
+ <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-accela-hamilton/accela_hamilton_settings.hpp b/filter-accela-hamilton/accela_hamilton_settings.hpp
new file mode 100644
index 00000000..71ddf479
--- /dev/null
+++ b/filter-accela-hamilton/accela_hamilton_settings.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include "spline/spline.hpp"
+#include "options/options.hpp"
+
+namespace detail::accela_hamilton {
+
+using namespace options;
+
+// ------------------------------------
+// debug knobs
+// ------------------------------------
+
+//#define DEBUG_ACCELA
+//#define SPLINE_ROT_DEBUG
+//#define SPLINE_TRANS_DEBUG
+
+struct settings_accela_hamilton : opts
+{
+ struct gains
+ {
+ double x, y;
+ };
+
+ static constexpr gains const rot_gains[] {
+ { 9, 300 },
+ { 8, 200 },
+ { 5, 100 },
+ { 2.5, 35 },
+ { 1.5, 8 },
+ { 1, 1.5 },
+ { .5, .4 },
+ };
+
+ static constexpr gains const pos_gains[] {
+ { 9, 200 },
+ { 8, 150 },
+ { 7, 110 },
+ { 5, 60 },
+ { 3, 24 },
+ { 2, 7.5 },
+ { 1.66, 4.5 },
+ { 1.33, 2.25 },
+ { .66, .75 },
+ { .33, .375 },
+ { 0, 0 },
+ };
+
+ static void make_splines(spline& rot, spline& pos);
+
+ value<slider_value> rot_smoothing { b, "rotation-sensitivity", { 1.5, .05, 2.5 } },
+ pos_smoothing { b, "translation-sensitivity", { 1., .05, 1.5 } },
+ rot_deadzone { b, "rotation-deadzone", { .03, 0, .2 } },
+ pos_deadzone { b, "translation-deadzone", { .1, 0, 1 } },
+ max_zoomed_smoothing { b, "max_zoomed_smoothing", { .0, .0, 10. } },
+ max_z { b, "max-z", { 10., .0, 30. } };
+
+ settings_accela_hamilton() : opts("accela-hamilton-sliders") {}
+};
+
+} // ns detail::accela_hamilton
+
+using detail::accela_hamilton::settings_accela_hamilton;
diff --git a/filter-accela-hamilton/lang/nl_NL.ts b/filter-accela-hamilton/lang/nl_NL.ts
new file mode 100644
index 00000000..13315922
--- /dev/null
+++ b/filter-accela-hamilton/lang/nl_NL.ts
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="nl_NL">
+<context>
+ <name>AccelaUICdialog_accela</name>
+ <message>
+ <source>Filter settings</source>
+ <translation type="unfinished">Filter-instellingen</translation>
+ </message>
+ <message>
+ <source>Smoothing</source>
+ <translation type="unfinished">Verzachten</translation>
+ </message>
+ <message>
+ <source>Position filtering (X, Y, Z - translation)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0mm</source>
+ <translation type="unfinished">0mm</translation>
+ </message>
+ <message>
+ <source>Deadzone</source>
+ <translation type="unfinished">Deadzone</translation>
+ </message>
+ <message>
+ <source>Rotation filtering (Yaw, pitch, and roll)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0°</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rotation Smoothing (Added when zoomed)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0° </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Added</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Ubuntu&apos;; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Accela + Hamilton Filter&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For both rotations and positions: No movement occurs within the dead zone.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For larger movements, rotation and translation occurs toward the new measurement. The strength is determined by the Smoothing setting and the builtin Accela gain curves.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;When you lean forward, smoothing is added up to the set maximum at the distance of Max Z.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>accela_hamiltonDll</name>
+ <message>
+ <source>AccelaHamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>dialog_accela_hamilton</name>
+ <message>
+ <source>%1°</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1mm</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/filter-accela-hamilton/lang/ru_RU.ts b/filter-accela-hamilton/lang/ru_RU.ts
new file mode 100644
index 00000000..7dd3e1eb
--- /dev/null
+++ b/filter-accela-hamilton/lang/ru_RU.ts
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+ <name>AccelaUICdialog_accela</name>
+ <message>
+ <source>Filter settings</source>
+ <translation>Настройка фильтра</translation>
+ </message>
+ <message>
+ <source>Smoothing</source>
+ <translation>Сглаживание</translation>
+ </message>
+ <message>
+ <source>Position filtering (X, Y, Z - translation)</source>
+ <translation>Фильтрация смещений (X, Y, Z)</translation>
+ </message>
+ <message>
+ <source>0mm</source>
+ <translation>0мм</translation>
+ </message>
+ <message>
+ <source>Deadzone</source>
+ <translation>Мертвая зона</translation>
+ </message>
+ <message>
+ <source>Rotation filtering (Yaw, pitch, and roll)</source>
+ <translation>Фильтрация поворотов (Рысканье, тангаж, крен)</translation>
+ </message>
+ <message>
+ <source>0°</source>
+ <translation></translation>
+ </message>
+ <message>
+ <source>Rotation Smoothing (Added when zoomed)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0° </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Added</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Ubuntu&apos;; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Accela + Hamilton Filter&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For both rotations and positions: No movement occurs within the dead zone.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For larger movements, rotation and translation occurs toward the new measurement. The strength is determined by the Smoothing setting and the builtin Accela gain curves.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;When you lean forward, smoothing is added up to the set maximum at the distance of Max Z.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>accela_hamiltonDll</name>
+ <message>
+ <source>AccelaHamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>dialog_accela_hamilton</name>
+ <message>
+ <source>%1°</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1mm</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/filter-accela-hamilton/lang/stub.ts b/filter-accela-hamilton/lang/stub.ts
new file mode 100644
index 00000000..2cd62df5
--- /dev/null
+++ b/filter-accela-hamilton/lang/stub.ts
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+ <name>AccelaUICdialog_accela</name>
+ <message>
+ <source>Filter settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Smoothing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Position filtering (X, Y, Z - translation)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0mm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deadzone</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rotation filtering (Yaw, pitch, and roll)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0°</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rotation Smoothing (Added when zoomed)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0° </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Added</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Ubuntu&apos;; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Accela + Hamilton Filter&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For both rotations and positions: No movement occurs within the dead zone.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For larger movements, rotation and translation occurs toward the new measurement. The strength is determined by the Smoothing setting and the builtin Accela gain curves.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;When you lean forward, smoothing is added up to the set maximum at the distance of Max Z.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>accela_hamiltonDll</name>
+ <message>
+ <source>AccelaHamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>dialog_accela_hamilton</name>
+ <message>
+ <source>%1°</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1mm</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/filter-accela-hamilton/lang/zh_CN.ts b/filter-accela-hamilton/lang/zh_CN.ts
new file mode 100644
index 00000000..43a12f5a
--- /dev/null
+++ b/filter-accela-hamilton/lang/zh_CN.ts
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="zh_CN">
+<context>
+ <name>AccelaUICdialog_accela</name>
+ <message>
+ <source>Filter settings</source>
+ <translation>过滤器设置</translation>
+ </message>
+ <message>
+ <source>Rotation filtering (Yaw, pitch, and roll)</source>
+ <translation>旋转过滤器 (偏航, 俯仰, 滚转)</translation>
+ </message>
+ <message>
+ <source>Smoothing</source>
+ <translation type="unfinished">平滑</translation>
+ </message>
+ <message>
+ <source>0°</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deadzone</source>
+ <translation>死区</translation>
+ </message>
+ <message>
+ <source>Position filtering (X, Y, Z - translation)</source>
+ <translation>方位过滤器 (X, Y, Z - 变换)</translation>
+ </message>
+ <message>
+ <source>0mm</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rotation Smoothing (Added when zoomed)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>0° </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Z</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Max Added</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Ubuntu&apos;; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Accela + Hamilton Filter&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For both rotations and positions: No movement occurs within the dead zone.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For larger movements, rotation and translation occurs toward the new measurement. The strength is determined by the Smoothing setting and the builtin Accela gain curves.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;When you lean forward, smoothing is added up to the set maximum at the distance of Max Z.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>accela_hamiltonDll</name>
+ <message>
+ <source>AccelaHamilton</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>dialog_accela_hamilton</name>
+ <message>
+ <source>%1°</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1mm</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>