Overview

The purpose of this document is to describe the APIs used to interface with AdHawk’s Eye Tracking module. Communication with the AdHawk Eye Tracking module can be accomplished via:
  1. AdHawk API Communication Protocol
  2. C SDK, which is built on top of the communication protocol and communicates with the device directly over USB or SPI.
C SDK via USB or SPI
  1. Python SDK, which is built on top of the communication protocol, but proxies commands through the AdHawk Backend Service. The C SDK can also be set up to proxy commands in this fashion. The advantage of running in this mode is that multiple apps can be run at the same time.
Python or C SDK via Backend

Communication Protocol

The communication packets consist of a packet type followed by zero or more data bytes:
Byte Type Description
0 uint8 The packet type
1… Payload
  • The length of payload is variable depending on the packet type
  • All values are stored in little endian (least significant byte first)

Control Interface

The control interface provides the ability to interact with AdHawk’s Eye Tracking module. The client/host initiates a command over the control interface by sending a request packet. The Control Packets section describes the list of available commands that the client/host can request over the control interface. A request to the control interface may take up to 8 seconds to complete. All requests to the control interface will receive a response, either containing the requested information, or containing the result of the request. The clients should only issue one request at a time. The responses that contain the result of the request consist of a 1-byte integer, where 0 indicates no error and successful execution of the requested command, and a non-zero value denotes the nature of error encountered while servicing the request. See the return codes section for details.

Stream Interface

AdHawk’s Eye Tracking module streams status and tracking data. Some streams like the tracker ready signal is always broadcasted. Other streams, such as the gaze vector stream, must be subscribed to.

Backend Service

The AdHawk Backend Service is the PC host component that communicates with AdHawk’s eye tracking hardware over USB, and allows multiple clients to interact with and receive data from the eye tracking module. In order to support multiple clients simultaneously, all communications between clients and the Backend Service is performed using UDP sockets. There are two sockets: control and data. The control socket is constant, and is configured to 11032. The backend service is always listening on the control socket for client requests, and the responses to those requests are sent back to the source UDP port that was specified in the request packet. The data socket is used to stream periodic eye tracking data to clients. Each client specifies its data port by sending a register endpoint packet to the control socket. The client data port may be the same as its control data port if desired.

Getting Started

Installation

Python SDK

pip install adhawk_py_sdk-<version>.tar.gz

C SDK

Refer to the README.md in the C SDK package

Setting up Communication

If communicating with the AdHawk Backend Service, a communication channel must be established over UDP. Start by registering as an endpoint by sending the register endpoint packet with the UDP port of the peer. If using the Python SDK, this is handled by the FrontendApi and can be accomplished as follows:
import adhawkapi
import adhawkapi.frontend

def on_connect():
    print('Connected to AdHawk Backend Service')

def on_disconnect():
    print('Disconnected from AdHawk Backend Service')

api = adhawkapi.frontend.FrontendApi()
api.start(connect_cb=on_connect, disconnect_cb=on_disconnect)
...
# Terminate communication
api.shutdown()
The C SDK only requires the AdHawk Backend Service when running in UDP mode. The USB and SPI modes communicate directly with the device and do not require the AdHawk Backend Service. The API initialization call will take care of all setup required depending on the specified mode. See ah_com.h for details on how to connect in different modes
ah_api_init(params)

Auto-Tune

To tune the device, send the trigger autotune packet while the user is looking straight ahead. The response indicates whether the Auto-Tune procedure was successful.
C
ah_api_runAutotune();
Python
api.trigger_autotune()

Calibrate

