计算拦截向量

Mik*_*keT 2 c# math vector

我有2个对象(我将它们称为目标拦截器).我知道目标的当前位置和速度.我知道拦截器的当前位置和速度.

从那以后,我现在需要知道的是:

  • 是否可以拦截,即在同一时间点的相同位置.
  • 拦截器需要传递什么载体
  • 拦截需要多长时间

即目标@(120,40),每秒V(5,2)和拦截器@(80,80),可以每秒10的速度行进.

我环顾四周,找到了很多方法来找出他们遇到的点,他们都围绕两个向量之间的角度旋转,因为我不知道第二个向量,我无法计算,我得到了失去了试图解决这个问题.

任何有关如何进行的建议或指导都表示赞赏.

Kev*_*vin 6

鉴于:

在时间0,目标位于A点,拦截器位于B点.在未来的某个时刻,它们将在C点相交.

线段a与点A相对,同样对于b和B,以及c和C.

在此输入图像描述


我们知道A和B的位置.我们可以从目标的航向得出角度CAB.我们知道线段ab的长度比等于(interceptor.speed/target.speed).

首先,找到角度CAB.
设矢量B ^等于目标的速度.
设矢量C ^等于(interceptor.position.x - target.position.x,interceptor.position.y - target.position.y).
使用点积公式确定它们之间的角度.

B dot C = ||B|| * ||C|| * cos(angle)
cos(angle) = (B dot C) / (||B|| * ||C||)
angle = arccos((B dot C) / (||B|| * ||C||))
Run Code Online (Sandbox Code Playgroud)

..."dot"是点积,|| B || 是矢量B的标量大小angle是角度CAB.

现在我们将找到角度ABC.
使用正弦定律,我们知道sin(ABC) / b == sin(CAB) / a.将等式重新排列为ABC = arcsin( sin(CAB) * (b/a) ).
我们在最后一步找到了CAB,我们知道b/a是target.speed/interceptor.speed,所以将这些值插入并找到ABC.

既然你知道两个角度和两个点,你应该能够得到C的位置.如果你使用度数,角度ACB等于180 - (CAB + ABC),或者如果你使用Pi - (CAB + ABC) '使用弧度.使用正弦定律确定边b和c的长度.现在你可以找到T using T = b / target.speed和C using C = target.position + (target.velocity * T).


我的C#有点生疏,所以这里是一个示例Python实现.让我们插入您的示例值,结果是:

Collision pos: Point(163.065368246, 57.2261472985)
Time: 8.61307364926
Angle A: 113.198590514
Angle B: 29.6680851288
Angle C: 37.1333243575
a: 86.1307364926
b: 46.3828210973
c: 56.5685424949
Run Code Online (Sandbox Code Playgroud)

位置和时间与gdir找到的位置和时间相同,所以我非常有信心我们的方法都有效.

编辑:MikeT:C#版本

public static double Dot(Vector a, Vector b)
{
    return a.X * b.X + a.Y * b.Y;
}
public static double Magnitude(Vector vec)
{
    return Math.Sqrt(vec.X * vec.X + vec.Y * vec.Y);
}
public static double AngleBetween(Vector b, Vector c)
{
    return Math.Acos(Dot(b, c) / (Magnitude(b) * Magnitude(c)));
}

public static  Vector? Find_collision_point(Point target_pos, Vector target_vel, Point interceptor_pos, double interceptor_speed)
{
    var k = Magnitude(target_vel) / interceptor_speed;
    var distance_to_target = Magnitude(interceptor_pos - target_pos);

    var b_hat = target_vel;
    var c_hat = interceptor_pos - target_pos;

    var CAB = AngleBetween(b_hat, c_hat);
    var ABC = Math.Asin(Math.Sin(CAB) * k);
    var ACB = (Math.PI) - (CAB + ABC);

    var j = distance_to_target / Math.Sin(ACB);
    var a = j * Math.Sin(CAB);
    var b = j * Math.Sin(ABC);


    var time_to_collision = b / Magnitude(target_vel);
    var collision_pos = target_pos + (target_vel * time_to_collision);

    return interceptor_pos - collision_pos;
}
Run Code Online (Sandbox Code Playgroud)

  • @Kevin这将是arcsin失败,"某种原因"将是数量'sin(CAB)*b/a`大于1(或小于-1).arccos*可以*失败,但仅由于舍入误差(对于近似共线B ^和C ^). (2认同)

gdi*_*dir 6

您可以使用2D矢量计算计算交点.目标沿着一条线移动.我们知道目标的起点,方向和速度.

在任何时候t> = 0,目标位于由x定义的点x处

在此输入图像描述

其中s_t是目标(120,40)的起始点,v_t是目标(5,2)的速度矢量.

我们知道拦截器的起点(s_i),它的速度(v_i),但不知道它的方向.我们可以用起点周围的圆来描述拦截器的范围,其半径随时间增加.在矢量微积分中,我们得到了

在此输入图像描述

其中x是圆上的点,s_i是拦截器(80,80)的起点,r是拦截器在时间t的半径(或范围),v_i是拦截器(10)的速度.

当目标和拦截器在时间t相遇时,它们的位置x必须相等.我们在圆周方程的x中使用线方程的x得到

在此输入图像描述

这只是t 的正规二次方程:

在此输入图像描述

你可以轻松解决这个问题.在这种情况下,您将获得有效且无效的解决方案:

t1 = -5.2328 =>无效,因为t必须> = 0

t2 = 8.61307

现在你知道了,你可以用第一个线方程计算交点.目标和拦截器见面(163.065,57.223)

  • 我喜欢这个答案。您还可以注意到,在某些情况下拦截器无法捕获目标 - 当您的二次方没有实数根 == 当二次方中的线性项(通常为 b^2)小于 4 时,就会发生这种情况* 平方项 * 常数项 (4*a*c)。我知道 Q 中的示例并非如此,但总的来说它可能会发生 (2认同)