Иллюзия зависания пружины
Содержание
Описание физического эксперимента[править]
Длинная пружина растянута и находиться в статическом положении. После чего отпускаем верхний конец пружины и видим, что нижний конец пружины находится в неподвижном состоянии в течение продолжительного времени.
Ниже будет представлена математическая модель и программа, демонстрирующая данный эффект, называемый "иллюзией зависания".
Математическая модель[править]
Задана система пружин с жесткостью
и грузиков с массой , подвешенных на креплении. На систему действует сила тяжести . Рассчитываются статические координаты такой системы. После чего убирается верхняя пружина, что приводит систему в движение.Цель - описать "зависание" нижнего грузика во время падения пружины.
Основные уравнения[править]
где — количество грузиков ; — текущий грузик ; — длина не растянутой пружины; — статическое удлинение пружины.
при :
Программа (лучше всего смотреть ее в Mozilla Firefox)
Скачать программу Spring_illusion.rar.
Файл "Spring_illusin.js"
1 window.addEventListener("load", Main_Spring, true);
2 function Main_Spring() {
3
4 // *** Некие исходные данные ***
5
6 var canvas = spring_canvas;
7 canvas.onselectstart = function () {return false;}; // запрет выделения canvas
8 var ctx = canvas.getContext("2d"); // на ctx происходит рисование
9 var w = canvas.width; // ширина окна в расчетных координатах
10 var h = canvas.height; // высота окна в расчетных координатах
11
12 var Pi = 3.1415926; // число "пи"
13 var g = 9.8; // гравитационная постоянная
14
15 var T0 = 0.01; // масштаб времени (период колебаний исходной системы)
16
17 var m0 = 0.15; // масштаб массы маятника
18 var C0 = 1; // масштаб жесткости пружины
19
20 var count = true; // проводить ли расчет системы
21 var v = 0; // скорость тела
22 var t = 0;
23
24 // параметры полученные из размеров холста
25 var rw = canvas.width / 4;
26 var rh = canvas.height / 100;
27
28 // параметры грузиков
29 var x0 = 0;
30 var y0 = 0;
31 var vy0 = 0;
32 var rad0 = 7;
33 var sTime = 0;
34 // параметры пружины
35 var Lp = 30; //длина пружины
36
37
38 // *** Задание вычислительных параметров ***
39
40 var fps = 60; // frames per second - число кадров в секунду (качечтво отображения)
41 var spf = 5; // steps per frame - число шагов интегрирования между кадрами
42 var dt = 50 * T0 / fps; // шаг интегрирования (качество расчета)
43 var steps = 0; // количество шагов интегрирования
44
45
46 // *** Задание физических параметров ***
47 var m = 1 * m0; // масса грузика
48 var C = 1 * C0; // жесткость пружины
49 var L0 = 0; // изначальное удлинение пружины
50 var n = 5; // количество тел
51 var circle; // круглые тела
52
53 // *** Установка слайдеров для переменных величин ***
54 slider_m.value = (m / m0).toFixed(1);
55 number_m.value = (m / m0).toFixed(1);
56 slider_spf.value = (spf).toFixed(1);
57 number_spf.value = (spf).toFixed(1);
58 slider_n.value = parseInt(n);
59 number_n.value = parseInt(n);
60
61 function setM(new_m) {
62 m = new_m * m0;
63 }
64
65 function setSpf(new_spf) {
66 spf = new_spf;
67 }
68 function setN(new_n) {
69 n = new_n;
70 StaticStart();
71 }
72
73 slider_m.oninput = function () {
74 number_m.value = slider_m.value;
75 setM(slider_m.value);
76 };
77 number_m.oninput = function () {
78 slider_m.value = number_m.value;
79 setM(number_m.value);
80 };
81
82
83 slider_spf.oninput = function () {
84 number_spf.value = slider_spf.value;
85 setSpf(slider_spf.value);
86 };
87 number_spf.oninput = function () {
88 slider_spf.value = number_spf.value;
89 setSpf(number_spf.value);
90 };
91
92 slider_n.oninput = function () {
93 number_n.value = slider_n.value;
94 setN(slider_n.value);
95 };
96 number_n.oninput = function () {
97 slider_n.value = number_n.value;
98 setN(number_n.value);
99 };
100
101 // *** Условие падения тела ***
102 var spring_dropped = false;
103 drop_spring.onclick = function () {
104 spring_dropped = true;
105 };
106
107 // *** Пересчет статических координат
108 new_static.onclick = function () {
109 StaticStart()
110 };
111
112 // *** Создание массива элементов ***
113 function StaticStart() {
114 spring_dropped = false;
115 circle = [];
116 for (var i = 0; i < n; i++) {
117 var circ = {};
118 circ.x = x0;
119 circ.y = y0;
120 circ.vy = vy0;
121 circ.rad = rad0;
122 circ.L = L0;
123
124 var rgb = HSVtoRGB(i / n * 2, 1, 1);
125
126 circ.fill = "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", 1)";
127 circle[i] = circ;
128 }
129 for (var i = 0; i < n; i++) {
130 if (i == 0) {
131 circle[i].x = w / 2;
132 circle[i].y0 = Lp + (n - i) * m * g / C;
133 circle[i].y = circle[i].y0;
134
135 } else {
136 circle[i].x = w / 2;
137 circle[i].y0 = circle[i - 1].y0 + Lp + (n - i) * m * g / C;
138 circle[i].y = circle[i].y0;
139 console.log(circle[i].y0);
140
141 }
142 }
143 }
144
145 // *** функция разукрашивания объектов
146 function HSVtoRGB(h, s, v) {
147 var r, g, b, i, f, p, q, t;
148 i = Math.floor(h * 6);
149 f = h * 6 - i;
150 p = v * (1 - s);
151 q = v * (1 - f * s);
152 t = v * (1 - (1 - f) * s);
153 switch (i % 6) {
154 case 0: r = v, g = t, b = p; break;
155 case 1: r = q, g = v, b = p; break;
156 case 2: r = p, g = v, b = t; break;
157 case 3: r = p, g = q, b = v; break;
158 case 4: r = t, g = p, b = v; break;
159 case 5: r = v, g = p, b = q; break;
160 }
161 return {
162 r: Math.floor(r * 255),
163 g: Math.floor(g * 255),
164 b: Math.floor(b * 255)
165 };
166 }
167
168 // график
169 var vGraph1 = new TM_graph( // определить график
170 "#vGraph1", // на html-элементе #vGraph
171 250, // сколько шагов по оси "x" отображается
172 0, 100, 5); // мин. значение оси Y, макс. значение оси Y, шаг по оси Y
173
174 // *** Функция обеспечивающая "жизнь" пружин ***
175 function control() {
176 calculate();
177 draw();
178 requestAnimationFrame(control);
179 }
180 StaticStart();
181 control();
182
183
184
185 // *** Функция расчетов координат ***
186 function calculate() {
187
188 for (var s = 1; s <= spf; s++) {
189 var k = n;
190 for (var i = 1; i < n; i++) {
191 if (spring_dropped)
192 circle[0].L = 0;
193 else
194 circle[0].L = circle[0].y - Lp;
195 circle[i].L = circle[i].y - circle[i - 1].y - Lp;
196 }
197
198 for (var i = 0; i < n; i++) {
199 if (i == n - 1)
200 circle[i].vy += ((-1) * C * (circle[i].L) / m + g) * dt;
201 else
202 circle[i].vy += ((-1) * C * (circle[i].L - circle[i + 1].L) / m + g) * dt;
203
204
205 circle[i].y += circle[i].vy * dt;
206
207 }
208 steps++;
209
210 if (spring_dropped)
211 { sTime ++;
212 if (sTime % 50 == 0) vGraph1.graphIter(sTime/50, (circle[n-1].y-circle[n-1].y0)) ;
213 };
214 }
215 }
216
217
218 // *** Функция рисования объектов ***
219 function draw() {
220 ctx.clearRect(0, 0, w, h);
221
222 // Рисование закрепления
223 ctx.lineWidth = 6;
224 ctx.strokeStyle = "#7394cb";
225 ctx.beginPath();
226 ctx.moveTo(200, 0);
227 ctx.lineTo(300, 0);
228 ctx.stroke();
229
230 for (var i = 0; i < n; i++) {
231
232 // Рисование пружинок
233 if (i == 0) {
234 if (!spring_dropped)
235 draw_spring(0, circle[i].y, w / 2, 10, 40);
236 } else
237 draw_spring(circle[i - 1].y, circle[i].y, w / 2, 10, 40);
238
239
240 }
241 for (var i = 0; i < n; i++) {
242
243 // Рисование грузиков
244 ctx.lineWidth = 6;
245 ctx.strokeStyle = "#8B008B";
246 ctx.beginPath();
247 ctx.moveTo(circle[i].x-20, circle[i].y);
248 ctx.lineTo(circle[i].x+20, circle[i].y);
249 ctx.stroke();
250 }
251
252 }
253
254 // *** Функция рисования пружины ***
255 function draw_spring(x_start, x_end, y, n, h) {
256 ctx.lineWidth = 1;
257
258 var L = x_end - x_start;
259 for (var i = 0; i < n; i++) {
260 var rgb = HSVtoRGB(i / n * 0.5, 1, 1);
261 ctx.strokeStyle = "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", 1)";
262
263 var x_st = x_start + L / n * i;
264 var x_end = x_start + L / n * (i + 1);
265 var l = x_end - x_st;
266 ctx.beginPath();
267 ctx.bezierCurveTo(y, x_st, y + h, x_st + l / 4, y, x_st + l / 2);
268 ctx.bezierCurveTo(y, x_st + l / 2, y - h, x_st + 3 * l / 4, y, x_st + l);
269 ctx.stroke();
270 }
271 }
272 }
Физическое объяснение[править]
Мы наблюдаем иллюзию "зависания" нижнего грузика потому, что до него должна дойти волна возмущений верхней пружины, прежде чем он придет в движение.
Ссылки[править]