-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathRotMat2quat.m
138 lines (119 loc) · 4.31 KB
/
RotMat2quat.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
function q = RotMat2quat(C)
%‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
% [Eq. 98a - 98b - 99a - 99b Trawny]
% ROTMAT2QUAT Converts direction cosine matrix to quaternion.
%
% INPUT:
% * C, Coordinate transformation matrix (3 x 3) matrix []
%
% OUTPUT:
% * q, Quaternion (q = [q0; q1; q2; q3], q0 is the scalar) (4 x 1) vector []
%
% Author: Livio Bisogni
%_______________________________________________________________________________________________________
% Check number of arguments
narginchk(1,1);
if (~isequal(size(C), [3 3]))
error('C must be a (3 x 3) matrix.');
end
% if (norm(C) ~= 1)
% warning('C should have norm 1.');
% end
if (abs(1 - norm(C)) > 1e-15)
warning(['C should have norm 1: norm(C) = ', num2str(norm(C)), ', norm(C) - 1 = ', num2str(norm(C)-1)])
end
for i=1:3
for j=1:3
if (C(i,j) < -1)
warning('C[%i,%i]=%f is smaller than -1', i, j, C(i,j));
elseif (C(i,j) > 1)
warning('C[%i,%i]=%f is greater than 1', i, j, C(i,j));
end
end
end
c11 = C(1,1);
c12 = C(1,2);
c13 = C(1,3);
c21 = C(2,1);
c22 = C(2,2);
c23 = C(2,3);
c31 = C(3,1);
c32 = C(3,2);
c33 = C(3,3);
% [Eq. 96 Trawny]
T = trace(C);
% "Each of these four solutions will be singular when the pivotal
% element is zero, but at least one will not be (since otherwise q
% could not have unit norm)1. For maximum numerical accuracy, the form
% with the largest pivotal element should be used."
[~, max_index] = max([c11, c22, c33, T]);
switch(max_index)
case 1
% [Eq. 98a Trawny]
q1 = sqrt(1 + 2 * c11 - T) / 2;
q = [q1;
(c12 + c21) / (4 * q1);
(c13 + c31) / (4 * q1);
(c23 - c32) / (4 * q1)];
case 2
% [Eq. 98b Trawny]
q2 = sqrt(1 + 2 * c22 - T) / 2;
q = [(c12 + c21) / (4 * q2);
q2;
(c23 + c32) / (4 * q2);
(c31 - c13) / (4 * q2)];
case 3
% [Eq. 99a Trawny]
q3 = sqrt(1 + 2 * c33 - T) / 2;
q = [(c13 + c31) / (4 * q3);
(c23 + c32) / (4 * q3);
q3;
(c12 - c21) / (4 * q3)];
case 4
% [Eq. 99b Trawny]
q4 = sqrt(1 + T) / 2;
q = [(c23 - c32) / (4 * q4);
(c31 - c13) / (4 * q4);
(c12 - c21) / (4 * q4);
q4];
otherwise
error('Unexpected behavior.')
end
% quaternion normalization, *** no need if dcm is really a dcm
q = q / norm(q);
% Ensure quaternion scalar part is non-negative
if (q(4) < 0)
q = -q;
end
q = [q(4); q(1); q(2); q(3)]; % poiché il nuovo paper usa lo scalare come primo elemento (anziché come ultimo)
%% ALTERNATIVE method
% % https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf
% % Check also: % https://gunjanpatel.wordpress.com/quaternions-to-rotation-angles-how-to-use-them/
%
% if (c33 < 0)
% if (c11 > c22)
% t = 1 + c11 - c22 - c33;
% q = [t; c12 + c21; c31 + c13; c23 - c32];
% else
% t = 1 - c11 + c22 - c33;
% q = [c12 + c21; t; c23 + c32; c31 - c13];
% end
% else
% if (c11 < -c22)
% t = 1 - c11 - c22 + c33;
% q = [c31 + c13; c23 + c32; t; c12 - c21];
% else
% t = 1 + m00 + m11 + m22;
% q =[c23 - c32, c31 - c13, c12 - c21, t];
% end
% end
%
% q = q * 0.5 / sqrt(t);
%
% % ensure q(4) is non-negative
% if (q(4) < 0)
% q = -q;
% end
%
% q = [q(4); q(1); q(2); q(3)]; % poiché il nuovo paper usa lo scalare come primo elemento (anziché come ultimo)
end