Войти
ПрограммированиеФорумФизика

Физика аркадного поворота

Страницы: 1 2 Следующая »
#0
15:30, 27 июня 2018

Здравствуйте.
Есть объект - простой космический кораблик с массой m и двигателем который может его толкать с силой F

Кораблик двигается по прямой, с вектором скорости v(vx ; vy)

Когда игрок нажимает клавишу поворота кораблик должен совершить движение по окружности по следующей траектории.
path | Физика аркадного поворота
Направление поворота задается знаком угла поворота - в право по часовой, влево против часовой

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

Как я предполагал надо сделать...
Посчитаем угловое ускорение
Изображение
Где R - длина радиус вектора до условной точки вокруг которой совершается оборот
k - коэффициент который увеличивает радиус поворота в зависимости от скорости, он равен
Изображение
В принципе k не обязателен, он может отсутсвовать, тогда просто кораблик будет поворачивать по окружности одного и того-же радиуса при любой скорости

ε домножается на 1 или -1 в зависимости от нажатой клавиши поворота и прибавляется к угловой скорости ω

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

На основе вышесказанного у меня почему-то получается вот такая траектория (взял положение корабля в каждый тик цикла, и построил из этого график)
path_curve | Физика аркадного поворота
На графике запечетлено движение, начиная с момента нажатия на клавишу поворота, при некой начальной скорости
Судя по графику, радиус поворота в начале соответсвует моей формуле, но потом начинает постоянно сокращаться, вот и получается спираль...

Как мне добиться необходимой траектории движения которую я привел в начале? Физически правильное круговое движение для моей задачи не обязательное, но если будет возможность получить такую траекторию физически правильным способом, то буду очень благодарен


#1
15:51, 27 июня 2018

NXTaar
> Как мне добиться необходимой траектории движения которую я привел в начале?
Просто применяй постоянную по модулю силу под прямым углом к текущей скорости - и будет равномерное вращение по окружности.
В пределе непрерывной во времени системы, ускорение, перпендикулярное к вектору скорости, будет изменять только направление скорости, не меняя его абсолютной величины.

    Изображение

Кривизна траектории, в свою очередь, задаётся отношением скорости к нормальной составляющей ускорения:

    Изображение

Соответственно, если ускорение всегда держать постоянным по модулю и перпендикулярным к скорости - то и скорость будет постоянной по модулю, и, как следствие, и радиус кривизны траектории будет постоянным.
У тебя из-за дискретности системы радиус и скорость будут медленно возрастать. Если стоит явная задача крутить длительное время по постоянной траектории, самый надёжный способ - это повесить обратную связь и компенсировать ей возникающие ошибки.

#2
16:16, 27 июня 2018

https://ru.wikipedia.org/wiki/%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B… D%D0%B8%D0%B5

альтернативный способ с сохранением модуля скорости несмотря на дискретизацию — можно просто поворачивать каждый тик вектор скорости на угол, равный [cht]\frac{|\vec v|}{R}[/cht], где [cht]R[/cht] — требуемый радиус поворота. результат будет точнее. обрати внимание, что [cht]R = +\infty[/cht]  — частный случай прямолинейного движения, когда любая конечная скорость поворачивается на нулевой угол. положительный радиус отвечает за поворот по часовой стрелке, отрицательный — против. или наоборот, в зависимости от того, что считать положительным направлением поворота.

#3
16:28, 27 июня 2018

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

#4
16:55, 27 июня 2018

Delfigamer

> Если стоит явная задача крутить длительное время по постоянной траектории, самый надёжный способ - это повесить обратную связь и компенсировать ей возникающие ошибки

Правильно я понимаю, что условно говоря действий следующий (поправьте, если я где-то ошибся)
дано: вектор скорости v(vx ; vy)

Найдем вектор-перпендикуляр n от v который будет равен Изображение где i равно 1 при повороте вправо, и -1 при повороте влево

