Created
January 28, 2025 22:44
-
-
Save arnodeceuninck/2952c715090f667316c348b0d44194db to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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