or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

batch-operations.mdbatch-rotations.mdcamera.mdcoordinates.mdeditor.mdindex.mdplot-utils.mdrotations.mdtrajectories.mdtransform-manager.mdtransformations.mduncertainty.mdurdf.mdvisualization.md

uncertainty.mddocs/

0

# Uncertainty

1

2

Operations on uncertain transformations with statistical estimation, covariance propagation, and sensor fusion for handling measurement uncertainties in 3D transformations.

3

4

## Capabilities

5

6

### Uncertain Transformation Composition

7

8

Functions for propagating uncertainty through transformation operations.

9

10

```python { .api }

11

def concat_globally_uncertain_transforms(A2B, cov_A2B, B2C, cov_B2C):

12

"""

13

Concatenate transformations with global uncertainty propagation.

14

15

Parameters:

16

- A2B: array, shape (4, 4) - First transformation

17

- cov_A2B: array, shape (6, 6) - Covariance of first transformation

18

- B2C: array, shape (4, 4) - Second transformation

19

- cov_B2C: array, shape (6, 6) - Covariance of second transformation

20

21

Returns:

22

- A2C: array, shape (4, 4) - Composed transformation

23

- cov_A2C: array, shape (6, 6) - Propagated covariance

24

"""

25

26

def concat_locally_uncertain_transforms(A2B, cov_A2B, B2C, cov_B2C):

27

"""

28

Concatenate transformations with local uncertainty propagation.

29

30

Parameters:

31

- A2B: array, shape (4, 4) - First transformation

32

- cov_A2B: array, shape (6, 6) - Local covariance of first transformation

33

- B2C: array, shape (4, 4) - Second transformation

34

- cov_B2C: array, shape (6, 6) - Local covariance of second transformation

35

36

Returns:

37

- A2C: array, shape (4, 4) - Composed transformation

38

- cov_A2C: array, shape (6, 6) - Propagated local covariance

39

"""

40

41

def invert_uncertain_transform(A2B, cov_A2B):

42

"""

43

Invert uncertain transformation with covariance propagation.

44

45

Parameters:

46

- A2B: array, shape (4, 4) - Transformation matrix

47

- cov_A2B: array, shape (6, 6) - Covariance matrix

48

49

Returns:

50

- B2A: array, shape (4, 4) - Inverted transformation

51

- cov_B2A: array, shape (6, 6) - Propagated covariance

52

"""

53

```

54

55

### Statistical Estimation

56

57

Functions for estimating mean transformations from samples with uncertainty quantification.

58

59

```python { .api }

60

def frechet_mean(poses, weights=None, init_pose=None, max_iter=100, tol=1e-9):

61

"""

62

Compute Fréchet mean of pose samples.

63

64

Parameters:

65

- poses: array, shape (n_poses, 4, 4) - Transformation samples

66

- weights: array, shape (n_poses,), optional - Sample weights

67

- init_pose: array, shape (4, 4), optional - Initial estimate

68

- max_iter: int - Maximum iterations

69

- tol: float - Convergence tolerance

70

71

Returns:

72

- mean_pose: array, shape (4, 4) - Mean transformation

73

"""

74

75

def estimate_gaussian_transform_from_samples(A2Bs, max_iter=100):

76

"""

77

Estimate Gaussian distribution parameters from transformation samples.

78

79

Parameters:

80

- A2Bs: array, shape (n_samples, 4, 4) - Transformation samples

81

- max_iter: int - Maximum iterations for convergence

82

83

Returns:

84

- mean_A2B: array, shape (4, 4) - Mean transformation

85

- cov_A2B: array, shape (6, 6) - Covariance matrix

86

"""

87

88

def estimate_gaussian_rotation_matrix_from_samples(Rs, max_iter=100):

89

"""

90

Estimate mean rotation and covariance from rotation matrix samples.

91

92

Parameters:

93

- Rs: array, shape (n_samples, 3, 3) - Rotation matrix samples

94

- max_iter: int - Maximum iterations

95

96

Returns:

97

- mean_R: array, shape (3, 3) - Mean rotation matrix

98

- cov_R: array, shape (3, 3) - Rotation covariance

99

"""

100

```

101

102

### Sensor Fusion

103

104

Multi-sensor pose fusion with uncertainty-weighted combination.

105

106

```python { .api }

107

def pose_fusion(poses, covariances, check_inputs=True):

108

"""

109

Fuse multiple pose estimates with uncertainties.

110

111

Parameters:

112

- poses: list of arrays, shape (4, 4) - Pose estimates

113

- covariances: list of arrays, shape (6, 6) - Covariance matrices

114

- check_inputs: bool - Validate input poses and covariances

115

116

Returns:

117

- fused_pose: array, shape (4, 4) - Fused pose estimate

118

- fused_cov: array, shape (6, 6) - Fused covariance

119

"""

120

```

