Предыстория.
У меня давно была идея попробовать написать одну игру, имеющую отношение к гонкам. Сейчас в очередной раз решил попробовать.
Задача такая: гоночный автомобиль едет по некой траектории, которая задается сплайном (*). Каждой точке сплайна соответствует некоторая величина кривизны траектории. Кривизна участка траектории ограничивает скорость, с которой автомобиль может двигаться по этому участку. Для того, чтобы автомобиль проехал трассу с максимальной скоростью, я придумал примерно такой алгоритм (*):
- рассчитать максимальную скорость для каждого участка траектории
- затем для каждого участка рассчитать максимальную скорость с учетом того, что возможное торможение автомобиля ограничено техническими параметрами автомобиля, поэтому тормозить надо начинать заранее (и рассчитать, когда именно)
- затем рассчитать фактическую скорость каждого участка с учетом мощности двигателя
Теперь к сути вопроса. Для задания траектории я выбрал сплайн Акимы (где-то попалась статья со сравнением разных типов сплайнов, этот показался самым привлекательным). Код (он у меня на java) не привожу, во-первых, потому что его много, и вряд ли кто-то захочет в нем разбираться, а во-вторых, мне кажется, что проблема в математической части решения. Но если кто-то захочет - могу выложить. Дальше порядок такой:
- задаю опорные точки
- массив опорных точек с координатами
![$(x_i, y_i)$ $(x_i, y_i)$](https://dxdy-01.korotkov.co.uk/f/c/e/6/ce6988121342d90ff4c10d6cf2959c2982.png)
преобразую в два массива
![$(t_i, x_i)$ $(t_i, x_i)$](https://dxdy-04.korotkov.co.uk/f/7/a/0/7a0d8a27278d4c5016d9474bef753b6b82.png)
и
![$(t_i, y_i)$ $(t_i, y_i)$](https://dxdy-04.korotkov.co.uk/f/3/d/c/3dcda078d12a133b2ec7b15de21cd93682.png)
, где
![$t_0 = 0$ $t_0 = 0$](https://dxdy-01.korotkov.co.uk/f/c/9/d/c9d7adaf70649e6eac596cb7eba2b33e82.png)
,
![$t_i$ $t_i$](https://dxdy-01.korotkov.co.uk/f/0/2/a/02ab12d0013b89c8edc7f0f2662fa7a982.png)
равно расстоянию от точки
![$i-1$ $i-1$](https://dxdy-03.korotkov.co.uk/f/6/f/4/6f471fb05a43809706b83a28f399076c82.png)
до
![$i$ $i$](https://dxdy-04.korotkov.co.uk/f/7/7/a/77a3b857d53fb44e33b53e4c8b68351a82.png)
- для каждого участка дуги рассчитываю коэффициенты функций
![$x(t)$ $x(t)$](https://dxdy-04.korotkov.co.uk/f/f/9/2/f92a2fed82f1dacdec6e4d5a05fbbf9782.png)
и
![$y(t)$ $y(t)$](https://dxdy-02.korotkov.co.uk/f/d/4/3/d4378ba898213096600125929214f90a82.png)
- затем сплайн (для упрощения расчетов вывода на экран) аппроксимируется ломаной линией: для каждой дуги я беру параметр
![$t$ $t$](https://dxdy-01.korotkov.co.uk/f/4/f/4/4f4f4e395762a3af4575de74c019ebb582.png)
, изменяю его от
![$t_i$ $t_i$](https://dxdy-01.korotkov.co.uk/f/0/2/a/02ab12d0013b89c8edc7f0f2662fa7a982.png)
до
![$t_{i+1}$ $t_{i+1}$](https://dxdy-02.korotkov.co.uk/f/9/f/c/9fc448b057f5a812c4f6eff427a4f54182.png)
c шагом
![$(t_{i+1} - t_i)/n$ $(t_{i+1} - t_i)/n$](https://dxdy-03.korotkov.co.uk/f/6/f/a/6faa3c461c86f4551299ca9ca687dc3782.png)
, где
![$n$ $n$](https://dxdy-02.korotkov.co.uk/f/5/5/a/55a049b8f161ae7cfeb0197d75aff96782.png)
- некоторое произвольное число (10, 20 или 30 обычно). Для каждого такого значения
![$t_j$ $t_j$](https://dxdy-01.korotkov.co.uk/f/c/8/f/c8f804b30c49e59f8206cdefe7fb0ec482.png)
вычисляю
![$x_j$ $x_j$](https://dxdy-01.korotkov.co.uk/f/4/d/8/4d8443b72a1de913b4a3995119296c9082.png)
и
![$y_j$ $y_j$](https://dxdy-04.korotkov.co.uk/f/f/b/a/fba353e8e83ce14fc4a80553757972f782.png)
, по получившимся точкам
![$(x_j, y_j)$ $(x_j, y_j)$](https://dxdy-04.korotkov.co.uk/f/3/8/6/386d0d3558cd735ebd3262a0493d026682.png)
строится ломаная. Выглядит она как-то так:
![Изображение](https://c2.staticflickr.com/8/7497/27500351282_2cf414350f_o.png)
(Цветом показана кривизна, чем краснее цвет, тем меньше радиус кривизны)
- далее беру уравнение эволюты (взял в
Википедии):
![$X = x-y' \dfrac{x'^2 + y'^2}{x'y'' - y'x''}$ $X = x-y' \dfrac{x'^2 + y'^2}{x'y'' - y'x''}$](https://dxdy-03.korotkov.co.uk/f/2/0/5/205b176d3609970bff56b0bd77b84ae682.png)
![$Y = y+x' \dfrac{x'^2 + y'^2}{x'y'' - y'x''}$ $Y = y+x' \dfrac{x'^2 + y'^2}{x'y'' - y'x''}$](https://dxdy-02.korotkov.co.uk/f/1/e/5/1e5f7b23040b1cae1c1948ecdcec780982.png)
По этим уравнениям для каждой точки
![$t_j$ $t_j$](https://dxdy-01.korotkov.co.uk/f/c/8/f/c8f804b30c49e59f8206cdefe7fb0ec482.png)
рассчитываю координаты соответствующей точки эволюты. Вообще я считал, что если взять некоторое значение параметра
![$t$ $t$](https://dxdy-01.korotkov.co.uk/f/4/f/4/4f4f4e395762a3af4575de74c019ebb582.png)
и найти координаты соответствующей точки сплайна (
![$A_t$ $A_t$](https://dxdy-02.korotkov.co.uk/f/d/f/0/df02e7666c632d22547b9c75b98c49bf82.png)
), затем по формуле выше рассчитать координаты точки эволюты (
![$A_e$ $A_e$](https://dxdy-01.korotkov.co.uk/f/0/8/8/08800426068a4c1a6e569a1a90f086ec82.png)
) при том же значении
![$t$ $t$](https://dxdy-01.korotkov.co.uk/f/4/f/4/4f4f4e395762a3af4575de74c019ebb582.png)
, то найденная точка
![$A_e$ $A_e$](https://dxdy-01.korotkov.co.uk/f/0/8/8/08800426068a4c1a6e569a1a90f086ec82.png)
будет центром касательной окружности, а точкой касания будет
![$A_t$ $A_t$](https://dxdy-02.korotkov.co.uk/f/d/f/0/df02e7666c632d22547b9c75b98c49bf82.png)
. Но сейчас подумал, что у меня нет оснований так считать. Правильное ли это предположение?
- далее для каждой пары точек (точка сплайна + точка эволюты) я рассчитываю расстояние между ними, беру (пока с потолка) некоторое значение предельной силы трения и рассчитываю максимальную скорость в данной точке. Но дальше возникает проблема. На рисунке выше представлен кусок сплайна. Вот так для него выглядит распределение максимальной скорости вдоль траектории:
![Изображение](https://c2.staticflickr.com/8/7281/27329223860_ab319b7595_o.png)
По оси абсцисс отложен номер промежуточной точки. Участок кривой между двумя опорными точками делится на 30 частей, соответственно каждая 30-я точка на графике соответствует опорной точке, все остальные точки - промежуточные. Тут видно два пика в районе второй и четвертой опорных точек - то есть в этих местах происходит небольшой излом. Для расчета оптимальной скорости автомобиля надо убрать по возможности такие скачки скорости. Буду рад любым советам...
(Наверное, может возникнуть вопрос, а с чего я вообще решил, что построенная таким образом кривая будет удовлетворять моим требованиям? Да, собственно, ни с чего. Просто не задумывался над этим. Я так понимаю, придется все сначала переделывать с другим типом сплайнов.)
_________
Знаком (*) обозначены вопросы, которые формально являются оффтопиком, но их тоже можно обсудить.
(P. S.)