# JSON C++/Python SDK\_Quaternion Manual

## 1. Introduction

### 1.1. Feature

This SDK acquires quaternions of hand joints based on JSON transmission format and supports both Windows and Linux environments.

### 1.2. File Download

&#x20; The quaternion SDK is open sourced.

* Download address:&#x20;

{% embed url="<https://drive.google.com/file/d/1mnoH55MmZlCgUq9ygxWHymecEpj02iTc/view?usp=drive_link>" %}

### 1.3. HandDriver Settings

* Check "Data Transmission" to turn on the data transmission.
* To transmit IMU data (only supported by gloves with IMU), select the IMU option; otherwise, IMU data will not be transmitted.
* Select the FPS, which supports 120Hz, 90Hz, or 60Hz. The default FPS is 120Hz.
* Click the "+" icon in the target address field, then enter the IP address and port number of the receiving side to enable data transmission (input 127.0.0.1 for local target).
* **The port number defaults to 5555. If modified, please keep it consistent with the SDK side.**
* After configuration, click the "Apply" button to save.

#### 1.3.1. HandDriver 2.2.2 or Above

Please select JSON as the Format. <mark style="color:red;">**When using this SDK, choose "Quater" for the Content and do not check the Old Plugin.**</mark>

<figure><img src="https://2082502898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8s1Ia6TfFovgyJ5JsDJZ%2Fuploads%2F9EQ4l1Ib199rMMYChFWt%2Fimage.png?alt=media&#x26;token=8658bbc7-5416-4cf8-a702-607dc2029a6c" alt="" width="563"><figcaption></figcaption></figure>

#### 1.3.2. HandDriver 2.2.1. and Earlier

