分离轴定律碰撞检测

 

自动驾驶领域在路径规划任务中会需要进行碰撞检测,以及在一些去重算法中,也经常会需要进行碰撞检测。

旋转矩阵

自动驾驶领域中,BEV视角下的车通常都会用一个旋转矩形来表示。目前笔者碰到一个需要是对于多个视角下(多个相机)的检测框,它们在BEV视角下用旋转矩形来表示,只要检测到它们有重叠,就要进行去重。

分离轴定律

两个凸多边形物体,如果我们能找到一个轴,使得两个在物体在该轴上的投影互不重叠,则这两个物体之间没有碰撞发生,该轴为 Separating Axis

一般会去检测垂直于多边形每条边的轴,此时分离轴定律变成:两个多边形在所有轴上的投影都发生重叠,则判定为碰撞;否则,没有发生碰撞。

因此可以使用分离轴定律来进行旋转矩形的碰撞检测。

实现思路

  1. 一个矩形有四条边,因此需要检测四个轴,但是四条边是两两平行的,所以检测两条轴即可。两两矩形都要互相判断,因此需要检测的轴是 4 个。
  2. 矩形在某个轴上的投影只需要将四个顶点投影到此轴上即可,将投影的最小值点和最大值点连线即为此矩形在此轴上的投影。
  3. 如果两个矩形在某个轴上的投影不重叠,则说明两个矩形不相交。

伪代码

def Project(point, axis):
    return Dot(point, axis)

def Dot(point, axis):
    return point.x * axis.x + point.y * axis.y

def Min(projs):
    return min(projs)

def Max(projs):
    return max(projs)

def Collision(rect1, rect2):
    axes = [rect1.axis1, rect1.axis2, rect2.axis1, rect2.axis2]
    for (axis in axes)
    {
        projs_1 = []
        for (corner in rect1)
        {
            projs_1.append(Project(corner, axis))
        }
        projs_2 = []
        for (corner in rect2)
        {
            projs_2.append(Project(corner, axis))
        }
        if (Max(projs_1) < Min(projs_2) || Max(projs_2) < Min(projs_1))
        {
            return false
        }
    }
    return true

参考资料

  1. 矩形旋转碰撞,OBB方向包围盒算法实现
  2. 判断两个旋转矩形是否重叠(相交和包含)