КП: Эффект Магнуса — различия между версиями

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск
(Обсуждение результатов и выводы)
(Обсуждение результатов и выводы)
 
(не показано 11 промежуточных версий 2 участников)
Строка 87: Строка 87:
 
* сброс всех данных до начальных при нажатии кнопки "Reload"
 
* сброс всех данных до начальных при нажатии кнопки "Reload"
  
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Shvarev/4.html |width=1100 |height=600 |border=0 }}
+
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Shvarev/4.html |width=1100 |height=500 |border=0 }}
 +
 
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
'''Текст программы на языке JavaScript:''' <div class="mw-collapsible-content">
 +
Файл '''"4.js"'''
 +
<syntaxhighlight lang="javascript" line start="1" enclose="div">
 +
 
 +
function main()
 +
{
 +
  var scene = new THREE.Scene();
 +
  var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
 +
  var render = new THREE.WebGLRenderer();
 +
  render.setClearColor(0x87CEFA, 1);
 +
  render.setSize(800, 400);
 +
 
 +
  var axes = new THREE.AxisHelper(20);
 +
  scene.add(axes);
 +
 
 +
  /**
 +
  var planeGeometry = new THREE.PlaneGeometry(105,68,50,1);
 +
  */
 +
  var planeGeometry = new THREE.PlaneGeometry(1000,500,50,1);
 +
  var planeMaterial = new THREE.MeshLambertMaterial({color:0x068000});
 +
  var plane = new THREE.Mesh(planeGeometry, planeMaterial);
 +
  plane.position.x=0;
 +
  plane.position.y=0;
 +
  plane.position.z=-0.11;
 +
 
 +
  scene.add(plane);
 +
 
 +
  var ballGeometry = new THREE.SphereGeometry( 0.11, 16, 16 );
 +
  var ballMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00,wireframe:true} );
 +
  var ball = new THREE.Mesh( ballGeometry, ballMaterial );
 +
  scene.add( ball );
 +
  ball.castShadow = true;
 +
 
 +
 
 +
  var cylinderGeometry = new THREE.CylinderGeometry(0.11,0.11,1,16);
 +
  var cylinderMaterial = new THREE.MeshLambertMaterial({color:0xffff00});
 +
  var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
 +
  cylinder.position.x=0;
 +
  cylinder.position.y=0;
 +
  cylinder.position.z=0;
 +
  scene.add(cylinder);
 +
  cylinder.castShadow = true;
 +
 
 +
  var trajectoryGeometryB = new THREE.SphereGeometry(0.05, 16, 16);
 +
  var trajectoryMaterialB = new THREE.MeshBasicMaterial( {color: 0x000000,wireframe:true} );
 +
 
 +
  var trajectoryGeometryC = new THREE.SphereGeometry(0.05, 16, 16);
 +
  var trajectoryMaterialC = new THREE.MeshBasicMaterial( {color: 0xFF0000,wireframe:true} );
 +
 
 +
  var traMaterialB = new THREE.MeshBasicMaterial({color: 0xffffff});
 +
  var traGeometryB = new THREE.CircleGeometry( 0.05, 16);       
 +
 
 +
  var traMaterialC = new THREE.MeshBasicMaterial({color: 0xFF9900});
 +
  var traGeometryC = new THREE.CircleGeometry( 0.05, 16);       
 +
 
 +
 
 +
  /**
 +
  var cubeGeometry = new THREE.CubeGeometry(4,4,4);
 +
  var cubeMesh = new THREE.MeshLambertMaterial({color:0xff0000, wireframe:false});
 +
  var cube = new THREE.Mesh(cubeGeometry, cubeMesh);
 +
  cube.position.x=-4;
 +
  cube.position.y=3;
 +
  cube.position.z=0;
 +
  scene.add(cube);
 +
 
 +
 
 +
  var cylinderGeometry = new THREE.CylinderGeometry(4,4,5,16);
 +
  var cylinderMaterial = new THREE.MeshLambertMaterial({color:0xaaee00});
 +
  var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
 +
  cylinder.position.x=10;
 +
  cylinder.position.y=10;
 +
  cylinder.position.z=0;
 +
 
 +
  scene.add(cylinder);
 +
  */
 +
 
 +
 
 +
 
 +
 
 +
  var  spotLight = new THREE.SpotLight(0xffffff);
 +
  spotLight.position.set(0,0,1500);
 +
  scene.add(spotLight);
 +
 
 +
 
 +
  spotLight.castShadow = true;
 +
 
 +
 
 +
 
 +
  render.shadowMapEnabled = true;
 +
  plane.receiveShadow = true;
 +
 
 +
  /**
 +
  cube.castShadow = true;
 +
  cylinder.castShadow = true;
 +
  */
 +
 
 +
 
 +
 
 +
  var a = new THREE.Vector3( 5, 2, -1 );
 +
  var b = new THREE.Vector3( -1, 1, 1 );
 +
 
 +
  var c = new THREE.Vector3();
 +
  c.crossVectors( a, b );
 +
 
 +
  camera.position.x= -30;
 +
  camera.position.y= 0;
 +
  camera.position.z= 60;
 +
  camera.lookAt(c);
 +
 
 +
  camera.lookAt(scene.position);
 +
  $("#webGL").append(render.domElement);
 +
 
 +
 
 +
 
 +
  var controls = new function() {
 +
    this.WindPowerX = 0;
 +
    this.WindPowerY = 0;
 +
    this.WindPowerZ = 0;
 +
    this.Mass = 0.45;
 +
    this.Radius = 0.11;
 +
this.Height = 0.22;
 +
    this.Viscosity = 0.000178;
 +
    this.AirDensity = 1.2754;
 +
    this.g = 9.8
 +
    this.Vx = 15;
 +
    this.Vy = 0;
 +
    this.Vz = 5;
 +
    this.OmegaX = 0;
 +
    this.OmegaY = 0;
 +
    this.OmegaZ = -10;
 +
  }
 +
  var gui = new dat.GUI();
 +
  gui.add(controls, 'WindPowerX',-10,10);
 +
  gui.add(controls, 'WindPowerY',-10,10);
 +
  gui.add(controls, 'WindPowerZ',-10,10);
 +
  gui.add(controls, 'Mass',0.41,0.45);
 +
  gui.add(controls, 'Radius',0.01,0.21);
 +
  gui.add(controls, 'Height',0.1, 1);
 +
  gui.add(controls, 'Viscosity',0.00001, 0.001)
 +
  gui.add(controls, 'AirDensity',1, 1000)
 +
  gui.add(controls, 'g',0, 20)
 +
  gui.add(controls, 'Vx',0,40);
 +
  gui.add(controls, 'Vy',0,40);
 +
  gui.add(controls, 'Vz',0,40);
 +
  gui.add(controls, 'OmegaX',-10,10);
 +
  gui.add(controls, 'OmegaY',-10,10);
 +
  gui.add(controls, 'OmegaZ',-10,10);
 +
 
 +
 
 +
  contr = new THREE.OrbitControls(camera);
 +
  contr.dumping = 0.2;
 +
 
 +
 
 +
 
 +
  /**contr = new THREE.TrackballControls(camera);
 +
  contr.rotateSpeed = 1.0;
 +
  contr.zoomSpeed = 1.2;
 +
  contr.panSpeed = 0.8;
 +
  contr.noZoom = false;
 +
  contr.noPan = false;
 +
  contr.staticMoving = true;
 +
  contr.dynamicDampingFactor = 0.3;
 +
  contr.keys = [65,83,68];
 +
  */
 +
 
 +
 
 +
  /**window.addEventListener('resize',onWindowResize,false);
 +
  function onWindowResize()
 +
  {
 +
    camera.aspect = window.innerWidth/window.innerHeight;
 +
    camera.updateProjectionMatrix();
 +
    render.setSize(window.innerWidth,window.innerHeight);
 +
 
 +
    renderer();
 +
  }
 +
  */
 +
 
 +
  var stats = initStats();
 +
  var step = 0;
 +
 
 +
 
 +
  Vx = 0;
 +
  Vy = 0;
 +
  Vz = 0;
 +
  Mass = 0;
 +
  Viscosity = 0;
 +
  dt = 0.01;
 +
  Radius = 0;
 +
  g = 0;
 +
  WindX = 0;
 +
  WindY = 0;
 +
  WindZ = 0;
 +
  AirDensity = 0;
 +
 
 +
  Height = 1;
 +
 
 +
  var VxB =controls.Vx;
 +
  var VxC =controls.Vx;
 +
  var VyB =controls.Vy;
 +
  var VyC =controls.Vy;
 +
  var VzB =controls.Vz;
 +
  var VzC =controls.Vz;
 +
 
 +
  OmegaXB = controls.OmegaX;
 +
  OmegaXC = controls.OmegaX;
 +
  OmegaYB = controls.OmegaY;
 +
  OmegaYC = controls.OmegaY;
 +
  OmegaZB = controls.OmegaZ;
 +
  OmegaZC = controls.OmegaZ;
 +
   
 +
 
 +
  pppB = 0;
 +
  pppC = 0;
 +
  kkk = 0;
 +
 
 +
  function renderer()
 +
  {
 +
    /**
 +
    cube.rotation.x+=controls.rotationSpeed;
 +
    cube.rotation.y+=controls.rotationSpeed;
 +
    cube.rotation.z+=controls.rotationSpeed;
 +
   
 +
    cylinder.position.x = 20+(10*(Math.cos(step)));
 +
    cylinder.position.y = 2+(10*(Math.abs(Math.sin(step))));
 +
   
 +
   
 +
    */
 +
 +
    if (pppB == 0)
 +
    {
 +
      VxB+=controls.Vx;   
 +
      VyB+=controls.Vy;
 +
      VzB+=controls.Vz;
 +
      WindX = controls.WindPowerX;
 +
      WindY = controls.WindPowerY;
 +
      WindZ = controls.WindPowerZ;
 +
     
 +
      OmegaXB = controls.OmegaX;
 +
      OmegaYB = controls.OmegaY;
 +
      OmegaZB = controls.OmegaZ;
 +
   
 +
           
 +
      pppB = 1;
 +
     
 +
    }
 +
   
 +
    UxB = VxB - WindX;
 +
    UyB = VyB - WindY;
 +
    UzB = VzB - WindZ;
 +
 
 +
    Mass=controls.Mass;
 +
    Radius=controls.Radius;
 +
    Viscosity = controls.Viscosity;
 +
    g = controls.g;
 +
   
 +
    AirDensity = controls.AirDensity;
 +
 
 +
   
 +
    if (ball.position.z >= 0)
 +
    {
 +
 +
/**
 +
      VxB += (-6*Math.PI*Viscosity*Radius*VxB/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UyB*OmegaZB - UzB*OmegaYB)/Mass)*dt;
 +
      VyB += (-6*Math.PI*Viscosity*Radius*VyB/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UzB*OmegaXB - UxB*OmegaZB)/Mass )*dt;
 +
      VzB += (-6*Math.PI*Viscosity*Radius*VzB/Mass - g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxB*OmegaYB - UyB*OmegaXB)/Mass)*dt;
 +
     
 +
      OmegaXB += -6*Math.PI*Viscosity*Radius*OmegaXB*Radius/Mass;
 +
      OmegaYB += -6*Math.PI*Viscosity*Radius*OmegaYB*Radius/Mass;
 +
      OmegaZB += -6*Math.PI*Viscosity*Radius*OmegaZB*Radius/Mass;
 +
     
 +
  */
 +
 
 +
  VxB += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UyB*OmegaZB - UzB*OmegaYB)/Mass)*dt;
 +
      VyB += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UzB*OmegaXB - UxB*OmegaZB)/Mass )*dt;
 +
      VzB += (-g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxB*OmegaYB - UyB*OmegaXB)/Mass)*dt;
 +
     
 +
      ball.position.x += VxB*dt;
 +
      ball.position.y += VyB*dt;
 +
      ball.position.z += VzB*dt;
 +
     
 +
     
 +
     
 +
      ball.rotation.x += OmegaXB*dt;
 +
      ball.rotation.y += OmegaYB*dt;
 +
      ball.rotation.z += OmegaZB*dt;
 +
     
 +
      var trajectoryB = new THREE.Mesh(trajectoryGeometryB, trajectoryMaterialB);
 +
      trajectoryB.position.x = ball.position.x;
 +
      trajectoryB.position.y = ball.position.y;
 +
      trajectoryB.position.z = ball.position.z;
 +
     
 +
      scene.add( trajectoryB );
 +
     
 +
     
 +
      var traB = new THREE.Mesh( traGeometryB, traMaterialB);
 +
      traB.position.x = ball.position.x;
 +
      traB.position.y = ball.position.y;
 +
      traB.position.z = 0;
 +
      scene.add(traB);
 +
     
 +
      document.getElementById("td1").innerHTML = ball.position.y ;
 +
      document.getElementById("td2").innerHTML = ball.position.x ;
 +
 
 +
    }
 +
   
 +
    requestAnimationFrame(renderer);
 +
   
 +
    contr.update();
 +
   
 +
    render.render(scene,camera);
 +
   
 +
   
 +
   
 +
   
 +
  }
 +
 
 +
  alpha1 = 0;
 +
