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"
   }
}
Use the 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.

{
   "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
            ]
         }
      ]
   }
}
Use the points in the ballTrajectory array to draw the golf ball trajectory at given time.

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.