Once the tracker ready signal is received or get tracker status returns success, the device is ready to be calibrated. Calibration is the process of mapping the eye tracking signal to an individual’s visual axis, which makes the eye tracking output meaningful for typical applications. To initiate the calibration procedure send a calibration start packet. The calibration procedure consists of the collection of a set of X, Y, Z gaze references. The gaze references are collected by instructing the user to look at a prescribed point and signaling the registration of the calibration data point through a register calibration point packet. When registering a calibration data point, the client must instruct AdHawk’s eye-tracking module of the user’s expected gaze during the collection of the calibration point. The expected gaze is specified in the payload of the Register calibration data point packet. Note that a response of ‘Left Eye Not Found’ or ‘Right Eye Not Found’ can be treated as a warning in binocular operation, but ‘Eyes Not Found’ is an error. After collecting the data points, send the calibration complete packet to indicate that no further points will be collected and that a new calibration should be generated. Once the calibration complete packet is received the eye-tracking module will compute the calibration coefficients based on the correspondence of sensor data and gaze references. The AdHawk’s eye-tracking module will respond with a zero (0) return code for successful calibration, and a non-zero value if calibration fails. See the return codes section for details. If calibration is successful, the device is capable of streaming the gaze vector stream and the pupil position stream.
C
ah_api_calibrationStart();
for (unsigned i = 0; i < num_points; i++)
{
    float x, y, z;
    // As the eye moves and fixates on each point on the screen,
    // register the position of the point
    // get_reference_point(&x, &y, &z);
    ah_api_calibrationRegisterPoint(x, y, z);
}
ah_api_calibrationComplete();
Python

def grid_points(nrows, ncols, xrange=20, yrange=12.5, xoffset=0, yoffset=2.5):
    '''Generates a grid of points based on range and number of rows/cols'''
    zpos = -0.6  # typically 60cm to screen
    # calculate x and y range for a xrange x yrange degree calibration window
    xmin, xmax = np.tan(np.deg2rad([xoffset - xrange, xoffset + xrange])) * np.abs(zpos)
    ymin, ymax = np.tan(np.deg2rad([yoffset - yrange, yoffset + yrange])) * np.abs(zpos)

    cal_points = []
    for ypos in np.linspace(ymin, ymax, nrows):
        for xpos in np.linspace(xmin, xmax, ncols):
            cal_points.append((xpos, ypos, zpos))

    print(f'grid_points(): generated {nrows}x{ncols} points'
          f' {xrange}x{yrange} deg box at {zpos}: {cal_points}')

    return cal_points

npoints = 9
nrows = int(np.sqrt(npts))
reference_points = grid_points(nrows, nrows)

api.start_calibration()
for point in reference_points:
    # As the eye moves and fixates on each point on the screen,
    # register the position of the point
    api.register_calibration_point(*point)
api.stop_calibration()

Enable data streams

Once the device is calibrated, to start receiving eye tracking data from the device, send a set stream control packet with the stream you want to enable and the rate at which you want to enable it. See Supported rates. At this point, the device will start streaming packets to the registered endpoint. The format of the streamed packets are listed in the Data Streams section.
C
static void gazeDataCallback(void *data)
{
    ah_gazeStreamData *gaze = data;
}

ah_api_setupStream(ah_streamType_Gaze, ah_streamRate_60Hz, gazeDataCallback);
Python
def handler(*data):
    timestamp, xpos, ypos, zpos, vergence = data

api.register_stream_handler(adhawkapi.PacketType.EXTENDED_GAZE, gaze_handler)
api.set_stream_control(adhawkapi.PacketType.EXTENDED_GAZE, 60)

Saving Calibrations

Once a device has been calibrated, the calibration coefficients can be saved using the blobs framework. The blobs framework allows saving and restoring run-time configuration objects of the eye-tracking module. Send a save blob packet with the blob type set to 1 (gaze calibration data). If the blob was saved successfully, a unique 32-bit identifier is returned in the response packet. The calibration can later be loaded by sending a load blob packet with this ID in the payload.
C
ah_api_calibrationSave();
Python > Only supported when using the AdHawk Backend Service
errcode, blob_id = api.save_blob(adhawkapi.BlobType.CALIBRATION)

API Reference

Control Packets

Calibration start [0x81]

A calibration start command packet will instruct AdHawk’s eye-tracking module to reset the calibration table and prepare for a new calibration procedure.
API
Byte Type Description
Request 0 uint8 0x81
Response 0 uint8 0x81
1 uint8 Return code
C
ah_result ah_api_calibrationStart(void);
Python
api.start_calibration()

Calibration complete [0x82]

A calibration complete command will instruct AdHawk’s eye-tracking module that no further points will be collected and that a new calibration should be generated. Once the Calibration complete packet is received the eye-tracking module will compute the calibration coefficients based on the correspondence of sensor data and gaze references. The AdHawk’s eye-tracking module will respond with a zero (0) return code for successful calibration, and a non-zero value if calibration fails.
API
Byte Type Description
Request 0 uint8 0x82
Response 0 uint8 0x82
1 uint8 Return code
C
ah_result ah_api_calibrationComplete(void);
Python
api.stop_calibration()

