diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2014-11-02 06:04:05 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2014-11-02 06:04:05 +0100 |
commit | c044ce0d0830902b9ca86dcd9a725e5ef4f72eb1 (patch) | |
tree | 30283eea8cbc4d73ee85440f1e1858ea276e5245 | |
parent | 69dc9c96a1f544857d3909dd0412515840d544ca (diff) |
use quaternions for centering
@KyokushinPL says was the only version that worked. Let's give it a try.
Goddamn issue: #63
-rw-r--r-- | ftnoir_posewidget/glwidget.cpp | 23 | ||||
-rw-r--r-- | opentrack/quat.hpp | 71 | ||||
-rw-r--r-- | opentrack/tracker.cpp | 32 | ||||
-rw-r--r-- | opentrack/tracker.h | 3 |
4 files changed, 93 insertions, 36 deletions
diff --git a/ftnoir_posewidget/glwidget.cpp b/ftnoir_posewidget/glwidget.cpp index bfb9190d..07445c8a 100644 --- a/ftnoir_posewidget/glwidget.cpp +++ b/ftnoir_posewidget/glwidget.cpp @@ -34,26 +34,17 @@ void GLWidget::paintEvent ( QPaintEvent * event ) { void GLWidget::rotateBy(double xAngle, double yAngle, double zAngle) { - double c1 = cos(zAngle / 57.295781); - double s1 = sin(zAngle / 57.295781); + double c1 = cos(yAngle / 57.295781); + double s1 = sin(yAngle / 57.295781); double c2 = cos(xAngle / 57.295781); double s2 = sin(xAngle / 57.295781); - double c3 = cos(yAngle / 57.295781); - double s3 = sin(yAngle / 57.295781); + double c3 = cos(zAngle / 57.295781); + double s3 = sin(zAngle / 57.295781); double foo[] = { - // z - c1 * c2, - c1 * s2 * s3 - c3 * s1, - s1 * s3 + c1 * c3 * s2, - // y - c2 * s1, - c1 * c3 + s1 * s2 * s3, - c3 * s1 * s2 - c1 * s3, - // x - -s2, - c2 * s3, - c2 * c3 + c2*c3, -c2*s3, s2, + c1*s3+c3*s1*s2, c1*c3-s1*s2*s3, -c2*s1, + s1*s3-c1*c3*s2, c3*s1+c1*s2*s3, c1*c2, }; for (int i = 0; i < 9; i++) diff --git a/opentrack/quat.hpp b/opentrack/quat.hpp new file mode 100644 index 00000000..e5e74df4 --- /dev/null +++ b/opentrack/quat.hpp @@ -0,0 +1,71 @@ +/* Copyright (c) 2012 Patrick Ruoff + * + * 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 <cmath> + +class Quat { +private: + static constexpr double pi = 3.141592653; + static constexpr double r2d = 180./pi; + double a,b,c,d; // quaternion coefficients +public: + Quat() : a(1.),b(0.),c(0.),d(0.) {} + Quat(double yaw, double pitch, double roll) { *this = from_euler_rads(yaw, pitch, roll); } + Quat(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {} + + Quat inv() const + { + return Quat(a,-b,-c, -d); + } + + // conversions + // see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles + static Quat from_euler_rads(double yaw, double pitch, double roll) + { + + const double sin_phi = sin(roll/2.); + const double cos_phi = cos(roll/2.); + const double sin_the = sin(pitch/2.); + const double cos_the = cos(pitch/2.); + const double sin_psi = sin(yaw/2.); + const double cos_psi = cos(yaw/2.); + + Quat q; + + q.a = cos_phi*cos_the*cos_psi + sin_phi*sin_the*sin_psi; + q.b = sin_phi*cos_the*cos_psi - cos_phi*sin_the*sin_psi; + q.c = cos_phi*sin_the*cos_psi + sin_phi*cos_the*sin_psi; + q.d = cos_phi*cos_the*sin_psi - sin_phi*sin_the*cos_psi; + + return q; + } + + void to_euler_rads(double& yaw, double& pitch, double& roll) const + { + roll = atan2(2.*(a*b + c*d), 1. - 2.*(b*b + c*c)); + pitch = asin(2.*(a*c - b*d)); + yaw = atan2(2.*(a*d + b*c), 1. - 2.*(c*c + d*d)); + } + + void to_euler_degrees(double& yaw, double& pitch, double& roll) const + { + to_euler_rads(yaw, pitch, roll); + yaw *= r2d; + pitch *= r2d; + roll *= r2d; + } + + const Quat operator*(const Quat& B) const + { + const Quat& A = *this; + return Quat(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication + A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c, + A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b, + A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a); + } +}; diff --git a/opentrack/tracker.cpp b/opentrack/tracker.cpp index 4a9be069..b9b43ee5 100644 --- a/opentrack/tracker.cpp +++ b/opentrack/tracker.cpp @@ -28,7 +28,6 @@ Tracker::Tracker(main_settings& s, Mappings &m, SelectedLibraries &libs) : enabledp(true), should_quit(false), libs(libs), - r_b (dmat<3, 3>::eye()), t_b {0,0,0} { } @@ -48,17 +47,6 @@ double Tracker::map(double pos, bool invertp, Mapping& axis) return fc.getValue(pos) + axis.opts.zero; } -// http://stackoverflow.com/a/18436193 -static dmat<3, 1> rmat_to_euler(const dmat<3, 3>& R) -{ - const double tmp[] = { - -atan2( -R(2,0), sqrt(R(2,1)*R(2,1) + R(2,2)*R(2,2)) ), - -atan2( R(2,1), R(2,2)), - -atan2( R(1,0), R(0,0)), - }; - return dmat<3, 1>(tmp); -} - // tait-bryan angles, not euler static dmat<3, 3> euler_to_rmat(const double* input) { @@ -124,26 +112,32 @@ void Tracker::logic() for (int i = 0; i < 6; i++) filtered_pose[i] *= inverts[i] ? -1. : 1.; + static constexpr double pi = 3.141592653; + static constexpr double d2r = pi / 180.; + if (centerp) { centerp = false; - dmat<3, 1> tmp; - r_b = euler_to_rmat(&filtered_pose[Yaw]); for (int i = 0; i < 3; i++) t_b[i] = filtered_pose(i); + q_b = Quat::from_euler_rads(filtered_pose(Yaw) * d2r, + filtered_pose(Pitch) * d2r, + filtered_pose(Roll) * d2r); } Pose raw_centered; { - const dmat<3, 3> rmat = euler_to_rmat(&filtered_pose[Yaw]); - const dmat<3, 3> m_ = rmat * r_b.t(); - const auto euler = rmat_to_euler(m_); + const Quat q(filtered_pose(Yaw)*d2r, + filtered_pose(Pitch)*d2r, + filtered_pose(Roll)*d2r); + const Quat q_ = q * q_b.inv(); + double ypr[3]; + q_.to_euler_degrees(ypr[0], ypr[1], ypr[2]); for (int i = 0; i < 3; i++) { - static constexpr double pi = 3.141592653; raw_centered(i) = filtered_pose(i) - t_b[i]; - raw_centered(i+3) = euler(i, 0) * 180./pi; + raw_centered(i+3) = ypr[i]; } } diff --git a/opentrack/tracker.h b/opentrack/tracker.h index 23939576..feb1f903 100644 --- a/opentrack/tracker.h +++ b/opentrack/tracker.h @@ -7,6 +7,7 @@ #include "plugin-support.h" #include "mappings.hpp" #include "pose.hpp" +#include "quat.hpp" #include "simple-mat.hpp" #include "../qfunctionconfigurator/functionconfig.h" @@ -32,7 +33,7 @@ private: std::atomic<bool> should_quit; SelectedLibraries const& libs; - dmat<3, 3> r_b; + Quat q_b; double t_b[3]; double map(double pos, bool invertp, Mapping& axis); |