open-space-toolkit-mathematics 4.6.0__py39-none-manylinux2014_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- open_space_toolkit_mathematics-4.6.0.dist-info/METADATA +28 -0
- open_space_toolkit_mathematics-4.6.0.dist-info/RECORD +68 -0
- open_space_toolkit_mathematics-4.6.0.dist-info/WHEEL +5 -0
- open_space_toolkit_mathematics-4.6.0.dist-info/top_level.txt +1 -0
- open_space_toolkit_mathematics-4.6.0.dist-info/zip-safe +1 -0
- ostk/__init__.py +1 -0
- ostk/mathematics/OpenSpaceToolkitMathematicsPy.cpython-39-aarch64-linux-gnu.so +0 -0
- ostk/mathematics/__init__.py +5 -0
- ostk/mathematics/__init__.pyi +11 -0
- ostk/mathematics/curve_fitting/__init__.pyi +155 -0
- ostk/mathematics/curve_fitting/interpolator.pyi +243 -0
- ostk/mathematics/geometry/__init__.pyi +504 -0
- ostk/mathematics/geometry/d2/__init__.pyi +809 -0
- ostk/mathematics/geometry/d2/object.pyi +1779 -0
- ostk/mathematics/geometry/d3/__init__.pyi +1032 -0
- ostk/mathematics/geometry/d3/object.pyi +3709 -0
- ostk/mathematics/geometry/d3/transformation/__init__.pyi +3 -0
- ostk/mathematics/geometry/d3/transformation/rotation.pyi +1358 -0
- ostk/mathematics/libopen-space-toolkit-mathematics.so.4 +0 -0
- ostk/mathematics/object.pyi +387 -0
- ostk/mathematics/solver.pyi +342 -0
- ostk/mathematics/test/__init__.py +1 -0
- ostk/mathematics/test/curve_fitting/__init__.py +1 -0
- ostk/mathematics/test/curve_fitting/interpolator/__init__.py +1 -0
- ostk/mathematics/test/curve_fitting/interpolator/test_barycentric_rational.py +44 -0
- ostk/mathematics/test/curve_fitting/interpolator/test_cubic_spline.py +55 -0
- ostk/mathematics/test/curve_fitting/interpolator/test_interpolator.py +71 -0
- ostk/mathematics/test/curve_fitting/interpolator/test_linear.py +45 -0
- ostk/mathematics/test/geometry/__init__.py +1 -0
- ostk/mathematics/test/geometry/d2/__init__.py +1 -0
- ostk/mathematics/test/geometry/d2/conftest.py +79 -0
- ostk/mathematics/test/geometry/d2/object/__init__.py +1 -0
- ostk/mathematics/test/geometry/d2/object/test_composite.py +93 -0
- ostk/mathematics/test/geometry/d2/object/test_line.py +57 -0
- ostk/mathematics/test/geometry/d2/object/test_linestring.py +174 -0
- ostk/mathematics/test/geometry/d2/object/test_multipolygon.py +94 -0
- ostk/mathematics/test/geometry/d2/object/test_point.py +213 -0
- ostk/mathematics/test/geometry/d2/object/test_point_set.py +100 -0
- ostk/mathematics/test/geometry/d2/object/test_polygon.py +370 -0
- ostk/mathematics/test/geometry/d2/object/test_segment.py +104 -0
- ostk/mathematics/test/geometry/d2/test_object.py +25 -0
- ostk/mathematics/test/geometry/d2/test_transformation.py +84 -0
- ostk/mathematics/test/geometry/d3/__init__.py +1 -0
- ostk/mathematics/test/geometry/d3/object/__init__.py +1 -0
- ostk/mathematics/test/geometry/d3/object/test_composite.py +262 -0
- ostk/mathematics/test/geometry/d3/object/test_cuboid.py +20 -0
- ostk/mathematics/test/geometry/d3/object/test_line.py +68 -0
- ostk/mathematics/test/geometry/d3/object/test_linestring.py +168 -0
- ostk/mathematics/test/geometry/d3/object/test_point.py +234 -0
- ostk/mathematics/test/geometry/d3/object/test_point_set.py +113 -0
- ostk/mathematics/test/geometry/d3/object/test_polygon.py +141 -0
- ostk/mathematics/test/geometry/d3/object/test_segment.py +120 -0
- ostk/mathematics/test/geometry/d3/objects/test_cuboid.py +20 -0
- ostk/mathematics/test/geometry/d3/test_intersection.py +3 -0
- ostk/mathematics/test/geometry/d3/test_object.py +3 -0
- ostk/mathematics/test/geometry/d3/test_transformation.py +3 -0
- ostk/mathematics/test/geometry/d3/transformation/__init__.py +1 -0
- ostk/mathematics/test/geometry/d3/transformation/rotation/__init__.py +1 -0
- ostk/mathematics/test/geometry/d3/transformation/rotation/test_euler_angle.py +138 -0
- ostk/mathematics/test/geometry/d3/transformation/rotation/test_quaternion.py +189 -0
- ostk/mathematics/test/geometry/d3/transformation/rotation/test_rotation_matrix.py +40 -0
- ostk/mathematics/test/geometry/d3/transformation/rotation/test_rotation_vector.py +47 -0
- ostk/mathematics/test/geometry/test_angle.py +345 -0
- ostk/mathematics/test/object/__init__.py +1 -0
- ostk/mathematics/test/object/test_interval.py +515 -0
- ostk/mathematics/test/object/test_vector.py +5 -0
- ostk/mathematics/test/solver/test_numerical_solver.py +176 -0
- ostk/mathematics/test/test_object.py +24 -0
|
@@ -0,0 +1,1358 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import numpy
|
|
3
|
+
import ostk.core.type
|
|
4
|
+
import typing
|
|
5
|
+
__all__ = ['EulerAngle', 'Quaternion', 'RotationMatrix', 'RotationVector', 'set_quaternion_array']
|
|
6
|
+
class EulerAngle:
|
|
7
|
+
class AxisSequence:
|
|
8
|
+
"""
|
|
9
|
+
Members:
|
|
10
|
+
|
|
11
|
+
Undefined
|
|
12
|
+
|
|
13
|
+
XYZ
|
|
14
|
+
|
|
15
|
+
ZXY
|
|
16
|
+
|
|
17
|
+
ZYX
|
|
18
|
+
"""
|
|
19
|
+
Undefined: typing.ClassVar[EulerAngle.AxisSequence] # value = <AxisSequence.Undefined: 0>
|
|
20
|
+
XYZ: typing.ClassVar[EulerAngle.AxisSequence] # value = <AxisSequence.XYZ: 1>
|
|
21
|
+
ZXY: typing.ClassVar[EulerAngle.AxisSequence] # value = <AxisSequence.ZXY: 2>
|
|
22
|
+
ZYX: typing.ClassVar[EulerAngle.AxisSequence] # value = <AxisSequence.ZYX: 3>
|
|
23
|
+
__members__: typing.ClassVar[dict[str, EulerAngle.AxisSequence]] # value = {'Undefined': <AxisSequence.Undefined: 0>, 'XYZ': <AxisSequence.XYZ: 1>, 'ZXY': <AxisSequence.ZXY: 2>, 'ZYX': <AxisSequence.ZYX: 3>}
|
|
24
|
+
def __eq__(self, other: typing.Any) -> bool:
|
|
25
|
+
...
|
|
26
|
+
def __getstate__(self) -> int:
|
|
27
|
+
...
|
|
28
|
+
def __hash__(self) -> int:
|
|
29
|
+
...
|
|
30
|
+
def __index__(self) -> int:
|
|
31
|
+
...
|
|
32
|
+
def __init__(self, value: int) -> None:
|
|
33
|
+
...
|
|
34
|
+
def __int__(self) -> int:
|
|
35
|
+
...
|
|
36
|
+
def __ne__(self, other: typing.Any) -> bool:
|
|
37
|
+
...
|
|
38
|
+
def __repr__(self) -> str:
|
|
39
|
+
...
|
|
40
|
+
def __setstate__(self, state: int) -> None:
|
|
41
|
+
...
|
|
42
|
+
def __str__(self) -> str:
|
|
43
|
+
...
|
|
44
|
+
@property
|
|
45
|
+
def name(self) -> str:
|
|
46
|
+
...
|
|
47
|
+
@property
|
|
48
|
+
def value(self) -> int:
|
|
49
|
+
...
|
|
50
|
+
__hash__: typing.ClassVar[None] = None
|
|
51
|
+
@staticmethod
|
|
52
|
+
def quaternion(quaternion: Quaternion, axis_sequence: typing.Any) -> EulerAngle:
|
|
53
|
+
"""
|
|
54
|
+
Create Euler angles from a quaternion with specified axis sequence.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
quaternion (Quaternion): The quaternion to convert.
|
|
58
|
+
axis_sequence (EulerAngle.AxisSequence): The desired axis sequence.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
EulerAngle: The equivalent Euler angles.
|
|
62
|
+
|
|
63
|
+
Example:
|
|
64
|
+
>>> quat = Quaternion.unit()
|
|
65
|
+
>>> euler = EulerAngle.quaternion(quat, EulerAngle.AxisSequence.XYZ)
|
|
66
|
+
"""
|
|
67
|
+
@staticmethod
|
|
68
|
+
def rotation_matrix(rotation_matrix: RotationMatrix, axis_sequence: typing.Any) -> EulerAngle:
|
|
69
|
+
...
|
|
70
|
+
@staticmethod
|
|
71
|
+
def rotation_vector(rotation_vector: RotationVector, axis_sequence: typing.Any) -> EulerAngle:
|
|
72
|
+
...
|
|
73
|
+
@staticmethod
|
|
74
|
+
def undefined() -> EulerAngle:
|
|
75
|
+
"""
|
|
76
|
+
Create an undefined Euler angle.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
EulerAngle: An undefined Euler angle object.
|
|
80
|
+
|
|
81
|
+
Example:
|
|
82
|
+
>>> undefined_euler = EulerAngle.undefined()
|
|
83
|
+
>>> undefined_euler.is_defined() # False
|
|
84
|
+
"""
|
|
85
|
+
@staticmethod
|
|
86
|
+
def unit() -> EulerAngle:
|
|
87
|
+
"""
|
|
88
|
+
Create a unit Euler angle (no rotation).
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
EulerAngle: A unit Euler angle representing no rotation.
|
|
92
|
+
|
|
93
|
+
Example:
|
|
94
|
+
>>> unit_euler = EulerAngle.unit()
|
|
95
|
+
>>> unit_euler.is_unitary() # True
|
|
96
|
+
"""
|
|
97
|
+
@staticmethod
|
|
98
|
+
def xyz(phi: typing.Any, theta: typing.Any, psi: typing.Any) -> EulerAngle:
|
|
99
|
+
"""
|
|
100
|
+
Create Euler angles with XYZ axis sequence.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
phi (Angle): The first rotation angle around X-axis.
|
|
104
|
+
theta (Angle): The second rotation angle around Y-axis.
|
|
105
|
+
psi (Angle): The third rotation angle around Z-axis.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
EulerAngle: An Euler angle with XYZ sequence.
|
|
109
|
+
|
|
110
|
+
Example:
|
|
111
|
+
>>> euler = EulerAngle.xyz(Angle.degrees(30.0), Angle.degrees(45.0), Angle.degrees(60.0))
|
|
112
|
+
"""
|
|
113
|
+
@staticmethod
|
|
114
|
+
def zxy(phi: typing.Any, theta: typing.Any, psi: typing.Any) -> EulerAngle:
|
|
115
|
+
"""
|
|
116
|
+
Create Euler angles with ZXY axis sequence.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
phi (Angle): The first rotation angle around Z-axis.
|
|
120
|
+
theta (Angle): The second rotation angle around X-axis.
|
|
121
|
+
psi (Angle): The third rotation angle around Y-axis.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
EulerAngle: An Euler angle with ZXY sequence.
|
|
125
|
+
|
|
126
|
+
Example:
|
|
127
|
+
>>> euler = EulerAngle.zxy(Angle.degrees(30.0), Angle.degrees(45.0), Angle.degrees(60.0))
|
|
128
|
+
"""
|
|
129
|
+
@staticmethod
|
|
130
|
+
def zyx(phi: typing.Any, theta: typing.Any, psi: typing.Any) -> EulerAngle:
|
|
131
|
+
"""
|
|
132
|
+
Create Euler angles with ZYX axis sequence.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
phi (Angle): The first rotation angle around Z-axis.
|
|
136
|
+
theta (Angle): The second rotation angle around Y-axis.
|
|
137
|
+
psi (Angle): The third rotation angle around X-axis.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
EulerAngle: An Euler angle with ZYX sequence.
|
|
141
|
+
|
|
142
|
+
Example:
|
|
143
|
+
>>> euler = EulerAngle.zyx(Angle.degrees(30.0), Angle.degrees(45.0), Angle.degrees(60.0))
|
|
144
|
+
"""
|
|
145
|
+
def __eq__(self, arg0: EulerAngle) -> bool:
|
|
146
|
+
...
|
|
147
|
+
@typing.overload
|
|
148
|
+
def __init__(self, phi: typing.Any, theta: typing.Any, psi: typing.Any, axis_sequence: typing.Any) -> None:
|
|
149
|
+
"""
|
|
150
|
+
Create Euler angles from three angle components and axis sequence.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
phi (Angle): The first rotation angle.
|
|
154
|
+
theta (Angle): The second rotation angle.
|
|
155
|
+
psi (Angle): The third rotation angle.
|
|
156
|
+
axis_sequence (EulerAngle.AxisSequence): The axis sequence (XYZ, ZXY, ZYX).
|
|
157
|
+
|
|
158
|
+
Example:
|
|
159
|
+
>>> phi = Angle.degrees(30.0)
|
|
160
|
+
>>> theta = Angle.degrees(45.0)
|
|
161
|
+
>>> psi = Angle.degrees(60.0)
|
|
162
|
+
>>> euler = EulerAngle(phi, theta, psi, EulerAngle.AxisSequence.XYZ)
|
|
163
|
+
"""
|
|
164
|
+
@typing.overload
|
|
165
|
+
def __init__(self, vector: numpy.ndarray[numpy.float64[3, 1]], angle_unit: typing.Any, axis_sequence: typing.Any) -> None:
|
|
166
|
+
"""
|
|
167
|
+
Create Euler angles from a 3D vector with specified angle unit and axis sequence.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
vector (np.array): Vector containing the three angle values.
|
|
171
|
+
angle_unit (Angle.Unit): The unit of the angles in the vector.
|
|
172
|
+
axis_sequence (EulerAngle.AxisSequence): The axis sequence.
|
|
173
|
+
|
|
174
|
+
Example:
|
|
175
|
+
>>> vector = np.array([30.0, 45.0, 60.0])
|
|
176
|
+
>>> euler = EulerAngle(vector, Angle.Unit.Degree, EulerAngle.AxisSequence.XYZ)
|
|
177
|
+
"""
|
|
178
|
+
def __ne__(self, arg0: EulerAngle) -> bool:
|
|
179
|
+
...
|
|
180
|
+
def __repr__(self) -> str:
|
|
181
|
+
...
|
|
182
|
+
def __str__(self) -> str:
|
|
183
|
+
...
|
|
184
|
+
def is_defined(self) -> bool:
|
|
185
|
+
"""
|
|
186
|
+
Check if the Euler angle is defined.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
bool: True if the Euler angle is defined, False otherwise.
|
|
190
|
+
|
|
191
|
+
Example:
|
|
192
|
+
>>> euler = EulerAngle(phi, theta, psi, EulerAngle.AxisSequence.XYZ)
|
|
193
|
+
>>> euler.is_defined() # True
|
|
194
|
+
"""
|
|
195
|
+
def is_near(self, euler_angle: EulerAngle, angular_tolerance: typing.Any) -> bool:
|
|
196
|
+
"""
|
|
197
|
+
Check if this Euler angle is near another Euler angle within tolerance.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
euler_angle (EulerAngle): The Euler angle to compare with.
|
|
201
|
+
angular_tolerance (Angle): The angular tolerance for comparison.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
bool: True if angles are within tolerance, False otherwise.
|
|
205
|
+
|
|
206
|
+
Example:
|
|
207
|
+
>>> euler1 = EulerAngle(phi1, theta1, psi1, sequence)
|
|
208
|
+
>>> euler2 = EulerAngle(phi2, theta2, psi2, sequence)
|
|
209
|
+
>>> euler1.is_near(euler2, Angle.degrees(1.0))
|
|
210
|
+
"""
|
|
211
|
+
def is_unitary(self) -> bool:
|
|
212
|
+
"""
|
|
213
|
+
Check if the Euler angle represents a unit rotation.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
bool: True if the Euler angle is unitary, False otherwise.
|
|
217
|
+
|
|
218
|
+
Example:
|
|
219
|
+
>>> euler = EulerAngle.unit()
|
|
220
|
+
>>> euler.is_unitary() # True
|
|
221
|
+
"""
|
|
222
|
+
@typing.overload
|
|
223
|
+
def to_string(self) -> ostk.core.type.String:
|
|
224
|
+
...
|
|
225
|
+
@typing.overload
|
|
226
|
+
def to_string(self, angle_unit: typing.Any) -> ostk.core.type.String:
|
|
227
|
+
...
|
|
228
|
+
def to_vector(self, angle_unit: typing.Any) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
229
|
+
"""
|
|
230
|
+
Convert the Euler angle to a 3D vector with specified unit.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
angle_unit (Angle.Unit): The unit for the output vector angles.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Vector3d: A vector containing [phi, theta, psi] in the specified unit.
|
|
237
|
+
|
|
238
|
+
Example:
|
|
239
|
+
>>> euler = EulerAngle(phi, theta, psi, EulerAngle.AxisSequence.XYZ)
|
|
240
|
+
>>> vector = euler.to_vector(Angle.Unit.Degree)
|
|
241
|
+
"""
|
|
242
|
+
@property
|
|
243
|
+
def axis_sequence(self) -> ...:
|
|
244
|
+
...
|
|
245
|
+
@property
|
|
246
|
+
def phi(self) -> ...:
|
|
247
|
+
...
|
|
248
|
+
@property
|
|
249
|
+
def psi(self) -> ...:
|
|
250
|
+
...
|
|
251
|
+
@property
|
|
252
|
+
def theta(self) -> ...:
|
|
253
|
+
...
|
|
254
|
+
class Quaternion:
|
|
255
|
+
class Format:
|
|
256
|
+
"""
|
|
257
|
+
Members:
|
|
258
|
+
|
|
259
|
+
XYZS
|
|
260
|
+
|
|
261
|
+
SXYZ
|
|
262
|
+
"""
|
|
263
|
+
SXYZ: typing.ClassVar[Quaternion.Format] # value = <Format.SXYZ: 1>
|
|
264
|
+
XYZS: typing.ClassVar[Quaternion.Format] # value = <Format.XYZS: 0>
|
|
265
|
+
__members__: typing.ClassVar[dict[str, Quaternion.Format]] # value = {'XYZS': <Format.XYZS: 0>, 'SXYZ': <Format.SXYZ: 1>}
|
|
266
|
+
def __eq__(self, other: typing.Any) -> bool:
|
|
267
|
+
...
|
|
268
|
+
def __getstate__(self) -> int:
|
|
269
|
+
...
|
|
270
|
+
def __hash__(self) -> int:
|
|
271
|
+
...
|
|
272
|
+
def __index__(self) -> int:
|
|
273
|
+
...
|
|
274
|
+
def __init__(self, value: int) -> None:
|
|
275
|
+
...
|
|
276
|
+
def __int__(self) -> int:
|
|
277
|
+
...
|
|
278
|
+
def __ne__(self, other: typing.Any) -> bool:
|
|
279
|
+
...
|
|
280
|
+
def __repr__(self) -> str:
|
|
281
|
+
...
|
|
282
|
+
def __setstate__(self, state: int) -> None:
|
|
283
|
+
...
|
|
284
|
+
def __str__(self) -> str:
|
|
285
|
+
...
|
|
286
|
+
@property
|
|
287
|
+
def name(self) -> str:
|
|
288
|
+
...
|
|
289
|
+
@property
|
|
290
|
+
def value(self) -> int:
|
|
291
|
+
...
|
|
292
|
+
__hash__: typing.ClassVar[None] = None
|
|
293
|
+
@staticmethod
|
|
294
|
+
def euler_angle(euler_angle: typing.Any) -> Quaternion:
|
|
295
|
+
"""
|
|
296
|
+
Create a quaternion from Euler angles.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
euler_angle (EulerAngle): The Euler angles.
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
Quaternion: The quaternion representing the rotation.
|
|
303
|
+
|
|
304
|
+
Example:
|
|
305
|
+
>>> ea = EulerAngle.zyx(Angle.radians(0.1), Angle.radians(0.2), Angle.radians(0.3))
|
|
306
|
+
>>> q = Quaternion.euler_angle(ea)
|
|
307
|
+
"""
|
|
308
|
+
@staticmethod
|
|
309
|
+
def lerp(first_quaternion: Quaternion, second_quaternion: Quaternion, ratio: ostk.core.type.Real) -> Quaternion:
|
|
310
|
+
"""
|
|
311
|
+
Linear interpolation between two quaternions.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
first_quaternion (Quaternion): The first quaternion.
|
|
315
|
+
second_quaternion (Quaternion): The second quaternion.
|
|
316
|
+
ratio (float): The interpolation ratio (0.0 to 1.0).
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Quaternion: The interpolated quaternion.
|
|
320
|
+
|
|
321
|
+
Example:
|
|
322
|
+
>>> q1 = Quaternion.unit()
|
|
323
|
+
>>> q2 = Quaternion(0.1, 0.2, 0.3, 0.9, Quaternion.Format.XYZS)
|
|
324
|
+
>>> q_interp = Quaternion.lerp(q1, q2, 0.5)
|
|
325
|
+
"""
|
|
326
|
+
@staticmethod
|
|
327
|
+
def nlerp(first_quaternion: Quaternion, second_quaternion: Quaternion, ratio: ostk.core.type.Real) -> Quaternion:
|
|
328
|
+
"""
|
|
329
|
+
Normalized linear interpolation between two quaternions.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
first_quaternion (Quaternion): The first quaternion.
|
|
333
|
+
second_quaternion (Quaternion): The second quaternion.
|
|
334
|
+
ratio (float): The interpolation ratio (0.0 to 1.0).
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
Quaternion: The normalized interpolated quaternion.
|
|
338
|
+
|
|
339
|
+
Example:
|
|
340
|
+
>>> q1 = Quaternion.unit()
|
|
341
|
+
>>> q2 = Quaternion(0.1, 0.2, 0.3, 0.9, Quaternion.Format.XYZS)
|
|
342
|
+
>>> q_interp = Quaternion.nlerp(q1, q2, 0.5)
|
|
343
|
+
"""
|
|
344
|
+
@staticmethod
|
|
345
|
+
def parse(string: ostk.core.type.String, format: typing.Any) -> Quaternion:
|
|
346
|
+
"""
|
|
347
|
+
Parse a quaternion from a string.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
string (str): The string representation of the quaternion.
|
|
351
|
+
format (Quaternion.Format): The format of the quaternion.
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
Quaternion: The parsed quaternion.
|
|
355
|
+
|
|
356
|
+
Example:
|
|
357
|
+
>>> q = Quaternion.parse("[0.0, 0.0, 0.0, 1.0]", Quaternion.Format.XYZS)
|
|
358
|
+
"""
|
|
359
|
+
@staticmethod
|
|
360
|
+
def rotation_matrix(rotation_matrix: typing.Any) -> Quaternion:
|
|
361
|
+
"""
|
|
362
|
+
Create a quaternion from a rotation matrix.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
rotation_matrix (RotationMatrix): The rotation matrix.
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Quaternion: The quaternion representing the rotation.
|
|
369
|
+
|
|
370
|
+
Example:
|
|
371
|
+
>>> rm = RotationMatrix.identity()
|
|
372
|
+
>>> q = Quaternion.rotation_matrix(rm)
|
|
373
|
+
"""
|
|
374
|
+
@staticmethod
|
|
375
|
+
def rotation_vector(rotation_vector: typing.Any) -> Quaternion:
|
|
376
|
+
"""
|
|
377
|
+
Create a quaternion from a rotation vector.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
rotation_vector (RotationVector): The rotation vector.
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
Quaternion: The quaternion representing the rotation.
|
|
384
|
+
|
|
385
|
+
Example:
|
|
386
|
+
>>> rv = RotationVector([0.1, 0.2, 0.3], Angle.radians(1.0))
|
|
387
|
+
>>> q = Quaternion.rotation_vector(rv)
|
|
388
|
+
"""
|
|
389
|
+
@staticmethod
|
|
390
|
+
def shortest_rotation(first_vector: numpy.ndarray[numpy.float64[3, 1]], second_vector: numpy.ndarray[numpy.float64[3, 1]]) -> Quaternion:
|
|
391
|
+
"""
|
|
392
|
+
Create a quaternion representing the shortest rotation between two vectors.
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
first_vector (np.array): The first vector.
|
|
396
|
+
second_vector (np.array): The second vector.
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
Quaternion: The quaternion representing the shortest rotation.
|
|
400
|
+
|
|
401
|
+
Example:
|
|
402
|
+
>>> v1 = np.array([1.0, 0.0, 0.0])
|
|
403
|
+
>>> v2 = np.array([0.0, 1.0, 0.0])
|
|
404
|
+
>>> q = Quaternion.shortest_rotation(v1, v2)
|
|
405
|
+
"""
|
|
406
|
+
@staticmethod
|
|
407
|
+
def slerp(first_quaternion: Quaternion, second_quaternion: Quaternion, ratio: ostk.core.type.Real) -> Quaternion:
|
|
408
|
+
"""
|
|
409
|
+
Spherical linear interpolation between two quaternions.
|
|
410
|
+
|
|
411
|
+
Args:
|
|
412
|
+
first_quaternion (Quaternion): The first quaternion.
|
|
413
|
+
second_quaternion (Quaternion): The second quaternion.
|
|
414
|
+
ratio (float): The interpolation ratio (0.0 to 1.0).
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
Quaternion: The spherically interpolated quaternion.
|
|
418
|
+
|
|
419
|
+
Example:
|
|
420
|
+
>>> q1 = Quaternion.unit()
|
|
421
|
+
>>> q2 = Quaternion(0.1, 0.2, 0.3, 0.9, Quaternion.Format.XYZS)
|
|
422
|
+
>>> q_interp = Quaternion.slerp(q1, q2, 0.5)
|
|
423
|
+
"""
|
|
424
|
+
@staticmethod
|
|
425
|
+
def undefined() -> Quaternion:
|
|
426
|
+
"""
|
|
427
|
+
Create an undefined quaternion.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
Quaternion: An undefined quaternion.
|
|
431
|
+
|
|
432
|
+
Example:
|
|
433
|
+
>>> q = Quaternion.undefined()
|
|
434
|
+
>>> q.is_defined() # False
|
|
435
|
+
"""
|
|
436
|
+
@staticmethod
|
|
437
|
+
def unit() -> Quaternion:
|
|
438
|
+
"""
|
|
439
|
+
Create a unit quaternion (identity rotation).
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
Quaternion: A unit quaternion.
|
|
443
|
+
|
|
444
|
+
Example:
|
|
445
|
+
>>> q = Quaternion.unit()
|
|
446
|
+
>>> q.is_unitary() # True
|
|
447
|
+
"""
|
|
448
|
+
@staticmethod
|
|
449
|
+
def xyzs(first_component: ostk.core.type.Real, second_component: ostk.core.type.Real, third_component: ostk.core.type.Real, fourth_component: ostk.core.type.Real) -> Quaternion:
|
|
450
|
+
"""
|
|
451
|
+
Create a quaternion in XYZS format.
|
|
452
|
+
|
|
453
|
+
Args:
|
|
454
|
+
first_component (float): The x component.
|
|
455
|
+
second_component (float): The y component.
|
|
456
|
+
third_component (float): The z component.
|
|
457
|
+
fourth_component (float): The s component.
|
|
458
|
+
|
|
459
|
+
Returns:
|
|
460
|
+
Quaternion: The quaternion in XYZS format.
|
|
461
|
+
|
|
462
|
+
Example:
|
|
463
|
+
>>> q = Quaternion.xyzs(0.0, 0.0, 0.0, 1.0)
|
|
464
|
+
"""
|
|
465
|
+
def __add__(self, arg0: Quaternion) -> Quaternion:
|
|
466
|
+
...
|
|
467
|
+
def __eq__(self, arg0: Quaternion) -> bool:
|
|
468
|
+
...
|
|
469
|
+
def __iadd__(self, arg0: Quaternion) -> Quaternion:
|
|
470
|
+
...
|
|
471
|
+
@typing.overload
|
|
472
|
+
def __init__(self, first_component: ostk.core.type.Real, second_component: ostk.core.type.Real, third_component: ostk.core.type.Real, fourth_component: ostk.core.type.Real, format: typing.Any) -> None:
|
|
473
|
+
"""
|
|
474
|
+
Create a quaternion from four components and format.
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
first_component (float): First component (x or w depending on format).
|
|
478
|
+
second_component (float): Second component (y or x depending on format).
|
|
479
|
+
third_component (float): Third component (z or y depending on format).
|
|
480
|
+
fourth_component (float): Fourth component (w or z depending on format).
|
|
481
|
+
format (Quaternion.Format): The quaternion format (XYZS or SXYZ).
|
|
482
|
+
|
|
483
|
+
Example:
|
|
484
|
+
>>> q = Quaternion(0.0, 0.0, 0.0, 1.0, Quaternion.Format.XYZS)
|
|
485
|
+
>>> q = Quaternion(1.0, 0.0, 0.0, 0.0, Quaternion.Format.SXYZ)
|
|
486
|
+
"""
|
|
487
|
+
@typing.overload
|
|
488
|
+
def __init__(self, vector: numpy.ndarray[numpy.float64[4, 1]], format: typing.Any) -> None:
|
|
489
|
+
"""
|
|
490
|
+
Create a quaternion from a 4D vector and format.
|
|
491
|
+
|
|
492
|
+
Args:
|
|
493
|
+
vector (np.array): The 4D vector containing quaternion components.
|
|
494
|
+
format (Quaternion.Format): The quaternion format.
|
|
495
|
+
|
|
496
|
+
Example:
|
|
497
|
+
>>> vector = np.array([0.0, 0.0, 0.0, 1.0])
|
|
498
|
+
>>> q = Quaternion(vector, Quaternion.Format.XYZS)
|
|
499
|
+
"""
|
|
500
|
+
@typing.overload
|
|
501
|
+
def __init__(self, vector_part: numpy.ndarray[numpy.float64[3, 1]], scalar_part: ostk.core.type.Real) -> None:
|
|
502
|
+
"""
|
|
503
|
+
Create a quaternion from vector and scalar parts.
|
|
504
|
+
|
|
505
|
+
Args:
|
|
506
|
+
vector_part (np.array): The vector part (x, y, z components).
|
|
507
|
+
scalar_part (float): The scalar part (s component).
|
|
508
|
+
|
|
509
|
+
Example:
|
|
510
|
+
>>> vector_part = np.array([0.0, 0.0, 0.0])
|
|
511
|
+
>>> scalar_part = 1.0
|
|
512
|
+
>>> q = Quaternion(vector_part, scalar_part)
|
|
513
|
+
"""
|
|
514
|
+
@typing.overload
|
|
515
|
+
def __init__(self, quaternion: Quaternion) -> None:
|
|
516
|
+
"""
|
|
517
|
+
Create a quaternion by copying another quaternion.
|
|
518
|
+
|
|
519
|
+
Args:
|
|
520
|
+
quaternion (Quaternion): The quaternion to copy.
|
|
521
|
+
|
|
522
|
+
Example:
|
|
523
|
+
>>> original = Quaternion(0.0, 0.0, 0.0, 1.0, Quaternion.Format.XYZS)
|
|
524
|
+
>>> copy = Quaternion(original)
|
|
525
|
+
"""
|
|
526
|
+
@typing.overload
|
|
527
|
+
def __mul__(self, arg0: Quaternion) -> Quaternion:
|
|
528
|
+
...
|
|
529
|
+
@typing.overload
|
|
530
|
+
def __mul__(self, arg0: numpy.ndarray[numpy.float64[3, 1]]) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
531
|
+
...
|
|
532
|
+
@typing.overload
|
|
533
|
+
def __mul__(self, arg0: float) -> Quaternion:
|
|
534
|
+
...
|
|
535
|
+
def __ne__(self, arg0: Quaternion) -> bool:
|
|
536
|
+
...
|
|
537
|
+
def __pow__(self, arg0: float) -> Quaternion:
|
|
538
|
+
...
|
|
539
|
+
def __repr__(self) -> str:
|
|
540
|
+
...
|
|
541
|
+
def __rmul__(self, arg0: float) -> Quaternion:
|
|
542
|
+
...
|
|
543
|
+
def __str__(self) -> str:
|
|
544
|
+
...
|
|
545
|
+
def __truediv__(self, arg0: Quaternion) -> Quaternion:
|
|
546
|
+
...
|
|
547
|
+
def angular_difference_with(self, quaternion: Quaternion) -> ...:
|
|
548
|
+
"""
|
|
549
|
+
Compute the angular difference with another quaternion.
|
|
550
|
+
|
|
551
|
+
Args:
|
|
552
|
+
quaternion (Quaternion): The quaternion to compare with.
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
Angle: The angular difference.
|
|
556
|
+
|
|
557
|
+
Example:
|
|
558
|
+
>>> q1 = Quaternion.unit()
|
|
559
|
+
>>> q2 = Quaternion(0.1, 0.2, 0.3, 0.9, Quaternion.Format.XYZS)
|
|
560
|
+
>>> angle = q1.angular_difference_with(q2)
|
|
561
|
+
"""
|
|
562
|
+
def conjugate(self) -> None:
|
|
563
|
+
"""
|
|
564
|
+
Conjugate the quaternion in-place.
|
|
565
|
+
|
|
566
|
+
Example:
|
|
567
|
+
>>> q = Quaternion(1.0, 2.0, 3.0, 4.0, Quaternion.Format.XYZS)
|
|
568
|
+
>>> q.conjugate()
|
|
569
|
+
"""
|
|
570
|
+
def cross_multiply(self, quaternion: Quaternion) -> Quaternion:
|
|
571
|
+
"""
|
|
572
|
+
Perform cross multiplication with another quaternion.
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
quaternion (Quaternion): The quaternion to multiply with.
|
|
576
|
+
|
|
577
|
+
Returns:
|
|
578
|
+
Quaternion: The result of cross multiplication.
|
|
579
|
+
|
|
580
|
+
Example:
|
|
581
|
+
>>> q1 = Quaternion.unit()
|
|
582
|
+
>>> q2 = Quaternion(0.1, 0.2, 0.3, 0.9, Quaternion.Format.XYZS)
|
|
583
|
+
>>> result = q1.cross_multiply(q2)
|
|
584
|
+
"""
|
|
585
|
+
def dot_multiply(self, quaternion: Quaternion) -> Quaternion:
|
|
586
|
+
"""
|
|
587
|
+
Perform dot multiplication with another quaternion.
|
|
588
|
+
|
|
589
|
+
Args:
|
|
590
|
+
quaternion (Quaternion): The quaternion to multiply with.
|
|
591
|
+
|
|
592
|
+
Returns:
|
|
593
|
+
Quaternion: The result of dot multiplication.
|
|
594
|
+
|
|
595
|
+
Example:
|
|
596
|
+
>>> q1 = Quaternion.unit()
|
|
597
|
+
>>> q2 = Quaternion(0.1, 0.2, 0.3, 0.9, Quaternion.Format.XYZS)
|
|
598
|
+
>>> result = q1.dot_multiply(q2)
|
|
599
|
+
"""
|
|
600
|
+
def dot_product(self, quaternion: Quaternion) -> ostk.core.type.Real:
|
|
601
|
+
"""
|
|
602
|
+
Compute the dot product with another quaternion.
|
|
603
|
+
|
|
604
|
+
Args:
|
|
605
|
+
quaternion (Quaternion): The quaternion to compute dot product with.
|
|
606
|
+
|
|
607
|
+
Returns:
|
|
608
|
+
float: The dot product result.
|
|
609
|
+
|
|
610
|
+
Example:
|
|
611
|
+
>>> q1 = Quaternion.unit()
|
|
612
|
+
>>> q2 = Quaternion(0.1, 0.2, 0.3, 0.9, Quaternion.Format.XYZS)
|
|
613
|
+
>>> dot = q1.dot_product(q2)
|
|
614
|
+
"""
|
|
615
|
+
def exp(self) -> Quaternion:
|
|
616
|
+
"""
|
|
617
|
+
Compute the exponential of the quaternion.
|
|
618
|
+
|
|
619
|
+
Returns:
|
|
620
|
+
Quaternion: The exponential of the quaternion.
|
|
621
|
+
|
|
622
|
+
Example:
|
|
623
|
+
>>> q = Quaternion(0.1, 0.2, 0.3, 0.0, Quaternion.Format.XYZS)
|
|
624
|
+
>>> exp_q = q.exp()
|
|
625
|
+
"""
|
|
626
|
+
def get_scalar_part(self) -> ostk.core.type.Real:
|
|
627
|
+
"""
|
|
628
|
+
Get the scalar part of the quaternion.
|
|
629
|
+
|
|
630
|
+
Returns:
|
|
631
|
+
float: The scalar part.
|
|
632
|
+
|
|
633
|
+
Example:
|
|
634
|
+
>>> q = Quaternion(0.0, 0.0, 0.0, 1.0, Quaternion.Format.XYZS)
|
|
635
|
+
>>> q.get_scalar_part() # 1.0
|
|
636
|
+
"""
|
|
637
|
+
def get_vector_part(self) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
638
|
+
"""
|
|
639
|
+
Get the vector part of the quaternion.
|
|
640
|
+
|
|
641
|
+
Returns:
|
|
642
|
+
Vector3d: The vector part.
|
|
643
|
+
"""
|
|
644
|
+
def inverse(self) -> None:
|
|
645
|
+
"""
|
|
646
|
+
Invert the quaternion in-place.
|
|
647
|
+
|
|
648
|
+
Example:
|
|
649
|
+
>>> q = Quaternion.unit()
|
|
650
|
+
>>> q.inverse()
|
|
651
|
+
"""
|
|
652
|
+
def is_defined(self) -> bool:
|
|
653
|
+
"""
|
|
654
|
+
Check if the quaternion is defined.
|
|
655
|
+
|
|
656
|
+
Returns:
|
|
657
|
+
bool: True if the quaternion is defined, False otherwise.
|
|
658
|
+
"""
|
|
659
|
+
def is_near(self, quaternion: Quaternion, angular_tolerance: typing.Any) -> bool:
|
|
660
|
+
"""
|
|
661
|
+
Check if the quaternion is near another quaternion.
|
|
662
|
+
|
|
663
|
+
Returns:
|
|
664
|
+
bool: True if the quaternion is near another quaternion, False otherwise.
|
|
665
|
+
"""
|
|
666
|
+
def is_unitary(self, norm_tolerance: ostk.core.type.Real = ...) -> bool:
|
|
667
|
+
"""
|
|
668
|
+
Check if the quaternion is unitary.
|
|
669
|
+
|
|
670
|
+
Returns:
|
|
671
|
+
bool: True if the quaternion is unitary, False otherwise.
|
|
672
|
+
"""
|
|
673
|
+
def log(self) -> Quaternion:
|
|
674
|
+
"""
|
|
675
|
+
Compute the natural logarithm of the quaternion.
|
|
676
|
+
|
|
677
|
+
Returns:
|
|
678
|
+
Quaternion: The natural logarithm of the quaternion.
|
|
679
|
+
|
|
680
|
+
Example:
|
|
681
|
+
>>> q = Quaternion.unit()
|
|
682
|
+
>>> log_q = q.log()
|
|
683
|
+
"""
|
|
684
|
+
def norm(self) -> ostk.core.type.Real:
|
|
685
|
+
"""
|
|
686
|
+
Compute the norm (magnitude) of the quaternion.
|
|
687
|
+
|
|
688
|
+
Returns:
|
|
689
|
+
float: The norm of the quaternion.
|
|
690
|
+
|
|
691
|
+
Example:
|
|
692
|
+
>>> q = Quaternion(1.0, 2.0, 3.0, 4.0, Quaternion.Format.XYZS)
|
|
693
|
+
>>> magnitude = q.norm()
|
|
694
|
+
"""
|
|
695
|
+
def normalize(self) -> None:
|
|
696
|
+
"""
|
|
697
|
+
Normalize the quaternion in-place.
|
|
698
|
+
|
|
699
|
+
Example:
|
|
700
|
+
>>> q = Quaternion(1.0, 1.0, 1.0, 1.0, Quaternion.Format.XYZS)
|
|
701
|
+
>>> q.normalize()
|
|
702
|
+
"""
|
|
703
|
+
def pow(self, value: ostk.core.type.Real) -> Quaternion:
|
|
704
|
+
"""
|
|
705
|
+
Raise the quaternion to a power.
|
|
706
|
+
|
|
707
|
+
Args:
|
|
708
|
+
value (float): The exponent.
|
|
709
|
+
|
|
710
|
+
Returns:
|
|
711
|
+
Quaternion: The quaternion raised to the power.
|
|
712
|
+
|
|
713
|
+
Example:
|
|
714
|
+
>>> q = Quaternion.unit()
|
|
715
|
+
>>> powered = q.pow(2.0)
|
|
716
|
+
"""
|
|
717
|
+
def rectify(self) -> None:
|
|
718
|
+
"""
|
|
719
|
+
Rectify the quaternion in-place (ensure positive scalar part).
|
|
720
|
+
|
|
721
|
+
Example:
|
|
722
|
+
>>> q = Quaternion(0.0, 0.0, 0.0, -1.0, Quaternion.Format.XYZS)
|
|
723
|
+
>>> q.rectify()
|
|
724
|
+
"""
|
|
725
|
+
def rotate_vector(self, vector: numpy.ndarray[numpy.float64[3, 1]], norm_tolerance: ostk.core.type.Real = ...) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
726
|
+
"""
|
|
727
|
+
Rotate a vector using this quaternion.
|
|
728
|
+
|
|
729
|
+
Args:
|
|
730
|
+
vector (np.array): The 3D vector to rotate.
|
|
731
|
+
norm_tolerance (float, optional): Tolerance for normalization check.
|
|
732
|
+
|
|
733
|
+
Returns:
|
|
734
|
+
Vector3d: The rotated vector.
|
|
735
|
+
|
|
736
|
+
Example:
|
|
737
|
+
>>> q = Quaternion.unit()
|
|
738
|
+
>>> vector = np.array([1.0, 0.0, 0.0])
|
|
739
|
+
>>> rotated = q.rotate_vector(vector)
|
|
740
|
+
"""
|
|
741
|
+
def s(self) -> ostk.core.type.Real:
|
|
742
|
+
"""
|
|
743
|
+
Get the s-coordinate of the quaternion.
|
|
744
|
+
|
|
745
|
+
Returns:
|
|
746
|
+
float: The s-coordinate.
|
|
747
|
+
"""
|
|
748
|
+
def to_conjugate(self) -> Quaternion:
|
|
749
|
+
"""
|
|
750
|
+
Get the conjugate of the quaternion.
|
|
751
|
+
|
|
752
|
+
Returns:
|
|
753
|
+
Quaternion: The conjugate quaternion.
|
|
754
|
+
|
|
755
|
+
Example:
|
|
756
|
+
>>> q = Quaternion(1.0, 2.0, 3.0, 4.0, Quaternion.Format.XYZS)
|
|
757
|
+
>>> conjugate = q.to_conjugate()
|
|
758
|
+
"""
|
|
759
|
+
def to_inverse(self) -> Quaternion:
|
|
760
|
+
"""
|
|
761
|
+
Get the inverse of the quaternion.
|
|
762
|
+
|
|
763
|
+
Returns:
|
|
764
|
+
Quaternion: The inverse quaternion.
|
|
765
|
+
|
|
766
|
+
Example:
|
|
767
|
+
>>> q = Quaternion.unit()
|
|
768
|
+
>>> inverse = q.to_inverse()
|
|
769
|
+
"""
|
|
770
|
+
def to_normalized(self) -> Quaternion:
|
|
771
|
+
"""
|
|
772
|
+
Get a normalized copy of the quaternion.
|
|
773
|
+
|
|
774
|
+
Returns:
|
|
775
|
+
Quaternion: The normalized quaternion.
|
|
776
|
+
|
|
777
|
+
Example:
|
|
778
|
+
>>> q = Quaternion(1.0, 1.0, 1.0, 1.0, Quaternion.Format.XYZS)
|
|
779
|
+
>>> normalized = q.to_normalized()
|
|
780
|
+
"""
|
|
781
|
+
def to_rectify(self) -> Quaternion:
|
|
782
|
+
"""
|
|
783
|
+
Get a rectified copy of the quaternion (with positive scalar part).
|
|
784
|
+
|
|
785
|
+
Returns:
|
|
786
|
+
Quaternion: The rectified quaternion.
|
|
787
|
+
|
|
788
|
+
Example:
|
|
789
|
+
>>> q = Quaternion(0.0, 0.0, 0.0, -1.0, Quaternion.Format.XYZS)
|
|
790
|
+
>>> rectified = q.to_rectify()
|
|
791
|
+
"""
|
|
792
|
+
@typing.overload
|
|
793
|
+
def to_string(self) -> ostk.core.type.String:
|
|
794
|
+
"""
|
|
795
|
+
Convert the quaternion to string representation.
|
|
796
|
+
|
|
797
|
+
Returns:
|
|
798
|
+
str: String representation of the quaternion.
|
|
799
|
+
|
|
800
|
+
Example:
|
|
801
|
+
>>> q = Quaternion.unit()
|
|
802
|
+
>>> q.to_string()
|
|
803
|
+
"""
|
|
804
|
+
@typing.overload
|
|
805
|
+
def to_string(self, format: typing.Any) -> ostk.core.type.String:
|
|
806
|
+
"""
|
|
807
|
+
Convert the quaternion to string representation with specified format.
|
|
808
|
+
|
|
809
|
+
Args:
|
|
810
|
+
format (Quaternion.Format): The format for string representation.
|
|
811
|
+
|
|
812
|
+
Returns:
|
|
813
|
+
str: String representation of the quaternion.
|
|
814
|
+
|
|
815
|
+
Example:
|
|
816
|
+
>>> q = Quaternion.unit()
|
|
817
|
+
>>> q.to_string(Quaternion.Format.SXYZ)
|
|
818
|
+
"""
|
|
819
|
+
def to_vector(self, format: typing.Any) -> numpy.ndarray[numpy.float64[4, 1]]:
|
|
820
|
+
"""
|
|
821
|
+
Convert the quaternion to a 4D vector.
|
|
822
|
+
|
|
823
|
+
Args:
|
|
824
|
+
format (Quaternion.Format): The format for the vector components.
|
|
825
|
+
|
|
826
|
+
Returns:
|
|
827
|
+
Vector4d: The quaternion as a 4D vector.
|
|
828
|
+
|
|
829
|
+
Example:
|
|
830
|
+
>>> q = Quaternion.unit()
|
|
831
|
+
>>> vector = q.to_vector(Quaternion.Format.XYZS)
|
|
832
|
+
"""
|
|
833
|
+
def x(self) -> ostk.core.type.Real:
|
|
834
|
+
"""
|
|
835
|
+
Get the x-coordinate of the quaternion.
|
|
836
|
+
|
|
837
|
+
Returns:
|
|
838
|
+
float: The x-coordinate.
|
|
839
|
+
"""
|
|
840
|
+
def y(self) -> ostk.core.type.Real:
|
|
841
|
+
"""
|
|
842
|
+
Get the y-coordinate of the quaternion.
|
|
843
|
+
|
|
844
|
+
Returns:
|
|
845
|
+
float: The y-coordinate.
|
|
846
|
+
"""
|
|
847
|
+
def z(self) -> ostk.core.type.Real:
|
|
848
|
+
"""
|
|
849
|
+
Get the z-coordinate of the quaternion.
|
|
850
|
+
|
|
851
|
+
Returns:
|
|
852
|
+
float: The z-coordinate.
|
|
853
|
+
"""
|
|
854
|
+
class RotationMatrix:
|
|
855
|
+
__hash__: typing.ClassVar[None] = None
|
|
856
|
+
@staticmethod
|
|
857
|
+
def columns(first_column: numpy.ndarray[numpy.float64[3, 1]], second_column: numpy.ndarray[numpy.float64[3, 1]], third_column: numpy.ndarray[numpy.float64[3, 1]]) -> RotationMatrix:
|
|
858
|
+
"""
|
|
859
|
+
Create a rotation matrix from column vectors.
|
|
860
|
+
|
|
861
|
+
Args:
|
|
862
|
+
first_column (Vector3d): The first column of the rotation matrix.
|
|
863
|
+
second_column (Vector3d): The second column of the rotation matrix.
|
|
864
|
+
third_column (Vector3d): The third column of the rotation matrix.
|
|
865
|
+
|
|
866
|
+
Returns:
|
|
867
|
+
RotationMatrix: A rotation matrix from column vectors.
|
|
868
|
+
|
|
869
|
+
Example:
|
|
870
|
+
>>> rot_matrix = RotationMatrix.columns(Vector3d(1.0, 0.0, 0.0), Vector3d(0.0, 1.0, 0.0), Vector3d(0.0, 0.0, 1.0))
|
|
871
|
+
"""
|
|
872
|
+
@staticmethod
|
|
873
|
+
def euler_angle(euler_angle: typing.Any) -> RotationMatrix:
|
|
874
|
+
"""
|
|
875
|
+
Create a rotation matrix from Euler angles.
|
|
876
|
+
|
|
877
|
+
Args:
|
|
878
|
+
euler_angle (EulerAngle): The Euler angles to convert.
|
|
879
|
+
|
|
880
|
+
Returns:
|
|
881
|
+
RotationMatrix: The equivalent rotation matrix.
|
|
882
|
+
|
|
883
|
+
Example:
|
|
884
|
+
>>> euler = EulerAngle.unit()
|
|
885
|
+
>>> rot_matrix = RotationMatrix.euler_angle(euler)
|
|
886
|
+
"""
|
|
887
|
+
@staticmethod
|
|
888
|
+
def quaternion(quaternion: Quaternion) -> RotationMatrix:
|
|
889
|
+
"""
|
|
890
|
+
Create a rotation matrix from a quaternion.
|
|
891
|
+
|
|
892
|
+
Args:
|
|
893
|
+
quaternion (Quaternion): The quaternion to convert.
|
|
894
|
+
|
|
895
|
+
Returns:
|
|
896
|
+
RotationMatrix: The equivalent rotation matrix.
|
|
897
|
+
|
|
898
|
+
Example:
|
|
899
|
+
>>> quat = Quaternion.unit()
|
|
900
|
+
>>> rot_matrix = RotationMatrix.quaternion(quat)
|
|
901
|
+
"""
|
|
902
|
+
@staticmethod
|
|
903
|
+
def rotation_vector(rotation_vector: RotationVector) -> RotationMatrix:
|
|
904
|
+
"""
|
|
905
|
+
Create a rotation matrix from a rotation vector.
|
|
906
|
+
|
|
907
|
+
Args:
|
|
908
|
+
rotation_vector (RotationVector): The rotation vector to convert.
|
|
909
|
+
|
|
910
|
+
Returns:
|
|
911
|
+
RotationMatrix: The equivalent rotation matrix.
|
|
912
|
+
|
|
913
|
+
Example:
|
|
914
|
+
>>> rot_vector = RotationVector.unit()
|
|
915
|
+
>>> rot_matrix = RotationMatrix.rotation_vector(rot_vector)
|
|
916
|
+
"""
|
|
917
|
+
@staticmethod
|
|
918
|
+
def rows(first_row: numpy.ndarray[numpy.float64[3, 1]], second_row: numpy.ndarray[numpy.float64[3, 1]], third_row: numpy.ndarray[numpy.float64[3, 1]]) -> RotationMatrix:
|
|
919
|
+
"""
|
|
920
|
+
Create a rotation matrix from row vectors.
|
|
921
|
+
|
|
922
|
+
Args:
|
|
923
|
+
first_row (Vector3d): The first row of the rotation matrix.
|
|
924
|
+
second_row (Vector3d): The second row of the rotation matrix.
|
|
925
|
+
third_row (Vector3d): The third row of the rotation matrix.
|
|
926
|
+
|
|
927
|
+
Returns:
|
|
928
|
+
RotationMatrix: A rotation matrix from row vectors.
|
|
929
|
+
|
|
930
|
+
Example:
|
|
931
|
+
>>> rot_matrix = RotationMatrix.rows(Vector3d(1.0, 0.0, 0.0), Vector3d(0.0, 1.0, 0.0), Vector3d(0.0, 0.0, 1.0))
|
|
932
|
+
"""
|
|
933
|
+
@staticmethod
|
|
934
|
+
def rx(rotation_angle: typing.Any) -> RotationMatrix:
|
|
935
|
+
"""
|
|
936
|
+
Create a rotation matrix for rotation around the X-axis.
|
|
937
|
+
|
|
938
|
+
Args:
|
|
939
|
+
rotation_angle (Angle): The angle of rotation around X-axis.
|
|
940
|
+
|
|
941
|
+
Returns:
|
|
942
|
+
RotationMatrix: A rotation matrix for X-axis rotation.
|
|
943
|
+
|
|
944
|
+
Example:
|
|
945
|
+
>>> rot_x = RotationMatrix.rx(Angle.degrees(90.0))
|
|
946
|
+
"""
|
|
947
|
+
@staticmethod
|
|
948
|
+
def ry(rotation_angle: typing.Any) -> RotationMatrix:
|
|
949
|
+
"""
|
|
950
|
+
Create a rotation matrix for rotation around the Y-axis.
|
|
951
|
+
|
|
952
|
+
Args:
|
|
953
|
+
rotation_angle (Angle): The angle of rotation around Y-axis.
|
|
954
|
+
|
|
955
|
+
Returns:
|
|
956
|
+
RotationMatrix: A rotation matrix for Y-axis rotation.
|
|
957
|
+
|
|
958
|
+
Example:
|
|
959
|
+
>>> rot_y = RotationMatrix.ry(Angle.degrees(90.0))
|
|
960
|
+
"""
|
|
961
|
+
@staticmethod
|
|
962
|
+
def rz(rotation_angle: typing.Any) -> RotationMatrix:
|
|
963
|
+
"""
|
|
964
|
+
Create a rotation matrix for rotation around the Z-axis.
|
|
965
|
+
|
|
966
|
+
Args:
|
|
967
|
+
rotation_angle (Angle): The angle of rotation around Z-axis.
|
|
968
|
+
|
|
969
|
+
Returns:
|
|
970
|
+
RotationMatrix: A rotation matrix for Z-axis rotation.
|
|
971
|
+
|
|
972
|
+
Example:
|
|
973
|
+
>>> rot_z = RotationMatrix.rz(Angle.degrees(90.0))
|
|
974
|
+
"""
|
|
975
|
+
@staticmethod
|
|
976
|
+
def undefined() -> RotationMatrix:
|
|
977
|
+
"""
|
|
978
|
+
Create an undefined rotation matrix.
|
|
979
|
+
|
|
980
|
+
Returns:
|
|
981
|
+
RotationMatrix: An undefined rotation matrix.
|
|
982
|
+
|
|
983
|
+
Example:
|
|
984
|
+
>>> undefined_matrix = RotationMatrix.undefined()
|
|
985
|
+
>>> undefined_matrix.is_defined() # False
|
|
986
|
+
"""
|
|
987
|
+
@staticmethod
|
|
988
|
+
def unit() -> RotationMatrix:
|
|
989
|
+
"""
|
|
990
|
+
Create a unit rotation matrix (identity matrix).
|
|
991
|
+
|
|
992
|
+
Returns:
|
|
993
|
+
RotationMatrix: The 3x3 identity rotation matrix.
|
|
994
|
+
|
|
995
|
+
Example:
|
|
996
|
+
>>> unit_matrix = RotationMatrix.unit()
|
|
997
|
+
>>> matrix = unit_matrix.get_matrix() # 3x3 identity matrix
|
|
998
|
+
"""
|
|
999
|
+
@staticmethod
|
|
1000
|
+
def vector_basis(source_vectors: tuple[numpy.ndarray[numpy.float64[3, 1]], numpy.ndarray[numpy.float64[3, 1]]], destination_vectors: tuple[numpy.ndarray[numpy.float64[3, 1]], numpy.ndarray[numpy.float64[3, 1]]]) -> RotationMatrix:
|
|
1001
|
+
"""
|
|
1002
|
+
Create a rotation matrix from two pairs of vectors.
|
|
1003
|
+
|
|
1004
|
+
Constructs orthonormal basis frames from each pair of vectors and returns
|
|
1005
|
+
the rotation matrix that transforms from the source basis to the destination basis.
|
|
1006
|
+
The first vector defines the primary direction, and the second vector is used
|
|
1007
|
+
to determine the orientation of the basis (via cross product).
|
|
1008
|
+
|
|
1009
|
+
Args:
|
|
1010
|
+
source_vectors (tuple[np.array, np.array]): A pair of 3-dimensional source vectors.
|
|
1011
|
+
destination_vectors (tuple[np.array, np.array]): A pair of 3-dimensional destination vectors.
|
|
1012
|
+
|
|
1013
|
+
Returns:
|
|
1014
|
+
RotationMatrix: Rotation matrix transforming from source to destination basis.
|
|
1015
|
+
|
|
1016
|
+
Example:
|
|
1017
|
+
>>> # Identity rotation
|
|
1018
|
+
>>> source1 = np.array([1.0, 0.0, 0.0])
|
|
1019
|
+
>>> source2 = np.array([0.0, 1.0, 0.0])
|
|
1020
|
+
>>> rot = RotationMatrix.vector_basis((source1, source2), (source1, source2))
|
|
1021
|
+
|
|
1022
|
+
>>> # 90-degree rotation around Z-axis
|
|
1023
|
+
>>> dest1 = np.array([0.0, 1.0, 0.0])
|
|
1024
|
+
>>> dest2 = np.array([-1.0, 0.0, 0.0])
|
|
1025
|
+
>>> rot = RotationMatrix.vector_basis((source1, source2), (dest1, dest2))
|
|
1026
|
+
"""
|
|
1027
|
+
def __eq__(self, arg0: RotationMatrix) -> bool:
|
|
1028
|
+
...
|
|
1029
|
+
@typing.overload
|
|
1030
|
+
def __init__(self, matrix: numpy.ndarray[numpy.float64[3, 3]]) -> None:
|
|
1031
|
+
"""
|
|
1032
|
+
Create a rotation matrix from a 3x3 matrix.
|
|
1033
|
+
|
|
1034
|
+
Args:
|
|
1035
|
+
matrix (Matrix3d): A 3x3 matrix representing the rotation.
|
|
1036
|
+
|
|
1037
|
+
Example:
|
|
1038
|
+
>>> matrix = Matrix3d.identity()
|
|
1039
|
+
>>> rotation_matrix = RotationMatrix(matrix)
|
|
1040
|
+
"""
|
|
1041
|
+
@typing.overload
|
|
1042
|
+
def __init__(self, first_coefficient: ostk.core.type.Real, second_coefficient: ostk.core.type.Real, third_coefficient: ostk.core.type.Real, fourth_coefficient: ostk.core.type.Real, fifth_coefficient: ostk.core.type.Real, sixth_coefficient: ostk.core.type.Real, seventh_coefficient: ostk.core.type.Real, eighth_coefficient: ostk.core.type.Real, ninth_coefficient: ostk.core.type.Real) -> None:
|
|
1043
|
+
"""
|
|
1044
|
+
Create a rotation matrix from nine coefficients (row-major order).
|
|
1045
|
+
|
|
1046
|
+
Args:
|
|
1047
|
+
first_coefficient (float): Matrix element (0,0).
|
|
1048
|
+
second_coefficient (float): Matrix element (0,1).
|
|
1049
|
+
third_coefficient (float): Matrix element (0,2).
|
|
1050
|
+
fourth_coefficient (float): Matrix element (1,0).
|
|
1051
|
+
fifth_coefficient (float): Matrix element (1,1).
|
|
1052
|
+
sixth_coefficient (float): Matrix element (1,2).
|
|
1053
|
+
seventh_coefficient (float): Matrix element (2,0).
|
|
1054
|
+
eighth_coefficient (float): Matrix element (2,1).
|
|
1055
|
+
ninth_coefficient (float): Matrix element (2,2).
|
|
1056
|
+
|
|
1057
|
+
Example:
|
|
1058
|
+
>>> rot_matrix = RotationMatrix(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
|
|
1059
|
+
"""
|
|
1060
|
+
@typing.overload
|
|
1061
|
+
def __mul__(self, arg0: RotationMatrix) -> RotationMatrix:
|
|
1062
|
+
...
|
|
1063
|
+
@typing.overload
|
|
1064
|
+
def __mul__(self, arg0: numpy.ndarray[numpy.float64[3, 1]]) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
1065
|
+
...
|
|
1066
|
+
def __ne__(self, arg0: RotationMatrix) -> bool:
|
|
1067
|
+
...
|
|
1068
|
+
def __repr__(self) -> str:
|
|
1069
|
+
...
|
|
1070
|
+
def __str__(self) -> str:
|
|
1071
|
+
...
|
|
1072
|
+
def get_column_at(self, index: int) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
1073
|
+
"""
|
|
1074
|
+
Get a column of the rotation matrix at specified index.
|
|
1075
|
+
|
|
1076
|
+
Args:
|
|
1077
|
+
index (int): The column index (0, 1, or 2).
|
|
1078
|
+
|
|
1079
|
+
Returns:
|
|
1080
|
+
Vector3d: The column vector at the specified index.
|
|
1081
|
+
|
|
1082
|
+
Example:
|
|
1083
|
+
>>> rot_matrix = RotationMatrix.unit()
|
|
1084
|
+
>>> first_column = rot_matrix.get_column_at(0) # [1, 0, 0]
|
|
1085
|
+
"""
|
|
1086
|
+
def get_matrix(self) -> numpy.ndarray[numpy.float64[3, 3]]:
|
|
1087
|
+
"""
|
|
1088
|
+
Get the underlying 3x3 matrix.
|
|
1089
|
+
|
|
1090
|
+
Returns:
|
|
1091
|
+
Matrix3d: The 3x3 rotation matrix.
|
|
1092
|
+
|
|
1093
|
+
Example:
|
|
1094
|
+
>>> rot_matrix = RotationMatrix.unit()
|
|
1095
|
+
>>> matrix = rot_matrix.get_matrix()
|
|
1096
|
+
"""
|
|
1097
|
+
def get_row_at(self, index: int) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
1098
|
+
"""
|
|
1099
|
+
Get a row of the rotation matrix at specified index.
|
|
1100
|
+
|
|
1101
|
+
Args:
|
|
1102
|
+
index (int): The row index (0, 1, or 2).
|
|
1103
|
+
|
|
1104
|
+
Returns:
|
|
1105
|
+
Vector3d: The row vector at the specified index.
|
|
1106
|
+
|
|
1107
|
+
Example:
|
|
1108
|
+
>>> rot_matrix = RotationMatrix.unit()
|
|
1109
|
+
>>> first_row = rot_matrix.get_row_at(0) # [1, 0, 0]
|
|
1110
|
+
"""
|
|
1111
|
+
def is_defined(self) -> bool:
|
|
1112
|
+
"""
|
|
1113
|
+
Check if the rotation matrix is defined.
|
|
1114
|
+
|
|
1115
|
+
Returns:
|
|
1116
|
+
bool: True if the rotation matrix is defined, False otherwise.
|
|
1117
|
+
|
|
1118
|
+
Example:
|
|
1119
|
+
>>> rot_matrix = RotationMatrix(Matrix3d.identity())
|
|
1120
|
+
>>> rot_matrix.is_defined() # True
|
|
1121
|
+
"""
|
|
1122
|
+
def to_transposed(self) -> RotationMatrix:
|
|
1123
|
+
"""
|
|
1124
|
+
Get the transpose of this rotation matrix.
|
|
1125
|
+
|
|
1126
|
+
Returns:
|
|
1127
|
+
RotationMatrix: The transposed rotation matrix.
|
|
1128
|
+
|
|
1129
|
+
Example:
|
|
1130
|
+
>>> rot_matrix = RotationMatrix.rx(Angle.degrees(90.0))
|
|
1131
|
+
>>> transposed = rot_matrix.to_transposed()
|
|
1132
|
+
"""
|
|
1133
|
+
def transpose(self) -> None:
|
|
1134
|
+
"""
|
|
1135
|
+
Transpose the rotation matrix in place.
|
|
1136
|
+
|
|
1137
|
+
Example:
|
|
1138
|
+
>>> rot_matrix = RotationMatrix.rx(Angle.degrees(90.0))
|
|
1139
|
+
>>> rot_matrix.transpose()
|
|
1140
|
+
"""
|
|
1141
|
+
class RotationVector:
|
|
1142
|
+
__hash__: typing.ClassVar[None] = None
|
|
1143
|
+
@staticmethod
|
|
1144
|
+
def euler_angle(euler_angle: typing.Any) -> RotationVector:
|
|
1145
|
+
"""
|
|
1146
|
+
Create a rotation vector from Euler angles.
|
|
1147
|
+
|
|
1148
|
+
Args:
|
|
1149
|
+
euler_angle (EulerAngle): The Euler angles to convert.
|
|
1150
|
+
|
|
1151
|
+
Returns:
|
|
1152
|
+
RotationVector: The equivalent rotation vector.
|
|
1153
|
+
|
|
1154
|
+
Example:
|
|
1155
|
+
>>> ea = EulerAngle.zyx(Angle.degrees(30), Angle.degrees(45), Angle.degrees(60))
|
|
1156
|
+
>>> rot_vector = RotationVector.euler_angle(ea)
|
|
1157
|
+
"""
|
|
1158
|
+
@staticmethod
|
|
1159
|
+
def quaternion(quaternion: Quaternion) -> RotationVector:
|
|
1160
|
+
"""
|
|
1161
|
+
Create a rotation vector from a quaternion.
|
|
1162
|
+
|
|
1163
|
+
Args:
|
|
1164
|
+
quaternion (Quaternion): The quaternion to convert.
|
|
1165
|
+
|
|
1166
|
+
Returns:
|
|
1167
|
+
RotationVector: The equivalent rotation vector.
|
|
1168
|
+
|
|
1169
|
+
Example:
|
|
1170
|
+
>>> q = Quaternion.unit()
|
|
1171
|
+
>>> rot_vector = RotationVector.quaternion(q)
|
|
1172
|
+
"""
|
|
1173
|
+
@staticmethod
|
|
1174
|
+
def rotation_matrix(rotation_matrix: typing.Any) -> RotationVector:
|
|
1175
|
+
"""
|
|
1176
|
+
Create a rotation vector from a rotation matrix.
|
|
1177
|
+
|
|
1178
|
+
Args:
|
|
1179
|
+
rotation_matrix (RotationMatrix): The rotation matrix to convert.
|
|
1180
|
+
|
|
1181
|
+
Returns:
|
|
1182
|
+
RotationVector: The equivalent rotation vector.
|
|
1183
|
+
|
|
1184
|
+
Example:
|
|
1185
|
+
>>> rm = RotationMatrix.identity()
|
|
1186
|
+
>>> rot_vector = RotationVector.rotation_matrix(rm)
|
|
1187
|
+
"""
|
|
1188
|
+
@staticmethod
|
|
1189
|
+
def undefined() -> RotationVector:
|
|
1190
|
+
"""
|
|
1191
|
+
Create an undefined rotation vector.
|
|
1192
|
+
|
|
1193
|
+
Returns:
|
|
1194
|
+
RotationVector: An undefined rotation vector.
|
|
1195
|
+
|
|
1196
|
+
Example:
|
|
1197
|
+
>>> undefined_vector = RotationVector.undefined()
|
|
1198
|
+
>>> undefined_vector.is_defined() # False
|
|
1199
|
+
"""
|
|
1200
|
+
@staticmethod
|
|
1201
|
+
def unit() -> RotationVector:
|
|
1202
|
+
"""
|
|
1203
|
+
Create a unit rotation vector (no rotation).
|
|
1204
|
+
|
|
1205
|
+
Returns:
|
|
1206
|
+
RotationVector: A rotation vector representing no rotation.
|
|
1207
|
+
|
|
1208
|
+
Example:
|
|
1209
|
+
>>> unit_vector = RotationVector.unit()
|
|
1210
|
+
>>> angle = unit_vector.get_angle() # 0 degrees
|
|
1211
|
+
"""
|
|
1212
|
+
@staticmethod
|
|
1213
|
+
def x(angle: typing.Any) -> RotationVector:
|
|
1214
|
+
"""
|
|
1215
|
+
Create a rotation vector around the x-axis.
|
|
1216
|
+
|
|
1217
|
+
Args:
|
|
1218
|
+
angle (Angle): The rotation angle around the x-axis.
|
|
1219
|
+
|
|
1220
|
+
Returns:
|
|
1221
|
+
RotationVector: A rotation vector around the x-axis.
|
|
1222
|
+
|
|
1223
|
+
Example:
|
|
1224
|
+
>>> rot_vector = RotationVector.x(Angle.degrees(90.0))
|
|
1225
|
+
"""
|
|
1226
|
+
@staticmethod
|
|
1227
|
+
def y(angle: typing.Any) -> RotationVector:
|
|
1228
|
+
"""
|
|
1229
|
+
Create a rotation vector around the y-axis.
|
|
1230
|
+
|
|
1231
|
+
Args:
|
|
1232
|
+
angle (Angle): The rotation angle around the y-axis.
|
|
1233
|
+
|
|
1234
|
+
Returns:
|
|
1235
|
+
RotationVector: A rotation vector around the y-axis.
|
|
1236
|
+
|
|
1237
|
+
Example:
|
|
1238
|
+
>>> rot_vector = RotationVector.y(Angle.degrees(90.0))
|
|
1239
|
+
"""
|
|
1240
|
+
@staticmethod
|
|
1241
|
+
def z(angle: typing.Any) -> RotationVector:
|
|
1242
|
+
"""
|
|
1243
|
+
Create a rotation vector around the z-axis.
|
|
1244
|
+
|
|
1245
|
+
Args:
|
|
1246
|
+
angle (Angle): The rotation angle around the z-axis.
|
|
1247
|
+
|
|
1248
|
+
Returns:
|
|
1249
|
+
RotationVector: A rotation vector around the z-axis.
|
|
1250
|
+
|
|
1251
|
+
Example:
|
|
1252
|
+
>>> rot_vector = RotationVector.z(Angle.degrees(90.0))
|
|
1253
|
+
"""
|
|
1254
|
+
def __eq__(self, arg0: RotationVector) -> bool:
|
|
1255
|
+
...
|
|
1256
|
+
@typing.overload
|
|
1257
|
+
def __init__(self, axis: numpy.ndarray[numpy.float64[3, 1]], angle: typing.Any) -> None:
|
|
1258
|
+
"""
|
|
1259
|
+
Create a rotation vector from axis and angle.
|
|
1260
|
+
|
|
1261
|
+
Args:
|
|
1262
|
+
axis (np.array): The rotation axis (will be normalized).
|
|
1263
|
+
angle (Angle): The rotation angle around the axis.
|
|
1264
|
+
|
|
1265
|
+
Example:
|
|
1266
|
+
>>> axis = np.array([0.0, 0.0, 1.0])
|
|
1267
|
+
>>> angle = Angle.degrees(90.0)
|
|
1268
|
+
>>> rot_vector = RotationVector(axis, angle)
|
|
1269
|
+
"""
|
|
1270
|
+
@typing.overload
|
|
1271
|
+
def __init__(self, vector: numpy.ndarray[numpy.float64[3, 1]], angle_unit: typing.Any) -> None:
|
|
1272
|
+
"""
|
|
1273
|
+
Create a rotation vector from a vector representation.
|
|
1274
|
+
|
|
1275
|
+
Args:
|
|
1276
|
+
vector (np.array): The rotation vector (magnitude represents angle).
|
|
1277
|
+
angle_unit (Angle.Unit): The unit of the angle in the vector magnitude.
|
|
1278
|
+
|
|
1279
|
+
Example:
|
|
1280
|
+
>>> vector = np.array([0.0, 0.0, 1.5708]) # π/2 in z-axis
|
|
1281
|
+
>>> rot_vector = RotationVector(vector, Angle.Unit.Radian)
|
|
1282
|
+
"""
|
|
1283
|
+
def __ne__(self, arg0: RotationVector) -> bool:
|
|
1284
|
+
...
|
|
1285
|
+
def __repr__(self) -> str:
|
|
1286
|
+
...
|
|
1287
|
+
def __str__(self) -> str:
|
|
1288
|
+
...
|
|
1289
|
+
def get_angle(self) -> ...:
|
|
1290
|
+
"""
|
|
1291
|
+
Get the rotation angle.
|
|
1292
|
+
|
|
1293
|
+
Returns:
|
|
1294
|
+
Angle: The rotation angle around the axis.
|
|
1295
|
+
|
|
1296
|
+
Example:
|
|
1297
|
+
>>> rot_vector = RotationVector(axis, Angle.degrees(90.0))
|
|
1298
|
+
>>> angle = rot_vector.get_angle() # 90 degrees
|
|
1299
|
+
"""
|
|
1300
|
+
def get_axis(self) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
1301
|
+
"""
|
|
1302
|
+
Get the rotation axis vector.
|
|
1303
|
+
|
|
1304
|
+
Returns:
|
|
1305
|
+
Vector3d: The normalized rotation axis.
|
|
1306
|
+
|
|
1307
|
+
Example:
|
|
1308
|
+
>>> rot_vector = RotationVector(np.array([1.0, 0.0, 0.0]), angle)
|
|
1309
|
+
>>> axis = rot_vector.get_axis() # [1.0, 0.0, 0.0]
|
|
1310
|
+
"""
|
|
1311
|
+
def is_defined(self) -> bool:
|
|
1312
|
+
"""
|
|
1313
|
+
Check if the rotation vector is defined.
|
|
1314
|
+
|
|
1315
|
+
Returns:
|
|
1316
|
+
bool: True if the rotation vector is defined, False otherwise.
|
|
1317
|
+
|
|
1318
|
+
Example:
|
|
1319
|
+
>>> rot_vector = RotationVector(axis, angle)
|
|
1320
|
+
>>> rot_vector.is_defined() # True
|
|
1321
|
+
"""
|
|
1322
|
+
def rectify(self) -> None:
|
|
1323
|
+
"""
|
|
1324
|
+
Rectify the rotation vector in-place (ensure angle is in [0, π]).
|
|
1325
|
+
|
|
1326
|
+
Example:
|
|
1327
|
+
>>> rot_vector = RotationVector(axis, Angle.degrees(270.0))
|
|
1328
|
+
>>> rot_vector.rectify() # Converts to equivalent rotation with angle ≤ π
|
|
1329
|
+
"""
|
|
1330
|
+
@typing.overload
|
|
1331
|
+
def to_string(self) -> ostk.core.type.String:
|
|
1332
|
+
"""
|
|
1333
|
+
Convert the rotation vector to string representation.
|
|
1334
|
+
|
|
1335
|
+
Returns:
|
|
1336
|
+
str: String representation of the rotation vector.
|
|
1337
|
+
|
|
1338
|
+
Example:
|
|
1339
|
+
>>> rot_vector = RotationVector.unit()
|
|
1340
|
+
>>> rot_vector.to_string()
|
|
1341
|
+
"""
|
|
1342
|
+
@typing.overload
|
|
1343
|
+
def to_string(self, precision: ostk.core.type.Integer) -> ostk.core.type.String:
|
|
1344
|
+
"""
|
|
1345
|
+
Convert the rotation vector to string representation with specified precision.
|
|
1346
|
+
|
|
1347
|
+
Args:
|
|
1348
|
+
precision (int): The precision for floating point numbers.
|
|
1349
|
+
|
|
1350
|
+
Returns:
|
|
1351
|
+
str: String representation of the rotation vector.
|
|
1352
|
+
|
|
1353
|
+
Example:
|
|
1354
|
+
>>> rot_vector = RotationVector.unit()
|
|
1355
|
+
>>> rot_vector.to_string(3)
|
|
1356
|
+
"""
|
|
1357
|
+
def set_quaternion_array(arg0: list[Quaternion]) -> None:
|
|
1358
|
+
...
|