КП: Штрафной удар по воротам — различия между версиями
(→См. также) |
(→Обсуждение результатов и выводы) |
||
(не показаны 84 промежуточные версии 11 участников) | |||
Строка 9: | Строка 9: | ||
'''Семестр:''' весна 2015 | '''Семестр:''' весна 2015 | ||
+ | [[File:W 1326974955.png|thumb|Штрайной удар Роберто Карлоса|450px]] | ||
== Аннотация проекта == | == Аннотация проекта == | ||
+ | Данный проект посвящен изучению динамики движения футбольного мяча во время штрафного удара. В ходе работы над проектом был рассмотрен конкретный штрафной удар, который был исполнен Роберто Карлосом в товарищеском матче Бразилия - Франция. Этот удар был симулирован на языке JavaScript <ref>[https://ru.wikipedia.org/wiki/JavaScript JavaScript]</ref>. | ||
== Формулировка задачи == | == Формулировка задачи == | ||
+ | * Написать программу, которая моделирует процесс движения футбольного мяча во время штрафного удара, с учетом внешних сил и воздействий. | ||
== Общие сведения по теме == | == Общие сведения по теме == | ||
+ | Роберто Карлос забил в 1997 году в ворота сборной Франции невероятный по красоте гол. | ||
+ | Мяч был установлен примерно в 30 - 35 м от ворот соперников, ближе к правому краю поля. После удара Карлоса мяч полетел далеко в правую сторону, облетел «стенку» в метре от нее и после этого чудесным образом мяч повернул влево и влетел в ворота - к изумлению игроков, вратаря и представителей СМИ. | ||
+ | |||
+ | Этот удар стал наглядным примером силы Магнуса, действующей на тело, движущееся с вращением при обтекании его потоком жидкости или газа. | ||
+ | |||
+ | [[Файл:g33viT3.gif|thumb|Траектория движения мяча во время штрафного удара|450px]] | ||
== Решение == | == Решение == | ||
+ | <math>\vec{F_{р}} = \vec{F_{тяж}} + \vec{F_{сопр}} + \vec{F_{м}} </math>, где | ||
+ | |||
+ | <math> \vec{F_{р}} </math> - Равнодействующая сил на мяч; | ||
+ | |||
+ | <math> \vec{F_{тяж}} </math> - Сила тяжести, действующая на мяч; | ||
+ | |||
+ | <math> \vec{F_{сопр}} </math> - Сила сопротивления воздуха; | ||
+ | |||
+ | <math> \vec{F_{м}} </math> - Сила Магнуса <ref> | ||
+ | [https://ru.wikipedia.org/wiki/Эффект_Магнуса Эффект Магнуса]</ref>. | ||
+ | |||
+ | |||
+ | Сила тяжести: | ||
+ | |||
+ | <big><math> \vec{F_{тяж}} = m\vec{g} </math></big>, где | ||
+ | |||
+ | <math> m </math> - масса мяча; | ||
+ | |||
+ | <math> g </math> - ускорение свободного падения. | ||
+ | |||
+ | |||
+ | Силу сопротивления воздуха будем считать с помощью закона Стокса: | ||
+ | |||
+ | <big><math>\vec{F} = -6πrη\vec{v} </math></big> , где | ||
+ | |||
+ | <math>\vec{F}</math> - сила Стокса, | ||
+ | |||
+ | <math>r</math> - радиус мяча, | ||
+ | |||
+ | <math>η</math> - динамическая вязкость, | ||
+ | |||
+ | <math>\vec{v}</math> - скорость мяча. | ||
+ | |||
+ | |||
+ | Силу Магнуса примем вида: | ||
+ | |||
+ | <big><math>\vec{F} = 2Sρr\vec{u}\times\vec{ω} </math></big> , где | ||
+ | |||
+ | <math>\vec{F}</math> - сила Магнуса, | ||
+ | |||
+ | <math>S</math> - площадь, на которую действует сила | ||
+ | |||
+ | <math>ρ</math> - плотность воздуха, | ||
+ | |||
+ | <math>r</math> - радиус мяча, | ||
+ | |||
+ | <math>\vec{u}</math> - относительная скорость мяча, | ||
+ | |||
+ | <math>\vec{ω}</math> - угловая скорость мяча. | ||
+ | |||
+ | Применив метод Эйлера, получим формулы для нахождения скорости и координаты мяча: | ||
+ | |||
+ | <big><math> | ||
+ | \begin{cases} | ||
+ | v_x^{i+1} = v_x^i + (-6πrηv_x^i/m + 2πρr^3(u_z^iω_y - u_y^iω_z)/m)\Delta t \\ | ||
+ | v_y^{i+1} = v_y^i + (-6πrηv_y^i/m + 2πρr^3(u_x^iω_z - u_z^iω_x)/m)\Delta t \\ | ||
+ | v_z^{i+1} = v_z^i + (-g-6πrηv_z^i/m + 2πρr^3(u_y^iω_x - u_x^iω_y)/m)\Delta t \\ | ||
+ | \end{cases} | ||
+ | </math></big> | ||
+ | |||
+ | <big><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></big>; | ||
+ | |||
+ | |||
+ | '''Возможности программы:''' | ||
+ | |||
+ | |||
+ | * По нажатию кнопки "Start" запускается процесс прорисовки траектории полета мяча, с выставленными параметрами. | ||
+ | * По нажатию кнопки "Update" мы обновляем страницу и можем выставить новые начальные значения(условия) полета мяча. | ||
+ | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/filimonov/K_NIR.html |width=1150 |height=575 |border=0 }} | ||
+ | |||
+ | <div class="mw-collapsible mw-collapsed"> | ||
+ | '''Текст программы на языке JavaScript:''' <div class="mw-collapsible-content"> | ||
+ | <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(900, 450); | ||
+ | |||
+ | //Половина футбольного поля | ||
+ | |||
+ | var planeGeometry = new THREE.PlaneGeometry(52.5,70,32,32); | ||
+ | var planeMaterial = new THREE.MeshLambertMaterial({color:0x009900}); | ||
+ | var plane = new THREE.Mesh(planeGeometry, planeMaterial); | ||
+ | plane.position.x=0; | ||
+ | plane.position.y=0; | ||
+ | plane.position.z=0; | ||
+ | scene.add(plane); | ||
+ | // | ||
+ | // Центр поля | ||
+ | |||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(-26.25,-35,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(-26.25,35,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line1 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line1 ); | ||
+ | |||
+ | var curve = new THREE.EllipseCurve( | ||
+ | -26.25, 0, // ax, aY | ||
+ | 9.15, 9.15, // xRadius, yRadius | ||
+ | -0.5*Math.PI, -1.5*Math.PI, // aStartAngle, aEndAngle | ||
+ | false // aClockwise | ||
+ | ); | ||
+ | |||
+ | var path = new THREE.Path( curve.getPoints( 50 ) ); | ||
+ | var geometry = path.createPointsGeometry( 50 ); | ||
+ | var material = new THREE.LineBasicMaterial( { color : 0xffffff } ); | ||
+ | |||
+ | // Create the final Object3d to add to the scene | ||
+ | var ellipse = new THREE.Line( geometry, material ); | ||
+ | scene.add(ellipse); | ||
+ | ellipse.position.x=0; | ||
+ | ellipse.position.y=0; | ||
+ | ellipse.position.z=0; | ||
+ | // | ||
+ | //Штрафная | ||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.25,20.16,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(9.75,20.16,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line ); | ||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.25,-20.16,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(9.75,-20.16,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line2 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line2 ); | ||
+ | |||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(9.75,-20.16,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(9.75,20.16,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line3 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line3 ); | ||
+ | // вратарская зона | ||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(20.75,-9.16,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.25,-9.16,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line4 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line4 ); | ||
+ | |||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(20.75,9.16,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.25,9.16,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line5 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line5 ); | ||
+ | |||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(20.75,-9.16,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(20.75,9.16,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line6 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line6 ); | ||
+ | // | ||
+ | // ворота | ||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.25,-3.66,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.25,3.66,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line7 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line7 ); | ||
+ | |||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.23,-3.66,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.23,3.66,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line8 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line8 ); | ||
+ | |||
+ | var line_geometry = new THREE.Geometry(); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.22,-3.66,0)); | ||
+ | line_geometry.vertices.push(new THREE.Vector3(26.22,3.66,0)); | ||
+ | var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false}); | ||
+ | var line9 = new THREE.Line(line_geometry,material_line); | ||
+ | |||
+ | scene.add( line9 ); | ||
+ | |||
+ | var geometry = new THREE.CylinderGeometry( 0.12, 0.12, 2.44, 32 ); | ||
+ | var material = new THREE.MeshBasicMaterial( {color: 0x000000} ); | ||
+ | var cylinder = new THREE.Mesh( geometry, material ); | ||
+ | cylinder.rotation.x=0.5*Math.PI; | ||
+ | cylinder.position.x=26.25; | ||
+ | cylinder.position.y=-3.66; | ||
+ | cylinder.position.z=1.22; | ||
+ | scene.add( cylinder ); | ||
+ | |||
+ | var geometry = new THREE.CylinderGeometry( 0.12, 0.12, 2.44, 32 ); | ||
+ | var material = new THREE.MeshBasicMaterial( {color: 0x000000} ); | ||
+ | var cylinder1 = new THREE.Mesh( geometry, material ); | ||
+ | cylinder1.rotation.x=0.5*Math.PI; | ||
+ | cylinder1.position.x=26.25; | ||
+ | cylinder1.position.y=3.66; | ||
+ | cylinder1.position.z=1.22; | ||
+ | scene.add( cylinder1 ); | ||
+ | |||
+ | var geometry = new THREE.CylinderGeometry( 0.12, 0.12, 7.56, 32 ); | ||
+ | var material = new THREE.MeshBasicMaterial( {color: 0x000000} ); | ||
+ | var cylinder1 = new THREE.Mesh( geometry, material ); | ||
+ | cylinder1.position.x=26.25; | ||
+ | cylinder1.position.y=0; | ||
+ | cylinder1.position.z=2.44; | ||
+ | scene.add( cylinder1 ); | ||
+ | // | ||
+ | var curve = new THREE.EllipseCurve( | ||
+ | 15.25, 0, // ax, aY | ||
+ | 9.15, 9.15, // xRadius, yRadius | ||
+ | 0.7*Math.PI, -0.7*Math.PI, // aStartAngle, aEndAngle | ||
+ | false // aClockwise | ||
+ | ); | ||
+ | |||
+ | var path = new THREE.Path( curve.getPoints( 50 ) ); | ||
+ | var geometry = path.createPointsGeometry( 50 ); | ||
+ | var material = new THREE.LineBasicMaterial( { color : 0xffffff } ); | ||
+ | |||
+ | // Create the final Object3d to add to the scene | ||
+ | var ellipse1 = new THREE.Line( geometry, material ); | ||
+ | scene.add(ellipse1); | ||
+ | ellipse1.position.x=0; | ||
+ | ellipse1.position.y=0; | ||
+ | ellipse1.position.z=0; | ||
+ | //точка пенальти | ||
+ | var material = new THREE.MeshBasicMaterial({ | ||
+ | color: 0xffffff}); | ||
+ | |||
+ | var radius = 0.4; | ||
+ | var segments = 32; | ||
+ | |||
+ | var circleGeometry = new THREE.CircleGeometry( radius, segments ); | ||
+ | var circle = new THREE.Mesh( circleGeometry, material ); | ||
+ | scene.add( circle ); | ||
+ | circle.position.x=15.25; | ||
+ | circle.position.y=0; | ||
+ | circle.position.z=0; | ||
+ | // мяч | ||
+ | |||
+ | |||
+ | var geometry = new THREE.SphereGeometry( 0.25, 32, 32 ); | ||
+ | var material = new THREE.MeshBasicMaterial( {color: 0xff0000} ); | ||
+ | var sphere = new THREE.Mesh( geometry, material ); | ||
+ | scene.add( sphere ); | ||
+ | sphere.position.x=-8.75; | ||
+ | sphere.position.y=-0.75; | ||
+ | sphere.position.z=0.25; | ||
+ | // | ||
+ | //стенка | ||
+ | /**var planeGeometry = new THREE.PlaneGeometry(1,4,1,1); | ||
+ | var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc}); | ||
+ | var plane = new THREE.Mesh(planeGeometry,planeMaterial); | ||
+ | plane.position.x = 0,75; | ||
+ | plane.position.y = -1,66; | ||
+ | plane.position.z = 0; | ||
+ | scene.add(plane);*/ | ||
+ | |||
+ | var geometry = new THREE.BoxGeometry( 0.5, 3.5, 1.8 ); | ||
+ | var material = new THREE.MeshBasicMaterial( {color: 0xcccccc} ); | ||
+ | var cube = new THREE.Mesh( geometry, material ); | ||
+ | cube.position.x = 0.75; | ||
+ | cube.position.y = 0; | ||
+ | cube.position.z = 0.9; | ||
+ | scene.add( cube ); | ||
+ | |||
+ | var radius1 = 0.25; | ||
+ | var segments1 = 32; | ||
+ | |||
+ | var circle1Geometry = new THREE.CircleGeometry( radius1, segments1 ); | ||
+ | var circle1 = new THREE.Mesh( circle1Geometry, material ); | ||
+ | scene.add( circle1 ); | ||
+ | circle1.position.x=0.75; | ||
+ | circle1.position.y=-0.5; | ||
+ | circle1.position.z=0.9; | ||
+ | |||
+ | |||
+ | |||
+ | // положение камеры | ||
+ | camera.position.x= 0; | ||
+ | camera.position.y= 0; | ||
+ | camera.position.z= 80; | ||
+ | camera.lookAt(scene.position); | ||
+ | $("#webGL").append(render.domElement); | ||
+ | |||
+ | var spotLight = new THREE.SpotLight(0xffffff); | ||
+ | spotLight.position.set(0,0,250) | ||
+ | scene.add(spotLight); | ||
+ | |||
+ | var trajectoryGeometry = new THREE.SphereGeometry(0.1, 16, 16); | ||
+ | var trajectoryMaterial = new THREE.MeshBasicMaterial( {color: 0x000000,wireframe:true} ); | ||
+ | |||
+ | |||
+ | |||
+ | var controls = new function() { | ||
+ | this.viscosity = 0.0000178; | ||
+ | this.AirDensity = 1.2754; | ||
+ | this.WindPowerX = 0; | ||
+ | this.WindPowerY = 0; | ||
+ | this.WindPowerZ = 0; | ||
+ | this.BallX_AngularVelocity = 0; | ||
+ | this.BallY_AngularVelocity = 0; | ||
+ | this.BallZ_AngularVelocity = 10 * 6.28318530718; | ||
+ | this.BallVelocityX = 35; | ||
+ | this.BallVelocityY = -8.5; | ||
+ | this.BallVelocityZ = 2.8; | ||
+ | } | ||
+ | var gui = new dat.GUI(); | ||
+ | gui.add(controls, 'viscosity',1,1.5); | ||
+ | gui.add(controls, 'AirDensity',1,1.5); | ||
+ | |||
+ | |||
+ | var guiScale = gui.addFolder('WindPower'); | ||
+ | guiScale.add(controls, 'WindPowerX', -100,100); | ||
+ | guiScale.add(controls, 'WindPowerY', -100,100); | ||
+ | guiScale.add(controls, 'WindPowerZ', -100,100); | ||
+ | |||
+ | var guiPosition = gui.addFolder('AngularVelocity'); | ||
+ | guiPosition.add(controls, 'BallX_AngularVelocity', -100,100); | ||
+ | guiPosition.add(controls, 'BallY_AngularVelocity', -100,100); | ||
+ | guiPosition.add(controls, 'BallZ_AngularVelocity', -100,100); | ||
+ | |||
+ | var guiRotation = gui.addFolder('BallLineVelocity'); | ||
+ | guiRotation.add(controls, 'BallVelocityX', 0,50); | ||
+ | guiRotation.add(controls, 'BallVelocityY', -50,50); | ||
+ | guiRotation.add(controls, 'BallVelocityZ', 0,50); | ||
+ | |||
+ | control1 = new THREE.OrbitControls(camera); | ||
+ | control1.dumping = 0.2; | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | 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; | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | var pi = Math.PI; | ||
+ | var r = 0.11; | ||
+ | var ro = controls.AirDensity; | ||
+ | var nu = controls.viscosity; | ||
+ | var m = 0.45; | ||
+ | var i = 0; | ||
+ | var vX = 0; | ||
+ | var vY = 0; | ||
+ | var vZ = 0; | ||
+ | var Wx = controls.BallX_AngularVelocity ; | ||
+ | var Wy = controls.BallY_AngularVelocity ; | ||
+ | var Wz = controls.BallZ_AngularVelocity ; | ||
+ | var dt = 0.01; | ||
+ | var g = 9.81 | ||
+ | |||
+ | vX += controls.BallVelocityX; | ||
+ | vY += controls.BallVelocityY; | ||
+ | vZ += controls.BallVelocityZ; | ||
+ | |||
+ | function renderer() | ||
+ | { | ||
+ | //stats.update(); | ||
+ | |||
+ | |||
+ | if (i == 0) | ||
+ | { | ||
+ | vX += controls.BallVelocityX; | ||
+ | vY += controls.BallVelocityY; | ||
+ | vZ += controls.BallVelocityZ; | ||
+ | windX = controls.WindPowerX; | ||
+ | windY = controls.WindPowerY; | ||
+ | windZ = controls.WindPowerZ; | ||
+ | |||
+ | Wx = controls.BallX_AngularVelocity; | ||
+ | Wy = controls.BallY_AngularVelocity; | ||
+ | Wz = controls.BallZ_AngularVelocity; | ||
+ | |||
+ | i = 1; | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | if (sphere.position.z >= 0.25 && sphere.position.x <= 40) | ||
+ | { | ||
+ | var Ux = vX-windX; | ||
+ | var Uy = vY-windY; | ||
+ | var Uz = vZ-windZ; | ||
+ | vX += (-6*pi*r*nu*vX/m + 2*pi*ro*r*r*r*((Uz)*Wy-((Uz))*Wz)/m)*dt; | ||
+ | vY += (-6*pi*r*nu*vY/m + 2*pi*ro*r*r*r*((Ux)*Wz)-((Uz))*Wx/m)*dt; | ||
+ | vZ += (-g-6*pi*r*nu*vZ/m + 2*pi*ro*r*r*r*((Uy)*Wx-((Ux))*Wy)/m)*dt; | ||
+ | |||
+ | |||
+ | sphere.position.x += vX*dt; | ||
+ | sphere.position.y += vY*dt; | ||
+ | sphere.position.z += vZ*dt; | ||
+ | |||
+ | var trajectory = new THREE.Mesh(trajectoryGeometry, trajectoryMaterial); | ||
+ | trajectory.position.x = sphere.position.x; | ||
+ | trajectory.position.y = sphere.position.y; | ||
+ | trajectory.position.z = sphere.position.z; | ||
+ | |||
+ | scene.add( trajectory ); | ||
+ | } | ||
+ | |||
+ | |||
+ | requestAnimationFrame(renderer); | ||
+ | control1.update(); | ||
+ | render.render(scene,camera); | ||
+ | |||
+ | |||
+ | } | ||
+ | this.start = renderer; | ||
+ | |||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | </div> | ||
== Обсуждение результатов и выводы == | == Обсуждение результатов и выводы == | ||
+ | * Таким образом, в ходе работы над проектом была написана программа, моделирующая траекторию движения мяча во время штрафного удара, а так же смоделирован конкретный удар, при известных условиях. | ||
+ | |||
+ | {{начало цитаты}} | ||
+ | |||
+ | '''Входные данные''' | ||
+ | |||
+ | * На основании статьи <ref>[http://technicamolodezhi.ru/rubriki_tm/tehnika_i_sport/fizika_futbola статья "Физика футбола"]</ref>, посвященной удару Роберто Карлоса можно вычленить входные данные для нашей программы и посмотреть на полученную в программе траекторию. | ||
+ | |||
+ | - <big><math> v_{0} = 35 (м/с) </math> - начальная скорость мяча</big>; | ||
+ | |||
+ | - <big><math> d = 35 (м) </math> - расстояние от мяча до ворот</big>; | ||
+ | |||
+ | - <big><math> \omega_{z} = 10 (об/с) =62.8 (рад/с)</math> - скорость вращения мяча во время полета</big>; | ||
+ | |||
+ | - <big>Также было известно, что погода была сухая и безветренная, то есть скорость ветра по всем осям равна 0.</big> | ||
+ | |||
+ | * ''' Подставив в программу данные, полученные учеными, можно увидеть как мяч залетает в ворота.''' | ||
+ | |||
+ | {{конец цитаты}} | ||
+ | |||
+ | '''Вывод:''' | ||
+ | В случае, когда удар нанесен с другой угловой скоростью ( <math> \omega_{z} = 9 (об/с)</math>, в результате работы программы можно увидеть, что мяч не залетает в ворота. | ||
+ | |||
+ | При угловой скорости мяча <math> \omega_{z} = 9 (об/с) </math> и при увеличении проекции начальной скорости в направлении удара <math> v_{x} = 45 (м/с) </math>, но с теми же значениями по ортогональным осям, мяч залетает в ворота. | ||
+ | |||
+ | На основании полученных результатов можно сказать, что мяч залетел с немалой долей удачи, так как даже с малым изменением параметров меняется вероятность попадания. | ||
+ | . | ||
<br> | <br> | ||
− | Скачать отчет: | + | Скачать отчет:[[Медиа:KursovoyProektFilimonov.docx | Отчет]] |
<br> | <br> | ||
Скачать презентацию: | Скачать презентацию: | ||
Строка 32: | Строка 511: | ||
== Ссылки по теме == | == Ссылки по теме == | ||
+ | == Примечания == | ||
+ | <references/> | ||
== См. также == | == См. также == |
Текущая версия на 04:07, 5 июня 2015
А.М. Кривцов > Теоретическая механика > Курсовые проекты ТМ 2015 > Штрафной удар по воротам
Курсовой проект по Теоретической механике
Исполнитель: Филимонов Александр
Группа: 09 (23604)
Семестр: весна 2015
Содержание
Аннотация проекта[править]
Данный проект посвящен изучению динамики движения футбольного мяча во время штрафного удара. В ходе работы над проектом был рассмотрен конкретный штрафной удар, который был исполнен Роберто Карлосом в товарищеском матче Бразилия - Франция. Этот удар был симулирован на языке JavaScript [1].
Формулировка задачи[править]
- Написать программу, которая моделирует процесс движения футбольного мяча во время штрафного удара, с учетом внешних сил и воздействий.
Общие сведения по теме[править]
Роберто Карлос забил в 1997 году в ворота сборной Франции невероятный по красоте гол.
Мяч был установлен примерно в 30 - 35 м от ворот соперников, ближе к правому краю поля. После удара Карлоса мяч полетел далеко в правую сторону, облетел «стенку» в метре от нее и после этого чудесным образом мяч повернул влево и влетел в ворота - к изумлению игроков, вратаря и представителей СМИ.
Этот удар стал наглядным примером силы Магнуса, действующей на тело, движущееся с вращением при обтекании его потоком жидкости или газа.
Решение[править]
, где
- Равнодействующая сил на мяч;
- Сила тяжести, действующая на мяч;
- Сила сопротивления воздуха;
[2].
- Сила Магнуса
Сила тяжести:
, где
- масса мяча;
- ускорение свободного падения.
Силу сопротивления воздуха будем считать с помощью закона Стокса:
, где
- сила Стокса,
- радиус мяча,
- динамическая вязкость,
- скорость мяча.
Силу Магнуса примем вида:
, где
- сила Магнуса,
- площадь, на которую действует сила
- плотность воздуха,
- радиус мяча,
- относительная скорость мяча,
- угловая скорость мяча.
Применив метод Эйлера, получим формулы для нахождения скорости и координаты мяча:
;
Возможности программы:
- По нажатию кнопки "Start" запускается процесс прорисовки траектории полета мяча, с выставленными параметрами.
- По нажатию кнопки "Update" мы обновляем страницу и можем выставить новые начальные значения(условия) полета мяча.
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(900, 450);
8
9 //Половина футбольного поля
10
11 var planeGeometry = new THREE.PlaneGeometry(52.5,70,32,32);
12 var planeMaterial = new THREE.MeshLambertMaterial({color:0x009900});
13 var plane = new THREE.Mesh(planeGeometry, planeMaterial);
14 plane.position.x=0;
15 plane.position.y=0;
16 plane.position.z=0;
17 scene.add(plane);
18 //
19 // Центр поля
20
21 var line_geometry = new THREE.Geometry();
22 line_geometry.vertices.push(new THREE.Vector3(-26.25,-35,0));
23 line_geometry.vertices.push(new THREE.Vector3(-26.25,35,0));
24 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
25 var line1 = new THREE.Line(line_geometry,material_line);
26
27 scene.add( line1 );
28
29 var curve = new THREE.EllipseCurve(
30 -26.25, 0, // ax, aY
31 9.15, 9.15, // xRadius, yRadius
32 -0.5*Math.PI, -1.5*Math.PI, // aStartAngle, aEndAngle
33 false // aClockwise
34 );
35
36 var path = new THREE.Path( curve.getPoints( 50 ) );
37 var geometry = path.createPointsGeometry( 50 );
38 var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
39
40 // Create the final Object3d to add to the scene
41 var ellipse = new THREE.Line( geometry, material );
42 scene.add(ellipse);
43 ellipse.position.x=0;
44 ellipse.position.y=0;
45 ellipse.position.z=0;
46 //
47 //Штрафная
48 var line_geometry = new THREE.Geometry();
49 line_geometry.vertices.push(new THREE.Vector3(26.25,20.16,0));
50 line_geometry.vertices.push(new THREE.Vector3(9.75,20.16,0));
51 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
52 var line = new THREE.Line(line_geometry,material_line);
53
54 scene.add( line );
55 var line_geometry = new THREE.Geometry();
56 line_geometry.vertices.push(new THREE.Vector3(26.25,-20.16,0));
57 line_geometry.vertices.push(new THREE.Vector3(9.75,-20.16,0));
58 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
59 var line2 = new THREE.Line(line_geometry,material_line);
60
61 scene.add( line2 );
62
63 var line_geometry = new THREE.Geometry();
64 line_geometry.vertices.push(new THREE.Vector3(9.75,-20.16,0));
65 line_geometry.vertices.push(new THREE.Vector3(9.75,20.16,0));
66 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
67 var line3 = new THREE.Line(line_geometry,material_line);
68
69 scene.add( line3 );
70 // вратарская зона
71 var line_geometry = new THREE.Geometry();
72 line_geometry.vertices.push(new THREE.Vector3(20.75,-9.16,0));
73 line_geometry.vertices.push(new THREE.Vector3(26.25,-9.16,0));
74 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
75 var line4 = new THREE.Line(line_geometry,material_line);
76
77 scene.add( line4 );
78
79 var line_geometry = new THREE.Geometry();
80 line_geometry.vertices.push(new THREE.Vector3(20.75,9.16,0));
81 line_geometry.vertices.push(new THREE.Vector3(26.25,9.16,0));
82 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
83 var line5 = new THREE.Line(line_geometry,material_line);
84
85 scene.add( line5 );
86
87 var line_geometry = new THREE.Geometry();
88 line_geometry.vertices.push(new THREE.Vector3(20.75,-9.16,0));
89 line_geometry.vertices.push(new THREE.Vector3(20.75,9.16,0));
90 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
91 var line6 = new THREE.Line(line_geometry,material_line);
92
93 scene.add( line6 );
94 //
95 // ворота
96 var line_geometry = new THREE.Geometry();
97 line_geometry.vertices.push(new THREE.Vector3(26.25,-3.66,0));
98 line_geometry.vertices.push(new THREE.Vector3(26.25,3.66,0));
99 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
100 var line7 = new THREE.Line(line_geometry,material_line);
101
102 scene.add( line7 );
103
104 var line_geometry = new THREE.Geometry();
105 line_geometry.vertices.push(new THREE.Vector3(26.23,-3.66,0));
106 line_geometry.vertices.push(new THREE.Vector3(26.23,3.66,0));
107 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
108 var line8 = new THREE.Line(line_geometry,material_line);
109
110 scene.add( line8 );
111
112 var line_geometry = new THREE.Geometry();
113 line_geometry.vertices.push(new THREE.Vector3(26.22,-3.66,0));
114 line_geometry.vertices.push(new THREE.Vector3(26.22,3.66,0));
115 var material_line = new THREE.LineBasicMaterial({ color: 0xEEEEEE, WireframeLinewidth: 10,wireframe: true, fog:false});
116 var line9 = new THREE.Line(line_geometry,material_line);
117
118 scene.add( line9 );
119
120 var geometry = new THREE.CylinderGeometry( 0.12, 0.12, 2.44, 32 );
121 var material = new THREE.MeshBasicMaterial( {color: 0x000000} );
122 var cylinder = new THREE.Mesh( geometry, material );
123 cylinder.rotation.x=0.5*Math.PI;
124 cylinder.position.x=26.25;
125 cylinder.position.y=-3.66;
126 cylinder.position.z=1.22;
127 scene.add( cylinder );
128
129 var geometry = new THREE.CylinderGeometry( 0.12, 0.12, 2.44, 32 );
130 var material = new THREE.MeshBasicMaterial( {color: 0x000000} );
131 var cylinder1 = new THREE.Mesh( geometry, material );
132 cylinder1.rotation.x=0.5*Math.PI;
133 cylinder1.position.x=26.25;
134 cylinder1.position.y=3.66;
135 cylinder1.position.z=1.22;
136 scene.add( cylinder1 );
137
138 var geometry = new THREE.CylinderGeometry( 0.12, 0.12, 7.56, 32 );
139 var material = new THREE.MeshBasicMaterial( {color: 0x000000} );
140 var cylinder1 = new THREE.Mesh( geometry, material );
141 cylinder1.position.x=26.25;
142 cylinder1.position.y=0;
143 cylinder1.position.z=2.44;
144 scene.add( cylinder1 );
145 //
146 var curve = new THREE.EllipseCurve(
147 15.25, 0, // ax, aY
148 9.15, 9.15, // xRadius, yRadius
149 0.7*Math.PI, -0.7*Math.PI, // aStartAngle, aEndAngle
150 false // aClockwise
151 );
152
153 var path = new THREE.Path( curve.getPoints( 50 ) );
154 var geometry = path.createPointsGeometry( 50 );
155 var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
156
157 // Create the final Object3d to add to the scene
158 var ellipse1 = new THREE.Line( geometry, material );
159 scene.add(ellipse1);
160 ellipse1.position.x=0;
161 ellipse1.position.y=0;
162 ellipse1.position.z=0;
163 //точка пенальти
164 var material = new THREE.MeshBasicMaterial({
165 color: 0xffffff});
166
167 var radius = 0.4;
168 var segments = 32;
169
170 var circleGeometry = new THREE.CircleGeometry( radius, segments );
171 var circle = new THREE.Mesh( circleGeometry, material );
172 scene.add( circle );
173 circle.position.x=15.25;
174 circle.position.y=0;
175 circle.position.z=0;
176 // мяч
177
178
179 var geometry = new THREE.SphereGeometry( 0.25, 32, 32 );
180 var material = new THREE.MeshBasicMaterial( {color: 0xff0000} );
181 var sphere = new THREE.Mesh( geometry, material );
182 scene.add( sphere );
183 sphere.position.x=-8.75;
184 sphere.position.y=-0.75;
185 sphere.position.z=0.25;
186 //
187 //стенка
188 /**var planeGeometry = new THREE.PlaneGeometry(1,4,1,1);
189 var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
190 var plane = new THREE.Mesh(planeGeometry,planeMaterial);
191 plane.position.x = 0,75;
192 plane.position.y = -1,66;
193 plane.position.z = 0;
194 scene.add(plane);*/
195
196 var geometry = new THREE.BoxGeometry( 0.5, 3.5, 1.8 );
197 var material = new THREE.MeshBasicMaterial( {color: 0xcccccc} );
198 var cube = new THREE.Mesh( geometry, material );
199 cube.position.x = 0.75;
200 cube.position.y = 0;
201 cube.position.z = 0.9;
202 scene.add( cube );
203
204 var radius1 = 0.25;
205 var segments1 = 32;
206
207 var circle1Geometry = new THREE.CircleGeometry( radius1, segments1 );
208 var circle1 = new THREE.Mesh( circle1Geometry, material );
209 scene.add( circle1 );
210 circle1.position.x=0.75;
211 circle1.position.y=-0.5;
212 circle1.position.z=0.9;
213
214
215
216 // положение камеры
217 camera.position.x= 0;
218 camera.position.y= 0;
219 camera.position.z= 80;
220 camera.lookAt(scene.position);
221 $("#webGL").append(render.domElement);
222
223 var spotLight = new THREE.SpotLight(0xffffff);
224 spotLight.position.set(0,0,250)
225 scene.add(spotLight);
226
227 var trajectoryGeometry = new THREE.SphereGeometry(0.1, 16, 16);
228 var trajectoryMaterial = new THREE.MeshBasicMaterial( {color: 0x000000,wireframe:true} );
229
230
231
232 var controls = new function() {
233 this.viscosity = 0.0000178;
234 this.AirDensity = 1.2754;
235 this.WindPowerX = 0;
236 this.WindPowerY = 0;
237 this.WindPowerZ = 0;
238 this.BallX_AngularVelocity = 0;
239 this.BallY_AngularVelocity = 0;
240 this.BallZ_AngularVelocity = 10 * 6.28318530718;
241 this.BallVelocityX = 35;
242 this.BallVelocityY = -8.5;
243 this.BallVelocityZ = 2.8;
244 }
245 var gui = new dat.GUI();
246 gui.add(controls, 'viscosity',1,1.5);
247 gui.add(controls, 'AirDensity',1,1.5);
248
249
250 var guiScale = gui.addFolder('WindPower');
251 guiScale.add(controls, 'WindPowerX', -100,100);
252 guiScale.add(controls, 'WindPowerY', -100,100);
253 guiScale.add(controls, 'WindPowerZ', -100,100);
254
255 var guiPosition = gui.addFolder('AngularVelocity');
256 guiPosition.add(controls, 'BallX_AngularVelocity', -100,100);
257 guiPosition.add(controls, 'BallY_AngularVelocity', -100,100);
258 guiPosition.add(controls, 'BallZ_AngularVelocity', -100,100);
259
260 var guiRotation = gui.addFolder('BallLineVelocity');
261 guiRotation.add(controls, 'BallVelocityX', 0,50);
262 guiRotation.add(controls, 'BallVelocityY', -50,50);
263 guiRotation.add(controls, 'BallVelocityZ', 0,50);
264
265 control1 = new THREE.OrbitControls(camera);
266 control1.dumping = 0.2;
267
268
269
270
271
272 window.addEventListener('resize',onWindowResize,false);
273 function onWindowResize()
274 {
275 camera.aspect = window.innerWidth/window.innerHeight;
276 camera.updateProjectionMatrix();
277 render.setSize(window.innerWidth,window.innerHeight);
278
279 renderer();
280 }
281 //var stats = initStats();
282 var step = 0;
283
284
285
286
287 var pi = Math.PI;
288 var r = 0.11;
289 var ro = controls.AirDensity;
290 var nu = controls.viscosity;
291 var m = 0.45;
292 var i = 0;
293 var vX = 0;
294 var vY = 0;
295 var vZ = 0;
296 var Wx = controls.BallX_AngularVelocity ;
297 var Wy = controls.BallY_AngularVelocity ;
298 var Wz = controls.BallZ_AngularVelocity ;
299 var dt = 0.01;
300 var g = 9.81
301
302 vX += controls.BallVelocityX;
303 vY += controls.BallVelocityY;
304 vZ += controls.BallVelocityZ;
305
306 function renderer()
307 {
308 //stats.update();
309
310
311 if (i == 0)
312 {
313 vX += controls.BallVelocityX;
314 vY += controls.BallVelocityY;
315 vZ += controls.BallVelocityZ;
316 windX = controls.WindPowerX;
317 windY = controls.WindPowerY;
318 windZ = controls.WindPowerZ;
319
320 Wx = controls.BallX_AngularVelocity;
321 Wy = controls.BallY_AngularVelocity;
322 Wz = controls.BallZ_AngularVelocity;
323
324 i = 1;
325
326 }
327
328
329 if (sphere.position.z >= 0.25 && sphere.position.x <= 40)
330 {
331 var Ux = vX-windX;
332 var Uy = vY-windY;
333 var Uz = vZ-windZ;
334 vX += (-6*pi*r*nu*vX/m + 2*pi*ro*r*r*r*((Uz)*Wy-((Uz))*Wz)/m)*dt;
335 vY += (-6*pi*r*nu*vY/m + 2*pi*ro*r*r*r*((Ux)*Wz)-((Uz))*Wx/m)*dt;
336 vZ += (-g-6*pi*r*nu*vZ/m + 2*pi*ro*r*r*r*((Uy)*Wx-((Ux))*Wy)/m)*dt;
337
338
339 sphere.position.x += vX*dt;
340 sphere.position.y += vY*dt;
341 sphere.position.z += vZ*dt;
342
343 var trajectory = new THREE.Mesh(trajectoryGeometry, trajectoryMaterial);
344 trajectory.position.x = sphere.position.x;
345 trajectory.position.y = sphere.position.y;
346 trajectory.position.z = sphere.position.z;
347
348 scene.add( trajectory );
349 }
350
351
352 requestAnimationFrame(renderer);
353 control1.update();
354 render.render(scene,camera);
355
356
357 }
358 this.start = renderer;
359
360 }
Обсуждение результатов и выводы[править]
- Таким образом, в ходе работы над проектом была написана программа, моделирующая траекторию движения мяча во время штрафного удара, а так же смоделирован конкретный удар, при известных условиях.
Входные данные
- На основании статьи [3], посвященной удару Роберто Карлоса можно вычленить входные данные для нашей программы и посмотреть на полученную в программе траекторию.
-
- начальная скорость мяча;-
- расстояние от мяча до ворот;-
- скорость вращения мяча во время полета;- Также было известно, что погода была сухая и безветренная, то есть скорость ветра по всем осям равна 0.
- Подставив в программу данные, полученные учеными, можно увидеть как мяч залетает в ворота.
Вывод: В случае, когда удар нанесен с другой угловой скоростью (
, в результате работы программы можно увидеть, что мяч не залетает в ворота.При угловой скорости мяча
и при увеличении проекции начальной скорости в направлении удара , но с теми же значениями по ортогональным осям, мяч залетает в ворота.На основании полученных результатов можно сказать, что мяч залетел с немалой долей удачи, так как даже с малым изменением параметров меняется вероятность попадания. .
Скачать отчет: Отчет
Скачать презентацию: