0

I've been trying to code projectile motion and everything has been working so far except the graphing portion, which i'm trying to iterate within the loop. I want to graph the x and y coordinate of the position vector, but i keep getting the error "module not callable"

import numpy as np
import math as m
import matplotlib as plt

g = np.array([0,-9.8,0])

r = np.array([0,1.2,0])

theta = 35 * m.pi / 180

v1 = 3.3

v = v1 * np.array([np.cos(theta),np.sin(theta),0])

a = g

t = 0

dt = .01

while r[1]  > 0:
    v = v + a * dt
    r = r + v * dt
    t = t + dt
    plt.plot(r)
    
print("r = ",r , "m")

print("t = ",t, "s")

print("v = ",v, "m/s")
  • You could use `print(f"{r = } m")` – AsukaMinato Sep 12 '22 at 07:05
  • Maybe this helps: https://www.geeksforgeeks.org/using-matplotlib-for-animations/ You have to create your figure and in the for loop you want to redraw your plot. Search for matplotlib.pyplot.draw or for an animation, there is enough material on google that you can try before asking a question on SO without code what you have tried so far. – 3dSpatialUser Sep 12 '22 at 07:09
  • my main issue is figuring out how to plot the x and y coordinate of the position vector r. If i defined x and y, it would be straightforward. but they're defined within r, which is an array and my confusion comes from how to plot the coordinates of r, within a loop – Sfv Join the madness Sep 12 '22 at 10:14

2 Answers2

1

I found two issues in your code:

  1. the plt import is not correct. Instead use from matplotlib import pyplot as plt
  2. plt.plot(r) works but nothing is shown since you are trying to draw a single point of infinitesimal size for each canvas. Since is a scatterplot, you should assign a dimension to each point, e.g.
    plt.plot(r[0], r[1], marker="o", markersize=5, markeredgecolor="blue", markerfacecolor="blue")
    
    enter image description here

If your goal is to generate an animation (as suggested by @3dSpatialUser), you need multiple pictures. Thus add plt.show() (or plt.savefig()) in the while loop.

0

Here it is a bit of code, that corrects your mistakes and uses ① a little different looping scheme, that I find more flexible, ② a simple animation trick, as suggested in other answers and comments, and ③ an alternative algorithm that gives very similar results when you use a small time step, but is more accurate if you use a longer time step.

I include no graphic output because it's an animation, test it yourself, please.

import numpy as np
import matplotlib.pyplot as plt

# CONSTANTS
a = np.array([0.0, -9.8, 0.0])
theta = np.radians(35.0)
v1 = 3.3

# Initial conditions
t, dt = 0.0, 0.01
r = np.array([0.0, 1.2, 0.0])
v = v1 * np.array([np.cos(theta),np.sin(theta),0])

# set the limits of the plots, to avoid annoying resizing, and grid
plt.axis((-0.05, 2.05, -0.05, 1.45))
plt.grid()

# imo, it's better a never ending loop with a break condition
# placed where it is needed - also, it's better to plot
# also the first and the last points
while 1:
    plt.scatter(r[0], r[1], color='red', s=3)
    plt.pause(.00001)
    if r[1]  < 0: break
    v = v + a * dt
    r = r + v * dt
    t = t + dt

# reset the initial conditions
t, dt = 0.0, 0.01
r = np.array([0.0, 1.2, 0.0])
v = v1 * np.array([np.cos(theta),np.sin(theta),0])

# here a little improvement, instead of using the FINAL value
# of the velocity to compute the final displacement, let's
# use the MEAN value of the velocity during the time step
while 1:
    plt.scatter(r[0], r[1], color='blue', s=3)
    plt.pause(.00001)
    if r[1]  < 0: break
    v0 = v
    v = v + a * dt
    r = r + (v0+v)/2 * dt
    t = t + dt
gboffi
  • 22,939
  • 8
  • 54
  • 85