Интеграция SciPy Projectile ODE

Я делаю проект, который включает использование SciPy Integrator для моделирования движения снаряда в этой стрелялке. Раньше мне никогда не приходилось ничего программировать на python, и мои расчеты немного заржавели, но через несколько часов мне также было трудно определить, что именно вызывает определенные ошибки. После нескольких часов проб и ошибок я заставил его работать с закомментированным кодом в методе интеграции (я думаю, что это интеграция Эйлера, но я, честно говоря, не уверен на 100%). Однако я также должен использовать два интегратора из библиотеки SciPy, которые не работают. Оба выдают одно и то же сообщение об ошибке в одном и том же месте:

"  File "**file extension**", line 17, in eq
    projX = x[0];
   TypeError: 'float' object has no attribute '__getitem__'"

Похоже, он ожидает другой тип объекта, но я, честно говоря, не знаю, что с этим делать. Я не могу сказать, неправильно ли я использую интегратор или ошибся в настройке ODE. Я действительно в тупике. Любая помощь вообще будет принята с благодарностью. Вот код:

from numpy import *
from scipy.integrate import ode
from scipy import *

# setup wind (it will be replaced with the current value of the wind at every
# instant in time) 
wd = array([0, 0])

# computes the ODE
def eq(x, t):

  # setup gravitational acceleration
  #this is Acceleration for Y
  GRAVITY = 9.81

  # get out the positions and velocities
  projX = x[0];
  projY = x[1];
  projVX = x[2];
  projVY = x[3];

  # TODO: setup the acceleration 
   #acceleration is the derivitive of velocity (VX..VY acceleration is GRAVITY) in this case        it's 0 (no wind)?
  ACCELERATION = 0 #will be effected by wind


  #TODO ground force

  # TODO: return appropriate things
  #needs to return: (x,y Time derivatives and x,y acceleration)
  #acceleration is  derivative of velocity. Velocity derivative of position.
 #is essentially dx/dt
  return array([x[2], x[3], ACCELERATION, -GRAVITY])


# integrates a projectile forward in time using simple Euler integration
# t:  the current time of the system
# dt: the time to step the system forward
# x:  the current state of the system ([x position, y position, x velocity, y
#     velocity)
# returns the new state of the system
def integrate(t, dt, x):
    #Euler Method
    #x[0] = x[0] + x[2]*dt
    #x[2] = x[2]
    #x[1] = x[1]+x[3]*dt
    #x[3] = x[3]-(9.81*dt)

    #SciPy Dopri5 Integration

    #vode Integrator
    method = ode(eq).set_integrator('vode', method = 'bdf')
    method.set_initial_value(x, t)
    method.integrate(method.t+dt)
    return x
    #write one function that represents one step of the diff equation

Он вызывается из projectile.py. Большая часть этого — просто рисование и настройка для PyGame, но фрагмент, где эта часть актуальна:

      # integrate the projectile forward in time
  x = dynamics.integrate(fireT, dt, array([projX, projY, projVX, projVY]))
  projX = x[0]
  projY = x[1]
  projVX = x[2]
  projVY = x[3]

  # update the time
  fireT = fireT + dt 

person user3458256    schedule 25.03.2014    source источник


Ответы (1)


Проблема в том, что eq определяется с аргументами в неправильном порядке. из документов из ode функция, которую вы передаете, должна быть определена как:

f : callable f(t, y, *f_args)

в то время как в вашем случае вы поменяли местами t и y, определив его с помощью

def eq(x, t):

Затем ваш код пытается получить доступ к t[0], вызывая ошибку TypeError.

Просто измените эту строку на

def eq(t, x):
person gg349    schedule 25.03.2014
comment
Спасибо вам большое за ваш ответ. Исправлена ​​ошибка TypeError, и теперь игра как минимум рисует снаряд. Однако снаряд просто сидит там и не движется вперед во времени, как предполагалось. Я не уверен, что интегратор просто не обновляет значения в массиве x или вообще успешно вызывает интегратор. Я думаю, что это последнее, поскольку добавление метода while method.successful(): перед вызовом method.integrate(method.t+dt) останавливает запуск снаряда в PyGame. Кто-нибудь знает, почему это может быть? - person user3458256; 25.03.2014
comment
добавьте несколько операторов print здесь и там, чтобы увидеть, обновляются ли значения. - person gg349; 25.03.2014
comment
Спасибо за предложение. Я реализовал оператор печати, значения x[0]-x[3] одинаковы на каждом временном шаге. Не знаю, почему он не обновляет значения, но это, безусловно, сужает его. Спасибо за вашу помощь. - person user3458256; 25.03.2014
comment
в integrate() вы должны вернуть method.y, а не x. См. примеры здесь - person gg349; 25.03.2014
comment
Я ПОНЯЛ! Интегратор не обновлял исходные значения, он возвращал собственные обновленные значения. Возвращая x, я отправлял исходные значения обратно в класс PyGame вместо того, чтобы отправлять обновленные значения. Все, что я сделал, это вернуть метод method.integrate(method.t+dt) вместо того, чтобы просто вернуть x. Еще раз спасибо, flebool, ваши предложения, скорее всего, сэкономили мне часы разочарования. - person user3458256; 25.03.2014
comment
Рад помочь :-) удачи и добро пожаловать в сообщество stackoverflow. - person gg349; 25.03.2014