* Format: Euler, Quater, and VMC are three mutually exclusive options—choose only one. <mark style="color:red;">**When using this SDK, please select "Quater" (Select "SDK" in older versions of HD).**</mark>
* When "Old Plugin" is checked, angle values are transmitted according to versions prior to HandDriver 2.1.1. For details, [see here](https://udexreal.gitbook.io/udexreal-docs/glove-data-c++-python-sdk-for-robotics/hand-model-and-data-specification).

<figure><img src="https://2082502898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8s1Ia6TfFovgyJ5JsDJZ%2Fuploads%2F1330cM4VlxtWUIFPZSdq%2Fimage.png?alt=media&#x26;token=702882a1-ab6c-4fd0-8ef0-13f51a47afde" alt="" width="563"><figcaption></figcaption></figure>

## 2. Coordinate system and data definition

### 2.1. Coordinate system

The data sent by the HandDriver follows a right-hand coordinate system standard, with the blue Z-axis pointing upwards, as shown in below figure:

<figure><img src="https://2082502898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8s1Ia6TfFovgyJ5JsDJZ%2Fuploads%2FoZeVgDWy4QwkZPEcDnrr%2Fimage.png?alt=media&#x26;token=9193068e-3a13-41da-97ed-6a7dffa6ef84" alt="" width="216"><figcaption></figcaption></figure>

### 2.2. Data format

The data content includes Device ID, Frame index, Device name, Calibration status, Battery, IMU data, bones quaternion and controllers data, as shown in below figure.      **Note:** The quaternion order for **fingers** is **XYZW**, while for **IMU** it is **WXYZ**.

<figure><img src="https://2082502898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8s1Ia6TfFovgyJ5JsDJZ%2Fuploads%2FrI16TlL2aA8Q0J1x3PFg%2Fimage.png?alt=media&#x26;token=7b67db9c-8c75-4d47-b747-8cc8daa70e06" alt="" width="375"><figcaption></figcaption></figure>

<table><thead><tr><th width="276.5" align="center"></th><th align="center">Proximal</th><th align="center">Intermediate</th><th align="center">Distal</th></tr></thead><tbody><tr><td align="center"><strong>Index, Middle, Ring, Little Finger</strong></td><td align="center">MP</td><td align="center">PIP</td><td align="center">DIP</td></tr><tr><td align="center"><strong>Thumb</strong></td><td align="center">CM</td><td align="center">MP</td><td align="center">IP</td></tr></tbody></table>

{% code overflow="wrap" %}

```json
{
"DeviceID":0, //According to the HandDriver role list, the first role is "0", the second is "1", and so on
"FrameIndex":0,
"DeviceName":"UDXST0001L",
"CalibrationStatus":-1,//Uncalibrated -1, Fist 0, Fingers Straight&Together 1, Spread Fingers 2, Finish 3
"Battery":5,//Battery 1-5, max 5
"Bones":[
[1,1,1,1],//{"LeftindexProximal":[1,1,1,1]}
[1,1,1,1],//{"LeftindexIntermediate":[1,1,1,1]}
[1,1,1,1],//{"LeftindexDistal":[1,1,1,1]}
[1,1,1,1],//{"LeftMiddleProximal":[1,1,1,1]}
[1,1,1,1],//{"LeftMiddlelntermediate":[1,1,1,1]}
[1,1,1,1],//{"LeftMiddleDistal":[1,1,1,1]}
[1,1,1,1],//{"LeftRingProximal":[1,1,1,1]}
[1,1,1,1],//{"LeftRingIntermediate":[1,1,1,1]}
[1,1,1,1],//{"LeftRingDistal":[1,1,1,1]}
[1,1,1,1],//{"LeftLittleProximal":[1,1,1,1]}
[1,1,1,1],//{"LeftLittlelntermediate":[1,1,1,1]}
[1,1,1,1],//{"LeftLittleDistal":[1,1,1,1]}
[1,1,1,1],//{"LeftThumbProximal":[1,1,1,1]}
[1,1,1,1],//{"LeftThumbintermediate":[1,1,1,1]}
[1,1,1,1],//{"LeftThumbDistal":[1,1,1,1]}
[1,1,1,1],//{"IMU Data":[1,1,1,1]}
]
"joyX":0,
"joyY":0,
"aButton":false,
"bButton":false,
"joyButton":false,
"menu":false
}
```

{% endcode %}

## 3. Windows SDK Description

This DLL contains a GloveSDK class, which is used to create a separate receiving thread to receive and parse data sent by HandDriver.

### 3.1. Data structure definition

{% code overflow="wrap" %}

```cpp
struct HandDriverData
{
    int DeviceID=0;
    int FrameIndex=0;
    string DeviceName;
    int CalibrationStatus;
    int Battery;
    // 15 finger joints, each with 4 data points, 16th is for IMU data
    array<array<float, 4>, 16> JointDatas;
};

// This structure stores data for a pair of gloves, divided into L (left) and R (right)
struct PairGloveData
{
    HandDriverData HandData_L;
    HandDriverData HandData_R;
    bool bPrintData;
};
```

{% endcode %}

### 3.2. Data call

#### 3.2.1. Retrieve glove data

**3.2.1.1. Retrieve glove driver info**

The example of retrieving device information ([see Figure](#id-2.2.-data-format)), refer to this example to get other information about the device.

```cpp
//Get the device name on the left hand of device '0'
string deviceName = glovePtr->GloveData[0].HandData_L.DeviceName;

//Get the battery level on the left hand of device '0'
int battery = glovePtr->GloveData[0].HandData_L.Battery;
```

**3.2.1.2. Retrieve glove finger data**

The GloveSDK class has an array GloveData with a length of 8, and its format of PairGloveData, meaning it can store data for 8 pairs of gloves. The data is accessed via subscripts.For example: `GloveData[0].HandData_L.JointDatas[6]` (accesses the sixth joint data in the left-hand array of device 0. The data corresponding to `JointDatas[6]` is [shown in Figure](#id-2.2.-data-format).).

```cpp
auto a = glovePtr->GloveData[0].HandData_L.JointDatas[6];
```

#### 3.2.2. Quaternion to euler angle

Use `glovePtr->toEulerAngle()` to convert a quaternion to Euler angles via `glove_sdk`. Pay attention to the quaternion order.

```cpp
glovePtr->toEulerAngle(a[0], a[1], a[2], a[3], roll, pitch, yaw);
```

#### 3.2.3. Euler angle to rotation angle

Use the conversion method `RadToAngle()` to obtain the rotation angle.

```cpp
glovePtr->RadToAngle(pitch);
```

### 3.3. Interface function definition

#### 3.3.1. Initialization

```cpp
bool Initialize (const char* udp_ip, unsigned short udp_port);
```

**Function description:** Create a Socket according to the parameters. If successful, start a thread to receive data.

**Parameter description:** udp\_ip is the IP address for receiving data, udp\_port is the port number, which can be the same as the sending HandDriver.

**Return value description:** Returns true if successful, false if failed.

#### 3.3.2. Close Thread

```cpp
void Shutdown ();
```

**Function description:** Used to close the receiving thread and clean up the Socket.   &#x20;

**Parameter description:** None.   &#x20;

**Return value description:** None.

#### 3.3.3. Registering callback function

```cpp
void RegisterGloveCallBack(GloveCallBack callback);
```

**Function description:** Used to register a callback function, which is called after the program has parsed the JSON data.   &#x20;

**Parameter description:** `callback` is a function of type `GloveCallBack`, and the parameter types can be modified in the `.h` file.   &#x20;

**Return value description:** None.

#### 3.3.4. Print thread entry

```cpp
void print_control_thread（GloveSDK* glove_sdk);
```

**Function description:** Used to print data on the console.   &#x20;

**Parameter description:** GloveSDK object pointer, the printing thread will print its data.   &#x20;

**Return value description:** None.

#### 3.3.5. Restricting printing content

```cpp
void OnlyPrintFrame();
```

**Function description:** After calling, printing parameters will only print the frame number for debugging.   &#x20;

**Parameter description:** None.   &#x20;

**Return value description:** None.

### 3.4. Demo and description

#### 3.4.1. Demo project description

The **`HandDriver_x64_Cpp_Quater`** project contains the **`HandDriver_x64_Cpp_Quater`**&#x66;older and the **`HandDriver_x64_Cpp_Quater.sln`** file. The **`HandDriver_x64_Cpp_Quater`**&#x66;older contains the library files. If needed, they can be copied for separate use. The version of Visual Studio is vs2019(When using higher versions, follow the log changes), c++14. Run **`HandDriver_x64_Cpp_Quater.sln`**, select the x64 platform, and run the sample program.

<figure><img src="https://2082502898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8s1Ia6TfFovgyJ5JsDJZ%2Fuploads%2FsGXcfjgHXNcE0APEz8KT%2Fimage.png?alt=media&#x26;token=dccabe39-5a67-4efe-a0d7-35a6d3383bb3" alt="" width="563"><figcaption></figcaption></figure>

#### 3.4.2. Brief introduction to code flow

1. Declare a function to register the callback

{% code overflow="wrap" %}

```cpp
void OnNewGloveData(GloveSDK* glovePtr) //The cache size defines a function for registering a callback
{
        //This function will be called in the receiving thread

        //Get finger joint data

        auto a = glovePtr->GloveData[0].HandData_L.JointDatas[6];//Get the 6th data

        cout << "LeftRingProximal： " << a[1] << endl;//Print the second number of quaternions

        glovePtr->toEulerAngle(a[0], a[1], a[2], a[3], roll, pitch, yaw);//Convert quaternions to Euler angles, note that IMU data is in WXYZ order

        cout << "roll:" << glovePtr->RadToAngle(roll) << " pitch:" << glovePtr->RadToAngle(pitch) << " yaw:" << glovePtr->RadToAngle(yaw) << endl;//Print angle

}
```

{% endcode %}

2. Create an instance of GloveSDK

```cpp
//Create an instance of GloveSDK
GloveSDK glove_sdk;
```

3. Register callback function

```cpp
//Registering callback function
glove_sdk.RegisterGloveCallBack(OnNewGloveData);
```

4. Create a socket and check if it is successful. If successful, start receiving and parsing data

{% code overflow="wrap" %}

```cpp
//Create a Socket and check if it is successful. If successful, receive and parse the data
if (!glove_sdk.Initialize("127.0.0.1", 7777))
        {
                cerr << "Failed to initialize GloveSDK." << endl;
                return -1;
        }
```

{% endcode %}

5. Start the print thread and print the glove\_sdk data

```cpp
//Start the print thread and print the glove_sdk data
thread print_th(print_control_thread, &glove_sdk);
```

6. Calling the function to print only the frame number

```cpp
//After calling, only the number of frames is printed
while (true)
        {
            int a;
            cin >> a;

            switch (a)
            {

            case 1:
                   OnlyPrintFrame();
                   break;

            case 0://Close and clean up the socket
                   glove_sdk.Shutdown();
                   printf("Shutdown");
                   break;
           }
        }
```

7. Waiting for input save program

```cpp
//Waiting for input, Save program
getchar();
```

8. Close and clean up the socket

```cpp
//close and clean up the socket
glove_sdk.Shutdown();
printf("Shutdown");
```
