КП: Эффект Магнуса — различия между версиями
(→Решение) |
(→Решение) |
||
Строка 87: | Строка 87: | ||
* сброс всех данных до начальных при нажатии кнопки "Reload" | * сброс всех данных до начальных при нажатии кнопки "Reload" | ||
− | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Shvarev/4.html |width=1100 |height= | + | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Shvarev/4.html |width=1100 |height=500 |border=0 }} |
Версия 12:07, 3 июня 2015
А.М. Кривцов > Теоретическая механика > Курсовые проекты ТМ 2015 > Эффект Магнуса
Курсовой проект по Теоретической механике
Исполнитель: Шварёв Николай
Группа: 09 (23604)
Семестр: весна 2015
Содержание
Аннотация проекта
Данный проект посвящен изучению эффекта Магнуса, возникающего в различных видах спорта, а также использующегося в баллистике, летательных аппаратах и кораблях.В ходе работы над проектом были рассмотрены траектории полета мяча и цилиндра в зависимости от различных начальных параметров (радиуса, динамической вязкости среды, плотности воздуха, линейной и угловой скорости). Программа написана на языке JavaScript с использование библиотеки Three.js.
Формулировка задачи
Построение и исследование математической модели движения объекта (в нашем случае - футбольного мяча и цилиндра), получение уравнения его движения и построение траектории в трехмерном пространстве с учётом различных внешних факторов, влияющих на движение, таких как сила сопротивления воздуха и эффект Магнуса.
Общие сведения по теме
Эффект Магнуса - образование подъемной силы, действующей на вращающееся тело при обтекании его потоком жидкости или газа, широко использующейся в спорте, баллистике, летательных аппаратах и кораблях. [2]
Данный эффект возникает в результате разности давлений (в соответствии с законом Бернулли[3]) на стенках объекта из-за разных скоростей движения воздуха. Возникающий дисбаланс заставляет объект отклоняться.
Решение
Силу сопротивления воздуха для мяча будем считать с помощью закона Стокса[4]:
, где
- сила Стокса,
- радиус мяча,
- динамическая вязкость среды,
- скорость мяча.
Силу Магнуса примем вида[5]:
, где
- сила Магнуса,
- площадь действия силы,
- плотность воздуха,
- радиус,
- относительная скорость,
- угловая скорость.
Применив метод Эйлера, получим формулы для нахождения скорости и координаты мяча:
Реализация алгоритма.
Возможности программы:
- поочередный запуск мяча и цилиндра,
- изменение параметров как в начале, так и во время полета,
- просмотр картинки в трехмерном изображении с помощью мыши
- сброс всех данных до начальных при нажатии кнопки "Reload"
Файл "4.js"
1 function main()
2 {
3 var scene = new THREE.Scene();
4 var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
5 var render = new THREE.WebGLRenderer();
6 render.setClearColor(0x87CEFA, 1);
7 render.setSize(800, 400);
8
9 var axes = new THREE.AxisHelper(20);
10 scene.add(axes);
11
12 /**
13 var planeGeometry = new THREE.PlaneGeometry(105,68,50,1);
14 */
15 var planeGeometry = new THREE.PlaneGeometry(1000,500,50,1);
16 var planeMaterial = new THREE.MeshLambertMaterial({color:0x068000});
17 var plane = new THREE.Mesh(planeGeometry, planeMaterial);
18 plane.position.x=0;
19 plane.position.y=0;
20 plane.position.z=-0.11;
21
22 scene.add(plane);
23
24 var ballGeometry = new THREE.SphereGeometry( 0.11, 16, 16 );
25 var ballMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00,wireframe:true} );
26 var ball = new THREE.Mesh( ballGeometry, ballMaterial );
27 scene.add( ball );
28 ball.castShadow = true;
29
30
31 var cylinderGeometry = new THREE.CylinderGeometry(0.11,0.11,1,16);
32 var cylinderMaterial = new THREE.MeshLambertMaterial({color:0xffff00});
33 var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
34 cylinder.position.x=0;
35 cylinder.position.y=0;
36 cylinder.position.z=0;
37 scene.add(cylinder);
38 cylinder.castShadow = true;
39
40 var trajectoryGeometryB = new THREE.SphereGeometry(0.05, 16, 16);
41 var trajectoryMaterialB = new THREE.MeshBasicMaterial( {color: 0x000000,wireframe:true} );
42
43 var trajectoryGeometryC = new THREE.SphereGeometry(0.05, 16, 16);
44 var trajectoryMaterialC = new THREE.MeshBasicMaterial( {color: 0xFF0000,wireframe:true} );
45
46 var traMaterialB = new THREE.MeshBasicMaterial({color: 0xffffff});
47 var traGeometryB = new THREE.CircleGeometry( 0.05, 16);
48
49 var traMaterialC = new THREE.MeshBasicMaterial({color: 0xFF9900});
50 var traGeometryC = new THREE.CircleGeometry( 0.05, 16);
51
52
53 /**
54 var cubeGeometry = new THREE.CubeGeometry(4,4,4);
55 var cubeMesh = new THREE.MeshLambertMaterial({color:0xff0000, wireframe:false});
56 var cube = new THREE.Mesh(cubeGeometry, cubeMesh);
57 cube.position.x=-4;
58 cube.position.y=3;
59 cube.position.z=0;
60 scene.add(cube);
61
62
63 var cylinderGeometry = new THREE.CylinderGeometry(4,4,5,16);
64 var cylinderMaterial = new THREE.MeshLambertMaterial({color:0xaaee00});
65 var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
66 cylinder.position.x=10;
67 cylinder.position.y=10;
68 cylinder.position.z=0;
69
70 scene.add(cylinder);
71 */
72
73
74
75
76 var spotLight = new THREE.SpotLight(0xffffff);
77 spotLight.position.set(0,0,1500);
78 scene.add(spotLight);
79
80
81 spotLight.castShadow = true;
82
83
84
85 render.shadowMapEnabled = true;
86 plane.receiveShadow = true;
87
88 /**
89 cube.castShadow = true;
90 cylinder.castShadow = true;
91 */
92
93
94
95 var a = new THREE.Vector3( 5, 2, -1 );
96 var b = new THREE.Vector3( -1, 1, 1 );
97
98 var c = new THREE.Vector3();
99 c.crossVectors( a, b );
100
101 camera.position.x= -30;
102 camera.position.y= 0;
103 camera.position.z= 60;
104 camera.lookAt(c);
105
106 camera.lookAt(scene.position);
107 $("#webGL").append(render.domElement);
108
109
110
111 var controls = new function() {
112 this.WindPowerX = 0;
113 this.WindPowerY = 0;
114 this.WindPowerZ = 0;
115 this.Mass = 0.45;
116 this.Radius = 0.11;
117 this.Height = 0.22;
118 this.Viscosity = 0.000178;
119 this.AirDensity = 1.2754;
120 this.g = 9.8
121 this.Vx = 15;
122 this.Vy = 0;
123 this.Vz = 5;
124 this.OmegaX = 0;
125 this.OmegaY = 0;
126 this.OmegaZ = -10;
127 }
128 var gui = new dat.GUI();
129 gui.add(controls, 'WindPowerX',-10,10);
130 gui.add(controls, 'WindPowerY',-10,10);
131 gui.add(controls, 'WindPowerZ',-10,10);
132 gui.add(controls, 'Mass',0.41,0.45);
133 gui.add(controls, 'Radius',0.01,0.21);
134 gui.add(controls, 'Height',0.1, 1);
135 gui.add(controls, 'Viscosity',0.00001, 0.001)
136 gui.add(controls, 'AirDensity',1, 1000)
137 gui.add(controls, 'g',0, 20)
138 gui.add(controls, 'Vx',0,40);
139 gui.add(controls, 'Vy',0,40);
140 gui.add(controls, 'Vz',0,40);
141 gui.add(controls, 'OmegaX',-10,10);
142 gui.add(controls, 'OmegaY',-10,10);
143 gui.add(controls, 'OmegaZ',-10,10);
144
145
146 contr = new THREE.OrbitControls(camera);
147 contr.dumping = 0.2;
148
149
150
151 /**contr = new THREE.TrackballControls(camera);
152 contr.rotateSpeed = 1.0;
153 contr.zoomSpeed = 1.2;
154 contr.panSpeed = 0.8;
155 contr.noZoom = false;
156 contr.noPan = false;
157 contr.staticMoving = true;
158 contr.dynamicDampingFactor = 0.3;
159 contr.keys = [65,83,68];
160 */
161
162
163 /**window.addEventListener('resize',onWindowResize,false);
164 function onWindowResize()
165 {
166 camera.aspect = window.innerWidth/window.innerHeight;
167 camera.updateProjectionMatrix();
168 render.setSize(window.innerWidth,window.innerHeight);
169
170 renderer();
171 }
172 */
173
174 var stats = initStats();
175 var step = 0;
176
177
178 Vx = 0;
179 Vy = 0;
180 Vz = 0;
181 Mass = 0;
182 Viscosity = 0;
183 dt = 0.01;
184 Radius = 0;
185 g = 0;
186 WindX = 0;
187 WindY = 0;
188 WindZ = 0;
189 AirDensity = 0;
190
191 Height = 1;
192
193 var VxB =controls.Vx;
194 var VxC =controls.Vx;
195 var VyB =controls.Vy;
196 var VyC =controls.Vy;
197 var VzB =controls.Vz;
198 var VzC =controls.Vz;
199
200 OmegaXB = controls.OmegaX;
201 OmegaXC = controls.OmegaX;
202 OmegaYB = controls.OmegaY;
203 OmegaYC = controls.OmegaY;
204 OmegaZB = controls.OmegaZ;
205 OmegaZC = controls.OmegaZ;
206
207
208 pppB = 0;
209 pppC = 0;
210 kkk = 0;
211
212 function renderer()
213 {
214 /**
215 cube.rotation.x+=controls.rotationSpeed;
216 cube.rotation.y+=controls.rotationSpeed;
217 cube.rotation.z+=controls.rotationSpeed;
218
219 cylinder.position.x = 20+(10*(Math.cos(step)));
220 cylinder.position.y = 2+(10*(Math.abs(Math.sin(step))));
221
222
223 */
224
225 if (pppB == 0)
226 {
227 VxB+=controls.Vx;
228 VyB+=controls.Vy;
229 VzB+=controls.Vz;
230 WindX = controls.WindPowerX;
231 WindY = controls.WindPowerY;
232 WindZ = controls.WindPowerZ;
233
234 OmegaXB = controls.OmegaX;
235 OmegaYB = controls.OmegaY;
236 OmegaZB = controls.OmegaZ;
237
238
239 pppB = 1;
240
241 }
242
243 UxB = VxB - WindX;
244 UyB = VyB - WindY;
245 UzB = VzB - WindZ;
246
247 Mass=controls.Mass;
248 Radius=controls.Radius;
249 Viscosity = controls.Viscosity;
250 g = controls.g;
251
252 AirDensity = controls.AirDensity;
253
254
255 if (ball.position.z >= 0)
256 {
257
258 /**
259 VxB += (-6*Math.PI*Viscosity*Radius*VxB/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UyB*OmegaZB - UzB*OmegaYB)/Mass)*dt;
260 VyB += (-6*Math.PI*Viscosity*Radius*VyB/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UzB*OmegaXB - UxB*OmegaZB)/Mass )*dt;
261 VzB += (-6*Math.PI*Viscosity*Radius*VzB/Mass - g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxB*OmegaYB - UyB*OmegaXB)/Mass)*dt;
262
263 OmegaXB += -6*Math.PI*Viscosity*Radius*OmegaXB*Radius/Mass;
264 OmegaYB += -6*Math.PI*Viscosity*Radius*OmegaYB*Radius/Mass;
265 OmegaZB += -6*Math.PI*Viscosity*Radius*OmegaZB*Radius/Mass;
266
267 */
268
269 VxB += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UyB*OmegaZB - UzB*OmegaYB)/Mass)*dt;
270 VyB += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UzB*OmegaXB - UxB*OmegaZB)/Mass )*dt;
271 VzB += (-g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxB*OmegaYB - UyB*OmegaXB)/Mass)*dt;
272
273 ball.position.x += VxB*dt;
274 ball.position.y += VyB*dt;
275 ball.position.z += VzB*dt;
276
277
278
279 ball.rotation.x += OmegaXB*dt;
280 ball.rotation.y += OmegaYB*dt;
281 ball.rotation.z += OmegaZB*dt;
282
283 var trajectoryB = new THREE.Mesh(trajectoryGeometryB, trajectoryMaterialB);
284 trajectoryB.position.x = ball.position.x;
285 trajectoryB.position.y = ball.position.y;
286 trajectoryB.position.z = ball.position.z;
287
288 scene.add( trajectoryB );
289
290
291 var traB = new THREE.Mesh( traGeometryB, traMaterialB);
292 traB.position.x = ball.position.x;
293 traB.position.y = ball.position.y;
294 traB.position.z = 0;
295 scene.add(traB);
296
297 document.getElementById("td1").innerHTML = ball.position.y ;
298 document.getElementById("td2").innerHTML = ball.position.x ;
299
300 }
301
302 requestAnimationFrame(renderer);
303
304 contr.update();
305
306 render.render(scene,camera);
307
308
309
310
311 }
312
313 alpha1 = 0;
314 alpha2 = 0;
315 alpha3 = 0;
316 rot1 = 0;
317 rot2 = 0;
318 rot3 = 0;
319
320 function renderer2()
321 {
322
323
324 if (pppC == 0)
325 {
326 VyC+=controls.Vy;
327 VxC+=controls.Vx;
328 VzC+=controls.Vz;
329 WindX = controls.WindPowerX;
330 WindY = controls.WindPowerY;
331 WindZ = controls.WindPowerZ;
332
333 OmegaXC = controls.OmegaX;
334 OmegaYC = controls.OmegaY;
335 OmegaZC = controls.OmegaZ;
336
337
338 pppC = 1;
339
340 }
341
342 UxC = VxC - WindX;
343 UyC = VyC - WindY;
344 UzC = VzC - WindZ;
345
346 Mass=controls.Mass;
347 Radius=controls.Radius;
348 Viscosity = controls.Viscosity;
349 g = controls.g;
350 Height = controls.Height;
351 AirDensity = controls.AirDensity;
352
353 var cylinderGeometry = new THREE.CylinderGeometry(2*Radius,2*Radius, Height, 16);
354
355 cylinder.geometry = cylinderGeometry;
356
357
358 if (cylinder.position.z >= 0)
359 {
360 /**
361 VxC += (-6*Math.PI*Viscosity*Radius*VxC/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
362 VyC += (-6*Math.PI*Viscosity*Radius*VyC/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
363 VzC += (-6*Math.PI*Viscosity*Radius*VzC/Mass - g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
364
365 OmegaXC += -6*Math.PI*Viscosity*Radius*OmegaXC*Radius/Mass;
366 OmegaYC += -6*Math.PI*Viscosity*Radius*OmegaYC*Radius/Mass;
367 OmegaZC += -6*Math.PI*Viscosity*Radius*OmegaZC*Radius/Mass;
368 */
369 /**
370 VxC += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
371 VyC += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
372 VzC += (-g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
373 */
374
375
376 alpha1 = (cylinder.rotation.x - rot1)/(2*Math.PI);
377 alpha2 = (cylinder.rotation.y - rot2)/(2*Math.PI);
378 alpha3 = (cylinder.rotation.z - rot3)/(2*Math.PI);
379
380 rot1 = cylinder.rotation.x;
381 rot2 = cylinder.rotation.y;
382 rot3 = cylinder.rotation.z;
383
384 VxC += (2*AirDensity*Radius*(2*Radius*Height*Math.cos(alpha1) + Math.PI*Radius*Radius*Math.sin(alpha1) )*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
385 VyC += (2*AirDensity*Radius*(2*Radius*Height*Math.sin(alpha2) + Math.PI*Radius*Radius*Math.cos(alpha2))*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
386 VzC += (-g + 2*AirDensity*Radius*(2*Radius*Height*Math.cos(alpha3) + Math.PI*Radius*Radius*Math.sin(alpha3))*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
387
388 cylinder.position.x += VxC*dt;
389 cylinder.position.y += VyC*dt;
390 cylinder.position.z += VzC*dt;
391
392 cylinder.rotation.x += OmegaXC*dt;
393 cylinder.rotation.y += OmegaYC*dt;
394 cylinder.rotation.z += OmegaZC*dt;
395
396
397
398 var trajectoryC = new THREE.Mesh(trajectoryGeometryC, trajectoryMaterialC);
399 trajectoryC.position.x = cylinder.position.x;
400 trajectoryC.position.y = cylinder.position.y;
401 trajectoryC.position.z = cylinder.position.z;
402
403 scene.add( trajectoryC );
404
405 var traC = new THREE.Mesh( traGeometryC, traMaterialC);
406 traC.position.x = cylinder.position.x;
407 traC.position.y = cylinder.position.y;
408 traC.position.z = 0;
409 scene.add(traC);
410
411 document.getElementById("td3").innerHTML = cylinder.position.y ;
412 document.getElementById("td4").innerHTML = cylinder.position.x;
413
414 }
415
416 requestAnimationFrame(renderer2);
417
418 contr.update();
419
420 render.render(scene,camera);
421
422 }
423
424 this.start = renderer;
425 this.start2 = renderer2;
426
427
428
429 }
430 function initStats()
431 {
432 var stats = new Stats();
433 stats.setMode(0);
434 stats.domElement.style.position='absolute';
435 stats.domElement.style.left = '0px';
436 stats.domElement.style.top = '0px';
437 $("#Stats").append(stats.domElement);
438 return stats;
439 }
Обсуждение результатов и выводы
Разработанный алгоритм был реализован в среде программирования Javascript с использование библиотеки Three.js. Была построена траектория движения и произведены эксперименты, результаты которых находятся в таблице ниже:
Шар:
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 14.585 |
15 | 0 | 5 | 0 | 0 | -10 | 0.41 | 0.11 | 15.945 |
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.01 | 0.011 |
15 | 0 | 5 | 0 | 0 | -5 | 0.45 | 0.11 | 7.399 |
7.5 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 7.292 |
Цилиндр:
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 0.22 | 14.508 |
15 | 0 | 5 | 0 | 0 | -10 | 0.41 | 0.11 | 0.22 | 15.844 |
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.01 | 0.22 | 0.011 |
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 1 | 13.287 |
15 | 0 | 5 | 0 | 0 | -5 | 0.45 | 0.11 | 0.22 | 7.389 |
7.5 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 0.22 | 7.254 |
где
, , - начальные линейные скорости, , , - начальные угловые скорости, - масса объекта, - радиус объекта, - высота цилиндра, а - полученное смещение по оси .Исходя из числовых данных, полученных после проведения экспериментов, можно сделать вывод, что при большей массе скорость меньше. Это объясняется тем, что на объект большей массы действует большая сила тяжести, препятствующая движению объекта. Также видим, что при уменьшении радиуса смещение уменьшается. Это объясняется тем, что на объект с меньшим радиусом действует меньшая разность давлений при вращении, и, следственно, меньшая сила Магнуса. А из уменьшения угловой или линейной скорости в 2 раза следует уменьшение отклонения в ~2 раза.
Скачать отчет: doc.
Скачать презентацию: pptx.