FCL: The Flexible Collision Library 碰撞检测算法库简单笔记
- FCL: The Flexible Collision Library
- 库的编译与安装
- API 简单笔记
- AABB
- 1. 几何体相关
- 1.0 CollisionGeometry
- 1.1 Box
- 1.2 Sphere
- 1.3 Ellipsoid
- 1.4 Capsule
- 1.5 Cone
- 1.6 Cylinder
- 1.7 Convex
- 1.8 Plane
- 1.9 Halfspace
- 1.10 Mesh
- 1.11 Octree
- 2 CollisionObject
- 3 Transform3
- 4 碰撞检测相关
- 4.1 CollisionRequest
- 4.1.1 GJKSolverType
- 4.2 CollisionResult
- 4.3 ContinuousCollisionRequest
- 4.4 ContinuousCollisionResult
- 4.5 collide()
- 4.6 distance()
- 4.7 continuousCollide()
- 4.8 BroadPhaseCollisionManager
- Examples and Tests
- Bullet
Created 2022.07.15 by Cong Yu; Last modified: 2022.07.19-V1.8.2
Contact: windmillyucong@163.com
Copyleft! 2022 Cong Yu. Some rights reserved.
FCL: The Flexible Collision Library
- github https://github.com/flexible-collision-library/fcl
- homepage https://flexible-collision-library.github.io/index.html
库的编译与安装
依赖
- ccd
- octomap
ccd
1
2
3
4
5
6
7
8
git clone https://github.com/danfis/libccd.git
cd libccd
mkdir build
cd build
cmake ..
make -j4
sudo make install
如果需要添加ccd的编译选项,可在cmakefile中添加
1
2
3
4
# Use "-fPIC" / "-fPIE" for all targets by default, including static libs
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# CMake doesn't add "-pie" by default for executables (CMake issue #14983)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
octomap
1
2
3
4
5
6
7
8
9
git clone https://github.com/Octomap/octomap.git
cd octomap
git checkout v1.9.0
mkdir build
cd build
camke ..
make -j4
sudo make install
FCL
1
2
3
4
5
6
7
8
9
git clone https://github.com/flexible-collision-library/fcl.git
cd fcl
git checkout 0.7.0
mkdir build
cd build
cmake ..
make -j4
sudo make install
API 简单笔记
AABB
- the AABB collision structure, which is a box in 3D space determined by two diagonal points. 由两个对角点表达的三维空间
- 一个基本的数据结构
1. 几何体相关
1.0 CollisionGeometry
- The geometry for the object for collision or distance computation.
- 碰撞几何的虚基类
CollisionGeometryf, CollisionGeometryd
1
2
using CollisionGeometryf = CollisionGeometry<float>;
using CollisionGeometryd = CollisionGeometry<double>;
OBJECT_TYPE
1
2
/// @brief object type: BVH (mesh, points), basic geometry, octree
enum OBJECT_TYPE {OT_UNKNOWN, OT_BVH, OT_GEOM, OT_OCTREE, OT_COUNT};
NODE_TYPE
1
2
3
/// @brief traversal node type: bounding volume (AABB, OBB, RSS, kIOS, OBBRSS, KDOP16, KDOP18, kDOP24), basic shape (box, sphere, ellipsoid, capsule, cone, cylinder, convex, plane, halfspace, triangle), and octree
enum NODE_TYPE {BV_UNKNOWN, BV_AABB, BV_OBB, BV_RSS, BV_kIOS, BV_OBBRSS, BV_KDOP16, BV_KDOP18, BV_KDOP24,
GEOM_BOX, GEOM_SPHERE, GEOM_ELLIPSOID, GEOM_CAPSULE, GEOM_CONE, GEOM_CYLINDER, GEOM_CONVEX, GEOM_PLANE, GEOM_HALFSPACE, GEOM_TRIANGLE, GEOM_OCTREE, NODE_COUNT};
computeLocalAABB()
- 计算AABB
computeCOM()
- 计算中心点
computeMomentofInertia()
- compute the inertia matrix, related to the origin. 计算关于原点的惯性矩阵
computeVolume()
- 计算体积
computeMomentofInertiaRelatedToCOM()
- 计算关于中心的惯性矩阵
1.1 Box
- 立方体
Boxf, Boxd
1
2
using Boxf = Box<float>;
using Boxd = Box<double>;
Box()
1
2
3
4
5
/// @brief Constructor
Box(S x, S y, S z);
/// @brief Constructor
Box(const Vector3<S>& side);
- 构造参数:xyz 或者 vector3S
getBoundVertices()
- get the vertices of some convex shape which can bound this shape in a specific configuration 计算一组包裹该形状的顶点
- 返回的是立方体的12个顶点
1.2 Sphere
- 球体
Spheref, Sphered
1
2
using Spheref = Sphere<float>;
using Sphered = Sphere<double>;
Sphere()
1
2
/// @brief Constructor
Sphere(S radius);
- 构造参数
- radius: 球体半径
getBoundVertices()
- 返回包裹球体的顶点集合
- 通常返回球体表面的采样点
1.3 Ellipsoid
- 椭球体
Ellipsoidf, Ellipsoidd
1
2
using Ellipsoidf = Ellipsoid<float>;
using Ellipsoidd = Ellipsoid<double>;
Ellipsoid()
1
2
3
4
5
/// @brief Constructor
Ellipsoid(S a, S b, S c);
/// @brief Constructor
Ellipsoid(const Vector3<S>& radii);
- 构造参数
- a, b, c: 椭球体在x、y、z轴方向的半径
- radii: 三个轴方向半径组成的向量
getBoundVertices()
- 返回包裹椭球体的顶点集合
- 椭球体表面的采样点
1.4 Capsule
- 胶囊体
Capsule()
1
2
/// @brief Constructor
Capsule(S radius, S lz);
- 构造参数
- radius: 半径
- lz: z方向的长度
getBoundVertices()
- 返回包裹它的36个点
1.5 Cone
- 椎体
Cone()
1
Cone(S radius, S lz);
- 构造参数
- radius: 底圆半径
- lz: z反向长度
1.6 Cylinder
- 圆柱体
Cylinderf, Cylinderd
1
2
using Cylinderf = Cylinder<float>;
using Cylinderd = Cylinder<double>;
Cylinder()
1
2
/// @brief Constructor
Cylinder(S radius, S lz);
- 构造参数
- radius: 圆柱体底面半径
- lz: 圆柱体沿z轴方向的高度
getBoundVertices()
- 返回包裹圆柱体的顶点集合
- 包括圆柱体两个底面圆周上的点和侧面的采样点
1.7 Convex
- 凸多面体
Convexf, Convexd
1
2
using Convexf = Convex<float>;
using Convexd = Convex<double>;
Convex()
1
2
3
4
5
/// @brief Constructor
Convex(const std::shared_ptr<const std::vector<Vector3<S>>>& vertices,
int num_faces,
const std::shared_ptr<const std::vector<int>>& faces,
bool throw_if_invalid = false);
- 构造参数
- vertices: 凸多面体的顶点集合
- num_faces: 面的数量
- faces: 面的索引信息
- throw_if_invalid: 是否在输入无效时抛出异常
getBoundVertices()
- 返回凸多面体的所有顶点
1.8 Plane
- 无限平面
Planef, Planed
1
2
using Planef = Plane<float>;
using Planed = Plane<double>;
Plane()
1
2
3
4
5
/// @brief Constructor
Plane(const Vector3<S>& n, S d);
/// @brief Constructor
Plane(S a, S b, S c, S d);
- 构造参数
- n: 平面法向量
- d: 平面到原点的距离
- a, b, c, d: 平面方程 ax + by + cz + d = 0 的系数
特点
- 平面是无限延伸的,主要用于半空间碰撞检测
- 平面方程为 n·x + d = 0,其中n是单位法向量
1.9 Halfspace
- 半空间
Halfspacef, Halfspaced
1
2
using Halfspacef = Halfspace<float>;
using Halfspaced = Halfspace<double>;
Halfspace()
1
2
3
4
5
/// @brief Constructor
Halfspace(const Vector3<S>& n, S d);
/// @brief Constructor
Halfspace(S a, S b, S c, S d);
- 构造参数
- n: 半空间边界平面的法向量
- d: 平面到原点的距离
- a, b, c, d: 平面方程 ax + by + cz + d = 0 的系数
特点
- 半空间由一个平面分割三维空间得到
- 法向量指向半空间的”内部”
- 常用于表示约束条件或障碍物边界
1.10 Mesh
- 三角网格模型
BVHModel
1
2
template<typename BV>
class BVHModel : public CollisionGeometry<typename BV::S>
- FCL中网格模型通过BVHModel类实现
- BV是边界体积类型,如OBB、AABB、RSS等
BVHModelf, BVHModeld
1
2
using BVHModelf = BVHModel<OBBf>;
using BVHModeld = BVHModel<OBBd>;
构建网格模型
1
2
3
4
5
// 创建网格模型
BVHModel<OBB<S>> mesh;
mesh.beginModel();
mesh.addSubModel(vertices, triangles);
mesh.endModel();
- beginModel(): 开始构建模型
- addSubModel(): 添加顶点和三角形数据
- endModel(): 完成模型构建
特点
- 支持多种边界体积层次结构(BVH)
- 可以处理复杂的三角网格模型
- 提供高效的碰撞检测性能
1.11 Octree
- 八叉树模型
OcTree
1
2
template<typename S>
class OcTree : public CollisionGeometry<S>
OcTreef, OcTreed
1
2
using OcTreef = OcTree<float>;
using OcTreed = OcTree<double>;
OcTree()
1
2
/// @brief Constructor
OcTree(const std::shared_ptr<const octomap::OcTree>& tree);
- 构造参数
- tree: octomap库中的八叉树对象
特点
- 基于octomap库实现
- 适用于处理体素化的三维环境
- 支持动态环境的高效表示和碰撞检测
- 常用于机器人路径规划和SLAM应用
2 CollisionObject
- the object for collision or distance computation, contains the geometry and the transform information
-
CollisionObject 可由 CollisionGeometry对象+Transform对象 构造出
1 2 3 4 5
//geom and tf are the geometry and the transform of the object std::shared_ptr<BVHModel<OBBRSSf>> geom = ... Transform3f tf = ... //Combine them together CollisionObjectf* obj = new CollisionObjectf(geom, tf);
3 Transform3
- 一个Transform对象由R和t构成
1
2
3
4
5
6
7
8
9
// R and T are the rotation matrix and translation vector
Matrix3f R;
Vector3f T;
// code for setting R and T
...
// transform is configured according to R and T
Transform3f pose = Transform3f::Identity();
pose.linear() = R;
pose.translation() = T;
linear()
translation()
4 碰撞检测相关
4.1 CollisionRequest
CollisionRequest()
1
CollisionRequest (size_t num_max_contacts_=1, bool enable_contact_=false, size_t num_max_cost_sources_=1, bool enable_cost_=false, bool use_approximate_cost_=true, GJKSolverType gjk_solver_type_=GST_LIBCCD)
-
参数说明
- num_max_contacts_: The maximum number of contacts will return.
- enable_contact_: whether the contact information (normal, penetration depth and contact position) will return
-
通常设置
1 2
int num_max_contacts = std::numeric_limits<int>::max(); bool enable_contact = true;
4.1.1 GJKSolverType
- Type of narrow phase GJK solver.
1
enum GJKSolverType { GST_LIBCCD, GST_INDEP }
- GST_LIBCCD
- GST_INDEP
4.2 CollisionResult
- 碰撞检测结果
CollisionResultf, CollisionResultd
1
2
using CollisionResultf = CollisionResult<float>;
using CollisionResultd = CollisionResult<double>;
主要方法
numContacts()
1
size_t numContacts() const;
- 返回碰撞接触点的数量
getContacts()
1
void getContacts(std::vector<Contact<S>>& contacts) const;
- 获取所有碰撞接触点信息
- contacts: 输出参数,存储Contact对象的向量
isCollision()
1
bool isCollision() const;
- 返回是否发生碰撞
clear()
1
void clear();
- 清空碰撞结果
Contact结构
1
2
3
4
5
6
7
template<typename S>
struct Contact {
Vector3<S> pos; // 接触点位置
Vector3<S> normal; // 接触点法向量
S penetration_depth; // 穿透深度
int b1, b2; // 碰撞的两个基本形状索引
};
4.3 ContinuousCollisionRequest
- 连续碰撞检测请求
ContinuousCollisionRequest()
1
2
3
4
5
6
7
8
ContinuousCollisionRequest(size_t num_max_contacts_ = 1,
bool enable_contact_ = false,
size_t num_max_cost_sources_ = 1,
bool enable_cost_ = false,
bool use_approximate_cost_ = true,
CCDSolverType ccd_solver_type_ = CCDC_NAIVE,
GJKSolverType gjk_solver_type_ = GST_LIBCCD,
S ccd_motion_type_ = CCDM_TRANS);
- 参数说明
- ccd_solver_type_: 连续碰撞检测求解器类型
- ccd_motion_type_: 运动类型(平移、旋转等)
CCDSolverType
1
2
3
4
5
6
enum CCDSolverType {
CCDC_NAIVE, // 朴素方法
CCDC_CONSERVATIVE_ADVANCEMENT, // 保守推进方法
CCDC_RAY_SHOOTING, // 射线投射方法
CCDC_POLYNOMIAL_SOLVER // 多项式求解方法
};
4.4 ContinuousCollisionResult
- 连续碰撞检测结果
主要属性
1
2
3
4
bool is_collide; // 是否发生碰撞
S time_of_contact; // 碰撞发生时间 (0-1之间)
Vector3<S> contact_tf1; // 对象1在碰撞时刻的位置
Vector3<S> contact_tf2; // 对象2在碰撞时刻的位置
主要方法
clear()
1
void clear();
- 清空连续碰撞结果
特点
- 用于运动物体间的碰撞检测
- 可以预测碰撞发生的时间
- 支持多种运动模式(直线运动、样条运动等)
4.5 collide()
1
2
3
4
5
6
7
8
9
// Given two objects o1 and o2
CollisionObjectf* o1 = ...
CollisionObjectf* o2 = ...
// set the collision request structure, here we just use the default setting
CollisionRequest request;
// result will be returned via the collision result structure
CollisionResult result;
// perform collision test
collide(o1, o2, request, result);
4.6 distance()
1
2
3
4
5
6
7
8
9
// Given two objects o1 and o2
CollisionObjectf* o1 = ...
CollisionObjectf* o2 = ...
// set the distance request structure, here we just use the default setting
DistanceRequest request;
// result will be returned via the collision result structure
DistanceResult result;
// perform distance test
distance(o1, o2, request, result);
4.7 continuousCollide()
1
2
3
4
5
6
7
8
9
10
11
12
13
// Given two objects o1 and o2
CollisionObjectf* o1 = ...
CollisionObjectf* o2 = ...
// The goal transforms for o1 and o2
Transform3f tf_goal_o1 = ...
Transform3f tf_goal_o2 = ...
// set the continuous collision request structure, here we just use the default
// settin
ContinuousCollisionRequest request;
// result will be returned via the continuous collision result structure
ContinuousCollisionResult result;
// perform continuous collision test
continuousCollide(o1, tf_goal_o1, o2, tf_goal_o2, request, result);
4.8 BroadPhaseCollisionManager
1
2
3
4
5
6
7
// Initialize the collision manager for the first group of objects.
// FCL provides various different implementations of CollisionManager.
// Generally, the DynamicAABBTreeCollisionManager would provide the best
// performance.
BroadPhaseCollisionManagerf* manager1 = new DynamicAABBTreeCollisionManagerf();
// Initialize the collision manager for the second group of objects.
BroadPhaseCollisionManagerf* manager2 = new DynamicAABBTreeCollisionManagerf();
registerObject()
1
2
3
4
5
6
7
8
9
// To add objects into the collision manager, using
// BroadPhaseCollisionManager::registerObject() function to add one object
std::vector<CollisionObjectf*> objects1 = ...
for(std::size_t i = 0; i < objects1.size(); ++i)
manager1->registerObject(objects1[i]);
// Another choose is to use BroadPhaseCollisionManager::registerObjects()
// function to add a set of objects
std::vector<CollisionObjectf*> objects2 = ...
manager2->registerObjects(objects2);
setup()
collide()
distance()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// In order to collect the information during broadphase, CollisionManager
// requires two settings:
// a) a callback to collision or distance;
// b) an intermediate data to store the information generated during the
// broadphase computation.
// For convenience, FCL provides default callbacks to satisfy a) and a
// corresponding call back data to satisfy b) for both collision and distance
// queries. For collision use DefaultCollisionCallback and DefaultCollisionData
// and for distance use DefaultDistanceCallback and DefaultDistanceData.
// The default collision/distance data structs are simply containers which
// include the request and distance structures for each query type as mentioned
// above.
DefaultCollisionData collision_data;
DefaultDistanceData distance_data;
// Setup the managers, which is related with initializing the broadphase
// acceleration structure according to objects input
manager1->setup();
manager2->setup();
// Examples for various queries
// 1. Collision query between two object groups and get collision numbers
manager2->collide(manager1, &collision_data, DefaultCollisionFunction);
int n_contact_num = collision_data.result.numContacts();
// 2. Distance query between two object groups and get the minimum distance
manager2->distance(manager1, &distance_data, DefaultDistanceFunction);
double min_distance = distance_data.result.min_distance;
// 3. Self collision query for group 1
manager1->collide(&collision_data, DefaultCollisionFunction);
// 4. Self distance query for group 1
manager1->distance(&distance_data, DefaultDistanceFunction);
// 5. Collision query between one object in group 1 and the entire group 2
manager2->collide(objects1[0], &collision_data, DefaultCollisionFunction);
// 6. Distance query between one object in group 1 and the entire group 2
manager2->distance(objects1[0], &distance_data, DefaultDistanceFunction);
Examples and Tests
- examples
- test_fcl_collision.cpp: provide examples for collision test
- test_fcl_distance.cpp: provide examples for distance test
- test_fcl_broadphase.cpp: provide examples for broadphase collision/distance test
- test_fcl_frontlist.cpp: provide examples for frontlist collision acceleration
- test_fcl_octomap.cpp: provide examples for collision/distance computation between octomap data and other data types.
- unit-tests
- https://github.com/flexible-collision-library/fcl/tree/master/test
Bullet
- github https://github.com/bulletphysics/bullet3
- homepage https://pybullet.org/wordpress/