0
# Time Series and Interpolation
1
2
Advanced functionality for working with quaternion time series including spherical interpolation methods and angular velocity integration. These functions are essential for smooth animation, physics simulation, and trajectory planning.
3
4
## Capabilities
5
6
### Spherical Linear Interpolation
7
8
Smooth interpolation between quaternion time series and individual quaternions.
9
10
```python { .api }
11
def slerp(R1, R2, t1, t2, t_out):
12
"""
13
Spherical linear interpolation between quaternion time series.
14
15
Args:
16
R1 (quaternion array): First quaternion time series
17
R2 (quaternion array): Second quaternion time series
18
t1 (array_like): Time values for R1
19
t2 (array_like): Time values for R2
20
t_out (array_like): Output time values for interpolation
21
22
Returns:
23
quaternion array: Interpolated quaternions at t_out times
24
25
Notes:
26
Provides smooth interpolation between two quaternion time series.
27
Handles time alignment and produces constant angular velocity
28
interpolation between corresponding points.
29
"""
30
31
def slerp_evaluate(q1, q2, t):
32
"""
33
Low-level slerp evaluation between two quaternions.
34
35
Args:
36
q1 (quaternion): Start quaternion
37
q2 (quaternion): End quaternion
38
t (float or array): Interpolation parameter (0=q1, 1=q2)
39
40
Returns:
41
quaternion or quaternion array: Interpolated quaternion(s)
42
43
Notes:
44
Core slerp function. For t in [0,1], produces shortest-path
45
interpolation on quaternion sphere with constant angular velocity.
46
"""
47
```
48
49
### Spherical Quadratic Interpolation
50
51
Higher-order interpolation for C1-continuous quaternion sequences.
52
53
```python { .api }
54
def squad(R_in, t_in, t_out, unflip_input_rotors=False):
55
"""
56
Spherical quadratic interpolation for smooth quaternion time series.
57
58
Args:
59
R_in (quaternion array): Input quaternion time series
60
t_in (array_like): Input time values
61
t_out (array_like): Output time values for interpolation
62
unflip_input_rotors (bool): Automatically ensure input continuity (default: False)
63
64
Returns:
65
quaternion array: Smoothly interpolated quaternions at t_out times
66
67
Notes:
68
Provides C1-continuous interpolation (continuous first derivative).
69
Superior to slerp for smooth animation and requires at least 4 input points.
70
Automatically handles tangent computation for smooth transitions.
71
"""
72
73
def squad_evaluate(q1, q2, a1, a2, t):
74
"""
75
Low-level squad evaluation between quaternions with control points.
76
77
Args:
78
q1 (quaternion): Start quaternion
79
q2 (quaternion): End quaternion
80
a1 (quaternion): First control quaternion
81
a2 (quaternion): Second control quaternion
82
t (float or array): Interpolation parameter (0=q1, 1=q2)
83
84
Returns:
85
quaternion or quaternion array: Interpolated quaternion(s)
86
87
Notes:
88
Core squad function using Bezier-like control points for smooth
89
interpolation with continuous first derivatives.
90
"""
91
```
92
93
### Angular Velocity Integration
94
95
Integrate angular velocity to produce quaternion time series for physics simulations.
96
97
```python { .api }
98
def integrate_angular_velocity(Omega, t0, t1, R0=None, tolerance=1e-12):
99
"""
100
Integrate angular velocity to get quaternion time series.
101
102
Args:
103
Omega (array_like): Angular velocity time series with shape (..., 3)
104
t0 (array_like): Time values for angular velocity data
105
t1 (array_like): Output time values for integration
106
R0 (quaternion, optional): Initial quaternion (default: identity)
107
tolerance (float): Integration tolerance (default: 1e-12)
108
109
Returns:
110
quaternion array: Quaternion time series at t1 times
111
112
Notes:
113
Numerically integrates angular velocity ω(t) to produce rotation
114
quaternions R(t). Essential for physics simulations where angular
115
velocity is known but orientations must be computed.
116
"""
117
```
118
119
### Time Series Utilities
120
121
Additional utilities for working with quaternion time series.
122
123
```python { .api }
124
def unflip_rotors(q, axis=-1, inplace=False):
125
"""
126
Ensure quaternion time series continuity by eliminating sign flips.
127
128
Args:
129
q (quaternion array): Input quaternion time series
130
axis (int): Time axis along which to enforce continuity (default: -1)
131
inplace (bool): Modify input array in place (default: False)
132
133
Returns:
134
quaternion array: Quaternion series with consistent sign choices
135
136
Notes:
137
Quaternions q and -q represent the same rotation. This function
138
ensures the quaternion time series uses consistent sign choices
139
to avoid sudden jumps that complicate interpolation and differentiation.
140
"""
141
142
def angular_velocity(R, t):
143
"""
144
Compute angular velocity from quaternion time series.
145
146
Args:
147
R (quaternion array): Quaternion time series representing rotations
148
t (array_like): Time values corresponding to quaternions
149
150
Returns:
151
ndarray: Angular velocity time series with shape (..., 3)
152
153
Notes:
154
Differentiates quaternion time series to extract angular velocity
155
vector ω(t). Uses numerical differentiation with appropriate
156
quaternion calculus formulas.
157
"""
158
159
def minimal_rotation(R, t, iterations=2):
160
"""
161
Find minimal rotation representation of quaternion time series.
162
163
Args:
164
R (quaternion array): Input quaternion time series
165
t (array_like): Time values corresponding to quaternions
166
iterations (int): Number of optimization iterations (default: 2)
167
168
Returns:
169
quaternion array: Optimized quaternion time series
170
171
Notes:
172
Minimizes the total rotation magnitude while preserving the
173
relative rotations in the time series. Useful for generating
174
smooth animation paths and reducing gimbal lock effects.
175
"""
176
```
177
178
## Usage Examples
179
180
```python
181
import quaternion
182
import numpy as np
183
184
# Create sample quaternion time series
185
t = np.linspace(0, 2*np.pi, 20)
186
# Rotation around z-axis with varying speed
187
angles = 0.5 * t**2
188
R_input = np.array([quaternion.from_euler_angles(0, 0, angle) for angle in angles])
189
190
# Interpolate with slerp for higher resolution
191
t_fine = np.linspace(0, 2*np.pi, 100)
192
R_slerp = quaternion.slerp(R_input, t, t_fine)
193
194
# Use squad for smoother interpolation
195
R_squad = quaternion.squad(R_input, t, t_fine)
196
197
# Direct slerp between two quaternions
198
q1 = quaternion.quaternion(1, 0, 0, 0) # Identity
199
q2 = quaternion.from_euler_angles(0, 0, np.pi/2) # 90° z-rotation
200
t_interp = np.linspace(0, 1, 10)
201
q_interpolated = quaternion.slerp_evaluate(q1, q2, t_interp)
202
203
# Squad evaluation with control points
204
# (Control points would typically be computed automatically by squad function)
205
a1 = quaternion.quaternion(0.9, 0.1, 0, 0).normalized()
206
a2 = quaternion.quaternion(0.9, 0, 0.1, 0).normalized()
207
q_squad_direct = quaternion.squad_evaluate(q1, q2, a1, a2, t_interp)
208
209
# Integrate angular velocity back to quaternions
210
t_integrate = np.linspace(0, 2*np.pi, 50)
211
# Use constant angular velocity for simple example
212
omega_const = np.zeros((len(t_integrate), 3))
213
omega_const[:, 2] = 1.0 # 1 rad/s around z-axis
214
215
R_integrated = quaternion.integrate_angular_velocity(
216
omega_const, t_integrate, t_integrate, R0=quaternion.one
217
)
218
219
print(f"Integrated quaternion sequence length: {len(R_integrated)}")
220
221
# Physics simulation example with varying angular velocity
222
dt = 0.01
223
time_steps = np.arange(0, 2, dt)
224
# Sinusoidal angular velocity
225
omega_physics = np.zeros((len(time_steps), 3))
226
omega_physics[:, 0] = 2 * np.sin(time_steps) # x-axis
227
omega_physics[:, 1] = 1 * np.cos(time_steps) # y-axis
228
229
# Integrate to get orientation time series
230
R_physics = quaternion.integrate_angular_velocity(
231
omega_physics, time_steps, time_steps
232
)
233
234
print(f"Physics simulation: {len(R_physics)} quaternions over {time_steps[-1]} seconds")
235
```