6 if (dcm == NULL || !isfinite(tol) || tol < 0.0) {
10 for (
int row = 0; row < 3; ++row) {
11 for (
int column = 0; column < 3; ++column) {
12 if (!isfinite(dcm[row][column])) {
18 for (
int left = 0; left < 3; ++left) {
19 for (
int right = 0; right < 3; ++right) {
21 double column_dot = 0.0;
22 for (
int index = 0; index < 3; ++index) {
23 row_dot += dcm[left][index] * dcm[right][index];
24 column_dot += dcm[index][left] * dcm[index][right];
26 const double expected = left == right ? 1.0 : 0.0;
27 if (fabs(row_dot - expected) > tol || fabs(column_dot - expected) > tol) {
33 const double determinant =
34 dcm[0][0] * (dcm[1][1] * dcm[2][2] - dcm[1][2] * dcm[2][1]) -
35 dcm[0][1] * (dcm[1][0] * dcm[2][2] - dcm[1][2] * dcm[2][0]) +
36 dcm[0][2] * (dcm[1][0] * dcm[2][1] - dcm[1][1] * dcm[2][0]);
37 if (fabs(determinant - 1.0) > tol) {
48 if (roll == NULL || pitch == NULL || yaw == NULL ||
53 const double horizontal = hypot(dcm[0][0], dcm[1][0]);
54 *pitch = atan2(-dcm[2][0], horizontal);
55 if (horizontal > 1e-12) {
56 *roll = atan2(dcm[2][1], dcm[2][2]);
57 *yaw = atan2(dcm[1][0], dcm[0][0]);
60 *yaw = atan2(-dcm[0][1], dcm[1][1]);
78 const double trace = dcm[0][0] + dcm[1][1] + dcm[2][2];
80 const double scale = 2.0 * sqrt(trace + 1.0);
82 q[1] = (dcm[2][1] - dcm[1][2]) / scale;
83 q[2] = (dcm[0][2] - dcm[2][0]) / scale;
84 q[3] = (dcm[1][0] - dcm[0][1]) / scale;
85 }
else if (dcm[0][0] > dcm[1][1] && dcm[0][0] > dcm[2][2]) {
86 const double scale = 2.0 * sqrt(1.0 + dcm[0][0] - dcm[1][1] - dcm[2][2]);
87 q[0] = (dcm[2][1] - dcm[1][2]) / scale;
89 q[2] = (dcm[0][1] + dcm[1][0]) / scale;
90 q[3] = (dcm[0][2] + dcm[2][0]) / scale;
91 }
else if (dcm[1][1] > dcm[2][2]) {
92 const double scale = 2.0 * sqrt(1.0 + dcm[1][1] - dcm[0][0] - dcm[2][2]);
93 q[0] = (dcm[0][2] - dcm[2][0]) / scale;
94 q[1] = (dcm[0][1] + dcm[1][0]) / scale;
96 q[3] = (dcm[1][2] + dcm[2][1]) / scale;
98 const double scale = 2.0 * sqrt(1.0 + dcm[2][2] - dcm[0][0] - dcm[1][1]);
99 q[0] = (dcm[1][0] - dcm[0][1]) / scale;
100 q[1] = (dcm[0][2] + dcm[2][0]) / scale;
101 q[2] = (dcm[1][2] + dcm[2][1]) / scale;
105 const double norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
106 for (
int index = 0; index < 4; ++index) {
110 for (
int index = 0; index < 4; ++index) {
111 q[index] = -q[index];
void dcm_to_euler(const double dcm[3][3], double *roll, double *pitch, double *yaw)
Convert a direction cosine matrix to intrinsic ZYX Euler angles.
int dcm_to_euler_checked(const double dcm[3][3], double *roll, double *pitch, double *yaw)
Checked DCM-to-Euler conversion.