Question: My end goal with this program is to simulate constrained pendulums with springs but that is a goal for later, currently I have been trying to learn how object creation, positioning and interactions would work and will eventually build the way up. Currently I have been trying to make my code produce N number of independent pendulums side by side but they all spawn at the same position. I have tried a lot of things from trying to define a method to create multiple pendulums at once to the current iteration where I try to use a for loop for creating and shifting the position of the pendulum but to no avail. 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)  Also this is my first time trying Object Oriented Programming so I would appreciate any tips on how to improve the coding style and any comments on things I have been doing wrong.

Answer: This is a classical example of a good question. You were almost complete in your code. I made a few change to it, and as I was doing this in google.colab, there might be some things that you'll need to add, 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)  To run it in colab, if you do, you'll have to do a few things. It is rather tricky to install manin there. You need to do this: !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  To run the code: %load_ext manim  and %%manim -ql -v WARNING PhysicalPendulum  Here is a snapshot: