or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-math.mdbasic-operations.mdconstruction.mdindex.mdinterpolation.mdrotation.md

interpolation.mddocs/

0

# Interpolation and Animation

1

2

Smooth interpolation between quaternion orientations for animation, trajectory planning, and quaternion integration over time.

3

4

## Capabilities

5

6

### Spherical Linear Interpolation (SLERP)

7

8

Smooth interpolation between two quaternions along the shortest path on the 4D unit hypersphere.

9

10

```python { .api }

11

@classmethod

12

def slerp(cls, q0, q1, amount=0.5):

13

"""

14

Spherical Linear Interpolation between quaternions.

15

16

Finds a valid quaternion rotation at a specified distance along the

17

minor arc of a great circle passing through two quaternion endpoints

18

on the unit radius hypersphere.

19

20

Parameters:

21

q0: Quaternion, first endpoint rotation

22

q1: Quaternion, second endpoint rotation

23

amount: float, interpolation parameter [0, 1]

24

0.0 returns q0, 1.0 returns q1, 0.5 returns midpoint

25

26

Returns:

27

Quaternion: Interpolated unit quaternion

28

29

Note:

30

Input quaternions are automatically normalized to unit length.

31

Takes the shorter rotation path by flipping quaternion sign if needed.

32

"""

33

```

34

35

**Usage Examples:**

36

37

```python

38

from pyquaternion import Quaternion

39

import numpy as np

40

41

# Create start and end orientations

42

q_start = Quaternion(axis=[0, 0, 1], degrees=0) # No rotation

43

q_end = Quaternion(axis=[0, 0, 1], degrees=90) # 90° about Z

44

45

# Interpolate at various points

46

q_quarter = Quaternion.slerp(q_start, q_end, 0.25) # 25% along path

47

q_half = Quaternion.slerp(q_start, q_end, 0.5) # 50% along path

48

q_three_quarter = Quaternion.slerp(q_start, q_end, 0.75) # 75% along path

49

50

print(f"Start: {q_start.degrees:.1f}°") # 0.0°

51

print(f"Quarter: {q_quarter.degrees:.1f}°") # ~22.5°

52

print(f"Half: {q_half.degrees:.1f}°") # ~45.0°

53

print(f"Three-quarter: {q_three_quarter.degrees:.1f}°") # ~67.5°

54

print(f"End: {q_end.degrees:.1f}°") # 90.0°

55

56

# Animate rotation by applying to vector

57

vector = [1, 0, 0]

58

for t in np.linspace(0, 1, 11):

59

q_t = Quaternion.slerp(q_start, q_end, t)

60

rotated = q_t.rotate(vector)

61

print(f"t={t:.1f}: {rotated}")

62

```

63

64

### Intermediate Quaternion Generation

65

66

Generate sequences of evenly spaced quaternions for smooth animation.

67

68

```python { .api }

69

@classmethod

70

def intermediates(cls, q0, q1, n, include_endpoints=False):

71

"""

72

Generate evenly spaced quaternion rotations between two endpoints.

73

74

Convenience method based on slerp() for creating animation sequences.

75

76

Parameters:

77

q0: Quaternion, initial endpoint rotation

78

q1: Quaternion, final endpoint rotation

79

n: int, number of intermediate quaternions within the interval

80

include_endpoints: bool, if True, includes q0 and q1 in sequence

81

resulting in n+2 total quaternions

82

if False, excludes endpoints (default)

83

84

Yields:

85

Generator[Quaternion]: Sequence of intermediate quaternions

86

87

Note:

88

Input quaternions are automatically normalized to unit length.

89

"""

90

```

91

92

**Usage Examples:**

93

94

```python

95

# Create smooth rotation sequence

96

q_start = Quaternion() # Identity

97

q_end = Quaternion(axis=[1, 1, 1], degrees=120)

98

99

# Generate 5 intermediate steps (excluding endpoints)

100

intermediates = list(Quaternion.intermediates(q_start, q_end, 5))

101

print(f"Generated {len(intermediates)} intermediate quaternions")

102

103

# Generate sequence including endpoints

104

full_sequence = list(Quaternion.intermediates(q_start, q_end, 5, include_endpoints=True))

105

print(f"Full sequence has {len(full_sequence)} quaternions")

106

107

# Use in animation loop

108

vector = [1, 0, 0]

109

print("Animation frames:")

110

for i, q in enumerate(full_sequence):

111

rotated = q.rotate(vector)

112

print(f"Frame {i}: {rotated}")

113

114

# Create continuous rotation animation

115

for q in Quaternion.intermediates(q_start, q_end, 20):

116

angle_deg = q.degrees if q.degrees is not None else 0.0

117

print(f"Rotation: {angle_deg:.1f}° about {q.axis}")

118

```

