BELFEM
0.9.0
Berkeley Lab Finite Element Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
fn_quaternion_from_rotation_matrix.hpp
Go to the documentation of this file.
1
/*
2
* BELFEM -- The Berkeley Lab Finite Element Framework
3
* Copyright (c) 2026, The Regents of the University of California,
4
* through Lawrence Berkeley National Laboratory (subject to receipt of any required
5
* approvals from the U.S. Dept. of Energy). All rights reserved.
6
*
7
* Developers: Christian Messe, Gregory Giard
8
*
9
* See the top-level LICENSE file for the complete license and disclaimer.
10
*/
11
12
#ifndef BELFEM_FN_QUATERNION_FROM_ROTATION_MATRIX_HPP
13
#define BELFEM_FN_QUATERNION_FROM_ROTATION_MATRIX_HPP
14
15
#include "
cl_Quaternion.hpp
"
16
#include "
cl_Matrix.hpp
"
17
#include "
assert.hpp
"
18
19
namespace
belfem
20
{
21
//------------------------------------------------------------------------------
22
34
template
<
typename
T >
35
Quaternion < T >
36
quaternion_from_rotation_matrix
(
const
Matrix < T > & aMatrix )
37
{
38
BELFEM_ASSERT
( aMatrix.
n_rows
() == 3 && aMatrix.
n_cols
() == 3,
39
"Input matrix must be 3x3"
);
40
41
T r00 = aMatrix( 0, 0 );
42
T r01 = aMatrix( 0, 1 );
43
T r02 = aMatrix( 0, 2 );
44
T r10 = aMatrix( 1, 0 );
45
T r11 = aMatrix( 1, 1 );
46
T r12 = aMatrix( 1, 2 );
47
T r20 = aMatrix( 2, 0 );
48
T r21 = aMatrix( 2, 1 );
49
T r22 = aMatrix( 2, 2 );
50
51
// check that the matrix is a proper rotation (det = +1); the determinant
52
// is formed inside the assert so it costs nothing once asserts compile out
53
BELFEM_ASSERT
( std::abs( r00 * ( r11 * r22 - r12 * r21 )
54
- r01 * ( r10 * r22 - r12 * r20 )
55
+ r02 * ( r10 * r21 - r11 * r20 )
56
- T( 1 ) ) < T( 100 ) *
BELFEM_EPSILON
,
57
"Input must be a proper rotation matrix (det = +1)"
);
58
T tTrace = r00 + r11 + r22;
59
60
T w, x, y, z;
61
62
if
( tTrace > T( 0 ) )
63
{
64
// trace > 0: recover w from the trace (w^2 >= 1/4, safe division)
65
T s = T( 0.5 ) / std::sqrt( tTrace + T( 1 ) );
66
w = T( 0.25 ) / s;
67
x = ( r21 - r12 ) * s;
68
y = ( r02 - r20 ) * s;
69
z = ( r10 - r01 ) * s;
70
}
71
else
if
( r00 > r11 && r00 > r22 )
72
{
73
// x is the largest component
74
T s = T( 2 ) * std::sqrt( T( 1 ) + r00 - r11 - r22 );
75
w = ( r21 - r12 ) / s;
76
x = T( 0.25 ) * s;
77
y = ( r01 + r10 ) / s;
78
z = ( r02 + r20 ) / s;
79
}
80
else
if
( r11 > r22 )
81
{
82
// y is the largest component
83
T s = T( 2 ) * std::sqrt( T( 1 ) + r11 - r00 - r22 );
84
w = ( r02 - r20 ) / s;
85
x = ( r01 + r10 ) / s;
86
y = T( 0.25 ) * s;
87
z = ( r12 + r21 ) / s;
88
}
89
else
90
{
91
// z is the largest component
92
T s = T( 2 ) * std::sqrt( T( 1 ) + r22 - r00 - r11 );
93
w = ( r10 - r01 ) / s;
94
x = ( r02 + r20 ) / s;
95
y = ( r12 + r21 ) / s;
96
z = T( 0.25 ) * s;
97
}
98
99
Quaternion < T > tQ( w, x, y, z );
100
tQ.
normalize
();
101
return
tQ;
102
}
103
104
//------------------------------------------------------------------------------
105
}
106
#endif
//BELFEM_FN_QUATERNION_FROM_ROTATION_MATRIX_HPP
assert.hpp
BELFEM_ASSERT
#define BELFEM_ASSERT(aCheck,...)
Definition
assert.hpp:244
cl_Matrix.hpp
cl_Quaternion.hpp
belfem::Matrix::n_rows
size_t n_rows() const
Definition
cl_AR_Matrix.hpp:205
belfem::Matrix::n_cols
size_t n_cols() const
Definition
cl_AR_Matrix.hpp:213
belfem::Quaternion::normalize
Quaternion< T > & normalize()
Definition
cl_Quaternion.hpp:269
belfem
USER GUIDES:
Definition
cl_Capacitor.cpp:16
belfem::quaternion_from_rotation_matrix
Quaternion< T > quaternion_from_rotation_matrix(const Matrix< T > &aMatrix)
Extract a unit quaternion from a 3x3 rotation matrix.
Definition
fn_quaternion_from_rotation_matrix.hpp:36
belfem::BELFEM_EPSILON
constexpr real BELFEM_EPSILON
Definition
typedefs.hpp:90
src
math
quaternion
fn_quaternion_from_rotation_matrix.hpp
Generated by
1.18.0