alpha2 = 0;
 +
alpha3 = 0;
 +
rot1 = 0;
 +
rot2 = 0;
 +
rot3 = 0;
 +
 
 +
  function renderer2()
 +
  {
 +
 
 +
 +
if (pppC == 0)
 +
{
 +
      VyC+=controls.Vy;
 +
      VxC+=controls.Vx;   
 +
      VzC+=controls.Vz;
 +
      WindX = controls.WindPowerX;
 +
      WindY = controls.WindPowerY;
 +
      WindZ = controls.WindPowerZ;
 +
     
 +
      OmegaXC = controls.OmegaX;
 +
      OmegaYC = controls.OmegaY;
 +
      OmegaZC = controls.OmegaZ;
 +
   
 +
           
 +
      pppC = 1;
 +
     
 +
    }
 +
   
 +
    UxC = VxC - WindX;
 +
    UyC = VyC - WindY;
 +
    UzC = VzC - WindZ;
 +
 
 +
    Mass=controls.Mass;
 +
    Radius=controls.Radius;
 +
    Viscosity = controls.Viscosity;
 +
    g = controls.g;
 +
    Height = controls.Height;
 +
    AirDensity = controls.AirDensity;
 +
 +
var cylinderGeometry = new THREE.CylinderGeometry(2*Radius,2*Radius, Height, 16);
 +
 +
cylinder.geometry = cylinderGeometry;
 +
 
 +
 
 +
if (cylinder.position.z >= 0)
 +
{
 +
/**
 +
VxC += (-6*Math.PI*Viscosity*Radius*VxC/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
 +
VyC += (-6*Math.PI*Viscosity*Radius*VyC/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
 +
VzC += (-6*Math.PI*Viscosity*Radius*VzC/Mass - g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
 +
 +
OmegaXC += -6*Math.PI*Viscosity*Radius*OmegaXC*Radius/Mass;
 +
OmegaYC += -6*Math.PI*Viscosity*Radius*OmegaYC*Radius/Mass;
 +
OmegaZC += -6*Math.PI*Viscosity*Radius*OmegaZC*Radius/Mass;
 +
*/
 +
/**
 +
VxC += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
 +
VyC += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
 +
VzC += (-g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
 +
*/
 +
 +
 
 +
alpha1 = (cylinder.rotation.x - rot1)/(2*Math.PI);
 +
alpha2 = (cylinder.rotation.y - rot2)/(2*Math.PI);
 +
alpha3 = (cylinder.rotation.z - rot3)/(2*Math.PI);
 +
 +
rot1 = cylinder.rotation.x;
 +
rot2 = cylinder.rotation.y;
 +
rot3 = cylinder.rotation.z;
 +
 +
VxC += (2*AirDensity*Radius*(2*Radius*Height*Math.cos(alpha1) + Math.PI*Radius*Radius*Math.sin(alpha1) )*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
 +
VyC += (2*AirDensity*Radius*(2*Radius*Height*Math.sin(alpha2) + Math.PI*Radius*Radius*Math.cos(alpha2))*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
 +
VzC += (-g + 2*AirDensity*Radius*(2*Radius*Height*Math.cos(alpha3) + Math.PI*Radius*Radius*Math.sin(alpha3))*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
 +
 +
cylinder.position.x += VxC*dt;
 +
cylinder.position.y += VyC*dt;
 +
cylinder.position.z += VzC*dt;
 +
 
 +
cylinder.rotation.x += OmegaXC*dt;
 +
cylinder.rotation.y += OmegaYC*dt;
 +
cylinder.rotation.z += OmegaZC*dt;
 +
 +
 
 +
 +
var trajectoryC = new THREE.Mesh(trajectoryGeometryC, trajectoryMaterialC);
 +
trajectoryC.position.x = cylinder.position.x;
 +
trajectoryC.position.y = cylinder.position.y;
 +
trajectoryC.position.z = cylinder.position.z;
 +
     
 +
scene.add( trajectoryC );
 +
     
 +
var traC = new THREE.Mesh( traGeometryC, traMaterialC);
 +
traC.position.x = cylinder.position.x;
 +
traC.position.y = cylinder.position.y;
 +
traC.position.z = 0;
 +
scene.add(traC);
 +
 +
document.getElementById("td3").innerHTML = cylinder.position.y ;
 +
document.getElementById("td4").innerHTML = cylinder.position.x;
 +
 +
}
 +
 +
requestAnimationFrame(renderer2);
 +
   
 +
    contr.update();
 +
   
 +
    render.render(scene,camera);
 +
 +
  }
 +
 
 +
  this.start = renderer;
 +
  this.start2 = renderer2;
 +
 
 +
 
 +
 
 +
}
 +
function initStats()
 +
{
 +
  var stats = new Stats();
 +
  stats.setMode(0);
 +
  stats.domElement.style.position='absolute';
 +
  stats.domElement.style.left = '0px';
 +
  stats.domElement.style.top = '0px';
 +
  $("#Stats").append(stats.domElement);
 +
  return stats;
 +
}
 +
 
 +
 
 +
 
 +
</syntaxhighlight>
 +
</div>
  
 
== Обсуждение результатов и выводы ==
 
== Обсуждение результатов и выводы ==
Строка 138: Строка 589:
 
  |0.01
 
  |0.01
 
  |0.011
 
  |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
 
  |}
 
  |}
  
