Python example: mrpt_poses_example.py
SE(2) and SE(3) pose composition, Lie algebra and pose PDFs with mrpt.poses.
Modules: mrpt.poses, mrpt.math
1#!/usr/bin/env python3
2"""
3SE(2) and SE(3) pose composition, Lie algebra and pose PDFs with mrpt.poses.
4
5Demonstrates:
6 - CPose2D: 2D pose composition, inverse, norm
7 - CPose3D: 3D pose, static builders, rotation matrix, inverseComposePoint
8 - CPose3DPDFGaussian: Gaussian PDF over SE(3)
9 - SE_average2 / SE_average3: pose averaging on the Lie group
10 - CPoint2D / CPoint3D: bare point types
11"""
12
13import math
14import numpy as np
15from mrpt.poses import (
16 CPose2D, CPose3D,
17 CPose3DPDFGaussian,
18 SE_average2, SE_average3,
19 CPoint2D, CPoint3D,
20)
21
22# ---------------------------------------------------------------------------
23# CPose2D — 2D pose arithmetic
24# ---------------------------------------------------------------------------
25print("── CPose2D ─────────────────────────────────")
26p1 = CPose2D(1.0, 2.0, math.radians(45.0))
27print(f"p1 = {p1}")
28
29p1.x += 0.5
30p1.phi = math.radians(90.0)
31print(f"p1 modified: {p1} norm={p1.norm():.4f}")
32
33p2 = CPose2D(2.0, 0.0, 0.0)
34p3 = p1 + p2
35print(f"p3 = p1 + p2: {p3}")
36
37p3_inv = p3.inverse()
38print(f"p3 inverse: {p3_inv}")
39
40# round-trip: p + (-p) ≈ identity
41identity = p3 + p3_inv
42print(f"p3 + p3_inv ≈ 0: x={identity.x:.6f} y={identity.y:.6f}")
43assert abs(identity.x) < 1e-6 and abs(identity.y) < 1e-6
44print(" composition round-trip ✓")
45
46# ---------------------------------------------------------------------------
47# CPose3D — 3D pose
48# ---------------------------------------------------------------------------
49print("\n── CPose3D ─────────────────────────────────")
50p3d = CPose3D.FromXYZYawPitchRoll(1.0, 2.0, 3.0, math.radians(30), 0, 0)
51print(f"p3d = {p3d}")
52print(f" z = {p3d.z:.4f}")
53
54p3d.z = 5.0
55print(f" z after set: {p3d.z:.4f}")
56
57import numpy as np
58rot = np.array(p3d.getRotationMatrix().as_numpy())
59print(f" rotation matrix (3x3 numpy):\n{rot}")
60assert rot.shape == (3, 3)
61
62# inverseComposePoint: transform a global point to robot frame
63global_pt = p3d.inverseComposePoint(1.0, 2.0, 5.0)
64print(f" inverseComposePoint((1,2,5)): {global_pt}")
65
66# ---------------------------------------------------------------------------
67# CPoint2D / CPoint3D
68# ---------------------------------------------------------------------------
69pt2 = CPoint2D(3.0, 4.0)
70pt3 = CPoint3D(1.0, 2.0, 3.0)
71print(f"\nCPoint2D: {pt2}")
72print(f"CPoint3D: {pt3}")
73
74# ---------------------------------------------------------------------------
75# CPose3DPDFGaussian — Gaussian distribution over SE(3)
76# ---------------------------------------------------------------------------
77print("\n── CPose3DPDFGaussian ──────────────────────")
78mean_pose = CPose3D(0, 0, 0, 0, 0, 0)
79pdf = CPose3DPDFGaussian(mean_pose)
80print(f"PDF mean: {pdf.mean}")
81
82pdf.mean = CPose3D(10, 0, 0, 0, 0, 0)
83print(f"PDF mean after set: {pdf.mean}")
84
85sample = pdf.drawSingleSample()
86print(f"Random sample: {sample}")
87
88# ---------------------------------------------------------------------------
89# SE_average3 — Lie-group mean of SE(3) poses
90# ---------------------------------------------------------------------------
91print("\n── SE_average3 ─────────────────────────────")
92avg = SE_average3()
93avg.append(CPose3D(10.0, 0.0, 0.0, 0, 0, 0))
94avg.append(CPose3D(10.1, 0.1, 0.0, 0, 0, 0))
95avg.append(CPose3D( 9.9, -0.1, 0.0, 0, 0, 0))
96result = avg.get_average()
97print(f"Average of 3 poses near (10,0,0): {result}")
98assert abs(result.x - 10.0) < 0.2
99print(" average check ✓")
100
101# SE_average2 — same for SE(2)
102avg2 = SE_average2()
103avg2.append(CPose2D(1.0, 0.0, 0.0))
104avg2.append(CPose2D(1.2, 0.0, 0.0))
105result2 = avg2.get_average()
106print(f"\nAverage of 2D poses: {result2}")
107
108# ---------------------------------------------------------------------------
109# Particle-based pose PDFs
110# ---------------------------------------------------------------------------
111from mrpt.math import TPose2D
112from mrpt.poses import CPosePDFParticles
113
114particles = CPosePDFParticles(1000)
115particles.resetUniform(-1.0, 1.0, -1.0, 1.0)
116cov, mean = particles.getCovarianceAndMean()
117print(f"\n1000 uniform particles: mean={mean}")
118print(f" covariance diagonal: {np.diag(np.asarray(cov))}")
119particles.resetAroundSetOfPoses([TPose2D(5.0, 0.0, 0.0)], 1000, 0.1, 0.1, 0.05)
120print(f" after resetAroundSetOfPoses: mean={particles.getMean()}")
121arr = particles.getParticlesAsNumpy() # columns: x, y, phi, log_weight
122print(f" particles as numpy: shape={arr.shape}")