Skip to content

Instantly share code, notes, and snippets.

@arnodeceuninck
Created January 28, 2025 22:44
Show Gist options
  • Save arnodeceuninck/2952c715090f667316c348b0d44194db to your computer and use it in GitHub Desktop.
Save arnodeceuninck/2952c715090f667316c348b0d44194db to your computer and use it in GitHub Desktop.
"""
Plot a moving pendulum in R1 (x, y), together with its projection to S1 (theta).
Code has been generated with the help of Gemini.
"""
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
# Choose your backend (if needed)
matplotlib.use('TkAgg')
# Pendulum parameters
g = 9.8
L = 1.0
# Initial conditions
theta0 = np.pi / 4
# Time parameters
dt = 0.01
t_final = 10.0
t = np.arange(0, t_final, dt)
# Solve the pendulum equation
theta = theta0 * np.cos(np.sqrt(g / L) * t)
# Calculate x and y coordinates
x = L * np.sin(theta)
y = -L * np.cos(theta)
# Set up the figure and axes
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6), gridspec_kw={'width_ratios': [1, 1]})
fig.set_tight_layout(True)
ax1.set_aspect('equal')
ax2.set_aspect('equal')
# Initialize plots
line, = ax1.plot([], [], 'o-', lw=2)
trace, = ax1.plot([], [], '-', lw=1, color='gray')
vert_line, = ax1.plot([0, 0], [-L, 0], '--', color='gray')
arc, = ax1.plot([], [], '-', color='red')
circle_s1, = ax2.plot(np.cos(np.linspace(0, 2 * np.pi, 100)), np.sin(np.linspace(0, 2 * np.pi, 100)), '--', color='gray')
circle, = ax2.plot([], [], 'o', markersize=5)
theta_line, = ax2.plot([], [], '-', color='blue')
horiz_line_s1, = ax2.plot([-1, 1], [0, 0], '--', color='black')
arc_s1, = ax2.plot([], [], '-', color='red')
# Text for coordinates and angle (Corrected and larger text size)
text_size = 14
x_text = ax1.text(0.1, 0.85, '', transform=ax1.transAxes, fontsize=text_size)
y_text = ax1.text(0.1, 0.8, '', transform=ax1.transAxes, fontsize=text_size)
theta_text = ax2.text(0.1, 0.85, '', transform=ax2.transAxes, fontsize=text_size)
# Set axis limits
ax1.set_xlim(-L * 1.2, L * 1.2)
ax1.set_ylim(-L * 1.2, L * 1.2) # Adjusted ylim to match data aspect ratio
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('Pendulum')
ax2.set_xlim(-1.2, 1.2)
ax2.set_ylim(-1.2, 1.2)
ax2.set_xlabel('cos(theta)')
ax2.set_ylabel('sin(theta)')
ax2.set_title('Angle')
def animate(i):
# Pendulum animation
line.set_data([0, x[i]], [0, y[i]])
trace.set_data(x[:i], y[:i])
# Calculate arc points (optimized)
arc_radius = 0.2 * L
arc_angles = np.linspace(np.pi / 2, np.pi / 2 - theta[i], 50)
arc.set_data(arc_radius * np.cos(arc_angles), -arc_radius * np.sin(arc_angles))
# Angle circle (optimized)
circle.set_data([np.cos(theta[i])], [np.sin(theta[i])])
theta_line.set_data([0, np.cos(theta[i])], [0, np.sin(theta[i])])
# Arc in S1 (optimized)
arc_radius_s1 = 0.2
arc_angles_s1 = np.linspace(0, theta[i], 50)
arc_s1.set_data(arc_radius_s1 * np.cos(arc_angles_s1), arc_radius_s1 * np.sin(arc_angles_s1))
# Update text (f-strings are already efficient)
x_text.set_text(f'x: {x[i]:.2f}')
y_text.set_text(f'y: {y[i]:.2f}')
theta_deg = np.degrees(theta[i]) # Convert to degrees
theta_text.set_text(f'θ: {theta_deg:.2f}°') # Display in degrees
return line, trace, vert_line, arc, circle, theta_line, x_text, y_text, theta_text, circle_s1, horiz_line_s1, arc_s1
ani = animation.FuncAnimation(fig, animate, frames=len(t), interval=20, blit=True, repeat=False)
plt.show()
ani.save('pendulum_animation.gif', writer='pillow', fps=30)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment