Measurements¶
On creating a web sockets connection, client application will start receiving measurement messages.
There are three types of measurement messages. Measurement at launch, live measurement and the final measurement. For a single hit, the client application will receive all three types of messages depending on the phase of flight of the golf ball.
1. Launch Data¶
Launch data message format is as below. Message contains below fields.
- Id : unique id of the measurement message. Used to distinguish the golf ball hit.
- Type : for launch messages it is set to
Measurement
- SubType : for launch message it is set to
LaunchData
- Time : time stamp when the ball was hit.
- Payload : launch mesurement data. It contains below fields
- BayId : the bay id from where the shot was hit.
- BayPosition : position of the bay
- TeePosition : launch postion
- Club : club information, ideally same as retrieved from
getClubs()
API - Measurement: Envelope for launch measurement data
- BallSpeed : speed of the ball, in mps.
- LaunchAngle: launch angle of the hit, in degrees.
- LaunchDirection : launch direction according to the target, in degrees.
{ "Id": "e4a38b4d-a4b6-4476-a5ca-d25ea22ff44e", "Type": "Measurement", "SubType": "LaunchData", "Payload": { "Measurement": { "BallSpeed": 39.5, "LaunchAngle": 22.9, "LaunchDirection" : 12.5, "Time": "2015-01-27T06:11:54.931185+01:00", "Kind": "LaunchData" }, "BayPosition": [0,0,10], "TeePosition": [0.5,0,10.2], "Club" : "Hybrid9", "BayId": "e8325297-d1c0-4996-b091-2dc8a4386f1d", "Id": "e4a38b4d-a4b6-4476-a5ca-d25ea22ff44e" } }
id
field to relate these different types of messages to each other. Use the type
field in the measurement message to differentiate between the types of messages.
Use only ballSpeed
and launchAngle
parameters for UI display.
2. Live Measurement¶
Live Measurement message is the current golf ball flight, at some time t in the flight. Client application will receive many live measurements for the same hit.
Live Measurement data message format is as below. Message contains below fields.
- Id : unique id of the measurement message. Used to distinguish the golf ball hit.
- Type : for launch messages it is set to
MeasurementLive
- Time : time stamp when the ball was hit.
- Payload : launch mesurement data. It contains below fields
- BayId : the bay id from where the shot was hit.
- PositionList : set of points on the trajectory path at given point in time. It contains below fields
- Time : relative time to the
time
field above in seconds. - position : co-ordinates of a point in time, according to the selected bay and target on the trajectory path, x, y and z respectively.
- Time : relative time to the
{ "Id": "e4a38b4d-a4b6-4476-a5ca-d25ea22ff44e", "Type": "LiveTrajectory", "Payload": { "BayId": "e8325297-d1c0-4996-b091-2dc8a4386f1d", "Id": "e4a38b4d-a4b6-4476-a5ca-d25ea22ff44e", "PositionList": [ { "Time": 0, "Position": [ 9.999999997831607, 10, 10.000023041159244 ] }, { "Time": 0.1111111111111111, "Position": [ 13.967568836663908, 11.68919397404065, 10.095637838825013 ] }, { "Time": 0.2222222222222222, "Position": [ 17.77904440202046, 13.310718663787815, 10.200772557831566 ] } ] } }
Note
It is recommended to re draw the trajectory every time from beginning when a data packet is received.
3. Final Measurement¶
Final measurement message is ideally received when the ball is landed.
Measurement data message format is as below. Message contains below fields.
- Id : unique id of the measurement message. Used to distinguish the golf ball hit.
- Type : for launch messages it is set to
Measurement
- Time : time stamp when the ball was hit.
- Payload : launch mesurement data. It contains below fields
- BayId : the bay id from where the shot was hit.
- BayPosition : position of the bay
- TeePosition : launch postion
- Club : club information, ideally same as retrieved from
getClubs()
API - Measurement : Ball flight measurement transformed to bay and target coordinates
- BallSpeed : speed of the ball, in mps.
- MaxHeight : maximum height in meters attained by the golf ball in the trajectory.
- Carry : the distance in meters till the first bounce.
- CarryActual : the actual carry distance based on the ground height layout.
- CarrySide: the side distance of the first ball landing.
- CarrySideActual: the side distance of the first ball landing based on the ground height layout.
- LaunchAngle: launch angle of the hit, in degrees.
- LaunchDirection : launch direction according to the target, in degrees.
- TargetDistance : distance of the postion where ball stopped from the target.
- LastData : value in meters when the last position of the ball was tracked.
- ReducedAccuracy : set of strings explaining which fields are less accurate.
- BallTrajectory : set of trajectory data since the ball flight start till it stopped bouncing few times.
- Kind : type of the golf ball trajectory either 'flight', 'bounce' or 'roll'
- XFit : trajectory x points in polynomial form
- YFit : trajectory y points in polynomial form
- ZFit : trajectory z points in polynomial form
- TimeInterval : start and end time interval for the given trajectory points, for carry
- ValidTimeInterval : start and end time interval of the trajectory that is valid for drawing trajectory, subect to level of the ground
- MeasuredTimeInterval : start and end time interval the ball trajectory was tracked
- SiteMeasurement : Ball flight measurement in the site (driving range) reference coordinates. Structure is same as Measurement (in bay coordinates)
- ProBallMeasurement : Ball flight measurement for pro ball (reference) conditions in the site (driving range) reference coordinates. Structure is same as Measurement (in bay coordinates) with addition of below fields
- HangTime : total time in seconds the ball was in flight
{ "Id": "2f6cd54b-e7a3-49bd-be1c-91c49998e74d", "Type": "Measurement", "SubType": "Measurement", "Payload": { "Id": "2f6cd54b-e7a3-49bd-be1c-91c49998e74d", "Measurement": { "MessageId": "2f6cd54b-e7a3-49bd-be1c-91c49998e74d", "BallSpeed": 50.7977, "MaxHeight": 32.129, "Carry": 139.983, "CarryActual": 137.983, "Total": 139.983, "LaunchAngle": 21.985, "LastData": 4.812, "LaunchDirection": 0, "TargetDistance" : 3.6777, "CarrySide": -9.644209665578169, "CarrySideActual": -9.2, "TotalSide": -9.644209665578169, "ReducedAccuracy": [ "SpinAxis", "SpinRate" ], "BallTrajectory": [ { "Kind": "Flight", "XFit": [ -0.728766922316, 47.214487841087, -10.608709296641, 2.242573023016, -0.31194448467, 0.02534731012, -0.000875865189 ], "YFit": [ 1, 19.2014, -1.33392, -0.877253, 0.164626, -0.0142685, 0.000477911 ], "ZFit": [ 9.026012340615, 0.469093862595, -1.223352684128, 0.353903575522, -0.061796893354, 0.006063647946, -0.000250930698 ], "TimeInterval": [ 0, 6.1203 ], "MeasuredTimeInterval": [ 0, 0.096256 ], "ValidTimeInterval": [ 0, 6.1203 ] } ], "BallVelocity": [ 47.179, 19.2014, 1.88941 ], "Time": "2017-04-11T07:46:36.4840678Z", "Kind": "Measurement" }, "SiteMeasurement": { "MessageId": "2f6cd54b-e7a3-49bd-be1c-91c49998e74d", "BallSpeed": 50.7977, "MaxHeight": 32.129, "Carry": 139.983, "CarryActual": 137.983, "Total": 139.983, "LaunchAngle": 21.985, "LastData": 4.812, "LaunchDirection": 2.309, "TargetDistance" : 1.6777, "CarrySide": -5.438273079175947, "CarrySide": -5.12, "TotalSide": -5.438273079175947, "ReducedAccuracy": [ "SpinAxis", "SpinRate" ], "BallTrajectory": [ { "Kind": "Flight", "XFit": [ -1, 47.179, -10.5671, 2.23091, -0.309944, 0.0251534, -0.000867919 ], "YFit": [ 1, 19.2014, -1.33392, -0.877253, 0.164626, -0.0142685, 0.000477911 ], "ZFit": [ 9, 1.88941, -1.54198, 0.421215, -0.0711543, 0.00682352, -0.000277169 ], "TimeInterval": [ 0, 6.1203 ], "MeasuredTimeInterval": [ 0, 0.096256 ], "ValidTimeInterval": [ 0, 6.1203 ] } ], "BallVelocity": [ 47.179, 19.2014, 1.88941 ], "Time": "2017-04-11T07:46:36.4840678Z", "Kind": "Measurement" }, "ProBallMeasurement": { "HangTime": 6.111389770507727, "MessageId": "2f6cd54b-e7a3-49bd-be1c-91c49998e74d", "BallSpeed": 50.7977, "MaxHeight": 32.129, "Carry": 139.983, "CarryActual": 135.983, "Total": 139.983, "LaunchAngle": 21.985, "LaunchDirection": 2.309, "TargetDistance" : 0.9777, "CarrySide": -5.438273079175947, "CarrySideActual": -5.14, "TotalSide": -5.438273079175947, "BallTrajectory": [ { "Kind": "Flight", "XFit": [ -0.003534057521, 47.195227468183, -10.219277942122, 2.074241280477, -0.277107233246, 0.021682118273, -0.000719015632 ], "YFit": [ -0.016348517754, 19.195805333423, -1.49820799109, -0.784423994666, 0.141647770626, -0.011495219012, 0.000347728703 ], "ZFit": [ -0.002778303652, 1.915151347011, 0.926556680829, -0.300144311688, 0.054957803582, -0.005548251996, 0.000234989363 ], "TimeInterval": [ 0, 6.111389770508 ], "MeasuredTimeInterval": [ 0, 6.111389770508 ], "ValidTimeInterval": [ 0, 6.111389770508 ] } ], "Time": "2017-04-11T07:46:36.4840678Z" }, "#Type": "Measurement", "BayId": "f7eec192-a8dc-4fa3-b7d2-3744f444fcdf", "BayName": "Dynaic Bay7:46 AM", "BayPosition": [ -1, 1, 9 ], "TeePosition": [ -1, 1, 9 ], "Time": "2017-04-11T07:46:36.4840678Z", "Club": "", "CreatedAt": "2017-04-11T07:46:36.5512851Z", "LastUpdatedAt": "2017-04-11T07:46:36.5512851Z" }, "Time": "2017-04-11T07:46:36.4840678Z" }
Note
The SiteMeasurement and Measurement values are same in above example but those will be different based on selected bay and target.
The fields mentioned in the reducedAccuracy set are approximate. It is recommended to not display these fields on UI.
The ball trajectory is given in polynomial form so as to reduce the data packet size for the final measurement. Client application has to expand this polynomial as a function of time so as the get the trajectory points. Refer to the sample code below.
Note
If the target is selected, the CarrySideActual, Launch Direction should be displayed from the Measurement
container.
Note
TargetDistance
Use this value to indicate the disatnce of the ball position where it stopped to the selected target. This is irrelevant if target is not selected.
4. Live Apex¶
This is received when the balls max height information is detected. It will be sent between the live measurement packages. It may be earlier than reaching the max height.
This message only contains the maximum height information.
- Id : unique id of the measurement message. Used to distinguish the golf ball hit.
- Type : for launch messages it is set to
Measurement
- SubType : This is set to
LiveApex
- Time : time stamp when the ball was hit.
- Payload : Apex mesurement data. It contains below fields
- BayId : the bay id from where the shot was hit.
- BayName : bay name
- Club : club information, ideally same as retrieved from
getClubs()
API - Measurement : This contains only the ball maximum height information
- MaxHeight : maximum height in meters attained by the golf ball in the trajectory.
- Kind : this is set to
LiveApex
{ "Id": "308f0436-2fef-442c-a98d-82013df36429", "Type": "Measurement", "SubType": "LiveApex", "Payload": { "Measurement": { "MessageId": "308f0436-2fef-442c-a98d-82013df36429", "MaxHeight": 15.16, "Time": "2017-03-17T09:23:58.7706749Z", "Kind": "LiveApex" }, "BayId": "1c6aaed7-ae22-48d4-a251-63caf6727531", "BayName": "7", "Club": "", "Id": "308f0436-2fef-442c-a98d-82013df36429" }, "Time": "2017-03-17T09:23:58.7706749Z" }
5. Sample Code¶
Below is a sample code to expand the ball trajectory set into points for the final measurement. This is a sample in java script. This function returns the x, y and z points along with the total time.
createTrajectory(trajectory) { var x = [] var y = [] var z = [] let totalTime = 0; for (var i = 0; i < trajectory.length; i++) { var t = trajectory[i]; var tStart = t.TimeInterval[0]; var tEnd = t.TimeInterval[1]; var tInterval = 0.1; x.push(this.polynomialExpand(t.XFit, tStart, tEnd, tInterval)); z.push(this.polynomialExpand(t.ZFit, tStart, tEnd, tInterval)); if (t.YFit) { y.push(this.polynomialExpand(t.YFit, tStart, tEnd, tInterval)); } else { y.push(this.polynomialExpand([0], tStart, tEnd, tInterval)); } totalTime = tEnd; } x = this.flatten(x); y = this.flatten(y); z = this.flatten(z); return [x, y, z, totalTime]; } polynomialExpand(p, t0, t1, ti) { var result = [] for (var t = t0; t < t1; t += ti) { result.push(this.polynomialEval(p, t)); } result.push(this.polynomialEval(p, t1)); return result; } polynomialEval(p, x) { var c = p.length; var y = p[c - 1]; for (var i = 1; i < c; i++) { y = p[c - 1 - i] + y * x; } return y; } flatten(array) { return $.map(array, function (n) { return n; }); }
Note
The final measurement may be received a little earlier than the actual golf ball flight completion. So drawing of the final trajectory can be delayed in time till the time interval on the trajectory data is completed from the beginning of the ball flight.