 |
Example - Golf
* The "\" symbol has been used at the end of lines to indicate that the line was too long for the display and has been
wrapped to the line below in order to fit within the width of the web page. These lines would need to be joined in the normal
program editor.
I. Introduction
In the game of golf, where a ball is struck with a club with the intention of it landing in the correct place, a great deal depends on the aerodynamics of the ball in flight, and the bouncing characteristics of the ball on the ground. This program performs a simple analysis of the trajectory of a golf ball, and allows the observation of the relative effects of the factors that affect it.

II. Physics Involved
1) Presentation of the Problem
Consider a 2-dimensional plane, where a golfer has to hit a ball in such a way that it falls into the hole. The x-axis of the plane is the horizontal axis and the y-axis represents the altitude. The golfer can hit the ball in a certain direction, with certain strength, giving it a consequential initial velocity vector. The ball will then be subjected to the following forces:
- Its weight, m.g , proportional to its mass, m , and gravity, g .
- Air resistance, determined by considering the horizontal and vertical speeds of the ball,
and and the speed of the wind, w , assumed to be a following wind for a positive w value.
2) Equations
2a) Movement of the Ball in the Air
The fundamental principle of dynamics says that the product of the weight and acceleration vector of a system (presently the ball) equals the sum of the force vectors applied to it, i.e. ma = mg + r k( v - w) 2 , where a is the acceleration vector of the ball, g is the gravity vector, r is the air density, k is the drag coefficient, v is the velocity of the ball relative to the ground and w is the wind, represented as a vector.
This is a differential equation since a = dv/dt . By solving this equation one can obtain the value of the ball's position vector, s, and so calculate the x and y position of the ball. Solving a differential equation such as this symbolically is not simple, but fortunately the FiniteElementArray object type will make it easy to solve numerically.
2b) Bounces
In an ideal case, when the ball would hit the ground it would rebound with the same speed, the y component just being reversed. In reality it's not like this; the ground absorbs a part of the kinetic energy of the ball, so its y speed component will decrease. The amount of decrease is determined by the bounce rate b r so that the new value of , will be given by . In the ideal case br would be 1, so no speed is lost; realistically b r is more likely to be around 0.5.
2c) Rolling of the Ball on the Ground
After a certain number of bounces the ball will simply roll on the ground, its horizontal velocity acting as before, but its vertical velocity being constant at zero. This is the least realistic part of the simulation, as it does not take into account friction with the ground, or any unevenness in the playing surface. However, since the rolling stage doesn't account for very much of the ball's total movement this doesn't affect the final result very much.
III. How the Program Works
1) Functionalities
This SBL program will allow the user to try to make the ball fall into the hole. Thus, he will be able to set the initial speed of the ball (by setting its horizontal and vertical values), but he will also be able to set many parameters:
- The weight of the ball
- The wind speed
- The gravity value
- The air density
- The bounce rate of the ground

2) Initialisation: the GolfInit() Function
The main() procedure calls the GolfInit() function to perform the initialisation. After initialising the form, the GolfInit() function declares the following variables:
GLOBAL xinit%%,yinit%%'initial position of the ball
GLOBAL xh%%'position of the hole
GLOBAL g%,p%,m%,w%,br%'gravity, air density, mass, wind and bounce rate
GLOBAL tempx%,tempy%,t%'temporary position of the ball and time
GLOBAL ballwidth%%,ballheight%%
GLOBAL lastx%,lasty%,Counter%
xinit%% = 100
yinit%% = 4
ballwidth%% = 15
ballheight%% = 15
xh%% = 750
Then it calls ControlsInit() , which sets the command buttons, text boxes and labels. But the most interesting part of the GolfInit() function is the initialisation of the finite element array:
GLOBAL fea AS FiniteElmtArray
fea.Name = "ballMvt"
DIM fa AS FiniteElmtAttribute
SET fa = fea.Add("x")'x-equation of the ball movement
fa.SetFormula("-(p%/40)*(x(1)-w%)*sqr((x(1)-w%)^2 + y(1)^2)/m%",2)
fa.Order = 2
fa.AllowableErrorFactor = 0.01
fa.AllowableErrorMin = 0.01
SET fa = fea.Add("y")'y-equation of the ball movement
fa.SetFormula("(-(p%/40)*y(1)*sqr((x(1)-w%)^2 + y(1)^2)/m%) - g%",2)
fa.Order = 2
fa.AllowableErrorFactor = 0.01
fa.AllowableErrorMin = 0.01
We need two Finite Element Attributes, x and y . Their equations are the x- and y-axis projections of the equations explained above:


where the value of k is taken to be 1/40.
3) Movement of the Ball in the Air; Bounces
Each time the user clicks the Start button the RunProc() function is called. It first initialises the variables used:
SUB RunProc()
' Make sure the ball is returned to the starting point
Golf.ball.move(xinit%% - 5,391 - yinit%%,ballwidth%%,ballheight%%)
FORM 1
lastx% = Golf.Ball.Left + INT (Golf.Ball.Width / 2) '(ballwidth%% / 2) + x% - 5
lasty% = Golf.Ball.Top + INT (Golf.Ball.Height / 2) '(ballheight%% / 2) + 391 - y%
fea.Stop()
fea.x.SetInitialValue(xinit%%)
fea.y.SetInitialValue(yinit%%)
fea.x.SetInitialValue( VAL (Golf.sx0Box.Text),1)
fea.y.SetInitialValue( VAL (Golf.sy0Box.Text),1)
g% = VAL (Golf.GravityBox.Text)
p% = VAL (Golf.DensityBox.Text)
m% = VAL (Golf.MassBox.Text)
w% = VAL (Golf.WindBox.Text)
br% = VAL (Golf.BounceBox.Text)
fea.AdvanceTo(0)
Then it draws the ball moving in the air and bouncing:
t% = 0.01
SET fc = Golf.Controls("ball")
CALL Draw(fea.x(),fea.y())
maxy% = 6
'while the ball is bouncing:
WHILE maxy% > 5 AND Golf.startbtn.Tag <> "" AND Golf.startbtn.Tag \ <> "stop"
maxy% = 4
WHILE tempy% >= yinit%% AND Golf.startbtn.Tag <> "" AND \ Golf.startbtn.Tag <> "stop"
fea.AdvanceTo(t%)
CALL Draw(fea.x(),fea.y())
IF tempy% > maxy% THEN maxy% = tempy%
t% = t% + 0.02
Process()
WEND
'initial values of the next bounce:
tempsx% = fea.x(1)'save this value before we stop the fea
tempsy% = - br% * fea.y(1)'the ball will be deadened
fea.Stop()'so that we can restart it with the new values:
fea.x.SetInitialValue(tempx%)
fea.x.SetInitialValue(tempsx%,1)
fea.y.SetInitialValue(tempsy%,1)
t% = 0
tempy% = yinit%%
WEND
The finite element array solves and integrates the differential equation; the x and y values are simply obtained by retrieving the value of fea.x() and fea.y() .
The Draw() function performs the drawing of the ball at the specified position.
When the ball hits the ground, it bounces: its x speed component does not change, while its y component is multiplied by -br as discussed in part I.
The ball begins to roll when it last bounced at an altitude lower than 5.
4) Rolling of the Ball
This time the y component of the speed is constant.
'now the ball will roll on the ground:
w% = 0' Remove the influence of the wind now that we are rolling
WHILE tdx% > 0.3 AND Golf.startbtn.Tag <> "" AND endloop%% = 0 \ AND Golf.startbtn.Tag <> "stop"
tdx% = 0
FOR i%% = 0 TO 99
dx% = tempx%
fea.AdvanceTo(t%)
CALL Draw(fea.x(),yinit%%)'this time y% is constant
t% = t% + 0.03
dx% = tempx% - dx%
tdx% = tdx% + ABS (dx%)
IF ABS (tempx% - xh%%) < 1 THEN
i%% = 99
endloop%% = - 1
END IF
Process()
IF Golf.startbtn.Tag = "" OR Golf.startbtn.Tag = "stop" THEN \ i%% = 99
NEXT i%%
WEND
IF endloop%% THEN
Golf.ball.move(xinit%% - 5,391 - yinit%%,ballwidth%%,ballheight%%)
Golf.Refresh()
REQUEST "Well done!","",2
ELSE IF Golf.startbtn.Tag = "stop" THEN
' Do nothing here
ELSE 'IF Golf.startbtn.Tag <> "" THEN
REQUEST "Missed!","",2
Golf.ball.move(xinit%% - 5,391 - yinit%%,ballwidth%%,ballheight%%)
Golf.Refresh()
END IF
Golf.startbtn.Tag = ""
END SUB
We check if the ball reaches the hole, and if it hasn't moved enough during a specific segment of time, we stop it.

|