Строка 187: Строка 658:
 
  |0.22
 
  |0.22
 
  |0.011
 
  |0.011
|-
+
|-
 
  |15
 
  |15
 
  |0
 
  |0
Строка 198: Строка 669:
 
  |1
 
  |1
 
  |13.287
 
  |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
 
  |}
 
  |}
  
 
где <math>V_x</math>, <math>V_y</math>, <math>V_z</math> - начальные линейные скорости, <math>ω_x</math>, <math>ω_y</math>, <math>ω_z</math> - начальные угловые скорости, <math>m</math> - масса объекта, <math>r</math> - радиус объекта, <math>h</math> - высота цилиндра, а <math>Δ_y</math> - полученное смещение по оси <math>y</math>.
 
где <math>V_x</math>, <math>V_y</math>, <math>V_z</math> - начальные линейные скорости, <math>ω_x</math>, <math>ω_y</math>, <math>ω_z</math> - начальные угловые скорости, <math>m</math> - масса объекта, <math>r</math> - радиус объекта, <math>h</math> - высота цилиндра, а <math>Δ_y</math> - полученное смещение по оси <math>y</math>.
  
Исходя из числовых данных, полученных после проведения экспериментов, можно сделать вывод, что при большей массе скорость меньше. Это объясняется тем, что на объект большей массы действует большая сила тяжести, препятствующая движению объекта. Также видим, что при уменьшении радиуса или высоты (в случае цилиндра) смещение уменьшается. Это объясняется тем, что на объект с меньшим радиусом действует меньшая разность давлений при вращении, и, следственно, меньшая сила Магнуса.
+
'''Вывод:''' Исходя из численных данных, полученных после проведения экспериментов, можно сделать вывод, что относительное смещение зависит от угловой скорости, радиуса, массы и силы тяжести, но не зависит от линейной скорости. Например, при уменьшении угловой скорости в 2 раза следует уменьшение относительного отклонения в ~2 раза, а при уменьшении линейной скорости в 2 раза относительное отклонение остается таким же.
  
  

