给定多维空间以及移动物体的目标位置和速度,如何确定物体是否朝向正确的方向,从而接近目标?
例如,如果我有一个三维空间,我有一个所需的目标位置[0,0,100],我知道我的移动物体的速度为[1,2,4],如何计算移动方向和所需方向之间的差异?
请注意我没有使用统一
答案 0 :(得分:2)
你提出的问题更多的是数学问题,而不是编程问题。我相信它仍然是主题,但这意味着我们将有更多的数学解决方案。我假设你掌握的数学函数很少。
(注意:这将涉及向量。如果变量是粗体,我将其视为向量。)
因此,我们希望达到 P f = [0,0,100]个单位。我们在 P i = [x i ,y i ,z i ] 单位。我们的速度为 v = [1,2,4]单位/帧。
如果我理解正确,我们想知道两件事:
我们只需要解决第二部分,然后我们就可以根据该解决方案找出第一部分。 (我稍后会自己解决第一部分问题。)
为了解决第二部分,我们最好的朋友是dot product!你的问题围绕着向量,而点积可以告诉我们两个向量有多紧密相关。
首先,我们需要两个 victim 向量。我们已经有一个: v ,当前的速度。然后,假设我们有 P i ,我们可以找到所需的路径,即 P i 之间的路径和 P f 。我称之为 s f = P f - P i 强>
(由于缺少用于点积的字符,点( m , n )代表 m 的点积和 n 。)
首先,我们将从维基百科文章提出的点积的一个定义开始:
(Equ 1)
点( v , s f )= || v || || <强>取值<子>˚F子> 强> || COS(Ɵ)
快速注意:双条表示magnitude,它等于矢量分量的平方和,或者
||的 v 强> || = sqrt(v x 2 + v y 2 + v z 2 )
为了使这更容易使用,我假设我们已经提前计算了大小,所以我们可以将它们留在方程式中。
无论如何,(Equ 1)还不够!我们不知道Ɵ或点( v , s f ),那么现在呢?
第一篇维基百科文章中还有另一种点积定义。它是这样的:
(Equ 2)
点( v , s f )= v x s fx + v < sub> y s fy + v z s fz
我们了解所有这些价值观!并且,由于(Equ 1)等于(Equ 2),我们可以将这两个方程组合起来。这让我们:
||的 v 强> || || <强>取值<子>˚F子> 强> || cos(Ɵ)= v x s fx + v y s fy + v z 子>取值<子> FZ 子>
Aaand在身边拖着东西......
cos(Ɵ)=(v x s fx + v y s fy + v z s fz )/(|| v || || s f || )
......或者......
Ɵ= cos -1 ((v x s fx + v y s fy + v z s fz )/(|| v || || s f < / strong> ||))
这是我们最后的等式!
嗯......现在我们实际上已经使用它了。如果你不是数学类型(或者,如果我的解释很糟糕而且我在某个地方失去了你),那么我将归结为最后一个等式可以为我们做些什么。
最后一个等式的结果决定了我们离开的角度。它的范围从0度到180度(或0弧度到π弧度)。 0度意味着我们直接朝向目标,而180度意味着我们正在直接朝向目标。
如果要么|| v ||或|| s f ||为零,则此等式无效。这是有道理的;如果我们已经在我们的目标之上,那么行进距离为零并且没有角度可以计算。同时,如果速度为零,那么我们不会去任何地方,也无法计算角度。请注意,如果其值的所有为零,则向量的幅度仅为零,因此这是一个简单的检查。
对于编码人员来说,我会更加熟悉这一点。
struct Vector3 { double x, y, z; }
float CalcMagnitude(Vector3 v)
{
return sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
}
float CalcAngle(Vector3 currentPos, Vector3 targetPos, Vector3 velocity)
{
Vector3 targetDir = targetPos - currentPos
if( `all the values in targetDir are zero`
or `all the values in velocity are zero` )
{
// We can't really return anything valid. Maybe return
// -1 or throw an exception or something
}
// Calculate the dot product
double numerator =
velocity.x * targetDir.x
+ velocity.y * targetDir.y
+ velocity.z * targetDir.z
double denominator = CalcMagnitude(velocity) * CalcMagnitude(targetDir)
return acos(numerator / denominator)
}