问题描述
我试图理解在 3D 中计算点和截锥之间的最短向量的某种实现。最初的想法是在 this paper 中引入的。
因此,如果我们有两个球形物体:物体 A 的半径为 rA,位置为 pA 和速度为 vA,物体 B 的半径为 rB,位置为 pB 和速度为 vB,那么我们可以用更简单的方式来表示,计算相对位置和相对位置速度,假设物体 A 是一个点,物体 B 的半径是 rA + rB。
在 2D 中,这看起来像是从图 (a) 到图 (b) 的转换,其中 tau 只是一个标量因子: 一个
3D 图形很相似,但我们有球体而不是圆形。
现在,如果相对速度向量位于灰色截锥内,我们应该找到向量u,它是相对速度V的最小变化来移动它到圆锥的圆周,如下图所示(注意:P 是相对位置):
这有两种情况:
-
如果相对速度低于截止圆的中心(蓝虚线下方)。在这种情况下,u 将位于截止圆(较小的圆)上。
-
第二种情况,我不明白它是如何计算的,当相对速度高于小圆(球体)的中心时,在这种情况下u将投影到圆锥的切线上。 P 和 V 向量表示的平面与大球体的交集是 u 所在的圆。
const Vector3 relativePosition = other->position_ - position_; const Vector3 relativeVeLocity = veLocity_ - other->veLocity_; const float distSq = absSq(relativePosition); const float combinedRadius = radius_ + other->radius_; const float combinedRadiusSq = sqr(combinedRadius); Plane plane; Vector3 u; if (distSq > combinedRadiusSq) { /* No collision. */ const Vector3 w = relativeVeLocity - tau * relativePosition; /* Vector from cutoff center to relative veLocity. */ const float wLengthSq = absSq(w); const float dotProduct = w * relativePosition; if (dotProduct < 0.0f && sqr(dotProduct) > combinedRadiusSq * wLengthSq) { /* Project on cut-off circle. */ const float wLength = std::sqrt(wLengthSq); const Vector3 unitW = w / wLength; plane.normal = unitW; u = (combinedRadius * tau - wLength) * unitW; } else { **/* Project on cone. I Don't understand this! */ const float a = distSq; const float b = relativePosition * relativeVeLocity; const float c = absSq(relativeVeLocity) - absSq(cross(relativePosition,relativeVeLocity)) / (distSq - combinedRadiusSq); const float t = (b + std::sqrt(sqr(b) - a * c)) / a; const Vector3 ww = relativeVeLocity - t * relativePosition; const float wwLength = abs(ww); const Vector3 unitWW = ww / wwLength; plane.normal = unitWW; u = (combinedRadius * t - wwLength) * unitWW;** } }
我知道最终我们需要找到 t(如代码中所示)来缩放 P。但是,我不明白这里是如何使用叉积的,以及我们试图求解的二次方程代表什么。
解决方法
...虽然我不明白collision avoidance
模型是如何工作的,但似乎可以通过考虑绕轴的一些角度来获得相关方程。
顺便说一句,它看起来像一个不适合SO的纯数学问题。如果您想提出此类问题,Mathematics Stack Exchange 可能是更好的地方。
附录:另一种方法
为了使问题/答案更加具有针对性,我想考虑另一种编码方法的可能性。由于我们可以在实际程序中毫不犹豫地使用很多数学函数(例如asin()
,sqrt()
),因此也可以通过使用数学函数和{来计算没有quadratic equation
的交叉点{1}},如下。
vector algebra