From 3a1f8606c5b415be00ebf21cd57f4fed6832b800 Mon Sep 17 00:00:00 2001 From: Tom Brazier Date: Tue, 30 May 2023 16:20:30 +0100 Subject: Picked a name - natural movement filter --- filter-nm/CMakeLists.txt | 1 + filter-nm/ftnoir_filter_nm.cpp | 48 +++ filter-nm/ftnoir_filter_nm.h | 93 ++++++ filter-nm/ftnoir_filter_nm_dialog.cpp | 88 +++++ filter-nm/ftnoir_nm_filtercontrols.ui | 610 ++++++++++++++++++++++++++++++++++ filter-nm/lang/nl_NL.ts | 78 +++++ filter-nm/lang/ru_RU.ts | 78 +++++ filter-nm/lang/stub.ts | 78 +++++ filter-nm/lang/zh_CN.ts | 78 +++++ 9 files changed, 1152 insertions(+) create mode 100644 filter-nm/CMakeLists.txt create mode 100644 filter-nm/ftnoir_filter_nm.cpp create mode 100644 filter-nm/ftnoir_filter_nm.h create mode 100644 filter-nm/ftnoir_filter_nm_dialog.cpp create mode 100644 filter-nm/ftnoir_nm_filtercontrols.ui create mode 100644 filter-nm/lang/nl_NL.ts create mode 100644 filter-nm/lang/ru_RU.ts create mode 100644 filter-nm/lang/stub.ts create mode 100644 filter-nm/lang/zh_CN.ts (limited to 'filter-nm') diff --git a/filter-nm/CMakeLists.txt b/filter-nm/CMakeLists.txt new file mode 100644 index 00000000..d98e90e2 --- /dev/null +++ b/filter-nm/CMakeLists.txt @@ -0,0 +1 @@ +otr_module(filter-tom) diff --git a/filter-nm/ftnoir_filter_nm.cpp b/filter-nm/ftnoir_filter_nm.cpp new file mode 100644 index 00000000..6bcfeae0 --- /dev/null +++ b/filter-nm/ftnoir_filter_nm.cpp @@ -0,0 +1,48 @@ +/* Copyright (c) 2023 Tom Brazier + * + * 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 + +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-nm/ftnoir_filter_nm.h b/filter-nm/ftnoir_filter_nm.h new file mode 100644 index 00000000..0f6d07c2 --- /dev/null +++ b/filter-nm/ftnoir_filter_nm.h @@ -0,0 +1,93 @@ +/* Copyright (c) 2023 Tom Brazier + * + * 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 responsiveness[6]; + value drift_speeds[6]; + + settings_tom() : + opts("tom-filter"), + responsiveness{ value(b, "x-responsiveness", { 10.0, .0, 20.0 }), + value(b, "y-responsiveness", { 10.0, .0, 20.0 }), + value(b, "z-responsiveness", { 10.0, .0, 20.0 }), + value(b, "yaw-responsiveness", { 10.0, .0, 20.0 }), + value(b, "pitch-responsiveness", { 10.0, .0, 20.0 }), + value(b, "roll-responsiveness", { 10.0, .0, 20.0 }) }, + drift_speeds{ value(b, "x-drift-speed", { 50.0, 1.0, 200.0 }), + value(b, "y-drift-speed", { 50.0, 1.0, 200.0 }), + value(b, "z-drift-speed", { 50.0, 1.0, 200.0 }), + value(b, "yaw-drift-speed", { 100.0, 1.0, 400.0 }), + value(b, "pitch-drift-speed", { 100.0, 1.0, 400.0 }), + value(b, "roll-drift-speed", { 100.0, 1.0, 400.0 }) } + { + } + + /* 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-nm/ftnoir_filter_nm_dialog.cpp b/filter-nm/ftnoir_filter_nm_dialog.cpp new file mode 100644 index 00000000..5a6ad3a4 --- /dev/null +++ b/filter-nm/ftnoir_filter_nm_dialog.cpp @@ -0,0 +1,88 @@ +/* Copyright (c) 2023 Tom Brazier + * + * 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-nm/ftnoir_nm_filtercontrols.ui b/filter-nm/ftnoir_nm_filtercontrols.ui new file mode 100644 index 00000000..1a135c1e --- /dev/null +++ b/filter-nm/ftnoir_nm_filtercontrols.ui @@ -0,0 +1,610 @@ + + + UICdialog_tom + + + + 0 + 0 + 438 + 559 + + + + Dialog + + + + + + Responsiveness + + + + + + X + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + 10.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + 40 + + + Qt::Horizontal + + + + + + + Y + + + + + + + + 30 + 0 + + + + 10.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 40 + + + Qt::Horizontal + + + + + + + Z + + + + + + + + 30 + 0 + + + + 10.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 40 + + + Qt::Horizontal + + + + + + + Yaw + + + + + + + + 30 + 0 + + + + 10.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 40 + + + Qt::Horizontal + + + + + + + Pitch + + + + + + + + 30 + 0 + + + + 10.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 40 + + + Qt::Horizontal + + + + + + + Roll + + + + + + + + 30 + 0 + + + + 10.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 40 + + + Qt::Horizontal + + + + + + + + + + + 0 + 0 + + + + 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. + + + Qt::PlainText + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Drift speeds + + + + + + Z + + + + + + + 1 + + + 200 + + + Qt::Horizontal + + + + + + + Roll + + + + + + + + 30 + 0 + + + + 50 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + °/s + + + + + + + mm/s + + + + + + + °/s + + + + + + + 1 + + + 200 + + + Qt::Horizontal + + + + + + + + 30 + 0 + + + + 50 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 30 + 0 + + + + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Y + + + + + + + + 30 + 0 + + + + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Pitch + + + + + + + 1 + + + 400 + + + Qt::Horizontal + + + + + + + X + + + + + + + + 30 + 0 + + + + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + mm/s + + + + + + + mm/s + + + + + + + Yaw + + + + + + + + 0 + 0 + + + + 1 + + + 200 + + + Qt::Horizontal + + + + + + + °/s + + + + + + + 1 + + + 400 + + + Qt::Horizontal + + + + + + + 1 + + + 400 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + 50 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + 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. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + buttonBox + accepted() + UICdialog_tom + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + UICdialog_tom + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/filter-nm/lang/nl_NL.ts b/filter-nm/lang/nl_NL.ts new file mode 100644 index 00000000..ce0aefe3 --- /dev/null +++ b/filter-nm/lang/nl_NL.ts @@ -0,0 +1,78 @@ + + + + + UICdialog_tom + + Dialog + + + + X + + + + Y + + + + Z + + + + Yaw + + + + Pitch + + + + Roll + + + + °/s + + + + mm/s + + + + Responsiveness + + + + 10.0 + + + + Drift speeds + + + + 50 + + + + 100 + + + + Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still. + + + + 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. + + + + + tomDll + + Tom + + + + diff --git a/filter-nm/lang/ru_RU.ts b/filter-nm/lang/ru_RU.ts new file mode 100644 index 00000000..b72d73ad --- /dev/null +++ b/filter-nm/lang/ru_RU.ts @@ -0,0 +1,78 @@ + + + + + UICdialog_tom + + Dialog + + + + X + + + + Y + + + + Z + + + + Yaw + + + + Pitch + + + + Roll + + + + °/s + + + + mm/s + + + + Responsiveness + + + + 10.0 + + + + Drift speeds + + + + 50 + + + + 100 + + + + Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still. + + + + 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. + + + + + tomDll + + Tom + + + + diff --git a/filter-nm/lang/stub.ts b/filter-nm/lang/stub.ts new file mode 100644 index 00000000..f212040f --- /dev/null +++ b/filter-nm/lang/stub.ts @@ -0,0 +1,78 @@ + + + + + UICdialog_tom + + Dialog + + + + X + + + + Y + + + + Z + + + + Yaw + + + + Pitch + + + + Roll + + + + °/s + + + + mm/s + + + + Responsiveness + + + + 10.0 + + + + Drift speeds + + + + 50 + + + + 100 + + + + Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still. + + + + 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. + + + + + tomDll + + Tom + + + + diff --git a/filter-nm/lang/zh_CN.ts b/filter-nm/lang/zh_CN.ts new file mode 100644 index 00000000..5a322913 --- /dev/null +++ b/filter-nm/lang/zh_CN.ts @@ -0,0 +1,78 @@ + + + + + UICdialog_tom + + Dialog + + + + X + + + + Y + + + + Z + + + + Yaw + + + + Pitch + + + + Roll + + + + °/s + + + + mm/s + + + + Responsiveness + + + + 10.0 + + + + Drift speeds + + + + 50 + + + + 100 + + + + Natural movement filter: cancels higher frequency noise and the natural tendency for our heads to drift even when we think we are sitting still. + + + + 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. + + + + + tomDll + + Tom + + + + -- cgit v1.2.3