Technical
Modelling Roquets
I wanted the equations of motion of a croquet balls so that I could model them on a virtual croquet lawn. The basic equations of motion relating initial velocity, distance and time, given Plummers for a lawn, were given here. The main results linking the initial velocity of a ball, u, the time, t, and distance travelled, s, and the friction (deceleration), a, against the grass were: u =a. √2.s_{final} / a(1) s =a. √2.s_{final} / a.t + ½.a.t^{2}(2) t_{final} = √2.s_{final} / a(3) Where s_{final} is the total distance travelled. The aim is to get a realistic cut rushtype action. For the person doing the modelling they will know the initial positions of the striker's ball, SB, and the roquetted ball, RB. They also know the desired final position of the roquetted ball. The balls are assumed to be elastic hard spheres. The position of the striker's ball when it first makes contact against the target ball can be calculated since we know that, on contact with the roquetted ball, the centres of the striker's ball and roquetted ball lie along the rush line (Figure 1.) Figure 2 below shows this in more detail.
The angle θ is derived from the start and final positions, RB(x_{1},y_{1}) and RB(x_{2},y_{2}), of the roquetted ball. Simple trigonometry gives values for Δx and Δy from the centre of the roquetted ball: Tan(θ) = (RB_{y2}  RB_{y1}) / (RB_{x2}  RB_{x1})(4a) Δx = 2r.Cos(θ) (4b) Δy = 2r.Sin(θ)(4c) It can also be done by equivalent triangles: 2r / s_{RB} = Δx / (RB_{x2}  RB_{x1}) = Δy / (RB_{y2}  RB_{y1})(5a) where s_{RB} = √(RB_{x2}  RB_{x1})^{2} + (RB_{y2}  RB_{y1})^{2}(5b) From the diagram: SB(x_{1},y_{1}) = RB(x_{1}  Δx, y_{1}  Δy)(6) We now know the location SB(x_{1},y_{1}) through which the striker's ball must pass to rush the roquetted ball at angle θ. Providing the striker's ball approaches anywhere less than perpendicular to the rush line (and from the right side!) and passes through SB(x_{1},y_{1}) then the roquetted ball will move down the rush line. From the above we know the line along which to launch the striker's ball. We still have to find the energy (via the initial velocity, u_{S}) to put into the striker's ball so that when it hits the roquetted ball the roquetted ball is driven the correct distance. Also we would like to calculate the scatter angle and striker's ball's subsequent velocity. Just to confirm the notation, the striker's ball is 'struck' from its starting position, SB(x_{0},y_{0}), through SB(x_{1},y_{1}), collides with the roquetted ball at RB(x_{1},y_{1}) and then the roquetted ball moves away along the rush line to RB(x_{2},y_{2}). The striker's ball scatters off to SB(x_{2},y_{2}).
As we now know SB(x_{1},y_{1}) and SB(x_{0},y_{0}), we can calculate the distance the striker's ball travels to the collision point using Pythagoras. s_{col} = √(SB_{x1}  SB_{x0})^{2} + (SB_{y1}  SB_{y0})^{2}(7) Hence to start the animation the striker's ball is launched through the collision position to a virtual end position s_{final}. However when it has travelled s_{col} we start the roquetted ball moving to its new rest position. After the collision the s_{final} is no longer appropriate since the striker's ball has lost energy in the collision and hence will travel a shorter distance, s' (sprimed), in a new direction. Figure 3 indicates velocity vectors not distances, at the instant of the roquet (not to scale). We can use the conservation of momentum here to form some equations. Momentum, p, is given by: p = m.v(8) At this stage we will assume that we have an instantaneous elastic collision. The total momentum therefore is conserved. The instant before collision the striker's ball has momentum: p = m.v_{S}(9) The 'roquetted' ball has zero momentum at this time. The instant after collision the momentum is partitioned between the roquetted ball and the recoiling striker's ball. p = m.v_{S} = m.v_{R} + m.v'_{S}(10) where v_{S} is the velocity of the striker's ball before collision, v'_{S} its velocity after collision (not to scale in the diagram) and v_{R}, the velocity of the roquetted ball after collision. All the ball masses, m, are the same so we can extract them. The angle between the balls after a collision is 90'. This arises from the conservation of kinetic energy, E_{K}= ½mv^{2}, as well as momentum, i.e. v_{S} = v'_{S}+ v_{R} = p / m(11a) v_{S}^{2} = v'_{S}^{2}+ v_{R}^{2} = 2.E_{K} / m(11b) Note (11a) is a vector addition; (11b) is scalar addition. From (11a) and (11b) the vector triangle must be right angled; the triangle which satisfies a^{2} + b^{2} = c^{2} is right angled (Pythagoras). We now have most of the pieces to work out the problem.
See Appendix 1 for notes on getting the correct angle for the departing striker's ball after the roquet. Where are we now?
Appendix 1Using the standard JavaScript Math.sin, Math.cos and Math.atan functions gives some programming headaches. The atan function returns values only between ±π/2 hence further logic is required to work out whether the returned angle is α or (α±π). When modelling the roquet, sin and cos are used to calculate the launch angle, Φ, of the striker's ball and the exit angle, θ, of the roquetted ball, equation (13). The signs of Δx' and Δy' need to be correctly set in equations (16a)(16b) to get the striker's ball to kick off in the correct direction after the collision. If you consider a roquet without reference to any axes some rules can be defined. A representative track of the striker's ball, SB, is shown approaching from the left. Given that you cannot produce a cutrush of more than 90º, the yellow sector shows allowed approach directions of the striker's ball towards the roquetted ball, RB. The angle Ω, as calculated in in (13) is the 'approach direction' of the striker's ball. When Ω is zero we get a straight rush and when it is ±90º, the roquetted ball is barely moved. Clearly if the striker's ball approaches in the left half of the yellow semicircle, the striker's ball kick off to the right and vice versa. To get the correct angle of exit of the striker's ball I used a decision tree based on my sign conventions similar to: if ((omega > 0) && (omega <= (pi/2))) { etc.
* Elastic collisions and snooker All rights reserved © 20142017