Calibration abort [0x83]

A calibration abort packet will instruct AdHawk’s eye-tracking module to discard all collected data for the new calibration, and restores the previous calibration.
API
Byte Type Description
Request 0 uint8 0x83
Response 0 uint8 0x83
1 uint8 Return code
C
ah_result ah_api_calibrationAbort(void);
Python
api.abort_calibration()

Register calibration point [0x84]

Once a target gaze point is established and the user is instructed to direct their gaze at the target, a calibration data point may be registered. Registering a data point requires the client to instruct the eye-tracking module of the intended gaze target such that a correspondence can be established between the user’s gaze and the sensor data. AdHawk’s eye-tracking module will respond with a zero (0) return code if the calibration point is successfully registered. Otherwise, a non-zero payload will be returned indicating that a correspondence between the user’s gaze and sensor data could not be established. X, Y and Z is the position of the point relative to the midpoint of the scanners. See AdHawk Coordinate System for details.
API
Byte Type Description
Request 0 uint8 0x84
1-4 float32 X position in meters
5-8 float32 Y position in meters
9-12 float32 Z position in meters
Response 0 uint8 0x84
1 uint8 Return code
C
ah_result ah_api_calibrationRegisterPoint(float xPos, float yPos, float zPos);
Python
api.register_calibration_point(0.0, -0.179, -0.6)

Trigger Autotune [0x85]

When trigger scanner ranging is signaled, the eye-tracking module will perform an auto-tune function on all attached trackers. The eye-tracking module will respond with a zero (0) to indicate that scanner ranging successfully completed on both eyes. Otherwise, a non-zero payload will indicate which eye encountered a failure.
API
Byte Type Description
Request 0 uint8 0x85
Response 0 uint8 0x85
1 uint8 Return code
C
ah_result ah_api_runAutotune(void);
Python
api.trigger_autotune()

Re-center calibration [0x8f]

Updates an existing calibration based on the specified calibration point. The payload of the calibration data point indicates the position of the gaze target. X, Y and Z is the position of the point relative to the midpoint of the scanners. See AdHawk Coordinate System for details.
API
Byte Type Description
Request 0 uint8 0x8f
1-4 float32 X position in meters
5-8 float32 Y position in meters
9-12 float32 Z position in meters
Response 0 uint8 0x8f
1 uint8 Return code
Python
api.recenter_calibration(0.0, -0.179, -0.6)

Get tracker status [0x90]

Retrieves the current state of the eye-tracking module. A response value of zero (0) indicates that the tracker is calibrated and fully working.
API
Byte Type Description
Request 0 uint8 0x90
Response 0 uint8 0x90
1 uint8 Return code
C
ah_result ah_api_getTrackerStatus(void);
Python
api.get_tracker_status()

Run-time configuration objects (blobs)

The C SDK simplifies the use of blobs. The can be read / written to with the following APIs:
C
ah_result ah_api_readBlob(ah_blobType blobType, uint8_t **blobData, uint16_t *blobSize);

ah_result ah_api_writeBlob(ah_blobType blobType, uint8_t *blobData, uint16_t blobSize);
These functions use the appropriate commands detailed below.

Blob size [0x92]

Retrieves a run-time configuration object from the eye tracking module. The client/host should get the size of the configuration object using get blob size command, and allocate the required buffer size to store the configuration content. Then, the client/host can get the blob data in chunks of max 25 bytes using the get blob data command until the entire configuration object is retrieved.

Get blob size

API
Byte Type Description
Request 0 uint8 0x92
1 uint8 Blob type
Response 0 uint8 0x92
1 uint8 Return code
2-3 uint16 The size of the blob
Python
errcode, blob_size = api.get_blob_size()

Set blob size

API
Byte Type Description
Request 0 uint8 0x92
1 uint8 Blob type
2-3 uint16 The size of the blob being written
Response 0 uint8 0x92
1 uint8 Return code
Python
api.set_blob_size(adhawkapi.BlobType.CALIBRATION, len(blob_data))

Blob data [0x93]

Applies a run-time configuration object to the eye tracking module. The client/host should set the size of the configuration object using the set blob size command. This will cause the eye tracking module to allocate the required buffer size to store the configuration content.Then the client/host can set the blob data in chunks of max 25 bytes using the set blob data command until the entire configuration object is written.

