使用欧拉法绘制单摆动画时遇FuncAnimation属性错误:无_resize_id属性
问题:使用欧拉法绘制单摆动画时触发AttributeError: FuncAnimation对象无‘_resize_id’属性
我尝试在Python中使用欧拉法,结合给定的θ值与公式绘制单摆动画,但运行时触发AttributeError,提示FuncAnimation对象不存在‘_resize_id’属性,请问问题出在哪里?
原代码
# Liður 2 import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation def ydot(t, y): g = 9.81 l = 1 z1 = y[1] z2 = -g/l*np.sin(y[0]) return np.array([z1, z2]) def eulerstep(t, x, h): return ([x[j]+h*ydot(t,x)[j] for j in range(len(x))]) def eulersmethod(Theta0, T, n): z = Theta0 h = T/n t = [i*h for i in range(n)] theta = [[],[]] for i in range(n): z = eulerstep(t[i], z, h) theta[0].append(z[0]) theta[1].append(z[1]) return(t, theta[0], theta[1]) def animate_pendulum(x, y, h): fig = plt.figure(figsize=(8,8)) ax = fig.add_subplot(autoscale_on = False, xlim=(-2.2, 2.2), ylim = (-2.2, 2.2)) ax.grid() line = ax.plot([],[], 'o', c='blue', lw=1) time_text = ax.text(0.05, 0.9, '', transform = ax.transAxes) def animate(i): xline = [0, x[1]] yline = [0, y[1]] line.set_data(xline, yline) time_text.set_text(f"time = {i*h:1f}s") return line, time_text ani = FuncAnimation( fig, animate, len(x), interval = h*1000, blit = True, repeat = False ) plt.show() def min(): L=2 T=20 n=500 h=T/n y_0 = [np.pi/12, 0] t, angle, velocity = eulersmethod(y_0, T, n) x, y = L*np.sin(angle[:]), -L*np.cos(angle[:]) animate_pendulum(x, y, h) min()
问题原因及修复方案
1. line对象类型错误
ax.plot()返回的是包含单个Line2D对象的列表,原代码直接将这个列表赋值给line,后续调用line.set_data()时会因为对象类型不匹配,导致动画初始化失败,进而触发_resize_id相关的AttributeError。
修复:用逗号解包拿到单个Line2D对象:
line, = ax.plot([],[], 'o', c='blue', lw=1)
2. 动画帧更新逻辑错误
原animate(i)函数中,xline和yline固定取x[1]和y[1],导致所有帧都显示同一个位置,动画无法正常播放,同时也可能加剧动画初始化时的异常。
修复:根据帧索引i获取对应位置的坐标:
xline = [0, x[i]] yline = [0, y[i]]
3. 函数命名冲突
原代码中函数名min()与Python内置函数min重名,可能引发潜在的命名冲突问题。
修复:将函数名改为main(),避免冲突。
修正后的完整代码
# Liður 2 import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation def ydot(t, y): g = 9.81 l = 1 z1 = y[1] z2 = -g/l*np.sin(y[0]) return np.array([z1, z2]) def eulerstep(t, x, h): return ([x[j]+h*ydot(t,x)[j] for j in range(len(x))]) def eulersmethod(Theta0, T, n): z = Theta0 h = T/n t = [i*h for i in range(n)] theta = [[],[]] for i in range(n): z = eulerstep(t[i], z, h) theta[0].append(z[0]) theta[1].append(z[1]) return(t, theta[0], theta[1]) def animate_pendulum(x, y, h): fig = plt.figure(figsize=(8,8)) ax = fig.add_subplot(autoscale_on = False, xlim=(-2.2, 2.2), ylim = (-2.2, 2.2)) ax.grid() # 修正:解包获取单个Line2D对象 line, = ax.plot([],[], 'o', c='blue', lw=1) time_text = ax.text(0.05, 0.9, '', transform = ax.transAxes) def animate(i): # 修正:根据帧索引i获取对应坐标 xline = [0, x[i]] yline = [0, y[i]] line.set_data(xline, yline) time_text.set_text(f"time = {i*h:.1f}s") return line, time_text ani = FuncAnimation( fig, animate, frames=len(x), interval = h*1000, blit = True, repeat = False ) plt.show() def main(): L=2 T=20 n=500 h=T/n y_0 = [np.pi/12, 0] t, angle, velocity = eulersmethod(y_0, T, n) x, y = L*np.sin(angle[:]), -L*np.cos(angle[:]) animate_pendulum(x, y, h) main()
内容的提问来源于stack exchange,提问作者Óli Jón Ólason
相关产品推荐
相关产品推荐

