!apt update -y
!apt install ffmpeg -y
import numpy as np
import matplotlib.pyplot as plt
import sympy
from matplotlib.animation import FFMpegWriter
from matplotlib.patches import Circle
# Defining our Parameters
g = 9.8 # Gravity (m/s^2)
L = 1 # Length (m)
m = 1 # In Kg
# Creating the time array for 10 second run time
dt = .001 # Seconds (s)
t_vec = np.arange(0,10,dt) # Time Vector
# Define vectors that will hold our state variables over time
# x Vectors of Zero
x_vec = np.zeros(len(t_vec))
dx_vec = np.zeros(len(t_vec))
ddx_vec = np.zeros(len(t_vec))
# y Vectors of Zero
y_vec = np.zeros(len(t_vec))
dy_vec = np.zeros(len(t_vec))
ddy_vec = np.zeros(len(t_vec))
# Lambda Vector (Constraint Force)
lambda_vec = np.zeros(len(t_vec))
# Establishing the inital conditions for x & y
x_vec[0] = -1 # x Initial Position
dx_vec[0] = 0 # dx Initial Velocity
y_vec[0] = 1 # y Initial Position
dy_vec[0] = 0 # dy Initial Velocity
# Loop Through 10 second time interval of equations solved from Matrix
# Creating Loop For the x Direction
for i in range(1, len(t_vec)):
x_vec[i] = x_vec[i-1] + dx_vec[i-1]*dt
ddx_vec[i-1] = -(2*x_vec[i-1]*(2*(dx_vec[i-1]**2) + g))/(4*(x_vec[i-1]**2) + 1)
dx_vec[i] = dx_vec[i-1] + ddx_vec[i-1]*dt
# Creating Loop For the y Direction
for i in range(1, len(t_vec)):
y_vec[i] = y_vec[i-1] + dy_vec[i-1]*dt
ddy_vec[i-1] = -(2*(2*g*x_vec[i-1]**2 - dx_vec[i-1]**2))/(4*x_vec[i-1]**2 + 1)
dy_vec[i] = dy_vec[i-1] + ddy_vec[i-1]*dt
# Creating Loop For the Lambda Component
for i in range(1, len(t_vec)):
lambda_vec[i] = (2*m*dx_vec[i-1]**2 + g*m)/(4*dx_vec[i-1]**2 + 1)
# Setting Up the x-axis
plt.plot(t_vec,x_vec)
plt.title('x-Positon')
plt.xlabel('time')
plt.ylabel('x')
plt.show()
# Setting Up the y-axis
plt.plot(t_vec,y_vec)
plt.title('y-Postion')
plt.xlabel('time')
plt.ylabel('y')
plt.show()
# Setting Up the Lambda
plt.plot(t_vec,lambda_vec)
plt.title('Constraint Force')
plt.xlabel('time')
plt.show()
# SETTING UP THE SIMULATION PORTION
# Setup Figure: Initialize Figure / Axle Handles
fig, ax = plt.subplots() # Initialize Figure and Axes
p, = ax.plot([], [], color='navy')
ax.axis('equal')
ax.set_xlim([-3, 3]) # X Lim
ax.set_ylim([-3, 3]) # Y Lim
ax.set_xlabel('x') # X Label
ax.set_ylabel('y') # Y Label
ax.set_title('Parabolic Wire Simulation:') # Plot Title
video_title = "Simulation Q1 Part C" # Naming of Animation
# Initialize Patch: (Circle On Wire)
# Creating Circle On Plot of Desired Location
c = Circle((0, 0), radius=0.2, color='palegreen')
ax.add_patch(c) # Add the patch to the axes
# Setup Animation Writer:
FPS = 20 # Frames per second for the video
sample_rate = int(1 / (dt * FPS)) # Rate at which we sample the simulation to visualize
dpi = 300 # Quality of the Video
writerObj = FFMpegWriter(fps=FPS) # Video Object
# We need to calculate the cartesian location of the pendulum:
# Initialize Array:
simulation_size = len(t_vec) # We use this alot, so lets store it.
x_var = np.linspace(-2,2,2000) # Creating Array for x placements
y_var = x_var**2 # What y would equal
plt.plot(x_var, y_var, color='black')
plt.show()
# Plot and Create Animation:
with writerObj.saving(fig, video_title+".mp4", dpi):
# We want to create video that represents the simulation
# So we need to sample only a few of the frames:
for i in range(0, simulation_size, sample_rate):
# Update Pendulum Arm:
x_data_points = x_vec[i]
y_data_points = y_vec[i]
# We want to avoid creating new plots to make an animation (Very Slow)
# Instead lets take the plot we made earlier and just update it with new data.
p.set_data(x_data_points, y_data_points) # Update plot with set_data
# Update Pendulum Patch:
patch_center = x_vec[i], y_vec[i]
c.center = patch_center # Same idea here, instead of drawing a new patch update its location
# Update Drawing:
fig.canvas.draw() # Update the figure with the new changes
# Grab and Save Frame:
writerObj.grab_frame()