Get blob data

API
Byte Type Description
Request 0 uint8 0x93
1 uint8 Blob type
2-3 uint16 The byte offset
Response 0 uint8 0x93
1 uint8 Return code
2.. Blob data (max 25 bytes)
Python
blob_type = adhawkapi.BlobType.CALIBRATION
_, size = api.get_blob_size(blob_type)
data = [None] * size
offset = 0

while offset <= size:
    _, chunk = api.get_blob_data(blob_type, offset)
    chunk_size = len(chunk)
    data[offset:offset + chunk_size] = chunk
    offset = offset + chunk_size
print(bytes(data))

Set blob data

API
Byte Type Description
Request 0 uint8 0x93
1 uint8 Blob type
2-3 uint16 The byte offset
4.. Blob data (max 25 bytes)
Response 0 uint8 0x93
1 uint8 Return code
Python
def chunks(data):
    '''Generator that breaks the data into chunks'''
    size = len(data)
    offset = 0
    chunk_len = adhawkapi.defaults.BLOB_CHUNK_LEN
    while (offset + chunk_len) <= size:
        yield offset, data[offset:offset + chunk_len]
        offset = offset + chunk_len
    yield offset, data[offset:]


blob_type = adhawkapi.BlobType.CALIBRATION
for offset, chunk in chunks(data):
    api.set_blob_data(blob_type, offset, chunk)

Load blob [0x94]

Applies a run-time configuration object to the eye tracking module. This is similar to writing a blob, except the data for the blob was previously saved to disk in the AdHawk Backend folder under cache as blob_.bin
Only supported when using the AdHawk Backend Service
API
Byte Type Description
Request 0 uint8 0x94
1 uint8 Blob type
2-5 uint32 ID of the blob to load
Response 0 uint8 0x94
1 uint8 Return code
Python
# Loading a calibration blob that was previously saved under cache/blob_1241123630.bin
api.load_blob(adhawkapi.BlobType.CALIBRATION, 1241123630)

Save blob [0x95]

Retrieves and saves a run-time configuration object from the eye tracking module. This is similar to reading a blob, except that the blob data is stored within the eye tracking module to disk in the AdHawk Backend folder under cache as blob_.bin, and the 32-bit unique identifier is returned to the clients for later use.
Only supported when using the AdHawk Backend Service
API
Byte Type Description
Request 0 uint8 0x95
1 uint8 Blob type
Response 0 uint8 0x95
1 uint8 Return code
2-5 uint32 ID of the saved blob
Python
errcode, blob_id = api.save_blob(adhawkapi.BlobType.CALIBRATION)

Properties

Get autotune position [0x9a, 0x01]

Get the center of the scan range. The returned values will be non-zero only if a trigger autotune command completed successfully or if the values were manually set through set autotune position In the case of monocular operation, 0xFFFF will be returned for the X mean and Y mean of the inactive eye
API
Byte Type Description
Request 0 uint8 0x9a
1 uint8 0x01
Response 0 uint8 0x9a
1 uint8 Return code
2 uint8 0x01
3-4 uint16 X mean (right eye), valid range is 0 – 100
5-6 uint16 Y mean (right eye), valid range is 0 – 100
7-8 uint16 X mean (left eye), valid range is 0 – 100
9-10 uint16 Y mean (left eye), valid range is 0 – 100
C
ah_result ah_api_getAutotunePosition(ah_autotunePosition pos[AH_NUM_EYES]);
Python
right_xmean, right_ymean, left_xmean, left_ymean = api.get_autotune_position()[2:]

Set autotune position [0x9b, 0x01]

Set the center of the scan range.
API
Byte Type Description
Request 0 uint8 0x9b
1 uint8 0x01
2-3 uint16 X mean (right eye), valid range is 0 – 100
4-5 uint16 Y mean (right eye), valid range is 0 – 100
6-7 uint16 X mean (left eye), valid range is 0 – 100
7-8 uint16 Y mean (left eye), valid range is 0 – 100
Response 0 uint8 0x9b
1 uint8 Return code
2 uint8 0x01
C
ah_result ah_api_setAutotunePosition(const ah_autotunePosition pos[AH_NUM_EYES]);
Python
api.set_autotune_position(right_xmean, right_ymean, left_xmean, left_ymean)

