14

I would like to optimize dramaticaly one of my algorithm, i will try to explain it the best way that i can.

The subject

We are in a 2D euclidian system at the time t = 0. In this system there is two object : O1 and O2.

O1 and O2 are respectively situated at the point PA and PC.

O1 moves at a constant and known speed in direction of the point PB. The object will stop when it reach PB.

O2 can move at a constant and known speed different or not of O1's in any direction. At the time 0, O2 has no direction, we will need to find one for it.

The knowns parameters:

  • O1 : Position, direction, speed
  • O2 : Position, speed

Here is a little diagram of the system.

Diagram of the system

We would like to find the point PI and the time ti for which : Position of O1 at the time ti = Position of O2 at the time ti = PI. Then we will make the object O2 move to the point PI to get the O2 direction.

When the direction of O2 (the point PI) is chosen and both objects O1 and O2 are on the move, the objects will never stop or wait for each other.

In this case, the result would be something like this (PI is noted D on this picture). Best intersection

The algorithm

You can find the working algorithm written in JS at this jsfiddle, it is also a great way to understand the problem.

At this time i use a simple algorithm who works, but can take a lot of operations, i will get the best intersection time, and get the intersection position afterwards.

To get this time, i will check the position of O1 at a moment, and check if O2 could possibly go to this position at this time. If O2 could not reach the object in time, we will increase the time by 150%, however if O2 could cross the O1-B line at the time, we will decrease the time by 50%.

Eventually, after many approximations, we will find the perfect time where both objects could meet.

PseudoCode

function getOptimalIntersectionTime time
   if distance between O1 and O2 at the time `time` < 1
       return time
   else if O2 could not reach the object O1 at the time `time`
       return getOptimalIntersectionTime time * 1.5
   else
       return getOptimalIntersectionTime time * 0.5

Why am I concern ?

My algorithm works, but in some case (e.g. the "Reverse Case" in the jsFiddle) it will take a large amount of calculus to find the best point.

In this jsFiddle, we are using little values for position (-1000 to 1000) and speed (1-200) but this algorithm is dramaticaly slower with bigger numbers.

I know that premature optimization is a bad idea, but I'm at the end of the project (which consists on databases insertions / selection and data analysis, including this algorithm called many many times) and this algorithm take up to 80% of the project system ressources in certain cases so an improvement could really improve the stability and the responsiveness of the system.

700 Software
  • 85,281
  • 83
  • 234
  • 341
mamadrood
  • 739
  • 5
  • 12
  • what are the constraints? Without constraints it's _always_ possible to pick some velocity vector for O2 that'll meet up with O1 at PI. – Alnitak Apr 27 '12 at 21:24
  • 1
    Your diagrams are nice. Thanks. I have a question, though: is the speed of O2 constrained? Because, if it isn't, then O2 can just shoot off really fast and hit O1 before O1 even has a chance to move. But I suspect that I have slightly misunderstood your question. For my benefit, would you clarify? – thb Apr 27 '12 at 21:26
  • 1
    What do you mean by _the nearest point PI_? nearest to PA, PB, or PC? – Islam Hassan Apr 27 '12 at 21:30
  • Even without looking at your problem I already see your optimization function is inefficient. Use fibonacci search (related to binary search). http://en.wikipedia.org/wiki/Fibonacci_search – dtech Apr 27 '12 at 21:37
  • O1's and O2's speed is fixed, you can't change it. I miswritten my idea when i said "nearest point PI" i really meant the "shortest ti time". – mamadrood Apr 27 '12 at 22:16
  • So, just to clarify: Known is O1 and O2's starting positions (p1, p2), their speeds (s1, s2), and for O1 ***only***, the Direction (a1)? And specifically NOT known is O2's direction (a2), which is to be choosen to minimize the time to interception, correct? – RBarryYoung Apr 27 '12 at 22:26
  • @RBarryYoung Exactly, i've edited my message to clarify that. We need to find the point where O2 needs to move. – mamadrood Apr 27 '12 at 22:29
  • This may be of help: http://cboard.cprogramming.com/brief-history-cprogramming-com/83460-vector-intersection.html – hatchet - done with SOverflow Apr 27 '12 at 22:39
  • @hatchet I would love to use vectors, unfortunatly, without the direction of O2, there is no vector operation possible. Except throwing random vectors in many directions, i tried it once, and it doesn't work really well. – mamadrood Apr 27 '12 at 22:45

4 Answers4

9

Without loss of generality, let O2 be located at (0,0).

Let s and v the location and velocity vectors of O1, v2 the speed of O2, and t the time to intercept. We then have:

