Найдите лучшее пересечение двух движущихся объектов

Я хотел бы оптимизировать драматический один из моих алгоритмов, я попытаюсь объяснить это наилучшим образом, что я могу.

Объект

Мы находимся в двумерной евклидовой системе в момент времени t = 0. В этой системе есть два объекта: O1 и O2.

O1 и O2 расположены соответственно в точке PA и ПК.

O1 перемещается со скоростью и известной скоростью в направлении точки PB. Объект остановится, когда он достигнет PB.

O2 может двигаться со скоростью и известной скоростью, отличной от O1, в любом направлении. В момент времени 0 O2 имеет нет направления, нам нужно будет найти его для него.

Известные параметры:

  • O1: положение, направление, скорость
  • O2: положение, скорость

Вот небольшая диаграмма системы.

Diagram of the system

Мы хотели бы найти точку PI и время ti, для которого: Position of O1 at the time ti = Position of O2 at the time ti = PI. Затем мы сделаем объект O2 перемещенным в точку PI, чтобы получить O2 direction.

Когда выбрано направление O2 (точка PI), и оба объекта O1 и O2 находятся в движении, объекты никогда не будут останавливаться или ждать друг для друга.

В этом случае результат будет примерно таким (PI отмечен D на этом снимке). Best intersection

Алгоритм

Вы можете найти рабочий алгоритм, написанный в JS, в jsfiddle, это также отличный способ понять проблему.

В это время я использую простой алгоритм, который работает, но может выполнять много операций, я получаю лучшее время пересечения и получаю позицию пересечения впоследствии.

Чтобы получить это время, я проверю позицию O1 в данный момент и проверьте, может ли O2 в данный момент перейти на эту позицию. Если O2 не смог достичь объекта во времени, мы увеличим время на 150%, однако, если O2 может пересечь линию O1-B в то время, мы уменьшим время на 50%.

В конце концов, после многих приближений мы найдем идеальное время, когда оба объекта могут встретиться.

псевдокод

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

Почему я беспокоюсь?

Мой алгоритм работает, но в некоторых случаях (например, "Обратный случай" в jsFiddle) для нахождения наилучшей точки потребуется большое количество исчислений.

В этом jsFiddle мы используем небольшие значения для позиции (от -1000 до 1000) и скорости (1-200), но этот алгоритм является более медленным с большими числами.

Я знаю, что преждевременная оптимизация - плохая идея, но я нахожусь в конце проекта (который состоит из вложений/выбора баз данных и анализа данных, включая этот алгоритм, который называется много раз), и этот алгоритм занимает до 80 % от ресурсов системы проекта в некоторых случаях, поэтому улучшение может действительно улучшить стабильность и отзывчивость системы.

Ответы

Ответ 1

Без ограничения общности, пусть O2 находится в точке (0,0).

Пусть s и v местоположение и скорость векторов O1, v2 скорость O2, t - время перехвата. Тогда имеем:

|s + v * t| = t * v2

По определению расстояния:

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

Умножение этого параметра и условия переупорядочения дают:

  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

то есть.

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

Как вы можете видеть, это квадратичное уравнение по t. Мы можем просто применить квадратичную формулу чтобы найти два возможных значения для t (если уравнение не имеет решения, потому что перехват невозможен). Вероятно, вы захотите использовать самый ранний будущий перехват, т.е. Меньший t, который равен > 0.

Как только вы вычислили t, найдя точку перехвата, и из-за этого направление перехвата должно быть легким.

Подводя итог, эта проблема может быть решена в постоянное время, итерация не требуется.

Ответ 2

Вы, кажется, слишком задумываетесь о проблеме, это просто простая геометрия.

Оставив в стороне проблему определения ближайшей точки, разрешите для ситуации, когда желаемая точка находится на полпути между PA и PB.

Мы должны принять период времени для всего цикла, назовем это T.

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

[разложите все формулы для координат x и y отдельно].

Существуют относительно простые формулы для определения ближайшего пересечения точки (ПК) с линией (PA → PB), хотя, как это определено, сложно, когда эта линия не бесконечно длинна.

Тогда вам нужно:

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

Эти последние две строки не зависят от более ранних предположений - если вы знаете точку перехвата, тогда скорость - это просто пройденное расстояние, деленное на время.

Следовательно, если вы не наложите некоторые дополнительные ограничения на V2, всегда есть решение и оно вычисляется в нескольких тривиальных математических операциях.

Ответ 3

Обновление: более поздний ответ @Meriton лучше моего. Я рекомендую попробовать его первый.

Как вы понимаете, у нас есть три одновременных уравнения в трех неизвестных vx2, vy2 и t - соответственно скорости x и y в 02 и время. Уравнения, к сожалению, не все линейны:

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

(Здесь x1o, y1o, x2o и y2o - координаты начальных положений.)

Если есть способ линеаризации проблемы, я ее не вижу. Тем не менее вы можете решить итеративно и быстро, тем же методом Newton-Raphson GPS использует, чтобы выработать свою позицию со спутниковых сигналов. Конечно, чтобы заполнить детали и реализовать это потребует некоторой работы!

Обновление: я думаю, что @Alnitak, возможно, линеаризует вашу проблему довольно аккуратно. Возможно, комбинация его подхода и моего успеха будет процветать. (Я все еще думаю, что вы захотите использовать итерацию Ньютона-Рафсона для слияния на @Altinak T.)

Ответ 4

Поскольку скорости фиксированы, это должно быть разрешено с использованием идеи параллельной навигации. Подумайте об этом так. В момент времени 0 существует линия между O1 и O2 (LOS или линия визирования). Если O2 следует оптимальному пути пересечения, то в момент времени 1 линия между O1 и O2 будет параллельна времени 0 LOS. Поскольку у вас есть скорость O2, вы можете рассчитать расстояние, которое оно будет перемещаться между временем 0 и временем 1, и из этого можно рассчитать, где это пересекает время 1 LOS. Подумайте о том, чтобы нарисовать круг вокруг исходного положения O2 с радиусом, равным расстоянию, которое он будет перемещать в этот промежуток времени. Пересечение этого круга со вторым LOS будет содержать решение. Если пересечения нет, решения нет. В начале этой онлайн-книги есть диаграмма и формулы, которые показывают концепцию:

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

Эта проблема имеет приложения реального мира, где вы также можете найти это решение. Например, подводные лодки могут использовать это для построения и поддержания курса перехвата со своей целью, сохраняя при этом LOS с постоянной мишенью по мере приближения к цели.

Edit:

enter image description here

Эта диаграмма показывает, о чем я говорю. Это можно решить с помощью тригонометрии, за исключением особого случая, когда цель O1 движется непосредственно к ракете O2 (или ее удалению тривиально) и/или удаляется.

На приведенной выше диаграмме мы можем взять некоторое произвольное небольшое количество времени. В течение этого времени t1, O1 будет пройденным расстоянием b, а O2 будет пройденным расстоянием f. Линия между O1 и O2 в момент времени t0 параллельна линии между O1 и O2 в момент времени t1. Поскольку нам даны начальные положения O1 и O2, мы знаем расстояние d, и поскольку нам дано направление O1, мы можем просто вычислить угол 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

с BC мы имеем решение, и любые другие аспекты треугольника начальных местоположений O1 и O2 и точки пересечения могут быть вычислены аналогичным образом. Прошло много лет с тех пор, как я использовал свой триггер в средней школе, поэтому может быть упрощение этого, которое я пропустил, но, надеюсь, объясняет подход к решению, который я изначально описал.