7#include <Eigen/Geometry>
8#include <Kokkos_Core.hpp>
15template <
typename Quaternion,
typename RotationMatrix>
17 const Quaternion& q,
const RotationMatrix& R
19 R(0, 0) = q(0) * q(0) + q(1) * q(1) - q(2) * q(2) - q(3) * q(3);
20 R(0, 1) = 2. * (q(1) * q(2) - q(0) * q(3));
21 R(0, 2) = 2. * (q(1) * q(3) + q(0) * q(2));
22 R(1, 0) = 2. * (q(1) * q(2) + q(0) * q(3));
23 R(1, 1) = q(0) * q(0) - q(1) * q(1) + q(2) * q(2) - q(3) * q(3);
24 R(1, 2) = 2. * (q(2) * q(3) - q(0) * q(1));
25 R(2, 0) = 2. * (q(1) * q(3) - q(0) * q(2));
26 R(2, 1) = 2. * (q(2) * q(3) + q(0) * q(1));
27 R(2, 2) = q(0) * q(0) - q(1) * q(1) - q(2) * q(2) + q(3) * q(3);
33template <
typename Quaternion,
typename View1,
typename View2>
35 const Quaternion& q,
const View1& v,
const View2& v_rot
37 v_rot(0) = (q(0) * q(0) + q(1) * q(1) - q(2) * q(2) - q(3) * q(3)) * v(0) +
38 2. * (q(1) * q(2) - q(0) * q(3)) * v(1) + 2. * (q(1) * q(3) + q(0) * q(2)) * v(2);
39 v_rot(1) = 2. * (q(1) * q(2) + q(0) * q(3)) * v(0) +
40 (q(0) * q(0) - q(1) * q(1) + q(2) * q(2) - q(3) * q(3)) * v(1) +
41 2. * (q(2) * q(3) - q(0) * q(1)) * v(2);
42 v_rot(2) = 2. * (q(1) * q(3) - q(0) * q(2)) * v(0) + 2. * (q(2) * q(3) + q(0) * q(1)) * v(1) +
43 (q(0) * q(0) - q(1) * q(1) - q(2) * q(2) + q(3) * q(3)) * v(2);
49template <
typename Quaternion,
typename Matrix>
68template <
typename QuaternionInput,
typename QuaternionOutput>
70 const QuaternionInput& q_in,
const QuaternionOutput& q_out
72 auto length = Kokkos::sqrt(
73 (q_in(0) * q_in(0)) + (q_in(1) * q_in(1)) + (q_in(2) * q_in(2)) + (q_in(3) * q_in(3))
77 q_out(0) = q_in(0) / length;
78 for (
auto i = 1; i < 4; ++i) {
79 q_out(i) = -q_in(i) / length;
86template <
typename Quaternion1,
typename Quaternion2,
typename QuaternionN>
88 const Quaternion1& q1,
const Quaternion2& q2, QuaternionN& qn
90 qn(0) = q1(0) * q2(0) - q1(1) * q2(1) - q1(2) * q2(2) - q1(3) * q2(3);
91 qn(1) = q1(0) * q2(1) + q1(1) * q2(0) + q1(2) * q2(3) - q1(3) * q2(2);
92 qn(2) = q1(0) * q2(2) - q1(1) * q2(3) + q1(2) * q2(0) + q1(3) * q2(1);
93 qn(3) = q1(0) * q2(3) + q1(1) * q2(2) - q1(2) * q2(1) + q1(3) * q2(0);
99template <
typename Vector,
typename Quaternion>
101 const Vector& phi,
const Quaternion& quaternion
103 const auto angle = Kokkos::sqrt((phi(0) * phi(0)) + (phi(1) * phi(1)) + (phi(2) * phi(2)));
104 const auto cos_angle = Kokkos::cos(angle / 2.);
105 const auto factor = (Kokkos::abs(angle) < 1.e-12) ? 0. : Kokkos::sin(angle / 2.) / angle;
107 quaternion(0) = cos_angle;
108 for (
auto i = 1; i < 4; ++i) {
109 quaternion(i) = phi(i - 1) * factor;
116template <
typename Quaternion,
typename Vector>
118 const Quaternion& quaternion,
const Vector& phi
120 auto theta = 2. * Kokkos::acos(quaternion(0));
121 const auto sin_half_theta = std::sqrt(1. - (quaternion(0) * quaternion(0)));
122 if (sin_half_theta > 1e-12) {
123 phi(0) = theta * quaternion(1) / sin_half_theta;
124 phi(1) = theta * quaternion(2) / sin_half_theta;
125 phi(2) = theta * quaternion(3) / sin_half_theta;
142KOKKOS_INLINE_FUNCTION
144 const auto length_squared = (q[0] * q[0]) + (q[1] * q[1]) + (q[2] * q[2]) + (q[3] * q[3]);
147 if (std::abs(length_squared - 1.) < 1.e-16) {
152 if (std::abs(length_squared) < 1.e-16) {
153 return Kokkos::Array<double, 4>{1., 0., 0., 0.};
157 const auto length = std::sqrt(length_squared);
158 auto normalized_quaternion = Kokkos::Array<double, 4>{};
159 for (
auto k = 0U; k < 4; ++k) {
160 normalized_quaternion[k] = q[k] / length;
162 return normalized_quaternion;
169 const std::array<double, 3>& tangent,
const double twist
171 const auto tan_vec = Eigen::Matrix<double, 3, 1>(tangent.data());
172 const auto e1 = tan_vec.normalized();
174 const auto temp = Eigen::Matrix<double, 3, 1>::Unit(1);
175 const auto plane_axis = (std::abs(e1.dot(temp)) > .9) ? Eigen::Matrix<double, 3, 1>::Unit(0)
176 : Eigen::Matrix<double, 3, 1>::Unit(1);
177 const auto a = e1.dot(plane_axis);
179 const auto e2 = (plane_axis - a * e1).normalized();
180 const auto e3 = e1.cross(e2);
182 const auto q_tan = Eigen::Quaternion<double>(Eigen::Matrix<double, 3, 3>(
183 {{e1(0), e2(0), e3(0)}, {e1(1), e2(1), e3(1)}, {e1(2), e2(2), e3(2)}}
185 const auto q_twist = Eigen::Quaternion<double>(Eigen::AngleAxis<double>(twist, e1));
186 const auto q_final = q_twist * q_tan;
187 return std::array{q_final.w(), q_final.x(), q_final.y(), q_final.z()};
198 return std::abs(q[0] - 1.) <= tolerance && std::abs(q[1]) <= tolerance &&
199 std::abs(q[2]) <= tolerance && std::abs(q[3]) <= tolerance;
Definition gl_quadrature.hpp:8
KOKKOS_INLINE_FUNCTION void QuaternionToRotationVector(const Quaternion &quaternion, const Vector &phi)
Returns a 3-D rotation vector from provided 4-D quaternion, i.e. the logarithmic map.
Definition quaternion_operations.hpp:117
std::array< double, 4 > TangentTwistToQuaternion(const std::array< double, 3 > &tangent, const double twist)
Returns a 4-D quaternion from provided tangent vector and twist (radians) about tangent.
Definition quaternion_operations.hpp:168
KOKKOS_INLINE_FUNCTION void QuaternionCompose(const Quaternion1 &q1, const Quaternion2 &q2, QuaternionN &qn)
Composes (i.e. multiplies) two quaternions and stores the result in a third quaternion.
Definition quaternion_operations.hpp:87
KOKKOS_INLINE_FUNCTION void RotationVectorToQuaternion(const Vector &phi, const Quaternion &quaternion)
Returns a 4-D quaternion from provided 3-D rotation vector, i.e. the exponential map.
Definition quaternion_operations.hpp:100
bool IsIdentityQuaternion(const std::array< double, 4 > &q, double tolerance=1e-12)
Checks if a quaternion is approximately the identity quaternion [1, 0, 0, 0].
Definition quaternion_operations.hpp:197
KOKKOS_INLINE_FUNCTION Kokkos::Array< double, 4 > NormalizeQuaternion(const Kokkos::Array< double, 4 > &q)
Normalizes a quaternion to ensure it is a unit quaternion.
Definition quaternion_operations.hpp:143
KOKKOS_INLINE_FUNCTION void RotateVectorByQuaternion(const Quaternion &q, const View1 &v, const View2 &v_rot)
Rotates provided vector by provided unit quaternion and returns the result.
Definition quaternion_operations.hpp:34
KOKKOS_INLINE_FUNCTION void QuaternionToRotationMatrix(const Quaternion &q, const RotationMatrix &R)
Converts a 4x1 quaternion to a 3x3 rotation matrix and returns the result.
Definition quaternion_operations.hpp:16
KOKKOS_INLINE_FUNCTION void QuaternionDerivative(const Quaternion &q, const Matrix &m)
Computes the derivative of a quaternion and stores the result in a 3x4 matrix.
Definition quaternion_operations.hpp:50
KOKKOS_INLINE_FUNCTION void QuaternionInverse(const QuaternionInput &q_in, const QuaternionOutput &q_out)
Computes the inverse of a quaternion.
Definition quaternion_operations.hpp:69