Set stream control [0x9b, 0x02]

Control the rate of a data stream. Setting the rate to 0 disables the stream.
API
Byte Type Description
Request 0 uint8 0x9b
1 uint8 0x02
2-5 uint32 Stream control bitmask
6-9 float32 Stream rate in Hz. A value of 0 will disable the stream. See Supported rates
Response 0 uint8 0x9b
1 uint8 Return code
2 uint8 0x02
Example: Sending 0x9b, 0x02, 1 << 3, 60 enables the gaze stream and sets its rate to 60Hz. Sending 0x9b, 0x02, 1 << 3, 0 disables the gaze stream.
C
ah_result ah_api_setupStream(ah_streamType type, ah_streamRate rate, ah_streamCallback dataCb);
Python
api.set_stream_control(adhawkapi.PacketType.EXTENDED_GAZE, 60)

Get stream control [0x9a, 0x02]

Get the current rate of a data stream
API
Byte Type Description
Request 0 uint8 0x9a
1 uint8 0x02
0-3 uint32 Stream control bitmask (Only a single stream is allowed)
Response 0 uint8 0x9a
1 uint8 Return code
2 uint8 0x02
3-6 float Stream rate in Hz
Example: Sending 0x9a, 0x02, 1 << 3 will return 0x9a, 0x0, 0x2, 60 indicating that the rate for the gaze stream is currently 60 Hz.
C
ah_result ah_api_getStreamRate(ah_streamType type, ah_streamRate *streamRate);
Python
stream_rate = api.get_stream_control(adhawkapi.PacketType.EXTENDED_GAZE)[2]

Get component offsets [0x9a, 0x04]

Get the currently configured component offsets. Component offsets can be used if the scanners are not in their nominal position. The offset is the position of the scanner relative to its nominal position. See AdHawk Coordinate System for details.
API
Byte Type Description
Request 0 uint8 0x9a
1 uint8 0x04
Response 0 uint8 0x9a
1 uint8 Return code
2 uint8 0x04
3-6 float right eye component offset x in millimeters
7-10 float right eye component offset y in millimeters
11-14 float right eye component offset z in millimeters
15-18 float left eye component offset x in millimeters
19-22 float left eye component offset y in millimeters
23-26 float left eye component offset z in millimeters
Python
rx, ry, rz, lx, ly, lz = api.get_component_offsets()[2:]

Set component offsets [0x9b, 0x04]

Configure the component offsets. Component offsets can be used if the scanners are not in their nominal position. The offset is the position of the scanner relative to its nominal position. See AdHawk Coordinate System for details.
API
Byte Type Description
Request 0 uint8 0x9a
1 uint8 0x04
Response 0 uint8 0x9a
1 uint8 Return code
2 uint8 0x04
3-6 float right eye component offset x in millimeters
7-10 float right eye component offset y in millimeters
11-14 float right eye component offset z in millimeters
15-18 float left eye component offset x in millimeters
19-22 float left eye component offset y in millimeters
23-26 float left eye component offset z in millimeters
Python
api.set_component_offsets(rx, ry, rz, lx, ly, lz)

System Control

Enable / Disable Eye Tracking [0x9c, 0x01]

Either enable or disable eye tracking
API
Byte Type Description
Request 0 uint8 0x9c
1 uint8 0x01
2 uint8 0 to disable eye tracking, 1 to enable eye tracking
Response 0 uint8 0x9c
1 uint8 Return code
2 uint8 0x01
C
ah_result ah_api_enableTracking(bool enable);
Python
api.enable_tracking(True)

Device Setup Procedures

Trigger Device Calibration [0xb0, 0x01]

Begin a device calibration, which runs on all active trackers and restores tuning configurations to factory values. A response value of zero (0) indicates that the calibration has started successfully.
Only supported when using the AdHawk Backend Service
API
Byte Type Description
Request 0 uint8 0xb0
1 uint8 0x01
Response 0 uint8 0xb0
1 uint8 Return code
2 uint8 0x01
Python
api.trigger_device_calibration()

Get Device Calibration Status [0xb1, 0x01]

Retrieves the state of the current device calibration. If the calibration has not encountered an error, the returned value is an integer which indicates the progress of the current calibration, ranging from [0, 100], where 100 indicates the calibration has completed successfully.
Only supported when using the AdHawk Backend Service
API
Byte Type Description
Request 0 uint8 0xb1
1 uint8 0x01
Response 0 uint8 0xb1
1 uint8 Return code
2 uint8 0x01
3 uint8 progress percentage
Python
errcode, _, status = api.get_device_calibration_status()

Trigger Update Firmware [0xb0, 0x02]

Begin a firmware update. A response value of zero (0) indicates that the update has started successfully.
Only supported when using the AdHawk Backend Service
API
Byte Type Description
Request 0 uint8 0xb0
1 uint8 0x02
Response 0 uint8 0xb0
1 uint8 Return code
2 uint8 0x02
Python
api.trigger_update_firmware()

Get Update Firmware Status [0xb1, 0x02]

Retrieves the state of the current firmware update. If the update has not encountered an error, the returned value is an integer which indicates the progress of the update, ranging from [0, 100], where 100 indicates the update has completed successfully.
Only supported when using the AdHawk Backend Service
API
Byte Type Description
Request 0 uint8 0xb1
1 uint8 0x02
Response 0 uint8 0xb1
1 uint8 Return code
2 uint8 0x02
3 uint8 progress percentage
Python
errcode, _, status = api.get_update_firmware_status()

Backend service communication

Register endpoint [0xc0]

Register as an endpoint to start communication with the AdHawk Backend Service.
API
Byte Type Description
Request 0 uint8 0xc0
1 uint32 The UDP port of the peer
Response 0 uint8 0xc0
1 uint8 Return code
PythonThe packet construction is handled within the start() function of the frontendApi()
def on_connect():
    print('Connected to AdHawk Backend Service')

def on_disconnect():
    print('Disconnected from AdHawk Backend Service')

api.start(connect_cb=on_connect, disconnect_cb=on_disconnect)

Deregister endpoint [0xc2]

Deregister as an endpoint to stop communication with the AdHawk Backend Service
API
Byte Type Description
Request 0 uint8 0xc2
Response 0 uint8 0xc2
1 uint8 Return code
Python
api.shutdown()

Ping endpoint [0xc5]

Must be used to ping the AdHawk backend service to indicate that the frontend is still alive, and to verify that the backend service is still reachable. Should be sent every 2s. This is automatically handled within the Python and C SDKs.
API
Byte Type Description
Request 0 uint8 0xc5
Response 0 uint8 0xc5
1 uint8 Return code
Python
The disconnect_cb passed into start is executed if the pings aren’t successful

Data Streams

Tracker ready [0x02]

The tracker ready packet type is an asynchronous status packet that is transmitted by AdHawk’s eye-tracking module when the system is ready to receive calibration commands. Once the tracker ready signal packet is received, the client/host system may go through a calibration process (send Calibration start, followed by Register calibration data point, and finally Calibration complete).
Byte Type Description
Stream 0 uint8 0x02

Gaze vector stream [0x03]

X, Y and Z are the estimated coordinates of the user’s gaze point relative to the midpoint of the scanners. Vergence is the angle between left and right eye gaze vectors. See AdHawk Coordinate System for details.
API
Byte Type Description
Stream 0 uint8 0x03
1-4 float32 Timestamp since system start in seconds
5-8 float32 X position in meters
9-12 float32 Y position in meters
13-16 float32 Z position in meters
17-20 float32 Vergence Angle in radians
C
typedef struct
{
    float xPos;
    float yPos;
    float zPos;
} ah_gazeData;
typedef struct __attribute__((__packed__))
{
    float timestamp;
    ah_gazeData gaze;
    float vergence;
} ah_gazeStreamData;
Python
def handler(*data):
    timestamp, xpos, ypos, zpos, vergence = data

api.register_stream_handler(adhawkapi.PacketType.EXTENDED_GAZE, handler)

Pupil position stream [0x04]

X, Y and Z are coordinates of the pupil relative to the point between the center of the two (left and right) scanners. See AdHawk Coordinate System for details.
API

Binocular

Byte Type Description
Stream 0 uint8 0x04
1-4 float32 Timestamp since system start in seconds
5-8 float32 X position of right pupil in millimeters
9-12 float32 Y position of right pupil in millimeters
13-16 float32 Z position of right pupil in millimeters
17-20 float32 X position of left pupil in millimeters
21-24 float32 Y position of left pupil in millimeters
25-28 float32 Z position of left pupil in millimeters

Monocular

Byte Type Description
Stream 0 uint8 0x04
1-4 float32 Timestamp since system start in seconds
5-8 float32 X position of active pupil in millimeters
9-12 float32 Y position of active pupil in millimeters
13-16 float32 Z position of active pupil in millimeters
C
typedef struct
{
    float x;
    float y;
    float z;
} ah_pupilPositionData;
typedef struct __attribute__((__packed__))
{
    float timestamp;
    ah_pupilPositionData pos[AH_NUM_EYES];
} ah_pupilPositionStreamData;
Python
# Binocular
def handler(*data):
    timestamp, rx, ry, rz, lx, ly, lz = data

api.register_stream_handler(adhawkapi.PacketType.PUPIL_POSITION, handler)
# Monocular
def handler(*data):
    timestamp, x, y, z = data

api.register_stream_handler(adhawkapi.PacketType.PUPIL_POSITION, handler)

Pupil diameter stream [0x05]

The stream indicating the diameter of the pupil in millimeters
API

Binocular

Byte Type Description
Stream 0 uint8 0x04
1-4 float32 Timestamp since system start in seconds
5-8 float32 Diameter of right pupil in millimeters
9-12 float32 Diameter of left pupil in millimeters

Monocular

Byte Type Description
Stream 0 uint8 0x04
1-4 float32 Timestamp since system start in seconds
5-8 float32 Diameter of active pupil in millimeters
C
struct ah_pupilSizeStreamData
{
    float timestamp;
    float diameter[AH_NUM_EYES];
};
Python
# Binocular
def handler(*data):
    timestamp, right_pupil, left_pupil = data

api.register_stream_handler(adhawkapi.PacketType.PUPIL_DIAMETER, handler)
api.set_stream_control(adhawkapi.PacketType.PUPIL_DIAMETER, rate)
# Monocular
def handler(*data):
    timestamp, pupil_diameter = data

api.register_stream_handler(adhawkapi.PacketType.PUPIL_DIAMETER, handler)
api.set_stream_control(adhawkapi.PacketType.PUPIL_DIAMETER, rate)

Per-eye gaze vector stream [0x06]

X, Y and Z are the coordinates of a unit vector relative to the center of each eye. See AdHawk Coordinate System for details.
API

Binocular

Byte Type Description
Stream 0 uint8 0x06
1-4 float32 Timestamp since system start in seconds
5-8 float32 X component of right eye gaze unit vector
9-12 float32 Y component of right eye gaze unit vector
13-16 float32 Z component of right eye gaze unit vector
17-20 float32 X component of left eye gaze unit vector
21-24 float32 Y component of left eye gaze unit vector
25-28 float32 Z component of left eye gaze unit vector

Monocular

Byte Type Description
Stream 0 uint8 0x06
1-4 float32 Timestamp since system start in seconds
5-8 float32 X component of active eye gaze unit vector
9-12 float32 Y component of active eye gaze unit vector
13-16 float32 Z component of active eye gaze unit vector
C
typedef struct
{
    float xPos;
    float yPos;
    float zPos;
} ah_gazeData;
typedef struct __attribute__((__packed__))
{
    float timestamp;
    ah_gazeData gaze[AH_NUM_EYES];
} ah_gazeStreamData;
Python
# Binocular
def handler(*data):
    timestamp, rx, ry, rz, lx, ly, lz = data

api.register_stream_handler(adhawkapi.PacketType.PER_EYE_GAZE, handler)
# Monocular
def handler(*data):
    timestamp, x, y, z = data

api.register_stream_handler(adhawkapi.PacketType.PER_EYE_GAZE, handler)

IMU data stream [0x17]

API
Byte Type Description
Stream 0 uint8 0x17
1-4 float32 Timestamp since system start
5-8 float32 Gyro x (mdps)
9-12 float32 Gyro y (mdps)
13-16 float32 Gyro z (mdps)
17-20 float32 Accelerometer x (mg)
21-24 float32 Accelerometer y (mg)
25-28 float32 Accelerometer z (mg)
Python
def handler(*data):
    timestamp, gx, gy, gz, accel_x, accel_y, accel_z = data

api.register_stream_handler(adhawkapi.PacketType.IMU, handler)
api.set_stream_control(adhawkapi.PacketType.IMU, rate)

