Question

I'm doing a project that involves using a SciPy Integrator to model projectile motion in this shooting game. I've never had to program anything in python before and my calculus is a little rusty, but after several hours I was also I'm having a hard time determining exactly what causes certain errors. After several hours of trial and error I've gotten it to work with the commented out code in the integration method (I think it's a Euler Integration but I'm honestly not 100% sure). However I'm also supposed to use two integrators from the SciPy library, which haven't been working. Both throw the same error message in the same place which is:

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

It seems like it's expecting a different object type, but I honestly don't know what to make of it. I can't tell if I'm using the integrator wrong, or if I made a mistake in setting up the ODE. I'm really stumped. Any help at all would be greatly appreciated. Here's the code:

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

It's called from projectile.py. Most of that is just drawing and set-up for the PyGame but the snippet where this part is relevant is:

      # 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 
Was it helpful?

Solution

The problem is that eq is defined with the arguments in the wrong order. from the docs of ode, the function that you pass in should be defined as:

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

while in your case you swapped t and y, by defining it with

def eq(x, t):

Then your code tries to access t[0], raising a TypeError.

Simply change that line to

def eq(t, x):
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top