нормализуем вектор n чтобы затем домножить его на |a| (a это вектор линейного ускорения, т.к. условно у кораблика всего один двигатель который всегда дает постоянную силу, отвечает за линейное движение и за повороты)
получившийся an это и есть наш вектор центростремительного ускорения
складываем вектора v и an - в результате получаем вектор скорости vn для кругового движения. Но из определения векторного сложения, результирующий вектор будет длиннее вектора v, поэтому мы принудительно задаем его длину равной |v|

Правильно я понимаю что вот это принудительное присвоение длины и есть как раз обратная связь которая компенсирует ошибки?

#5
17:15, 27 июня 2018

NXTaar
> складываем вектора v и an
Воу, воу, притормози. Как ты собрался складывать скорость и ускорение? Это же разнородные величины.

NXTaar
> Правильно я понимаю что вот это принудительное присвоение длины и есть как раз
> обратная связь которая компенсирует ошибки?
Нет, это не обратная связь.
Я имел в виду контур управления наподобие того из соседней темы - вычисляется отклонение корабля от желаемой траектории, и к базовому ускорению прибавляется небольшой дополнительный вектор, который заставит корабль вернуться в желаемую позицию.

#6
17:40, 27 июня 2018

Delfigamer
но ведь ускорение это величина на которую увеличивается скорость в каждый момент времени. Я собрался прибавить вектор ускорения к вектору скорости, чтобы получить новый вектор скорости для следующего момента времени.

Delfigamer
> вычисляется отклонение корабля от желаемой траектории
А на основе чего мы понимаем что кораблик "отклонился" от траектории, если мы заранее не знаем где у нас правильное следующее положение? Ведь единственное знание что у нас "что-то пошло не так" это изменившаяся длина вектора скорости. Нужно при начале поворота составить уравнение окружности и проверять позицию корабля что она принадлежит этому уравнению?

#7
18:33, 27 июня 2018

NXTaar
> Я собрался прибавить вектор ускорения к вектору скорости, чтобы получить новый
> вектор скорости для следующего момента времени.
у них размерности разные. имеет смысл вектор ускорения как минимум помножить на шаг по времени, чтобы схема к чему-то вменяемому сходилась, а скорость от fps не зависела.

#8
18:47, 27 июня 2018

Откуда там такие лютые погрешности что он на первом же круге сбивается? Может стоит double вместо float взять?

#9
19:20, 27 июня 2018

kipar
> стоит double вместо float взять
Нету double. Целевая платформа web, поэтому язык - Javascript

Suslik
> у них размерности разные

Как это разные, если v и a это вектора с координатами (vx ; vy) и (ax ; ay). Почему размерности разные, мы же можем складывать координаты с координатами?

#10
20:27, 27 июня 2018

kipar
> Может стоит double вместо float взять?
Оно как-то сильно не похоже на погрешность недостатка разрядности.

NXTaar
> Нету double. Целевая платформа web, поэтому язык - Javascript
Что? Number=double.

#11
20:28, 27 июня 2018

NXTaar
Потому что размерность скорости - это м/с, а размерность ускорения - это м/с2.
Их сумма не имеет физического смысла, потому что при смене единиц измерения у тебя получится совершенно другое число.
Например, запишем вот такое "уравнение":

    Изображение

В каких единицах измеряется U?
Посмотрим, как в зависимости от единиц измерения изменяется скорость:

    Изображение

    Изображение

То есть - при переходе от единицы измерения длины "м" к единице "1/N м", численные значения скоростей возрастают в N раз. При смене единицы измерения времени от "с" к "1/N с" - напротив, численное значение скорости умножается на N-1.
Поэтому говорят - размерность скорости является м с-1, единица длины поделённая на единицу времени.

Аналогичной закономерностью обладают ускорения:

    Изображение

    Изображение

Однако, если посмотреть на сумму скорости и ускорения - она не обладает такими свойствами. Какие бы единицы в U мы не подставляли, они не дадут правильного соответствия между преобразованиями единиц и изменением численного значения "величины". То есть - её нельзя выразить в таком виде, чтобы физический смысл "величины" не зависел от того, какой линейкой мы производим измерения. Следовательно - она не является настоящей физической величиной.

