OK, I have a 3d ship with velocity v1, a target ship with velocity v2, and have a projectile that has speed x.
I am wanting to know the facing angle of my ship with v1 to shoot a projectile and get it to collide with target ship.
Canning
Printable View
OK, I have a 3d ship with velocity v1, a target ship with velocity v2, and have a projectile that has speed x.
I am wanting to know the facing angle of my ship with v1 to shoot a projectile and get it to collide with target ship.
Canning
Again, your question is quite vague. I'll try to make reasonable assumptions to fill in the gaps, but if you could be clearer in the future that would be helpful.
If your ship starts at p1 and the target is at p2, as functions of time these positions are p1(t) = p1 + t*v1, p2(t) = p2 + t*v2. Suppose the projectile is fired at velocity v3 at time 0 from position p1. The projectile's position is p3(t) = p1 + t*v3. By assumption, |v3| = x.
You want the line p3(t) and the line p2(t) to intersect, so for some t0,
p3(t0) = p2(t0), i.e.
p1 + t0*v3 = p2 + t0*v2
Physically, v3 must be in the plane containing p1 and the line p2(t), which is spanned by the vectors (p2(1) - p1) and (p2(0) - p1). So, v3 = c (p2(1) - p1) + d (p2(0) - p1) = c (p2 + v2 - p1) + d(p2 - p1) = e*(p2 - p1) + f*(v2) for some constants e and f. Plugging this in to the above and grouping terms about (p2 - p1) and v2 gives
p2 - p1 = t0(v3 - v2)
= t0(e(p2-p1) + f v2 - v2)
=>
(p2 - p1) * (e*t0 - 1) + v2 * t0*(f - 1) = 0
=>
e*t0 = 1 and t0*(f-1) = 0
where the last line follows from the linear independence of (p2 - p1) and v2. [If they're linearly dependent, they're parallel, so the linear combination we choose doesn't particularly matter, allowing us to pick the given constraints anyway.]
From the second equation, t0 = 0 or f=1. If t0=0, the collision occurs immediately, so p2 = p1, which really shouldn't be allowed. So, f=1. Finally, we have our last constraint, |v3| = x. Using dot products and the previous equations, this condition gives a quadratic constraint on t0:
|v3|^2 = x^2 = v3 dot v3
= (e (p2 - p1) + f v2) dot (e (p2 - p1) + f v2)
= e^2 [(p2 - p1) dot (p2 - p1)] + 2ef [(p2 - p1) dot v2] + f^2 [v2 dot v2]
Multiplying the previous equation by t0^2 and using the above relations turns it into
x^2 t0^2 = [(p2 - p1) dot (p2 - p1)] + 2 t0 [(p2 - p1) dot v2] + t0^2 [v2 dot v2]
=> ([v2 dot v2] - x^2) t0^2 + (2 [(p2 - p1) dot v2]) t0 + ([(p2 - p1) dot (p2 - p1)]) = 0
Letting
a = [v2 dot v2] - x^2,
b = 2 [(p2 - p1) dot v2]
c = (p2 - p1) dot (p2 - p1)
from the quadratic equation we finally get
t0 = (-b +/- sqrt(b^2 - 4*a*c)) / (2a)
If the term inside the square root is negative, that indicates the ship is going too quickly for a projectile to ever catch up. A negative solution indicates essentially that a projectile could have been fired in the past from the second ship, hitting the first at t=0. In any case, we'll always want the larger of the two solutions, so we have
t0 = (-b + sqrt(b^2 - 4*a*c)) / (2a)
Since e = 1/t0 and f = 1:
v3 = 1/t0 * (p2 - p1) + v2
In summary,
p1 = initial position of first ship
p2 = initial position of second ship
v3 = velocity vector of projectile [from which you can find an angle if you wish]
v3 = 1/t0 * (p2 - p1) + v2
where
t0 = (-b + sqrt(b^2 - 4*a*c)) / (2a)
a = [v2 dot v2] - x^2,
b = 2 [(p2 - p1) dot v2]
c = (p2 - p1) dot (p2 - p1)
and if b^2 - 4*a*c < 0, there is no solution
[dot indicating the dot product]
It would be good to double-check my algebra, though the final answer is at least reasonable.
Found a tutorial on how to do it.
Here is the code if anyone is interested:
Thanks for your input jemidiah.Code:Public Function GetCrossPoint(ByVal TargetPos As MTV3D65.TV_3DVECTOR, ByVal Pos As MTV3D65.TV_3DVECTOR, ByVal MovementVec As MTV3D65.TV_3DVECTOR, ByVal Speed As Single) As MTV3D65.TV_3DVECTOR
Dim A, B, C, T As Single
Dim Diff As MTV3D65.TV_3DVECTOR
Diff = Maths.VSubtract(TargetPos, Pos)
A = Sqr(MovementVec.x) + Sqr(MovementVec.y) + Sqr(MovementVec.z) - Sqr(Speed)
B = 2 * Diff.x * MovementVec.x + 2 * Diff.y * MovementVec.y + 2 * Diff.z * MovementVec.z
C = Sqr(Diff.x) + Sqr(Diff.y) + Sqr(Diff.z)
If A = 0 Then
GetCrossPoint = TargetPos
Else
T = (-B + System.Math.Sqrt(Sqr(B) - 4 * A * C)) / (2 * A)
If T < 0 Then
T = (-B - System.Math.Sqrt(Sqr(B) - 4 * A * C)) / (2 * A)
End If
If T <= 0 Then
GetCrossPoint = TargetPos
Else
GetCrossPoint.x = TargetPos.x + MovementVec.x * T
GetCrossPoint.y = TargetPos.y + MovementVec.y * T
GetCrossPoint.z = TargetPos.z + MovementVec.z * T
End If
End If
End Function
Canning
I'd like to mention the code you posted and the formulas I gave are essentially identical. You've written out the dot products component-wise while I left them implicit, and I also derived the projectile's velocity vector (so you don't have to fiddle with angles to reverse engineer it).
The code you posted will throw an error when the terms inside the square root are negative (corresponding physically to the case when the projectile can't possibly hit the target because the speeds don't work out), which should be handled gracefully rather than not at all.
A question... will my code work for when a ship is moving, or only when it is stationary?
Canning
I have no idea what your question could possibly mean. Both ships are assumed to be moving without accelerating. If one ship or the other is accelerating, the code will not still work (which I hope is physically obvious).