-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathorientation.ts
107 lines (90 loc) · 2.91 KB
/
orientation.ts
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
/*
adapted from https://github.com/expo/expo/discussions/7893 ...
which I assume to be licensed under the same terms as Expo itself.
*/
const halfPI = Math.PI * 0.5;
export type Rotation = {
alpha: number;
beta: number;
gamma: number;
};
function attitudeTo3x3Matrix(rotation: Rotation): number[] {
// zxy (yaw roll pitch)
const [roll, pitch, yaw] = [rotation.alpha, rotation.beta, rotation.gamma];
const yawSin = Math.sin(yaw);
const rollSin = Math.sin(roll);
const pitchSin = Math.sin(pitch);
const yawCos = Math.cos(yaw);
const rollCos = Math.cos(roll);
const pitchCos = Math.cos(pitch);
// Z
const rotationZ0 = yawCos * rollCos - yawSin * pitchSin * rollSin;
const rotationZ1 = -pitchCos * yawSin;
const rotationZ2 = rollCos * yawSin * pitchSin + yawCos * rollSin;
// X
const rotationX0 = rollCos * yawSin + yawCos * pitchSin * rollSin;
const rotationX1 = yawCos * pitchCos;
const rotationX2 = yawSin * rollSin - yawCos * rollCos * pitchSin;
// Y
const rotationY0 = -pitchCos * rollSin;
const rotationY1 = pitchSin;
const rotationY2 = pitchCos * rollCos;
return [
rotationZ0,
rotationZ1,
rotationZ2,
rotationX0,
rotationX1,
rotationX2,
rotationY0,
rotationY1,
rotationY2,
];
}
function orientationMatrixToOrientation(orientation: number[]) {
const [rot1, rot2, _rot3, rot4, rot5, _rot6, rot7, rot8, rot9] = orientation;
let rotationAlpha;
let rotationBeta;
let rotationGamma;
if (rot9 > 0) {
rotationAlpha = Math.atan2(-rot2, rot5);
rotationBeta = Math.asin(rot8);
rotationGamma = Math.atan2(-rot7, rot9);
} else if (rot9 < 0) {
rotationAlpha = Math.atan2(rot2, -rot5);
rotationBeta = -Math.asin(rot8);
rotationBeta += rotationBeta < 0 ? Math.PI : -Math.PI;
rotationGamma = Math.atan2(rot7, -rot9);
} else {
if (rot7 > 0) {
rotationAlpha = Math.atan2(-rot2, rot5);
rotationBeta = Math.asin(rot8);
rotationGamma = -halfPI;
} else if (rot7 < 0) {
rotationAlpha = Math.atan2(rot2, -rot5);
rotationBeta = -Math.asin(rot8);
rotationBeta += rotationBeta < 0 ? Math.PI : -Math.PI;
rotationGamma = -halfPI;
} else {
rotationAlpha = Math.atan2(rot4, rot1);
rotationBeta = rot8 <= 0 ? -halfPI : halfPI;
rotationGamma = 0;
}
}
if (rotationAlpha <= 0) {
rotationAlpha = Math.PI * 2 + rotationAlpha;
}
return [rotationAlpha, rotationBeta, rotationGamma];
}
function radiansToDegrees(radians: number) {
return (radians * 180) / Math.PI;
}
export function transformOrientation(sensorReading: Rotation): Rotation {
const matrix = attitudeTo3x3Matrix(sensorReading);
const [rotationAlpha, rotationBeta, rotationGamma] =
orientationMatrixToOrientation(matrix);
const alpha = radiansToDegrees(rotationAlpha);
const beta = radiansToDegrees(rotationBeta);
const gamma = radiansToDegrees(rotationGamma);
return { alpha, beta, gamma };
}