|s + v * t| = t * v2

By the definition of distance:

(sx + vx * t) ^ 2 + (sy + vy * t) ^ 2 = (t * v2) ^ 2

Multiplying this out and reordering terms gives:

  sx^ 2 + 2 * sx * vx * t + vx^2 * t^2
+ sy^ 2 + 2 * sy * vy * t + vy^2 * t^2
-                           v2^2 * t^2
= 0

i.e.

  sx^2 + sy^2 + (2 * sx * vx + 2 * sy * vy) * t + (vx^2 + vy^2 - v2^2) * t^2 = 0
  \---   ---/   \------------   ----------/       \--------   ------/
      \ /                    \ /                           \ /
       c                      b                             a

As you can see, this a quadratic equation in t. We can simply apply the quadratic formula to find the two possible values for t (if the equation has no solution, that's because no interception is possible). You'll probably want to use the earliest future interception, i.e. the smaller t that is > 0.

Once you have computed the t, finding the interception point and from that the interception direction should be easy.

To summarize, this problem can be solved in constant time, no iteration is necessary.

meriton
  • 68,356
  • 14
  • 108
  • 175
  • The starting equation is a tat confusing until one reminds oneself that `v2` is a _vector_ but `v` is a _speed_. It however is correct and may be understood with the idea of a circle centered at the inital position of `O2` and viewed as all the points `O2` can reach in time `t`. – mjv Apr 28 '12 at 01:45
  • Ok, i tried your solution, i've translated the whole thing to put O2 in 0,0. Then i must do something wrong somewhere. For the `v` vector I define it like this `v = {x: (b.x - a.x) / time, y: (b.y - a.y) / time}` where `time` is the time for the object O1 to move from A to B. Then as `s` i take the translated positions of the object O1. The rest is done right, i guess. But i've got wrong values, am i doing something wrong ? – mamadrood Apr 28 '12 at 02:07
  • @mjv: You mean v2 is a speed, and v is a vector? Better naming suggestings are welcome. – meriton Apr 28 '12 at 12:14
  • @mamadrood: That sounds right so far. Can you give me the numbers for a case where the values are "wrong"? – meriton Apr 28 '12 at 12:20
  • +1. Well done. Your answer is better than mine. For interest, I would observe that there is still probably an iteration in the calculation of the quadratic formula's square root. However, from a hardware perspective, assuming that an x87 unit or equivalent is available, the square-root iteration need not be programmed, for it is implemented already in hard circuitry, which is very fast (and, I suppose, also relatively power-efficient). So, your answer is better than mine for this reason among others. I like it. – thb Apr 28 '12 at 12:32
  • Hum, i tried with the "reverse case" in the jsFiddle. My algorithm give me a time around 4, and this one a time around 2, i will put this implementation on this jsFiddle later. – mamadrood Apr 28 '12 at 16:44
  • I've edited the jsFiddle, now it will print the results from the two different methods. – mamadrood Apr 28 '12 at 16:59
  • I have exactly the same question. but there is a problem with the answer. as the angle (direction) of the second object is unknown so V2x and V2y are unknown. and the time (t) can not be calculated. we should find the angle (direction vector) of the V2 first. can anyone provide a correction for the solution? – Ashkan Mobayen Khiabani Jul 16 '12 at 13:20
  • @AshkanMobayenKhiabani: Where in my answer do you see a variable V2x or V2y? My answer only uses the magnitude of O2's speed, which it calls `v2` ... – meriton Sep 04 '12 at 16:26
1

You appear to be over-thinking the problem, it should just be simple geometry.

Leaving aside the problem of how you define the nearest point, let's solve for the situation where the desired point is midway between PA and PB.

We have to assume a time period for the entire cycle, let's call that T.

PI = (PB - PA) / 2;  // simplified
TI = T / 2;          // simplified

[decompose all formulae for the x and y coordinates separately].

There are relatively simple formulae for determining the closest intersection of a point (PC) with a line (PA -> PB), although how that's defined is complicated when that line isn't infinitely long.

Then you need:

V1 = (PB - PA) / T;  // O1's velocity
V2 = (PI - PC) / T;  // O2's velocity

These last two lines don't depend on the earlier assumptions - if you know the interception point then the velocity is simply the distance travelled divided by the time taken.

Hence unless you impose some additional constraints on V2, there is always a solution and it's calculated in a few trivial math operations.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Good point, and I think that you are right. However, unless I misunderstand the OP's question, T is one of the variables that wants calculation. – thb Apr 27 '12 at 21:43
  • @thb if `V1` is known (as the OP asserts) then `T` is trivially calculated. – Alnitak Apr 27 '12 at 21:44
  • The reason I wrote what I wrote is that, according to my understanding, the point along O1's path at which the collision occurs is to be calculated. It is true that, once the collision point is calculated, `T` is trivially known, but then I do not believe that one can assume prior, trivial knowledge of `T` to calculate the collision point. This is all I meant. – thb Apr 27 '12 at 21:48
  • 1
    There must be some constraints the OP has omitted, because as you've shown, the solution seems rather simple to arrive at. – hatchet - done with SOverflow Apr 27 '12 at 21:48
  • However, I like your formulation because it sets up a neat Newton-Raphson iteration on `T`, without squaring anything. – thb Apr 27 '12 at 21:49
  • I think it's the OP's wording that confused me. I think the problem is that you are given O1's T0 position, speed and direction, and O2's T0 position and speed. From that determine the soonest intersection, and O2 direction to achieve it. – hatchet - done with SOverflow Apr 27 '12 at 22:05
  • @hatchet you may be right - it's completely unclear which values are _given_ and which must be _calculated_. Yes, your interpretation makes sense, now I re-read the question. – Alnitak Apr 27 '12 at 22:06
  • @hatchet : This is exactly what i would say (sorry if it wasn't clear). I don't want to *simply* hit the middle of the PA-PB segment because the object O1 will never stops and the object O2 may never been able to reach the middle of PA-PB. I don't want O1 to stop neither, so even if he can reach the middle of PA-PB in time, i don't want it to stop. – mamadrood Apr 27 '12 at 22:23
1

Update: @Meriton's later answer is better than mine. I recommend trying his first.

As you realize, we have three, simultaneous equations in the three unknowns vx2, vy2 and t -- respectively the x and y velocities of 02, and time. The equations unfortunately are not all linear:

x1o + vx1*t == x2o + vx2*t
y1o + vy1*t == y2o + vy2*t
vx2*vx2 + vy2*vy2 == vy*vy

(Here, x1o, y1o, x2o and y2o are coordinates of the initial positions.)

If there is a way to linearize the problem, I don't see it. You can however solve iteratively, and quickly, by the same Newton-Raphson technique GPS uses to work out your position from satellite signals. Of course, to fill in the details and implement this will demand some work!

Update: I think that @Alnitak may have linearized your problem rather neatly. Perhaps a combination of his approach and mine therefore would prosper. (I still think that you'll want to use a Newton-Raphson iteration to converge on @Altinak's T.)

thb
  • 13,796
  • 3
  • 40
  • 68
0

Since the speeds are fixed, this should be solvable using the idea of parallel navigation. Think of it this way. At time 0, there is a line between O1 and O2 (the LOS, or line of sight). If O2 follows the optimal intersect path, then at time 1, the line between O1 and O2 will be parallel to the time 0 LOS. Since you have O2's speed, you can calculate the distance it will travel between time 0 and time 1, and from that can calculate where that intersects the time 1 LOS. Think of scribing a circle around O2's original position with radius equal to the distance it will travel in that interval of time. The intersection(s) of that circle with the second LOS will contain the solution. If there is no intersect, there is no solution. The beginning of this online book has a diagram and formulas that show the concept:

http://www.crcnetbase.com/doi/abs/10.1201/9781420062281.ch2

This problem has real world applications where you may also find this solution talked about. For instance submarines can use this to plot and maintain an intercept course with their target by keeping the LOS bearing to their target constant as they close on their target.

Edit:

enter image description here

This diagram shows what I'm talking about. This can be solved using trigonometry except for the special case where the target O1 is moving directly towards or away from the missile O2 (which can be solved trivially).

In the diagram above we can take some arbitrary small amount of time. During that time t1, O1 will have traveled distance b, and O2 will have traveled distance f. The line between O1 and O2 at time t0 is parallel to the line between O1 and O2 at time t1. Since we are given the initial positions of O1 and O2 we know distance d, and since we are given O1's direction, we can simply calculate the angle A.

So given A, b, f, and d, using the law of Cosines,
a = sqrroot(c^2 + b^2 - (2cb * cos(A)))
and
B = arccos((a^2 + c^2 - b^2)/2ac)
Using the law of Sines
E = arcsin((a * sin(B))/f)  or the ambiguous value of 180 - that value
and with that
BC = 180 - E   (because C = 180 - B - E so C+B = 180 - E

with BC we have the solution, and the any other aspects of the triangle of the initial locations of O1 and O2 and the intersection point can be similarly calculated. It's been many years since I used my high school trig, so there may be a simplification of this that I've missed, but this hopefully explains the solution approach I initially described.