Python example: mrpt_maps_example.py
Point clouds, occupancy grids, voxel maps and multi-maps with mrpt.maps.
Modules: mrpt.maps, mrpt.config, mrpt.obs, mrpt.math, mrpt.poses
1#!/usr/bin/env python3
2"""
3Point clouds, occupancy grids, voxel maps and multi-maps with mrpt.maps.
4
5Demonstrates:
6 - CSimplePointsMap: point cloud creation, numpy import/export
7 - COccupancyGridMap2D: create, set/get cells, numpy export
8"""
9
10import numpy as np
11import tempfile, os
12from mrpt.maps import CSimplePointsMap, COccupancyGridMap2D
13
14# ---------------------------------------------------------------------------
15# CSimplePointsMap — XYZ point cloud
16# ---------------------------------------------------------------------------
17pts = CSimplePointsMap()
18
19# Insert individual points
20for i in range(5):
21 pts.insertPoint(float(i), float(i) * 0.1, 0.0)
22
23print(f"CSimplePointsMap: {len(pts)} points")
24x, y, z = pts.getPoint(2)
25print(f" point[2]: ({x:.2f}, {y:.2f}, {z:.2f})")
26
27# NumPy round-trip
28cloud = np.array([[1.0, 2.0, 3.0],
29 [4.0, 5.0, 6.0],
30 [7.0, 8.0, 9.0]], dtype=np.float32)
31pts2 = CSimplePointsMap()
32pts2.setPointsFromNumpy(cloud)
33arr = pts2.getPointsAsNumpy()
34print(f"\nNumPy round-trip: {arr.shape}")
35np.testing.assert_allclose(arr, cloud, atol=1e-5)
36print(" numpy round-trip ✓")
37
38# Save/load text
39with tempfile.NamedTemporaryFile(suffix=".txt", delete=False) as f:
40 fname = f.name
41try:
42 pts2.save3D_to_text_file(fname)
43 pts3 = CSimplePointsMap()
44 pts3.load3D_from_text_file(fname)
45 assert pts3.size() == 3
46 print(f" save/load text ✓ ({pts3.size()} points)")
47finally:
48 os.unlink(fname)
49
50# ---------------------------------------------------------------------------
51# COccupancyGridMap2D — probabilistic 2D occupancy grid
52# ---------------------------------------------------------------------------
53grid = COccupancyGridMap2D(-5.0, 5.0, -5.0, 5.0, 0.1) # 10x10 m, 0.1 m/cell
54print(f"\nCOccupancyGridMap2D: {grid.getSizeX()}x{grid.getSizeY()} cells, "
55 f"res={grid.getResolution()} m")
56
57# Mark an obstacle cell (low probability = occupied)
58grid.setCell(50, 50, 0.1)
59grid.setPos(1.0, 1.0, 0.1)
60
61print(f" cell(50,50) occupancy = {grid.getCell(50,50):.2f}")
62print(f" pos(1,1) occupancy = {grid.getPos(1.0,1.0):.2f}")
63
64# Index ↔ metric conversion
65ix = grid.x2idx(1.0)
66iy = grid.y2idx(1.0)
67print(f" pos(1,1) → cell index ({ix},{iy})")
68print(f" cell({ix},{iy}) → pos ({grid.idx2x(ix):.2f},{grid.idx2y(iy):.2f})")
69
70# NumPy export
71g_np = grid.getAsNumpy()
72print(f"\nGrid as numpy: shape={g_np.shape}, dtype={g_np.dtype}")
73assert g_np.shape == (grid.getSizeY(), grid.getSizeX())
74print(" numpy export ✓")
75
76# ---------------------------------------------------------------------------
77# CMultiMetricMap: several maps defined in a config file, updated together
78# ---------------------------------------------------------------------------
79import math
80from mrpt.config import CConfigFileMemory
81from mrpt.maps import CMultiMetricMap, TSetOfMetricMapInitializers, CVoxelMap, COctoMap
82from mrpt.obs import CObservation2DRangeScan, CSensoryFrame
83from mrpt.math import TPoint3D
84from mrpt.poses import CPose3D
85
86map_defs = TSetOfMetricMapInitializers()
87map_defs.loadFromConfigFile(CConfigFileMemory(
88 "[Maps]\noccupancyGrid_count=1\npointsMap_count=1\n"
89 "[Maps_occupancyGrid_00_creationOpts]\nresolution=0.05\n"), "Maps")
90multimap = CMultiMetricMap(map_defs)
91print(f"\n{multimap}: {[type(m).__name__ for m in multimap]}")
92
93scan = CObservation2DRangeScan()
94scan.aperture = math.pi
95scan.resizeScan(181)
96for i in range(181):
97 scan.setScanRange(i, 3.0)
98 scan.setScanRangeValidity(i, True)
99sf = CSensoryFrame()
100sf.insert(scan)
101multimap.insertObs(sf) # inserted into both maps
102points = next(m for m in multimap if isinstance(m, CSimplePointsMap))
103print(f" points after inserting a scan: {len(points)}")
104print(f" observation log-likelihood at origin: "
105 f"{multimap.computeObservationLikelihood(scan, CPose3D()):.2f}")
106
107# ---------------------------------------------------------------------------
108# 3D occupancy: sparse voxel map and octomap
109# ---------------------------------------------------------------------------
110voxels = CVoxelMap(0.1)
111voxels.insertPointCloudAsRays(points, TPoint3D(0, 0, 0))
112wall_pt = points.getPoint(90) # (x, y, z) of the central ray end point
113print(f"\nCVoxelMap: {len(voxels.getOccupiedVoxels())} occupied voxels, "
114 f"p(occupied) at a wall = {voxels.getPointOccupancy(*wall_pt):.2f}, "
115 f"at the sensor = {voxels.getPointOccupancy(0.5, 0.0, 0.0):.2f}")
116
117octo = COctoMap(0.1)
118octo.insertPointCloud(points, 0.0, 0.0, 0.0)
119print(f"COctoMap: {octo.size()} nodes")