Coal (Flexible Collision Library Extension)
Coal is an extension of the Flexible Collision Library (FCL) that provides efficient implementations of GJK and EPA algorithms for collision detection and distance computation in robotics and related fields. It offers robust Python bindings for easy prototyping and integration. Originally a fork named HPP-FCL, it was officially renamed to Coal in 2024. The library is actively maintained, with version 3.0.2 being the latest stable release.
Common errors
-
ERROR: Could not build wheels for coal which use PEP 517 and cannot be installed directly
cause This error occurs when `pip` cannot find a pre-built binary wheel for your system and attempts to build from source, but the necessary C++ compilers, CMake, or other build dependencies are missing or misconfigured. This is common for Python packages with underlying C++ code.fixInstall a C++ compiler (e.g., `build-essential` on Debian/Ubuntu, Xcode Command Line Tools on macOS, Visual Studio with C++ development tools on Windows) and CMake. Alternatively, use `conda install -c conda-forge coal` if available, as conda often provides pre-compiled binaries with all dependencies. -
ModuleNotFoundError: No module named 'coal'
cause The `coal` package was not successfully installed, or you are attempting to import it using an incorrect name. This can also happen if you previously installed the old `hpp-fcl` package.fixEnsure the installation was successful (`pip install coal` or `conda install -c conda-forge coal`). If migrating from `hpp-fcl`, verify that the old package is uninstalled and `coal` is correctly installed, and update your import statements from `import hppfcl` to `import coal`.
Warnings
- breaking The project was renamed from HPP-FCL to Coal in 2024. Code using the old 'hppfcl' import or package name will break.
- gotcha Direct `pip install coal` might fail if pre-built wheels are not available for your specific Python version and operating system, often requiring manual compilation.
- gotcha Coal explicitly implements its own GJK and EPA algorithms and does not rely on `libccd`, a common component in other Flexible Collision Library (FCL) wrappers.
Install
-
pip install coal -
conda install -c conda-forge coal
Imports
- coal
import hppfcl
import coal
- Transform3s
import coal trans = coal.Transform3s()
Quickstart
import numpy as np
import coal
# Define geometries
radius = 0.1
length = 0.5
capsule1_geom = coal.Capsule(radius, length)
capsule2_geom = coal.Capsule(radius, length)
# Define poses (transformations)
# Capsule 1 at origin, identity orientation
capsule1_tf = coal.Transform3s.Identity()
# Capsule 2 shifted along X-axis
capsule2_tf = coal.Transform3s.Identity()
capsule2_tf.translation[:] = np.array([0.2, 0.0, 0.0])
# Create collision objects
obj1 = coal.CollisionObject(capsule1_geom, capsule1_tf)
obj2 = coal.CollisionObject(capsule2_geom, capsule2_tf)
# Perform collision check
req = coal.CollisionRequest()
res = coal.CollisionResult()
# Note: coal.collide returns a boolean indicating collision state
collision_occurred = coal.collide(obj1, obj2, req, res)
if collision_occurred:
print(f"Collision detected! Number of contacts: {len(res.contacts)}")
for contact in res.contacts:
print(f" Contact point: {contact.pos.transpose()}, Normal: {contact.normal.transpose()}")
else:
print("No collision detected.")
# Example for distance computation
req_dist = coal.DistanceRequest()
res_dist = coal.DistanceResult()
distance_found = coal.distance(obj1, obj2, req_dist, res_dist)
if distance_found:
print(f"Minimum distance: {res_dist.min_distance}")
print(f"Closest point on obj1: {res_dist.nearest_points[0].transpose()}")
print(f"Closest point on obj2: {res_dist.nearest_points[1].transpose()}")