Текущая версия на 13:51, 3 июня 2015

А.М. Кривцов > Теоретическая механика > Курсовые проекты ТМ 2015 > Эффект Магнуса


Курсовой проект по Теоретической механике

Исполнитель: Шварёв Николай

Группа: 09 (23604)

Семестр: весна 2015

Сила Магнуса[1]

Аннотация проекта[править]

Данный проект посвящен изучению эффекта Магнуса, возникающего в различных видах спорта, а также использующегося в баллистике, летательных аппаратах и кораблях.В ходе работы над проектом были рассмотрены траектории полета мяча и цилиндра в зависимости от различных начальных параметров (радиуса, динамической вязкости среды, плотности воздуха, линейной и угловой скорости). Программа написана на языке JavaScript с использование библиотеки Three.js.

Формулировка задачи[править]

Построение и исследование математической модели движения объекта (в нашем случае - футбольного мяча и цилиндра), получение уравнения его движения и построение траектории в трехмерном пространстве с учётом различных внешних факторов, влияющих на движение, таких как сила сопротивления воздуха и эффект Магнуса.

Общие сведения по теме[править]

Пример влияния силы Магнуса на траекторию движения мяча[1]

Эффект Магнуса - образование подъемной силы, действующей на вращающееся тело при обтекании его потоком жидкости или газа, широко использующейся в спорте, баллистике, летательных аппаратах и кораблях. [2]

