Python binding of OctoMap, the 3D occupancy mapping library.
OctoMap builds a probabilistic 3D occupancy map (an octree) from point clouds:
you stream in sensor measurements and query whether any point in space is
occupied, free, or still unknown. This package exposes that C++ library to
Python with NumPy arrays as the interchange format, so point clouds and queries
are plain np.ndarrays.
pip install octomap-python
Or with uv:
uv add octomap-python
Binary wheels are published for Linux (x86_64, aarch64), macOS (Apple Silicon), and Windows (AMD64), CPython 3.10-3.14. Other platforms build from the sdist and need a C++ compiler.
import numpy as np import octomap # Resolution is the smallest voxel edge length, in meters. octree = octomap.OcTree(0.1) # Insert a point cloud measured from a sensor at `origin`. points = np.random.uniform(-1, 1, size=(1000, 3)) octree.insertPointCloud( pointcloud=points, origin=np.array([0.0, 0.0, 0.0]), ) # Query a coordinate: occupied / free / unknown (never observed). node = octree.search(points[0]) try: print("occupied" if octree.isNodeOccupied(node) else "free") except octomap.NullPointerException: print("unknown") # Bounding box of everything mapped so far. print(octree.getMetricMin(), octree.getMetricMax()) # Persist to / restore from the OctoMap binary format. octree.writeBinary("tree.bt") restored = octomap.OcTree(0.1) restored.readBinary("tree.bt")
ColorOcTree adds a per-voxel RGB color on top of the same occupancy API:
octree = octomap.ColorOcTree(0.1) point = np.array([1.0, 2.0, 3.0]) octree.updateNode(point, True) octree.setNodeColor(point, 255, 0, 0) octree.updateInnerOccupancy() print(octree.search(point).getColor()) # (255, 0, 0) # Color is preserved by the full map format (.ot), not the binary format (.bt). octree.write("tree.ot") restored = octomap.ColorOcTree.read("tree.ot")
Runnable demos live in examples/. pointcloud_to_octree.py
shows the four views from the teaser above (pointcloud / occupied / occupied
(color) / empty) in a single window, with the cameras synchronized so dragging
one view rotates all four together:
git clone --recursive https://github.com/wkentaro/octomap-python.git cd octomap-python uv sync --group examples cd examples uv run python pointcloud_to_octree.py
It builds both an OcTree and a ColorOcTree so the same scan renders as a
red occupancy grid and in its measured RGB color side by side. The viewer
itself (the synced 2x2 window) lives in examples/viewer.py, so the example
reads as a concise walk through the octomap API.
Releases are published to PyPI by the publish workflow, which fires when a
GitHub Release is published. It builds the wheel matrix + sdist and uploads via
PyPI Trusted Publishing (OIDC, no
stored token).
To cut a release:
- Bump
versioninpyproject.tomlto match the new tag and commit it. - Create a GitHub Release with tag
vX.Y.Z(e.g.v1.8.0.13). - The
publishworkflow runs and uploads the built distributions to PyPI.
This is a fork of neka-nat/python-octomap.
BSD-3-Clause (LICENSE)
