This SDK acquires joint angles or quaternion data of the hand based on the Protobuf transmission format, supporting both Windows and Linux environments.
Check "Data Transmission" to turn on the data transmission.
Select the Format: Protobuf.
Choose the Content: Euler or Quater. (Typically, the robotics field prefers Euler.)
Options: To transmit IMU data (only supported for gloves with IMU sensors), check the IMU option; otherwise, IMU data will not be transmitted.
The Old Plugin does not apply here.
Select the FPS, which supports 120Hz, 90Hz, and 60Hz. The default FPS is 120Hz.
In the target address section, click the "+" icon, then enter the IP address and port number of the receiving end to enable data transmission. (For local transmission, enter 127.0.0.1.)
Multiple target addresses can be set.
After completing the settings, click the "Apply" button to save.
The Protocol Buffer definition file is as follows:
handdriver_teleop.proto
handdriver_teleop.proto
2.3. Angle Value Reception Notes
Regarding the received angle values, please refer to the data page in the HandDriver. The data displayed on that page is consistent with the data received by the SDK:
Sign conventions are consistent.
Specific numerical values are displayed as integers in HandDriver.
This project is a C++ application designed for real-time reception and parsing of hand data. It utilizes Windows Socket (Winsock2) for UDP communication and integrates Google Protocol Buffers (Protobuf) for serialized data parsing.
3.1. Overview
This program operates as a UDP server, listening for broadcast or unicast data packets on a specified port.
Core Features:
UDP Communication: Based on the UDP protocol to ensure low-latency data transmission.
Protobuf Parsing: Supports parsing two core data packet types:
TeleopDataAngle: Data based on joint angles (suitable for robotic hand control).
TeleopDataQuat: Data based on quaternions (suitable for 3D rendering/Unity/UE).
Cross-Platform Design: The core logic is compatible with Linux, while the network layer is adapted for Windows using Winsock2.
3.2. Structure
3.3. Environment Setup and Compilation
This project relies on CMake for build management and vcpkg for third-party library (Protobuf) management.
3.3.1. Dependency Preparation
Install Visual Studio: Ensure the "Desktop development with C++" workload is included.
Install CMake: Version 3.10 or higher is recommended.
Install vcpkg:
Download vcpkg and run bootstrap-vcpkg.bat.
Install the Protobuf library: powershell vcpkg install protobuf:x64-windows
3.3.2. Compilation Steps
We provide two compilation modes: Release (recommended, better performance) and Debug (for debugging purposes).
1
Generate Project Files
In the project root directory, use CMake to configure the project. Please ensure you replace the path with your local vcpkg path.
2
Execute Compilation
Compilation Output:
After successful compilation, the executable file udp_receiver.exe and its required DLLs (libprotobuf.dll, abseil_dll.dll) will be automatically generated in the build/Release directory.
3.4. Execution and Parameter Description
The program is a command-line tool that supports flexible configuration through parameters.
3.4.1. Startup Command Format
3.4.2. Parameter Details
Parameter
Short Form
Required
Default Value
Data Type
Description
--port
-p
No
5555
Integer
The local UDP port the program listens on. Ensure this port is not blocked by the firewall.
--type
-t
No
angle
String
Specifies the protocol to parse:
angle: Parses joint angle data.
quat: Parses joint quaternion data.
3.4.3. Execution Examples
Scenario 1: Default Execution
Listens on port 5555 and parses angle data.
powershell build\Release\udp_receiver.exe
Scenario 2: Receiving Data from a Unity Client
Assuming Unity sends quaternion data to port 6666.
Initialize Winsock: Call WSAStartup to initialize the Windows network library.
Parse Arguments: Parse command-line arguments to obtain the port and data type.
Create Socket: Establish a UDP socket (SOCK_DGRAM).
Bind Port (Bind): Bind the socket to INADDR_ANY and the specified port, allowing it to receive traffic from all network interfaces.
Receive Loop (While Loop):
recvfrom: Block and wait until a data packet is received.
Deserialization: Based on the --type argument, select either a TeleopDataAngle or TeleopDataQuat object and call ParseFromString() to parse the binary data.
Data Processing: If parsing is successful, call the print_*_data function to print the string representation (DebugString()) of the data content.
Resource Cleanup: Close the socket and clean up Winsock.
3.6. Secondary Development Guide
If you need to write your own code to read the data, please refer to the following C++ example:
1
Include Header Files
2
Parsing Logic
4. C++ SDK Linux
4.1. Overview
This project is a C++-based UDP network receiver program, specifically designed to receive and parse glove data serialized via Google Protocol Buffers (Protobuf). The program supports two primary data transmission modes: Angle mode and Quaternion mode.
4.2. Compilation and Build
This project uses CMake for build management.
4.2.1. Environment Dependency Installation
This project runs in a Linux (Ubuntu/Debian) environment. Please follow the steps below to install the required dependencies:
1
Update the Software Source
2
Install Basic Build Tools
Install the C++ compiler (g++) and the CMake build tool:
3
Install Protocol Buffers
This project relies on Google Protocol Buffers for data serialization. It requires the installation of the compiler (protoc) and the C++ development library (libprotobuf-dev):
4.2.2. Compilation Steps
Please execute the following commands in the project's root directory:
After successful compilation, the executable file udp_receiver will be generated in the current directory.
4.3. Usage Instructions
The program is configured via command-line parameters, supporting custom listening ports and data types.
4.3.1. Parameter Description
Parameter
Short Form
Required
Default Value
Description
--port
-p
No
5555
Sets the UDP listening port.
--type
-t
No
angle
Sets the data parsing type. Options: angle, quat.
4.3.2. Execution Examples
Run with default settings (Listens on port 5555, parses Angle type data):
Specify port and type (Listens on port 6000, parses Quat type data):
4.4. Code Logic and Interfaces
4.4.1. Main Program Flow (main.cpp)
Parameter Parsing: Uses getopt_long to parse command-line arguments port and type.
Socket Initialization: Creates a UDP socket and binds it to the specified port (INADDR_ANY).
Reception Loop:
recvfrom blocks and receives a UDP data packet.
Based on the type argument, selects the corresponding Protobuf message type (TeleopDataAngle or TeleopDataQuat) for deserialization (ParseFromString).
If parsing is successful, calls the corresponding print function.
If parsing fails, outputs an error message and continues to the next loop iteration.
Function: Prints the details of Quaternion type telemetry data.
Implementation: Same as above, calls DebugString().
5. Python SDK - Linux/Win
This SDK supports both Windows and Linux.
This tool listens on a specified port via the UDP protocol, receives binary data packets, and uses Google Protocol Buffers (Protobuf) to deserialize them according to the specified data type (angle or quat), finally printing the parsed data to the console.
5.1. Environment Dependencies
Python 3.x
Protobuf library
Install dependencies:
5.2. Interface Description and Data Access
5.2.1. Communication Protocol
Protocol: UDP
Default Port: 5555
Data Format: Protobuf-serialized binary stream
5.2.2. Reception Process (Python)
Create Socket: Establish a UDP socket.
Bind Port: Bind to a specified IP (0.0.0.0) and port.
Reception Loop: Use recvfrom to receive data packets.
Deserialization:
If the data type is angle, use TeleopDataAngle.ParseFromString(data).
If the data type is quat, use TeleopDataQuat.ParseFromString(data).
Data Access: Access fields of the parsed object (e.g., msg.LeftHand.joints[0]).
5.3. Usage Demo
The script udp_receiver.py provides a simple command-line interface.
5.3.1. Parameter Description
--port: Specifies the listening port (default: 5555)
--type: Specifies the expected data type (angle or quat, default: angle)
5.3.2. Example 1: Receiving Angle Data (Default)
Or specify explicitly:
5.3.3. Example 2: Receiving Quaternion Data
If the sender is transmitting data in quaternion format:
syntax = "proto3";
package HandDriver;
import "handdriver_algebra.proto";
// Index description for joints array (Angle)
enum JointsIndex_Angle
{
THUMB_DISTAL_PITCH = 0; // Thumb Distal Pitch
THUMB_INTERMEDIATE_PITCH = 1; // Thumb Intermediate Pitch
THUMB_PROXIMAL_PITCH = 2; // Thumb Proximal Pitch
THUMB_PROXIMAL_YAW = 3; // Thumb Proximal Yaw
INDEX_DISTAL_PITCH = 4; // Index Distal Pitch
INDEX_INTERMEDIATE_PITCH = 5; // Index Intermediate Pitch
INDEX_PROXIMAL_PITCH = 6; // Index Proximal Pitch
INDEX_PROXIMAL_YAW = 7; // Index Proximal Yaw
MIDDLE_DISTAL_PITCH = 8; // Middle Distal Pitch
MIDDLE_INTERMEDIATE_PITCH = 9; // Middle Intermediate Pitch
MIDDLE_PROXIMAL_PITCH = 10; // Middle Proximal Pitch
MIDDLE_PROXIMAL_YAW = 11; // Middle Proximal Yaw
RING_DISTAL_PITCH = 12; // Ring Distal Pitch
RING_INTERMEDIATE_PITCH = 13; // Ring Intermediate Pitch
RING_PROXIMAL_PITCH = 14; // Ring Proximal Pitch
RING_PROXIMAL_YAW = 15; // Ring Proximal Yaw
PINKY_DISTAL_PITCH = 16; // Pinky Distal Pitch
PINKY_INTERMEDIATE_PITCH = 17; // Pinky Intermediate Pitch
PINKY_PROXIMAL_PITCH = 18; // Pinky Proximal Pitch
PINKY_PROXIMAL_YAW = 19; // Pinky Proximal Yaw
THUMB_PROXIMAL_ROLL = 20; // Thumb Proximal Roll
INDEX_PROXIMAL_ROLL = 21; // Index Proximal Roll
PINKY_PROXIMAL_ROLL = 22; // Pinky Proximal Roll
}
// Index description for joints array (Quat)
enum JointsIndex_Quat{
INDEX_PROXIMAL = 0; // Index Proximal
INDEX_INTERMEDIATE = 1; // Index Intermediate
INDEX_DISTAL = 2; // Index Distal
MIDDLE_PROXIMAL = 3; // Middle Proximal
MIDDLE_INTERMEDIATE = 4; // Middle Intermediate
MIDDLE_DISTAL = 5; // Middle Distal
RING_PROXIMAL = 6; // Ring Proximal
RING_INTERMEDIATE = 7; // Ring Intermediate
RING_DISTAL = 8; // Ring Distal
PINKY_PROXIMAL = 9; // Pinky Proximal
PINKY_INTERMEDIATE = 10; // Pinky Intermediate
PINKY_DISTAL = 11; // Pinky Distal
THUMB_PROXIMAL = 12; // Thumb Proximal
THUMB_INTERMEDIATE = 13; // Thumb Intermediate
THUMB_DISTAL = 14; // Thumb Distal
}
message GloveHandDataAngle{
string serialNumber = 1; // Device Serial Number
int32 battery = 2; // Battery Level
int32 calibrationState = 3; // Calibration State
bool aButton = 4; // A Button State
bool bButton = 5; // B Button State
bool menuButton = 6; // Menu Button State
bool joyButton = 7; // Joystick Button State
Vec2 joyPosition = 8; // Joystick Position
Quat imu = 9; // Hand IMU Orientation
repeated float joints = 10; // Joint Angles
int32 gesture = 11; // Recognized Gesture Index
}
message GloveHandDataQuat{
string serialNumber = 1; // Device Serial Number
int32 battery = 2; // Battery Level
int32 calibrationState = 3; // Calibration State
bool aButton = 4; // A Button State
bool bButton = 5; // B Button State
bool menuButton = 6; // Menu Button State
bool joyButton = 7; // Joystick Button State
Vec2 joyPosition = 8; // Joystick Position
Quat imu = 9; // Hand IMU Orientation
repeated Quat joints = 10; // Joint API Rotations
int32 gesture = 11; // Recognized Gesture Index
}
message TeleopDataAngle
{
int64 TimeStamp = 1; // Milliseconds
uint64 FrameIndex = 2; // Frame index at start of transmission
string RoleName = 3; // User Role Name
GloveHandDataAngle LeftHand = 4; // Left Hand Data
GloveHandDataAngle RightHand = 5; // Right Hand Data
}
message TeleopDataQuat
{
int64 TimeStamp = 1; // Milliseconds
uint64 FrameIndex = 2; // Frame index at start of transmission
string RoleName = 3; // User Role Name
GloveHandDataQuat LeftHand = 4; // Left Hand Data
GloveHandDataQuat RightHand = 5; // Right Hand Data
}
syntax = "proto3";
package HandDriver;
message Vec2 {
float x = 1;
float y = 2;
}
message Vec3 {
float x = 1;
float y = 2;
float z = 3;
}
message Quat {
float x = 1;
float y = 2;
float z = 3;
float w = 4;
}
d:/udp_receiver_cpp/
├── CMakeLists.txt # CMake build script, managing dependencies and compilation rules
├── main.cpp # Main program entry point, containing Socket logic and data printing
├── handdriver_teleop.proto # Core data protocol definitions (hand data, telemetry packets)
├── handdriver_algebra.proto # Basic mathematical type definitions (vectors, quaternions)
├── build/ # (Auto-generated) CMake build directory
└── Release/ # Output directory for compiled Release executable files
# Replace <path_to_vcpkg> with the actual path, for example C:/vcpkg.
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=<path_to_vcpkg>/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release
// Assuming buffer is the received char* data and n is its length
std::string raw_data(buffer, n);
HandDriver::TeleopDataAngle packet;
if (packet.ParseFromString(raw_data)) {
// 1. Get the timestamp
long long ts = packet.timestamp();
// 2. Get the bending degree of the left thumb tip
// Access path: TeleopData -> LeftHand -> Joints Array -> Index 0
float thumb_bend = packet.lefthand().joints(0);
// 3. Get the wrist pose
auto imu = packet.lefthand().imu();
printf("Wrist Quat: x=%.2f, y=%.2f\n", imu.x(), imu.y());
}