OBB盒构建方法

本文主要参考:Morgan_Kaufmann.Real-Time Collision Detection(2005)

包围盒是一个简单的几何空间,里面包含着复杂形状的物体。最常见的包围盒算法有包围球(Sphere),轴对齐包围盒(Axis-aligned bounding box)AABB盒,OBB方向包围盒(Oriented bounding box), FDH固定方向凸包(Fixed directions hulls或k-DOP)等。这些表示法对于规则形状的物体较为有效,计算速度较快,但在捕捉不规则形状时由于包含了一定的无用空间,因此可能存在一定的精度损失。

OBB紧凑地贴合物体的实际形状,与物体的主要方向对齐。这种贴合性使得OBB能够较精确地反映被包围物体的外形,它减少了不必要的安全距离。

虽然OBB的碰撞检测计算复杂度高于AABB,但它在处理复杂或长条形状物体时更为有效,因为它减少了误报的碰撞检测次数。与AABB不同,OBB随物体旋转而旋转,保持与物体的相对方向一致。这使得OBB在处理旋转物体时保持了包围盒的大小和形状不变,从而在动态环境中提供了更稳定的避障性能。

OBB盒有不同的表示方法,首选的是一个中心点加一个主方向矩阵和三个半边长度,这种表示方法更易于进行包围盒与包围盒之间的交叉测试。

第一步,准备数据,收集物体的所有顶点数据。

第二步,计算所有顶点的平均位置即几何中心,可以初步确定为OBB盒的中心点。

中心点=\frac{1}{N}\sum_{i}^{N} Pi  。其中,N是顶点的数量,Pi是第 i个顶点的位置。

第三步,进行PCA分析,获取这组数据的主要分布方向。

主成分分析(PCA)是一种通过正交变换,将一组可能相关的变量集合变换成一组线性不相关的变量集合,即主成分。在这里引入协方差矩阵的概念,协方差表示的使两个变量之间的线性相关程度。协方差越小则表示两个变量之间越独立,即线性相关性小。

cov(X_{i},X_{j})=E[(X_{i}-\mu _{i})(X_{j}-\mu _{j})]

由此可以得到一个协方差矩阵(if 三维数据)

A= \begin{pmatrix} cov(x,x)& cov(x,y) & cov(x,z)\\ cov(x,y)& cov(y,y) &cov(y,z) \\ cov(x,z) &cov(y,z) & cov(z,z) \end{pmatrix}

主对角线的元素表示变量的方差,主对角线的元素较大则表示强信号。非主对角线的元素表示变量之间的协方差,较大的非对角线元素表示数据的畸变。由于协方差矩阵是一个实对称矩阵,所以为了减小畸变,可以重新定义变量间的线性组合,将协方差矩阵相似对角化。

Q^{T}AQ=Q^{-1}AQ=diag(\lambda _{1},\lambda _{2},\lambda _{3})

通过矩阵相似变换可以求得其特征值\lambda和特征向量Q,特征向量代表数据中的主要方向,而对应的特征值则表示这些方向的方差大小,即分布的广度。

第四步,确定OBB包围盒的朝向和中心点。

第五步,投影计算半边长度。将各个顶点投影到主轴上,计算投影后的极值,物体的尺寸即可通过计算最大值和最小值的差来得到,由此可以得到各个主轴方向的半边长度。

由此,基本上可以生成一个OBB包围盒。

如何判断多个OBB盒是否相撞?

分离轴定理:即如果存在一个轴(即分离轴),使得将两个对象在这个轴上的投影分开,那么这两个对象不相交。而在两个OBB包围盒,至多存在15个轴。两个OBB的每个局部坐标轴(共6个轴);两个盒子的轴之间的交叉乘积(可能的9个轴)。但是绝多数情况下是不需要全算完的。

两个盒子不发生碰撞的充要条件是\left | T\cdot L \right |>r_{A}+r_{B}.

代码可参考Chatgpt生成,MATLAB的确实会简单很多。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
首先,需要理解obb的概念和计算方法obb是一种用于包围物体的子,它的面朝物体的表面,可以用来快速计算物体的碰撞和运动。obb的计算方法通常是通过求解物体的协方差矩阵,然后求解矩阵的特征值和特征向量,进而计算obb的位置和方向。 在Eigen库中,可以使用Matrix类来表示矩阵,并使用SelfAdjointEigenSolver类来求解特征值和特征向量。下面是一个示例代码,用于计算obb的位置、方向和大小。 ```c++ #include <Eigen/Dense> #include <Eigen/Eigenvalues> using namespace Eigen; void computeOBB(const MatrixXf& points, Vector3f& position, Matrix3f& orientation, Vector3f& halfExtents) { int numPoints = points.cols(); // Compute the center of mass Vector3f center = points.rowwise().mean(); // Compute the covariance matrix Matrix3f cov = Matrix3f::Zero(); for (int i = 0; i < numPoints; i++) { Vector3f p = points.col(i) - center; cov += p * p.transpose(); } cov /= numPoints; // Compute the eigenvectors and eigenvalues SelfAdjointEigenSolver<Matrix3f> solver(cov); Vector3f eigenvalues = solver.eigenvalues(); Matrix3f eigenvectors = solver.eigenvectors(); // Set the position to the center of mass position = center; // Set the orientation to the eigenvectors orientation = eigenvectors; // Set the half extents to the square roots of the eigenvalues halfExtents = eigenvalues.array().sqrt(); } ``` 在这个示例代码中,MatrixXf表示一个矩阵,其中每一列代表一个点的坐标。Vector3f和Matrix3f分别表示一个三维向量和一个三维矩阵。SelfAdjointEigenSolver类用于求解协方差矩阵的特征值和特征向量。 在函数的实现中,首先计算点云的中心点,然后计算协方差矩阵。接着,使用SelfAdjointEigenSolver类求解特征值和特征向量。最后,将中心点、特征向量和特征值的平方根设置为obb的位置、方向和大小。 需要注意的是,这个示例代码中没有考虑obb的旋转角度。如果需要计算obb的旋转角度,可以使用Quaternion类来表示四元数,并计算特征向量之间的旋转矩阵。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值