121

122

### Uncertainty Visualization

123

124

Functions for visualizing uncertainty as ellipsoids and projections.

125

126

```python { .api }

127

def to_ellipsoid(mean, cov, n_steps=20):

128

"""

129

Convert covariance matrix to ellipsoid surface points.

130

131

Parameters:

132

- mean: array, shape (3,) - Mean position

133

- cov: array, shape (3, 3) - Position covariance matrix

134

- n_steps: int - Number of surface discretization steps

135

136

Returns:

137

- ellipsoid: array, shape (n_steps**2, 3) - Ellipsoid surface points

138

"""

139

140

def to_projected_ellipsoid(mean, cov, n_steps=20):

141

"""

142

Project 3D uncertainty ellipsoid to 2D plane.

143

144

Parameters:

145

- mean: array, shape (3,) - Mean position

146

- cov: array, shape (3, 3) - Position covariance

147

- n_steps: int - Discretization steps

148

149

Returns:

150

- projection: array, shape (n_steps, 2) - 2D ellipse points

151

"""

152

153

def plot_projected_ellipsoid(ax, mean, cov, n_steps=20, **kwargs):

154

"""

155

Plot projected uncertainty ellipsoid on 2D axis.

156

157

Parameters:

158

- ax: matplotlib axis - 2D plotting axis

159

- mean: array, shape (3,) - Mean position

160

- cov: array, shape (3, 3) - Position covariance

161

- n_steps: int - Ellipse discretization

162

"""

163

```

164

165

## Usage Examples

166

167

### Uncertain Transform Composition

168

169

```python

170

import numpy as np

171

import pytransform3d.uncertainty as pu

172

import pytransform3d.transformations as pt

173

174

# Create two uncertain transformations

175

T1 = pt.transform_from(p=[1, 0, 0])

176

cov1 = np.diag([0.01, 0.01, 0.01, 0.001, 0.001, 0.001]) # [translation, rotation] variances

177

178

T2 = pt.transform_from(p=[0, 1, 0])

179

cov2 = np.diag([0.02, 0.02, 0.02, 0.002, 0.002, 0.002])

180

181

# Compose with uncertainty propagation

182

T_composed, cov_composed = pu.concat_globally_uncertain_transforms(T1, cov1, T2, cov2)

183

184

print(f"Composed transformation:\n{T_composed}")

185

print(f"Propagated uncertainty diagonal: {np.diag(cov_composed)}")

186

```

187

188

### Multi-Sensor Fusion

189

190

```python

191

import numpy as np

192

import pytransform3d.uncertainty as pu

193

import pytransform3d.transformations as pt

194

195

# Simulate multiple pose measurements

196

true_pose = pt.transform_from(p=[2, 1, 0.5])

197

198

# Sensor 1: High precision in position, low precision in orientation

199

pose1 = true_pose + np.random.normal(0, 0.01, (4, 4))

200

pose1 = pt.transform_from(p=pose1[:3, 3]) # Extract position

201

cov1 = np.diag([0.01, 0.01, 0.01, 0.1, 0.1, 0.1])

202

203

# Sensor 2: Low precision in position, high precision in orientation

204

pose2 = true_pose + np.random.normal(0, 0.05, (4, 4))

205

pose2 = pt.transform_from(p=pose2[:3, 3])

206

cov2 = np.diag([0.05, 0.05, 0.05, 0.01, 0.01, 0.01])

207

208

# Sensor 3: Medium precision overall

209

pose3 = true_pose + np.random.normal(0, 0.02, (4, 4))

210

pose3 = pt.transform_from(p=pose3[:3, 3])

211

cov3 = np.diag([0.02, 0.02, 0.02, 0.02, 0.02, 0.02])

212

213

# Fuse measurements

214

poses = [pose1, pose2, pose3]

215

covariances = [cov1, cov2, cov3]

216

217

fused_pose, fused_cov = pu.pose_fusion(poses, covariances)

218

219

print(f"True position: {true_pose[:3, 3]}")

220

print(f"Fused position: {fused_pose[:3, 3]}")

221

print(f"Position error: {np.linalg.norm(fused_pose[:3, 3] - true_pose[:3, 3]):.4f}")

222

print(f"Fused uncertainty (diagonal): {np.diag(fused_cov)}")

223

```

224

225

### Statistical Estimation

226

227