Данный эффект возникает в результате разности давлений (в соответствии с законом Бернулли[3]) на стенках объекта из-за разных скоростей движения воздуха. Возникающий дисбаланс заставляет объект отклоняться.

Решение[править]

Силу сопротивления воздуха для мяча будем считать с помощью закона Стокса[4]:

[math]\vec{F} = -6πrη\vec{v} [/math] , где

[math]\vec{F}[/math] - сила Стокса,

[math]r[/math] - радиус мяча,

[math]η[/math] - динамическая вязкость среды,

[math]\vec{v}[/math] - скорость мяча.


Силу Магнуса примем вида[5]:

[math]\vec{F} = 2Sρr\vec{u}\times\vec{ω} [/math] , где

[math]\vec{F}[/math] - сила Магнуса,

[math]S[/math] - площадь действия силы,

[math]ρ[/math] - плотность воздуха,

[math]r[/math] - радиус,

[math]\vec{u}[/math] - относительная скорость,

[math]\vec{ω}[/math] - угловая скорость.


Применив метод Эйлера, получим формулы для нахождения скорости и координаты мяча:

[math] \begin{cases} v_x^{i+1} = v_x^i + (-6πrηv_x^i/m + 2Sρr(u_y^iω_z - u_z^iω_y)/m)\Delta t \\ v_y^{i+1} = v_y^i + (-6πrηv_y^i/m + 2Sρr(u_z^iω_w - u_x^iω_z)/m)\Delta t \\ v_z^{i+1} = v_z^i + (-6πrηv_z^i/m - g + 2Sρr(u_x^iω_y - u_y^iω_x)/m)\Delta t \\ \end{cases} [/math]

