Python example: mrpt_obs_example.py
Sensor observations, odometry motion models and rawlogs with mrpt.obs.
Modules: mrpt.obs, mrpt.poses, mrpt.core
1#!/usr/bin/env python3
2"""
3Sensor observations, odometry motion models and rawlogs with mrpt.obs.
4
5Demonstrates:
6 - CObservation2DRangeScan: 2D laser scan, numpy helpers
7 - CObservationOdometry: odometry reading
8 - CObservationIMU: IMU data
9 - CActionRobotMovement2D + CActionCollection
10 - CSensoryFrame: bundle of observations
11"""
12
13import math, numpy as np
14from mrpt.obs import (
15 CObservation2DRangeScan,
16 CObservationOdometry,
17 CObservationIMU,
18 CActionRobotMovement2D,
19 CActionCollection,
20 CSensoryFrame,
21)
22from mrpt.poses import CPose2D, CPose3D
23from mrpt.core import Clock
24
25# ---------------------------------------------------------------------------
26# CObservation2DRangeScan
27# ---------------------------------------------------------------------------
28scan = CObservation2DRangeScan()
29scan.sensorLabel = "LIDAR_FRONT"
30scan.aperture = math.pi # 180° FOV
31scan.maxRange = 80.0
32scan.rightToLeft = True
33scan.resizeScan(360) # 0.5° resolution
34
35# Fill synthetic ranges (arc at 5 m)
36for i in range(360):
37 scan.setScanRange(i, 5.0)
38 scan.setScanRangeValidity(i, True)
39
40print(f"CObservation2DRangeScan: {scan}")
41print(f" getScanSize = {scan.getScanSize()}")
42print(f" getScanRange(180) = {scan.getScanRange(180):.2f} m")
43
44ranges = scan.getScanRangesAsNumpy()
45valid = scan.getValidRangesAsNumpy()
46print(f" ranges numpy: shape={ranges.shape}, mean={ranges.mean():.2f}")
47assert valid.all(), "All rays should be valid"
48print(" validity check ✓")
49
50# ---------------------------------------------------------------------------
51# CObservationOdometry
52# ---------------------------------------------------------------------------
53odo = CObservationOdometry()
54odo.sensorLabel = "ODO"
55odo.odometry = CPose2D(1.5, 0.0, 0.1)
56print(f"\nCObservationOdometry: {odo.odometry}")
57
58# ---------------------------------------------------------------------------
59# CActionRobotMovement2D + CActionCollection
60# ---------------------------------------------------------------------------
61action = CActionRobotMovement2D()
62# Probabilistic odometry increment, from a Gaussian motion model:
63motion_model = CActionRobotMovement2D.TMotionModelOptions()
64motion_model.modelSelection = CActionRobotMovement2D.mmGaussian
65action.computeFromOdometry(CPose2D(0.5, 0.0, 0.05), motion_model)
66print(f"\nOdometry pose change PDF mean: {action.poseChange.getMean()}")
67
68col = CActionCollection()
69col.insert(action)
70print(f"\nCActionCollection: {col.size()} actions")
71assert col.size() == 1
72
73# ---------------------------------------------------------------------------
74# CSensoryFrame — bundle of observations
75# ---------------------------------------------------------------------------
76sf = CSensoryFrame()
77sf.insert(scan)
78sf.insert(odo)
79print(f"\nCSensoryFrame: {sf.size()} observations")
80assert sf.size() == 2
81
82# ---------------------------------------------------------------------------
83# Datasets: CRawlog (actions + observations) and CSimpleMap (keyframes)
84# ---------------------------------------------------------------------------
85import os, tempfile
86from mrpt.obs import CRawlog, CSimpleMap
87from mrpt.poses import CPose3DPDFGaussian
88
89rawlog = CRawlog()
90rawlog.insert(col) # the action collection
91rawlog.insert(sf) # the sensory frame
92simplemap = CSimpleMap()
93simplemap.insert(CPose3DPDFGaussian(CPose3D()), sf)
94
95with tempfile.TemporaryDirectory() as tmpdir:
96 fname = os.path.join(tmpdir, "demo.rawlog")
97 assert rawlog.saveToRawLogFile(fname)
98 loaded = CRawlog()
99 assert loaded.loadFromRawLogFile(fname)
100 print(f"\nRawlog saved and loaded back: {loaded}")
101 for i, entry in enumerate(loaded):
102 print(f" [{i}] {type(entry).__name__}")
103 # Large rawlogs are better processed as a stream, see
104 # CRawlog.ReadFromArchive() in global_localization.py
105
106print(f"CSimpleMap: {simplemap}, first keyframe pose: {simplemap[0].pose.getMean()}")