Моделирование «Двойной маятник»
Автор: melvit • Август 3, 2023 • Контрольная работа • 2,462 Слов (10 Страниц) • 131 Просмотры
Министерство науки и высшего образования Российской Федерации
федеральное государственное автономное образовательное учреждение высшего образования
«НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ УНИВЕРСИТЕТ ИТМО»
Моделирование
по теме «Двойной маятник»
по дисциплине «Физика»
Авторы: Шашкевич Эльфрида, Флийчук Михаил, Мирошников Егор
Факультет: ФИТиП (2 курс)
Группа: М32101
Преподаватель: Хуснутдинова Наира Рустемовна
[pic 1]
Санкт-Петербург
2022
Моделирование «Двойной маятник»
Цель: создание модели двойного маятника и демонстрация его хаотичного поведения.
В качестве инструмента был использован язык программирования Python.
Описание:
Маятник состоит из двух невесомых стержней и двух материальных точек. Он, как правило, вращается вокруг горизонтальной оси так, что оба подвеса лежат в одной плоскости и составляют с вертикалью некоторые углы. Такой маятник, движущийся в одной плоскости, имеет две степени свободы. Фактически маятник состоит из двух круговых математических маятников одинаковой или разной длины и массы, причем второй маятник подвешен к грузу первого. Если двойной маятник с одинаковыми подвесами и грузами вывести из равновесия произвольным образом и предоставить самому себе, то каждый из грузов будет совершать довольно сложное движение, в котором трудно уловить какую-либо закономерность.
Однако, при некоторых начальных условиях движение маятника оказывается очень простым: оба груза совершают гармонические колебания с одной и той же частотой, причем амплитуды и фазы этих колебаний находятся в определенной связи друг с другом.
Код с комментариями:
- В данной реализации используется модуль tkinter из библиотеки TK. Даёт возможность показывать холст с графическим рисунком, показывает программу с оконным интерфейсом.
- Данный код был написан нашей командной работой.
import tkinter as tk
import random
from math import pi, sin, cos
G = 9.81
class DoublePendulum():
# конструктор класса отвечает за инициализацию переменных и ползунков
def __init__(self, mass_1, mass_2, length_1, length_2, theta_1, theta_2, delta):
self.mass_1 = mass_1
self.mass_2 = mass_2
self.length_1 = length_1
self.length_2 = length_2
self.theta_1 = theta_1
self.theta_2 = theta_2
self.delta = delta
self.deriv_theta_1 = 0
self.deriv_theta_2 = 0
self.frame = tk.Frame(root)
self.scl_length_1 = tk.Scale(self.frame, from_=15, to=165, length=300, tickinterval=50,
label="Length of Pendulum 1", orient=tk.HORIZONTAL)
self.scl_length_1.set(length_1)
self.scl_length_2 = tk.Scale(self.frame, from_=15, to=165, length=300, tickinterval=50,
label="Length of Pendulum 2", orient=tk.HORIZONTAL)
self.scl_length_2.set(length_1)
self.scl_mass_1 = tk.Scale(self.frame, from_=15, to=165, length=300, tickinterval=50,
label="Mass of the first pendulum", orient=tk.HORIZONTAL)
self.scl_mass_1.set(mass_1)
self.scl_mass_2 = tk.Scale(self.frame, from_=15, to=165, length=300, tickinterval=50,
label="Mass of the second pendulum", orient=tk.HORIZONTAL)
self.scl_mass_2.set(mass_2)
self.grid_widgets()
def grid_widgets(self):
# отображение элементов в окне
self.frame.grid(row=0, column=1, rowspan=3)
self.scl_length_1.grid(row=0, column=0, padx=10, pady=5)
self.scl_length_2.grid(row=1, column=0, padx=10, pady=5)
self.scl_mass_1.grid(row=2, column=0, padx=10, pady=5)
self.scl_mass_2.grid(row=3, column=0, padx=10, pady=5)
def update_pendulum(self, pivot_x, pivot_y):
# расчёты по формулам (формулы взяты отсюда https://www.myphysicslab.com/pendulum/double-pendulum-en.html)
self.length_1 = self.scl_length_1.get()
self.length_2 = self.scl_length_2.get()
self.mass_1 = self.scl_mass_1.get()
self.mass_2 = self.scl_mass_2.get()
# Компоненты для первого маятника
comp_1 = -G * (2 * self.mass_1 + self.mass_2) * sin(self.theta_1) - self.mass_2 * G * sin(
self.theta_1 - 2 * self.theta_2)
comp_2 = 2 * sin(self.theta_1 - self.theta_2) * self.mass_2 * (
self.deriv_theta_2 ** 2 * self.length_2 + self.deriv_theta_1 ** 2 * self.length_1 * cos(
self.theta_1 - self.theta_2))
comp_3 = self.length_1 * (
2 * self.mass_1 + self.mass_2 - self.mass_2 * cos(2 * self.theta_1 - 2 * self.theta_2))
sec_deriv_theta_1 = (comp_1 - comp_2) / comp_3
# Компоненты для второго маятника
comp_1 = 2 * sin(self.theta_1 - self.theta_2)
comp_2 = self.deriv_theta_1 ** 2 * self.length_1 * (self.mass_1 + self.mass_2) + G * (
self.mass_1 + self.mass_2) * cos(
self.theta_1) + self.deriv_theta_2 ** 2 * self.length_2 * self.mass_2 * cos(self.theta_1 - self.theta_2)
comp_3 = self.length_2 * (
2 * self.mass_1 + self.mass_2 - self.mass_2 * cos(2 * self.theta_1 - 2 * self.theta_2))
sec_deriv_theta_2 = (comp_1 * comp_2) / comp_3
# изменение углов маятников
self.deriv_theta_1 += sec_deriv_theta_1 * self.delta
self.deriv_theta_2 += sec_deriv_theta_2 * self.delta
self.theta_1 += self.deriv_theta_1 * self.delta
self.theta_2 += self.deriv_theta_2 * self.delta
# изменение координат оснований маятников
pend_1_x = pivot_x + self.length_1 * sin(self.theta_1)
pend_1_y = pivot_y + self.length_1 * cos(self.theta_1)
pend_2_x = pend_1_x + self.length_2 * sin(self.theta_2)
pend_2_y = pend_1_y + self.length_2 * cos(self.theta_2)
return pend_1_x, pend_1_y, pend_2_x, pend_2_y
class MainApplication(tk.Tk):
# класс отвечающий за графическое отображение маятника на экране
def __init__(self, master, double_pendulum_params):
self.master = master
self.frm_upper = tk.Frame(self.master)
self.btn_double = tk.Button(self.frm_upper, text="Double Pendulum", state=tk.DISABLED,
command=lambda: self.switch(0))
self.frm_canvas = tk.Frame(self.master)
self.canvas = tk.Canvas(self.frm_canvas, height=700, width=700, bg="black")
self.frm_lower = tk.Frame(self.master)
# инициализация кнопок внизу окна
self.chk_trace = tk.Checkbutton(self.frm_lower, text="Trace", command=self.start_trace)
self.btn_clear = tk.Button(self.frm_lower, text="Clear Trace", command=self.clear_trace)
self.btn_pause = tk.Button(self.frm_lower, text="Pause", width=7, command=self.pause)
self.double_pendulum = DoublePendulum(**double_pendulum_params)
self.pivot_x = int(self.canvas['width']) / 2 # Расположение осей маятников на экране
self.pivot_y = 300
self.btn_randomize = self.btn_randomize = tk.Button(self.double_pendulum.frame,
text="Randomize (Initial Theta)", command=self.randomize)
self.bool_trace = False
self.bool_pause = False
self.all_traces = []
self.curr_trace = []
self.grid_pack_widgets()
self.draw_double_pendulum()
def grid_pack_widgets(self):
# инициализация кнопок взаимодействия
self.frm_upper.grid(row=0, column=0)
self.frm_canvas.grid(row=1, column=0)
self.frm_lower.grid(row=2, column=0)
self.btn_double.pack(side=tk.LEFT)
self.canvas.pack()
self.chk_trace.pack(side=tk.LEFT)
self.btn_clear.pack(side=tk.LEFT)
self.btn_pause.pack(side=tk.LEFT)
self.btn_randomize.grid(row=4, column=0, padx=10, pady=5)
def draw_double_pendulum(self):
# прорисовка траекторий
if self.bool_pause:
tk.after_id = self.canvas.after(15, self.draw_double_pendulum)
else:
self.canvas.delete("pendulum")
self.canvas.delete("line")
self.canvas.delete("trace")
self.double_motion()
tk.after_id = self.canvas.after(15, self.draw_double_pendulum)
def double_motion(self):
# инициализация рёбер (их движение)
(x, y, x2, y2) = self.double_pendulum.update_pendulum(self.pivot_x, self.pivot_y)
radius = 10
self.canvas.create_oval(x - radius, y - radius, x + radius, y + radius, tag="pendulum", fill="red")
self.canvas.create_oval(x2 - radius, y2 - radius, x2 + radius, y2 + radius, tag="pendulum", fill="white")
self.canvas.create_line(self.pivot_x, self.pivot_y, x, y, width=3, tag="line", fill="red")
self.canvas.create_line(x, y, x2, y2, width=3, tag="line", fill="white")
if self.bool_trace:
self.curr_trace.append((x2, y2, x2, y2))
if self.all_traces:
for trace in self.all_traces:
self.canvas.create_line(trace, tag="trace", fill="red")
if self.curr_trace:
self.canvas.create_line(self.curr_trace, tag="trace", fill="red")
def start_trace(self):
# начало прорисовки
if self.curr_trace:
self.all_traces.append(self.curr_trace)
self.curr_trace = []
self.bool_trace = not self.bool_trace
def clear_trace(self):
# удаление прорисовки
self.curr_trace = []
self.all_traces = []
self.canvas.delete('trace')
def pause(self):
# пауза
if self.bool_pause:
self.btn_pause['text'] = "Pause"
self.bool_pause = False
else:
self.btn_pause['text'] = "Resume"
self.bool_pause = True
def randomize(self):
# генерация случайного расположения маятника
if self.curr_trace:
self.all_traces.append(self.curr_trace)
self.curr_trace = []
self.double_pendulum.theta_1 = random.uniform(-pi, pi)
self.double_pendulum.deriv_theta_1 = 0
self.double_pendulum.theta_2 = random.uniform(-pi, pi)
self.double_pendulum.deriv_theta_2 = 0
# начальные параметры для запуска по умолчанию
if __name__ == '__main__':
dub_pend_params = {
'length_1': 165,
'length_2': 165,
'mass_1': 5,
'mass_2': 5,
'theta_1': pi / 2,
'theta_2': 3 * pi / 4,
'delta': .1,
}
root = tk.Tk()
root.title("Pendulum Simulation")
root.resizable(False, False)
root.columnconfigure(1, weight=1)
app = MainApplication(root, dub_pend_params)
root.mainloop()
...