Когда ты симулируешь систему методом численного интегрирования - а то, что ты пытаешься сделать, называется именно так - то ускорение умножается на длительность шага интегрирования.
Правильные уравнения системы выглядят так:

    Изображение

    Изображение

где dt - это шаг симуляции. Если проанализировать эти уравнения на размерность - то теперь всё сходится:

    Изображение

    Изображение

Ну и самое интересное.
На самом деле, всё это время ты считал именно по уравнениям с dt. Однако, если ты явно не умножал ни на какое число - тогда получается, что dt = 1; поскольку умножение на единицу не изменяет численного значения.
В чём измеряется эта единица? Из баланса размерностей вытекает ответ - это должна быть единица времени. Что это означает? Это означает, что всё это время ты производил симуляцию с шагом времени, равным одной единице измерения времени; либо, что то же самое - твоей единицей измерения времени является шаг симуляции.
Тогда твоя скорость обретает физический смысл "изменение положения за один шаг симуляции"; а физический смысл ускорения, соответственно, - "изменение скорости за один шаг симуляции".

Суслик говорит тебе, что если ты на самом деле хочешь измерять время в реальных единицах - например, в секундах реального времени - то тогда и в уравнениях системы нужно задавать не фиксированный dt, а подставлять в него реальное время, на которое следует продвинуть систему - например, реальная длительность кадра в секундах.
Тогда величины скоростей и ускорений обретут физический смысл "изменения за единицу реального времени".

#12
21:32, 27 июня 2018

Delfigamer
Спасибо за пояснение. Я наконец-то впервые прочитал внятное и понятное объяснение что за dt и почему на него везде все домножается. Да, я интуитивно задавал dt = 1 потому что мне было достаточно измерять время в 1 шаг симуляции.

Итого возвращаясь к моей проблеме
имеем единичный перпедикулярный вектор vn от вектора скорости v
имеем массу корабля m и силу двигателя F, на основе которых считаем модуль |a| для вектора ускорения, который двигатель корабля, может этому самому кораблю в любом направлении сообщить (|a| = F/m)

Получим вектор центростремительного ускорения an путем умножения vn на |a|*dt (изходя из написанного Delfigamer и Suslik)
Теперь мы имеем возможность сложить вектора v и an. Получаем новый вектор скорости v1, и следовательно точку Изображение  в которой окажется корабль в следующий момент времени.
Но!!! Как вы, Delfigamer, пишете здесь есть проблема из-за дискретности системы, а значит наш x1 надо скорректировать.

И вот тут у меня затык немного. Как расчитать это самое отклонение от желаемой траектории? Правильно я понимаю что это будет некий небольшой вектор, который добавится к v1?
У меня только следующая мысль в голову приходит. Можно в тот момент времени t, когда произошло нажатие на кнопку поворота, составить уравнение окружности, по которой должен двигаться корабль. Радиус мы посчитаем по формуле Изображение, а зная радиус и сторону поворота, можно будет найти координаты центра окружности

В это составленное уравнение можем подставить x1 и проверить лежит ли наша точка, в которой окажется корабль в следующий момент времени, на нужной нам траектории круга. Точка естественно уравнению удовлетворять не будет. И как в таком случаее ее корректировать?

#13
21:35, 27 июня 2018

NXTaar
> В свою очередь на угол ω доворачивается спрайт кораблика

В коде добавьте:

Если угол ω больше %значение% то угол ω равен %значение%

#14
21:39, 27 июня 2018

> У меня только следующая мысль в голову приходит.
Вполне годится, для данной задачи.

> Точка естественно уравнению удовлетворять не будет. И как в таком случаее ее корректировать?
Ну тупо x1:=C+R*(x1-C)/|x1-C|, где C - это центр окружности.

Страницы: 1 2 Следующая »
ПрограммированиеФорумФизика

Тема в архиве.

Тема закрыта.