2015-01-05 2 views
6

Я работаю над небольшой программой, показывающей движущиеся гребные лодки. Ниже приведен простой пример кода (Python 2.x):Код, похожий на ход гребля

import time 
class Boat: 
    def __init__(self, pace, spm): 
     self.pace = pace #velocity of the boat in m/s 
     self.spm = spm #strokes per minute 
     self.distance = 0 #distance travelled 

    def move(self, deltaT): 
     self.distance = self.distance + (self.pace * deltaT) 

boat1 = Boat(3.33, 20) 
while True: 
    boat1.move(0.1) 
    print boat1.distance 
    time.sleep(0.1) 

Как вы можете видеть, лодка имеет темп и строки с числом ударов в минуту. Каждый раз, когда метод move(deltaT) называется, он перемещается на определенное расстояние в соответствии с темпом.

Вышеупомянутая лодка просто путешествует в постоянном темпе, что нереально. Настоящая гребная лодка ускоряется в начале хода, а затем замедляется после того, как гребные лезвия покинули воду. Есть много графиков онлайн, которые показывают типичную кривую гребной (усилие, показанное здесь, скорость выглядит примерно):

Rowing Stroke Graph Источник: highperformancerowing.net

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

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

Примечание: Любые идеи о том, как лучше отметить этот вопрос? Это проблема алгоритма?

+1

Используйте сплайн-интерполяцию, например, из SciPy. – nwk

+0

См. Также сайт SE для статистики http://stats.stackexchange.com – smci

+0

И сглаживающее преобразование stat_smooth в библиотеке ggplot. – smci

ответ

2

Если ваша цель состоит в том, чтобы просто придумать что-то визуально правдоподобное и не делать полное физическое моделирование, вы можете просто добавить синусоиду в положение.

class Boat: 
    def __init__(self, pace, spm, var=0.5): 
     self.pace = pace #average velocity of the boat in m/s 
     self.sps = spm/60.0 #strokes per second 
     self.var = var  #variation in speed from 0-1 
     self.totalT = 0  #total time 
     self.distance = 0 #distance traveled 

    def move(self, deltaT): 
     self.totalT += deltaT 
     self.distance = self.pace * (self.totalT + self.var * math.sin(self.totalT * self.sps * 2*math.pi) 

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

+0

Результат работы кода, так как я тестировал гребца со скоростью 10 м/с и SPM 20 рядов 30 м в такте: https://ideone.com/wHjZs3 Скорость во время удара, однако, кажется прыгать взад-вперед. Любые идеи, что не так в расчете? Разве мы не должны вводить темп в синусоидальную волну вместо времени? – MOnsDaR

+0

@MOnsDaR извините, у меня была коррекция, которую я сделал, но не копировал в ответ. '/ Self.sps' должен быть' * self.sps'. –

+0

Это трюк, значения теперь увеличиваются/уменьшаются вдоль синусоидальной волны: https://ideone.com/2Cb6u8 Однако кривая полностью противоположна тому, что я ожидаю: она начинается быстро, идет медленнее, быстро заканчивается. Это должно быть наоборот. Я играл с уравнением, но не мог заставить его работать правильно, не могли бы вы помочь в последний раз? – MOnsDaR

1

Вы можете преобразовать такую ​​форму кривой в полиномиальное уравнение для скорости.

Описание/пример того, как это сделать, можно найти по адресу:

python numpy/scipy curve fitting

Это показывает вам, как взять набор х, у координаты (которые вы можете получить путем проверки существующий сюжет или фактические данные) и создать полиномиальную функцию.

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

+1

Просто заметил, что ваш график имеет силу на оси y. Сила - это массовое * ускорение. Поскольку ваша масса постоянна, это по существу график ускорения (а не скорость). – jrel

+0

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

1

Вы можете выполнить простую интеграцию дифференциального уравнения движения. (Это то, что вы уже делаете, чтобы получить пространство как функцию времени, с постоянной скоростью, x' = x + V.dt.)

Предположим, что простая модель с постоянной силой во время хода и без силы во время скольжения, и сопротивление, пропорциональное скорость.

Таким образом, ускорение a = P - D.v во время хода и - D.v во время скольжения (торможения).

Скорость приближается v' = v + a.dt.

Пространство ориентировано на x' = x + v.dt.

Если dt достаточно мало, это движение должно выглядеть реалистично. Вы можете уточнить модель с более точным законом силы и лучшими методами интеграции, такими как Runge-Kutta, но я не уверен, что это того стоит.

Ниже приведен пример зависимости скорости и пространства от времени с использованием этой техники.Он показывает скоростные колебания, быстро устанавливающие периодический режим, и квазилинейное смещение с волнами.

enter image description here

+0

Я думаю, это достаточно хорошее общее решение. Однако мой вопрос больше предназначен для того, чтобы спросить: «Как я могу моделировать кривую как удар по гребле, но сохранить общий темп». – MOnsDaR

Смежные вопросы