Types reference

Return codes

API
Response Description
0 Request successful
1 Internal failure
2 Invalid argument
3 Tracker not ready
4 No eyes detected
5 Right eye not detected
6 Left eye not detected
7 Not calibrated
8 Not supported
11 Request Timeout
15 System Busy
C
typedef enum
{
    ah_result_Success,
    ah_result_Failure,
    ah_result_InvalidArgument,
    ah_result_TrackerNotReady,
    ah_result_EyesNotFound,
    ah_result_RightEyeNotFound,
    ah_result_LeftEyeNotFound,
    ah_result_NotCalibrated,
    ah_result_NotSupported,
    ah_result_SessionAlreadyRunning,
    ah_result_NoCurrentSession,
    ah_result_RequestTimeout,
    ah_result_UnexpectedResponse,
} ah_result;
Python
class AckCodes(enum.IntEnum):
    '''List of acknowledgement payload values'''

    SUCCESS = 0
    FAILURE = 1
    INVALID_ARGUMENT = 2
    TRACKER_NOT_READY = 3
    EYES_NOT_FOUND = 4
    RIGHT_EYE_NOT_FOUND = 5
    LEFT_EYE_NOT_FOUND = 6
    NOT_CALIBRATED = 7
    NOT_SUPPORTED = 8
    SESSION_ALREADY_RUNNING = 9
    NO_CURRENT_SESSION = 10
    REQUEST_TIMEOUT = 11
    UNEXPECTED_RESPONSE = 12
    BUSY = 15

Stream Control Bitmask

API
Bit Stream Type
1 Pupil position
2 Pupil diameter
3 Gaze
4 Per Eye Gaze
31 IMU
C
typedef enum
{
    ah_streamType_Gaze,
    ah_streamType_PupilPosition,

    ah_streamType_Count
} ah_streamType;

Blob Type

API
Blob Type Description
1 Gaze calibration data
Python
class BlobType(enum.IntEnum):
    '''Enum representing set of blob types'''
    CALIBRATION = 1

Supported Rates

The current listed of supported stream rates are: 30, 60, 125, 200, 250, 333, 500
C
typedef enum
{
    ah_streamRate_Off,
    ah_streamRate_30Hz,
    ah_streamRate_60Hz,
    ah_streamRate_125Hz,
    ah_streamRate_200Hz,
    ah_streamRate_250Hz,
    ah_streamRate_333Hz,
    ah_streamRate_500Hz,

    ah_streamRate_Count,
} ah_streamRate;
Python
class StreamRates(enum.IntEnum):
    '''Enum representing the set of supported rates'''
    OFF = 0
    RATE_30 = 30
    RATE_60 = 60
    RATE_125 = 125
    RATE_200 = 200
    RATE_250 = 250
    RATE_333 = 333
    RATE_500 = 500

Extended Usage Notes

Python SDK

In the Python SDK, you can chose to make the API calls blocking or non-blocking. To perform a non-blocking operation, provide a callback function as a parameter to be executed when the operation is complete. This mode of operation is useful for GUI applications. If a callback function is not provided, the call blocks till a response is received and returns the response on success or raises an exception on failure.
# blocking operation
try:
    api.trigger_autotune()
except adhawkapi.APIRequestError as err:
    print(err.ackcode)
# non-blocking operation
def on_autotune_complete(errcode):
    if errcode == adhawkapi.AckCodes.SUCCESS:
        print('Autotune complete')
    else:
        print(f'Autotune failed: {adhawkapi.errormsg(response)}')

api.trigger_autotune(callback=on_autotune_complete)

AdHawk Coordinate System

Coordinate System
In the AdHawk coordinate system X, Y and Z are coordinates relative to a particular origin where:
  • X is oriented in the positive direction to the right (user’s point of view)
  • Y is oriented in the positive direction going up
  • Z is oriented in the positive direction when behind the user
The origin is specific to the stream or command and is the same whether operating in monocular or binocular mode. In general the origin is either:
  • The midpoint of the scanners
  • The cyclopean eye
  • The center of the eye
Origin
Stream Origin
Gaze Vector Midpoint of scanners
Pupil Position Midpoint of scanners
Per-Eye Gaze Vector Center of eye
Copyright 2021 AdHawk Microsystems Inc STRICTLY CONFIDENTIAL