# 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="/files/o3NijIoR15dlqw5cE3aZ" 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](/udexreal-docs/glove-data-c++-python-sdk-for-robotics/hand-model-and-data-specification.md).

<figure><img src="/files/7ZIt13FDxv4KRzrVLjCQ" 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="/files/PiWm4RsJobQ51FVqjIAi" 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="/files/0GXpKmfZ96JsJr4Nj315" 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="/files/7blLD6w2kGrHznv1ciUi" 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");
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://udexreal.gitbook.io/udexreal-docs/glove-data-c++-python-sdk-for-robotics/json-c++-python-sdk_quaternion-manual.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
