RobotCore
1.0
WPILib port to raspberry Pi
Toggle main menu visibility
Loading...
Searching...
No Matches
Quaternion.java
1
// Copyright (c) FIRST and other WPILib contributors.
2
// Open Source Software; you can modify and/or share it under the terms of
3
// the WPILib BSD license file in the root directory of this project.
4
5
package
org.wpilib.math.geometry;
6
7
import
io.avaje.jsonb.Json;
8
import
java.util.Objects;
9
import
org.wpilib.math.geometry.proto.QuaternionProto;
10
import
org.wpilib.math.geometry.struct.QuaternionStruct;
11
import
org.wpilib.math.linalg.VecBuilder;
12
import
org.wpilib.math.linalg.Vector;
13
import
org.wpilib.math.numbers.N3;
14
import
org.wpilib.util.protobuf.ProtobufSerializable;
15
import
org.wpilib.util.struct.StructSerializable;
16
18
@Json
19
public
final
class
Quaternion
implements
ProtobufSerializable
,
StructSerializable
{
20
// Scalar r in versor form
21
@Json.Ignore
private
final
double
m_w;
22
23
// Vector v in versor form
24
@Json.Ignore
private
final
double
m_x;
25
@Json.Ignore
private
final
double
m_y;
26
@Json.Ignore
private
final
double
m_z;
27
29
public
Quaternion
() {
30
m_w = 1.0;
31
m_x = 0.0;
32
m_y = 0.0;
33
m_z = 0.0;
34
}
35
44
@Json.Creator
45
public
Quaternion
(
46
@Json.Alias(
"W"
)
double
w,
47
@Json.Alias(
"X"
)
double
x,
48
@Json.Alias(
"Y"
)
double
y,
49
@Json.Alias(
"Z"
)
double
z) {
50
m_w = w;
51
m_x = x;
52
m_y = y;
53
m_z = z;
54
}
55
62
public
Quaternion
plus
(
Quaternion
other) {
63
return
new
Quaternion
(
64
getW
() + other.
getW
(),
getX
() + other.
getX
(),
getY
() + other.
getY
(),
getZ
() + other.
getZ
());
65
}
66
73
public
Quaternion
minus
(
Quaternion
other) {
74
return
new
Quaternion
(
75
getW
() - other.
getW
(),
getX
() - other.
getX
(),
getY
() - other.
getY
(),
getZ
() - other.
getZ
());
76
}
77
84
public
Quaternion
divide
(
double
scalar) {
85
return
new
Quaternion
(
getW
() / scalar,
getX
() / scalar,
getY
() / scalar,
getZ
() / scalar);
86
}
87
94
public
Quaternion
times
(
double
scalar) {
95
return
new
Quaternion
(
getW
() * scalar,
getX
() * scalar,
getY
() * scalar,
getZ
() * scalar);
96
}
97
104
public
Quaternion
times
(
Quaternion
other) {
105
// https://en.wikipedia.org/wiki/Quaternion#Scalar_and_vector_parts
106
final
var r1 = m_w;
107
final
var r2 = other.m_w;
108
109
// v₁ ⋅ v₂
110
double
dot
= m_x * other.m_x + m_y * other.m_y + m_z * other.m_z;
111
112
// v₁ x v₂
113
double
cross_x = m_y * other.m_z - other.m_y * m_z;
114
double
cross_y = other.m_x * m_z - m_x * other.m_z;
115
double
cross_z = m_x * other.m_y - other.m_x * m_y;
116
117
return
new
Quaternion
(
118
// r = r₁r₂ − v₁ ⋅ v₂
119
r1 * r2 -
dot
,
120
// v = r₁v₂ + r₂v₁ + v₁ x v₂
121
r1 * other.m_x + r2 * m_x + cross_x,
122
r1 * other.m_y + r2 * m_y + cross_y,
123
r1 * other.m_z + r2 * m_z + cross_z);
124
}
125
126
@Override
127
public
String toString() {
128
return
String.format(
"Quaternion(%s, %s, %s, %s)"
,
getW
(),
getX
(),
getY
(),
getZ
());
129
}
130
137
@Override
138
public
boolean
equals
(Object obj) {
139
return
obj instanceof
Quaternion
other
140
&& Math.abs(
dot
(other) -
norm
() * other.norm()) < 1e-9
141
&& Math.abs(
norm
() - other.norm()) < 1e-9;
142
}
143
144
@Override
145
public
int
hashCode() {
146
return
Objects.hash(m_w, m_x, m_y, m_z);
147
}
148
154
public
Quaternion
conjugate
() {
155
return
new
Quaternion
(
getW
(), -
getX
(), -
getY
(), -
getZ
());
156
}
157
164
public
double
dot
(
final
Quaternion
other) {
165
return
getW
() * other.
getW
()
166
+
getX
() * other.
getX
()
167
+
getY
() * other.
getY
()
168
+
getZ
() * other.
getZ
();
169
}
170
176
public
Quaternion
inverse
() {
177
var
norm
=
norm
();
178
return
conjugate
().
divide
(
norm
*
norm
);
179
}
180
186
public
double
norm
() {
187
return
Math.sqrt(
dot
(
this
));
188
}
189
195
public
Quaternion
normalize
() {
196
double
norm
=
norm
();
197
if
(
norm
== 0.0) {
198
return
new
Quaternion
();
199
}
else
{
200
return
new
Quaternion
(
getW
() /
norm
,
getX
() /
norm
,
getY
() /
norm
,
getZ
() /
norm
);
201
}
202
}
203
210
public
Quaternion
pow
(
double
t) {
211
// q^t = e^(ln(q^t)) = e^(t * ln(q))
212
return
this.
log
().
times
(t).
exp
();
213
}
214
225
public
Quaternion
exp
() {
226
var scalar = Math.
exp
(
getW
());
227
228
var axial_magnitude = Math.sqrt(
getX
() *
getX
() +
getY
() *
getY
() +
getZ
() *
getZ
());
229
var cosine = Math.cos(axial_magnitude);
230
231
double
axial_scalar;
232
233
if
(axial_magnitude < 1e-9) {
234
// Taylor series of sin(θ) / θ near θ = 0: 1 − θ²/6 + θ⁴/120 + O(n⁶)
235
var axial_magnitude_sq = axial_magnitude * axial_magnitude;
236
var axial_magnitude_sq_sq = axial_magnitude_sq * axial_magnitude_sq;
237
axial_scalar = 1.0 - axial_magnitude_sq / 6.0 + axial_magnitude_sq_sq / 120.0;
238
}
else
{
239
axial_scalar = Math.sin(axial_magnitude) / axial_magnitude;
240
}
241
242
return
new
Quaternion
(
243
cosine * scalar,
244
getX
() * axial_scalar * scalar,
245
getY
() * axial_scalar * scalar,
246
getZ
() * axial_scalar * scalar);
247
}
248
259
public
Quaternion
log
() {
260
var
norm
=
norm
();
261
if
(
norm
== 0.0) {
262
return
new
Quaternion
(0.0, 0.0, 0.0, 0.0);
263
}
264
265
var scalar = Math.log(
norm
);
266
267
var v_norm = Math.sqrt(
getX
() *
getX
() +
getY
() *
getY
() +
getZ
() *
getZ
());
268
269
var w =
getW
();
270
var s_norm = w /
norm
;
271
272
if
(Math.abs(s_norm + 1) < 1e-9) {
273
return
new
Quaternion
(scalar, -Math.PI, 0, 0);
274
}
275
276
double
v_scalar;
277
278
if
(v_norm < 1e-9 && w != 0.0) {
279
// Taylor series expansion of atan2(y/x)/y at y = 0:
280
//
281
// 1/x - 1/3 y²/x³ + O(y⁴)
282
v_scalar = 1.0 / w - 1.0 / 3.0 * v_norm * v_norm / (w * w * w);
283
}
else
if
(v_norm == 0.0) {
284
v_scalar = 0.0;
285
}
else
{
286
v_scalar = Math.atan2(v_norm, w) / v_norm;
287
}
288
289
return
new
Quaternion
(scalar, v_scalar *
getX
(), v_scalar *
getY
(), v_scalar *
getZ
());
290
}
291
297
@Json.Property(value =
"W"
)
298
public
double
getW
() {
299
return
m_w;
300
}
301
307
@Json.Property(value =
"X"
)
308
public
double
getX
() {
309
return
m_x;
310
}
311
317
@Json.Property(value =
"Y"
)
318
public
double
getY
() {
319
return
m_y;
320
}
321
327
@Json.Property(value =
"Z"
)
328
public
double
getZ
() {
329
return
m_z;
330
}
331
342
public
static
Quaternion
fromRotationVector
(
Vector<N3>
rvec) {
343
double
theta = rvec.
norm
();
344
345
double
cos = Math.cos(theta / 2);
346
347
double
axial_scalar;
348
349
if
(theta < 1e-9) {
350
// taylor series expansion of sin(θ/2) / θ = 1/2 - θ²/48 + O(θ⁴)
351
axial_scalar = 1.0 / 2.0 - theta * theta / 48.0;
352
}
else
{
353
axial_scalar = Math.sin(theta / 2) / theta;
354
}
355
356
return
new
Quaternion
(
357
cos,
358
axial_scalar * rvec.
get
(0, 0),
359
axial_scalar * rvec.
get
(1, 0),
360
axial_scalar * rvec.
get
(2, 0));
361
}
362
370
public
Vector<N3>
toRotationVector
() {
371
// See equation (31) in "Integrating Generic Sensor Fusion Algorithms with
372
// Sound State Representation through Encapsulation of Manifolds"
373
//
374
// https://arxiv.org/pdf/1107.1119.pdf
375
double
norm
= Math.sqrt(
getX
() *
getX
() +
getY
() *
getY
() +
getZ
() *
getZ
());
376
377
double
coeff;
378
if
(
norm
< 1e-9) {
379
coeff = 2.0 /
getW
() - 2.0 / 3.0 *
norm
*
norm
/ (
getW
() *
getW
() *
getW
());
380
}
else
{
381
if
(
getW
() < 0.0) {
382
coeff = 2.0 * Math.atan2(-
norm
, -
getW
()) /
norm
;
383
}
else
{
384
coeff = 2.0 * Math.atan2(
norm
,
getW
()) /
norm
;
385
}
386
}
387
388
return
VecBuilder
.
fill
(coeff *
getX
(), coeff *
getY
(), coeff *
getZ
());
389
}
390
392
public
static
final
QuaternionProto
proto
=
new
QuaternionProto
();
393
395
public
static
final
QuaternionStruct
struct
= new
QuaternionStruct
();
396
}
org.wpilib.math.geometry.Quaternion.proto
static final QuaternionProto proto
Definition
Quaternion.java:392
org.wpilib.math.geometry.Quaternion.Quaternion
Quaternion()
Definition
Quaternion.java:29
org.wpilib.math.geometry.Quaternion.pow
Quaternion pow(double t)
Definition
Quaternion.java:210
org.wpilib.math.geometry.Quaternion.times
Quaternion times(Quaternion other)
Definition
Quaternion.java:104
org.wpilib.math.geometry.Quaternion.norm
double norm()
Definition
Quaternion.java:186
org.wpilib.math.geometry.Quaternion.toRotationVector
Vector< N3 > toRotationVector()
Definition
Quaternion.java:370
org.wpilib.math.geometry.Quaternion.times
Quaternion times(double scalar)
Definition
Quaternion.java:94
org.wpilib.math.geometry.Quaternion.fromRotationVector
static Quaternion fromRotationVector(Vector< N3 > rvec)
Definition
Quaternion.java:342
org.wpilib.math.geometry.Quaternion.getX
double getX()
Definition
Quaternion.java:308
org.wpilib.math.geometry.Quaternion.minus
Quaternion minus(Quaternion other)
Definition
Quaternion.java:73
org.wpilib.math.geometry.Quaternion.normalize
Quaternion normalize()
Definition
Quaternion.java:195
org.wpilib.math.geometry.Quaternion.getY
double getY()
Definition
Quaternion.java:318
org.wpilib.math.geometry.Quaternion.divide
Quaternion divide(double scalar)
Definition
Quaternion.java:84
org.wpilib.math.geometry.Quaternion.inverse
Quaternion inverse()
Definition
Quaternion.java:176
org.wpilib.math.geometry.Quaternion.plus
Quaternion plus(Quaternion other)
Definition
Quaternion.java:62
org.wpilib.math.geometry.Quaternion.dot
double dot(final Quaternion other)
Definition
Quaternion.java:164
org.wpilib.math.geometry.Quaternion.getW
double getW()
Definition
Quaternion.java:298
org.wpilib.math.geometry.Quaternion.getZ
double getZ()
Definition
Quaternion.java:328
org.wpilib.math.geometry.Quaternion.exp
Quaternion exp()
Definition
Quaternion.java:225
org.wpilib.math.geometry.Quaternion.equals
boolean equals(Object obj)
Definition
Quaternion.java:138
org.wpilib.math.geometry.Quaternion.Quaternion
Quaternion( @Json.Alias("W") double w, @Json.Alias("X") double x, @Json.Alias("Y") double y, @Json.Alias("Z") double z)
Definition
Quaternion.java:45
org.wpilib.math.geometry.Quaternion.conjugate
Quaternion conjugate()
Definition
Quaternion.java:154
org.wpilib.math.geometry.Quaternion.log
Quaternion log()
Definition
Quaternion.java:259
org.wpilib.math.geometry.proto.QuaternionProto
Definition
QuaternionProto.java:12
org.wpilib.math.geometry.struct.QuaternionStruct
Definition
QuaternionStruct.java:11
org.wpilib.math.linalg.VecBuilder
Definition
VecBuilder.java:23
org.wpilib.math.linalg.VecBuilder.fill
static Vector< N1 > fill(double n1)
Definition
VecBuilder.java:46
org.wpilib.math.linalg.Vector
Definition
Vector.java:28
org.wpilib.math.linalg.Vector.get
double get(int row)
Definition
Vector.java:67
org.wpilib.math.linalg.Vector.norm
double norm()
Definition
Vector.java:127
org.wpilib.util.protobuf.ProtobufSerializable
Definition
ProtobufSerializable.java:16
org.wpilib.util.struct.StructSerializable
Definition
StructSerializable.java:16
org
wpilib
math
geometry
Quaternion.java
Generated by
1.18.0