[math] \begin{cases} x^{i+1} = x^i + v_x^i\Delta t \\ y^{i+1} = y^i + v_y^i\Delta t \\ z^{i+1} = z^i + v_z^i\Delta t \\ \end{cases} [/math]


Реализация алгоритма.

Возможности программы:

  • поочередный запуск мяча и цилиндра,
  • изменение параметров как в начале, так и во время полета,
  • просмотр картинки в трехмерном изображении с помощью мыши
  • сброс всех данных до начальных при нажатии кнопки "Reload"


Текст программы на языке JavaScript:

Файл "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. Была построена траектория движения и произведены эксперименты, результаты которых находятся в таблице ниже:

Шар:

[math]V_x[/math] [math]V_y[/math] [math]V_z[/math] [math]ω_x[/math] [math]ω_y[/math] [math]ω_z[/math] [math]m[/math] [math]r[/math] [math]Δ_y[/math]
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

Цилиндр:

[math]V_x[/math] [math]V_y[/math] [math]V_z[/math] [math]ω_x[/math] [math]ω_y[/math] [math]ω_z[/math] [math]m[/math] [math]r[/math] [math]h[/math] [math]Δ_y[/math]
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

где [math]V_x[/math], [math]V_y[/math], [math]V_z[/math] - начальные линейные скорости, [math]ω_x[/math], [math]ω_y[/math], [math]ω_z[/math] - начальные угловые скорости, [math]m[/math] - масса объекта, [math]r[/math] - радиус объекта, [math]h[/math] - высота цилиндра, а [math]Δ_y[/math] - полученное смещение по оси [math]y[/math].

Вывод: Исходя из численных данных, полученных после проведения экспериментов, можно сделать вывод, что относительное смещение зависит от угловой скорости, радиуса, массы и силы тяжести, но не зависит от линейной скорости. Например, при уменьшении угловой скорости в 2 раза следует уменьшение относительного отклонения в ~2 раза, а при уменьшении линейной скорости в 2 раза относительное отклонение остается таким же.



Скачать отчет: doc.
Скачать презентацию: pptx.

Ссылки по теме[править]

См. также[править]