```python

228

import numpy as np

229

import pytransform3d.uncertainty as pu

230

import pytransform3d.transformations as pt

231

232

# Generate noisy pose samples around true pose

233

true_pose = pt.transform_from(p=[1, 2, 3])

234

n_samples = 100

235

236

pose_samples = []

237

for _ in range(n_samples):

238

# Add noise to position and orientation

239

noise_pos = np.random.normal(0, 0.1, 3)

240

noise_rot = np.random.normal(0, 0.05, 3)

241

242

# Create noisy pose

243

T_noise = pt.transform_from(p=noise_pos)

244

R_noise = pr.matrix_from_euler(noise_rot, "xyz", extrinsic=True)

245

T_noise[:3, :3] = R_noise

246

247

noisy_pose = pt.concat(true_pose, T_noise)

248

pose_samples.append(noisy_pose)

249

250

pose_samples = np.array(pose_samples)

251

252

# Estimate mean and covariance

253

mean_pose, cov_estimate = pu.estimate_gaussian_transform_from_samples(pose_samples)

254

255

print(f"True position: {true_pose[:3, 3]}")

256

print(f"Estimated position: {mean_pose[:3, 3]}")

257

print(f"Position error: {np.linalg.norm(mean_pose[:3, 3] - true_pose[:3, 3]):.4f}")

258

print(f"Estimated covariance diagonal: {np.diag(cov_estimate)}")

259

```

260

261

### Uncertainty Visualization

262

263

```python

264

import numpy as np

265

import matplotlib.pyplot as plt

266

import pytransform3d.uncertainty as pu

267

268

# Define uncertain position

269

mean_pos = np.array([1, 2, 0])

270

cov_pos = np.array([[0.1, 0.05, 0.02],

271

[0.05, 0.2, 0.01],

272

[0.02, 0.01, 0.05]])

273

274

# Generate ellipsoid surface

275

ellipsoid_points = pu.to_ellipsoid(mean_pos, cov_pos, n_steps=20)

276

277

# 3D visualization

278

fig = plt.figure(figsize=(12, 5))

279

280

# 3D ellipsoid

281

ax1 = fig.add_subplot(121, projection='3d')

282

ax1.scatter(ellipsoid_points[:, 0], ellipsoid_points[:, 1], ellipsoid_points[:, 2],

283

alpha=0.6, s=1)

284

ax1.scatter(*mean_pos, c='red', s=100, label='Mean')

285

ax1.set_xlabel('X')

286

ax1.set_ylabel('Y')

287

ax1.set_zlabel('Z')

288

ax1.legend()

289

ax1.set_title('3D Uncertainty Ellipsoid')

290

291

# 2D projection

292

ax2 = fig.add_subplot(122)

293

projection = pu.to_projected_ellipsoid(mean_pos, cov_pos[:2, :2])

294

ax2.plot(projection[:, 0], projection[:, 1], 'b-', alpha=0.7)

295

ax2.scatter(*mean_pos[:2], c='red', s=100, label='Mean')

296

ax2.set_xlabel('X')

297

ax2.set_ylabel('Y')

298

ax2.legend()

299

ax2.set_title('2D Projection')

300

ax2.set_aspect('equal')

301

302

plt.tight_layout()

303

plt.show()

304

```

305

306

### Uncertainty Propagation Chain

307

308

```python

309

import numpy as np

310

import pytransform3d.uncertainty as pu

311

import pytransform3d.transformations as pt

312

313

# Create chain of uncertain transformations

314

transforms = []

315

covariances = []

316

317

# Base to sensor mount

318

T_base_sensor = pt.transform_from(p=[0.1, 0, 0.5])

319

cov_base_sensor = np.diag([0.001, 0.001, 0.001, 0.0001, 0.0001, 0.0001])

320

transforms.append(T_base_sensor)

321

covariances.append(cov_base_sensor)

322

323

# Sensor mount to camera

324

T_sensor_cam = pt.transform_from(p=[0.05, 0.02, 0])

325

cov_sensor_cam = np.diag([0.002, 0.002, 0.002, 0.0005, 0.0005, 0.0005])

326

transforms.append(T_sensor_cam)

327

covariances.append(cov_sensor_cam)

328

329

# Propagate uncertainty through chain

330

T_result = transforms[0]

331

cov_result = covariances[0]

332

333

for i in range(1, len(transforms)):

334

T_result, cov_result = pu.concat_globally_uncertain_transforms(

335

T_result, cov_result, transforms[i], covariances[i]

336

)

337

338

print(f"Final transformation: {T_result[:3, 3]}")

339

print(f"Final uncertainty (diagonal): {np.diag(cov_result)}")

340

print(f"Position std dev: {np.sqrt(np.diag(cov_result)[:3])}")

341

print(f"Orientation std dev: {np.sqrt(np.diag(cov_result)[3:])}")

342

```