119

120

### Quaternion Derivatives

121

122

Compute instantaneous quaternion derivatives for angular velocity integration.

123

124

```python { .api }

125

def derivative(self, rate):

126

"""

127

Get instantaneous quaternion derivative for a quaternion rotating at 3D rate.

128

129

Computes the time derivative of the quaternion given angular velocity,

130

useful for integrating rotational motion.

131

132

Parameters:

133

rate: array-like, 3-element angular velocity vector [ωx, ωy, ωz]

134

Units should be consistent (e.g., rad/s)

135

Represents rotation rates about global x, y, z axes

136

137

Returns:

138

Quaternion: Quaternion derivative representing rotation rate

139

Formula: 0.5 * self * Quaternion(vector=rate)

140

"""

141

```

142

143

### Quaternion Integration

144

145

Integrate quaternion rotations over time with constant angular velocity.

146

147

```python { .api }

148

def integrate(self, rate, timestep):

149

"""

150

Advance quaternion to its value after time interval with constant angular velocity.

151

152

Modifies the quaternion object in-place using closed-form integration.

153

The quaternion remains normalized throughout the process.

154

155

Parameters:

156

rate: array-like, 3-element angular velocity [ωx, ωy, ωz]

157

Rotation rates about global x, y, z axes (e.g., rad/s)

158

timestep: float, time interval for integration

159

Must have consistent units with rate (e.g., seconds)

160

161

Note:

162

- Modifies the quaternion object directly

163

- Assumes constant angular velocity over the timestep

164

- Smaller timesteps give more accurate results for varying rates

165

- Automatically maintains unit quaternion property

166

"""

167

```

168

169

**Usage Examples:**

170

171

```python

172

import numpy as np

173

174

# Initial orientation

175

q = Quaternion() # Identity quaternion

176

177

# Angular velocity (rad/s)

178

angular_velocity = [0, 0, 1.0] # 1 rad/s about Z-axis

179

dt = 0.1 # 100ms timestep

180

181

# Simulate rotation over time

182

print("Quaternion integration simulation:")

183

print(f"Time: 0.0s, Angle: {q.degrees:.1f}°")

184

185

for step in range(10):

186

# Get derivative

187

q_dot = q.derivative(angular_velocity)

188

189

# Integrate one timestep

190

q.integrate(angular_velocity, dt)

191

192

time = (step + 1) * dt

193

angle = q.degrees if q.degrees is not None else 0.0

194

print(f"Time: {time:.1f}s, Angle: {angle:.1f}°")

195

196

# Verify final result

197

expected_angle = np.degrees(1.0) # 1 rad/s * 1.0s total

198

print(f"Expected final angle: {expected_angle:.1f}°")

199

200

# Integration with varying angular velocity

201

q = Quaternion() # Reset

202

time_points = np.linspace(0, 2*np.pi, 100)

203

dt = time_points[1] - time_points[0]

204

205

trajectory = []

206

for t in time_points:

207

# Time-varying angular velocity (sinusoidal)

208

omega = [np.sin(t), np.cos(t), 0.5]

209

q.integrate(omega, dt)

210

trajectory.append((t, q.degrees, q.axis.copy()))

211

212

# Analyze trajectory

213

print(f"\nTrajectory analysis:")

214

print(f"Final time: {time_points[-1]:.2f}s")

215

print(f"Final angle: {trajectory[-1][1]:.1f}°")

216

print(f"Final axis: {trajectory[-1][2]}")

217

```

218

219

### Advanced Integration Examples

220

221

```python

222

# Spacecraft attitude control simulation

223

class SpacecraftAttitude:

224

def __init__(self):

225

self.orientation = Quaternion() # Initial orientation

226

self.angular_velocity = np.zeros(3) # rad/s

227

228

def apply_torque(self, torque, dt):

229

"""Apply torque for time dt (simplified dynamics)."""

230

# Simplified: assume torque directly changes angular velocity

231

self.angular_velocity += torque * dt

232

233

# Integrate orientation

234

self.orientation.integrate(self.angular_velocity, dt)

235

236

def get_attitude(self):

237

"""Get current attitude as rotation matrix."""

238

return self.orientation.rotation_matrix

239

240

# Usage

241

spacecraft = SpacecraftAttitude()

242

243

# Apply control torques

244

control_torque = [0.1, 0, 0] # Torque about x-axis

245

dt = 0.01 # 10ms control timestep

246

247

for i in range(1000): # 10 seconds of simulation

248

spacecraft.apply_torque(control_torque, dt)

249

250

if i % 100 == 0: # Print every second

251

time = i * dt

252

angle = spacecraft.orientation.degrees

253

print(f"t={time:.1f}s: attitude angle={angle:.1f}°")

254

```