我这个程序的最终目标是用弹簧模拟约束摆,但这是以后的目标,目前我一直在尝试学习对象创建、定位和交互如何工作,并最终建立起来。
目前我一直在尝试让我的代码并排产生N个独立的摆,但它们都在同一位置产生。
我尝试了很多事情,从尝试定义一种方法来一次创建多个钟摆,到当前的迭代,我尝试使用 for 循环来创建和移动钟摆的位置,但没有成功。
import numpy as np
import manim as mn
class Pendulum:
def __init__(self, mass, length, theta):
self.mass = mass
self.length = length
self.g = -9.81
self.angle = theta
self.angular_vel = 0
def step(self, dt):
# Defining RK4
def runge_kutta_4(f, t, y0, h=None):
if h is None:
h = t[1] - t[0]
n = len(t)
y = np.zeros((n, len(y0)))
y[0] = y0
for i in range(n - 1):
k1 = h * f(t[i], y[i])
k2 = h * f(t[i] + h/2, y[i] + k1/2)
k3 = h * f(t[i] + h/2, y[i] + k2/2)
k4 = h * f(t[i] + h, y[i] + k3)
y[i+1] = y[i] + (k1 + 2*k2 + 2*k3 + k4) / 6
return y
def pendulum_equations(t, state):
theta, omega = state
force = self.mass * self.g * np.sin(theta)
torque = force * self.length
MoI = 1/3 * self.mass * self.length**2
alpha = torque / MoI
return np.array([omega, alpha])
state = np.array([self.angle, self.angular_vel])
t = np.array([0, dt])
sol = runge_kutta_4(pendulum_equations, t, state)
self.angle = sol[-1, 0]
self.angular_vel = sol[-1, 1]
class PhysicalPendulum(mn.Scene):
def construct(self):
p = Pendulum(2, 10, np.pi/2)
N = 3 # change number of pendulums here
pendulums = []
scale = 0.5
spacing = 3 # Adjust the spacing between pendulums as needed
def get_pendulum(i, rod_width=0.2, rod_height=1):
rod = mn.Rectangle(width=rod_width, height=scale * p.length, color=mn.BLUE)
rod.shift(mn.DOWN * scale * p.length / 2)
rod.rotate(p.angle, about_point=rod.get_top())
pendulum = mn.VGroup(rod)
pendulum.shift(mn.UP * 3) # Adjust the vertical shift as needed
if i % 2 == 0:
pendulum.shift(mn.RIGHT * spacing * i)
else:
pendulum.shift(mn.LEFT * spacing * i)
return pendulum
def step(pendulum, dt, i):
p.step(dt)
pendulum.become(get_pendulum(i))
for i in range(N):
pendulum = get_pendulum(i)
pendulum.add_updater(lambda mob, dt: step(mob, dt, i))
pendulums.append(pendulum)
self.add(*pendulums)
self.wait(20)
for pendulum in pendulums:
pendulum.remove_updater(step)
这也是我第一次尝试面向对象编程,因此我将不胜感激任何有关如何改进编码风格的提示以及对我做错的事情的任何评论。
这是一个好问题的经典例子。您的代码几乎已完成。我对它做了一些更改,当我在 google.colab 中执行此操作时,您可能需要添加一些内容,
import numpy as np
import manim as mn
class Pendulum:
g = -9.81
def __init__(self, mass, length, theta):
self.mass = mass
self.length = length
self.angle = theta
self.angular_vel = 0
def step(self, dt):
def runge_kutta_4(f, t, y0, h=None):
if h is None:
h = t[1] - t[0]
n = len(t)
y = np.zeros((n, len(y0)))
y[0] = y0
for i in range(n - 1):
k1 = h * f(t[i], y[i])
k2 = h * f(t[i] + h/2, y[i] + k1/2)
k3 = h * f(t[i] + h/2, y[i] + k2/2)
k4 = h * f(t[i] + h, y[i] + k3)
y[i+1] = y[i] + (k1 + 2*k2 + 2*k3 + k4) / 6
return y
def pendulum_equations(t, state):
theta, omega = state
force = self.mass * self.g * np.sin(theta)
torque = force * self.length
moment_of_inertia = 1/3 * self.mass * self.length**2
alpha = torque / moment_of_inertia
return np.array([omega, alpha])
state = np.array([self.angle, self.angular_vel])
t = np.array([0, dt])
sol = runge_kutta_4(pendulum_equations, t, state)
self.angle = sol[-1, 0]
self.angular_vel = sol[-1, 1]
class PhysicalPendulum(mn.Scene):
def construct(self):
N = 3
pendulums = [Pendulum(2, 10, np.pi/2) for _ in range(N)]
scale = 0.5
spacing = 3
def get_pendulum(pendulum, i, rod_width=0.2, rod_height=1):
rod = mn.Rectangle(width=rod_width, height=scale * pendulum.length, color=mn.BLUE)
rod.shift(mn.DOWN * scale * pendulum.length / 2)
rod.rotate(pendulum.angle, about_point=rod.get_top())
pendulum_group = mn.VGroup(rod)
pendulum_group.shift(mn.UP * 3)
pendulum_group.shift(mn.RIGHT * spacing * i)
return pendulum_group
def step(pendulum, dt, i):
pendulums[i].step(dt)
pendulum.become(get_pendulum(pendulums[i], i))
pendulum_groups = []
for i in range(N):
pendulum_group = get_pendulum(pendulums[i], i)
pendulum_group.add_updater(lambda mob, dt, i=i: step(mob, dt, i))
pendulum_groups.append(pendulum_group)
self.add(*pendulum_groups)
self.wait(20)
for pendulum_group in pendulum_groups:
pendulum_group.remove_updater(step)
要在 Colab 中运行它,如果你这样做,你将必须做一些事情。在那里安装
manin
是相当棘手的。你需要这样做:
!pip install manim
!apt-get install texlive texlive-latex-extra texlive-fonts-extra texlive-latex-recommended texlive-science dvipng
!apt-get install ffmpeg
!apt-get install sox
!apt-get install libcairo2-dev libjpeg-dev libgif-dev
!pip install manim
运行代码:
%load_ext manim
和
%%manim -ql -v WARNING PhysicalPendulum
这是快照: