Skip to content

Getting started with Python

The MANUS Python SDK is a Python wrapper for the MANUS SDK that allows you to interact with MANUS gloves through Python. The SDK is compatible with both Windows and Linux. The Python SDK provides access to all major SDK functions including glove data streaming, landscape information, ergonomics data, and more.

Overview

The Python SDK comes with two example projects: SDK Client and SDK Minimal Client. The SDK Client is a full example demonstrating all functionality from the SDK with an interactive menu-driven interface. The SDK Minimal Client is a bare-bones example that demonstrates the minimal amount of code needed to get the SDK connected and receiving glove data.

Installation

Prerequisites

  • Any supported Python version (3.9, 3.10, 3.11, or 3.12)
  • Platform-specific dependencies:

Step 1: Install the Python SDK

pip install -e .

Or if you have a pre-built distribution package:

pip install .

This installs the SDK with all pre-compiled extensions for your Python version.

Step 2: Install Runtime Dependencies

pip install -r requirements.txt

This installs the required runtime packages:

  • cffi>=1.17.0 - Runtime dependency (pre-compiled extensions are already built, no compilation needed)

Step 3: Verify Installation

To verify the installation was successful:

python -c "from manus_sdk import lib, ffi, ManusSDK; print('SDK loaded successfully')"

If you see "SDK loaded successfully", the installation is complete and you're ready to use the SDK.

About Pre-compiled Extensions

The Python SDK includes pre-compiled CFFI extensions (.pyd files on Windows, .so on Linux) for Python 3.9, 3.10, 3.11, and 3.12. These are built once and bundled with the SDK - no compilation is needed on your machine. The correct extension for your Python version will be automatically selected at runtime.

Step 3: Run an Example

Start with the Minimal Client example:

python examples/minimal_client.py

Quick Start

Basic Initialization

from manus_sdk import lib, ffi
from manus_sdk.generated._enums import SDKReturnCode

# Initialize SDK in Integrated mode
result = lib.CoreSdk_InitializeIntegrated()
if result == SDKReturnCode.Success:
    print("SDK initialized!")
else:
    print(f"Failed to initialize SDK: {result}")

Connection Modes

The Python SDK supports three connection modes:

1. Integrated Mode

  • Runs MANUS Core standalone without network connection
  • Best for: Single-machine applications, Linux
  • No network connection or MANUS Core Dashboard needed
result = lib.CoreSdk_InitializeIntegrated()

2. Local Mode

  • Connects to MANUS Core running on the same machine (localhost)
  • Best for: Development, applications on same PC as MANUS Core
  • MANUS Core must be running locally
result = lib.CoreSdk_InitializeCore()
# Then connect to localhost

3. Remote Mode

  • Connects to MANUS Core running on another machine on the network
  • Best for: Multi-machine setups, distributed applications
  • Automatically discovers available MANUS Core instances
result = lib.CoreSdk_InitializeCore()
# Then discover and connect to remote host

Finding and Connecting to MANUS Core

from manus_sdk import lib, ffi
from manus_sdk.generated._enums import SDKReturnCode, AxisView, AxisPolarity, Side

# Initialize SDK (required before connecting)
result = lib.CoreSdk_InitializeCore()
if result != SDKReturnCode.Success:
    print("Failed to initialize SDK")
    exit(1)

# Set up coordinate system (required before connecting)
coord_system = ffi.new("CoordinateSystemVUH*")
coord_system.view = AxisView.XFromViewer
coord_system.up = AxisPolarity.PositiveZ
coord_system.handedness = Side.Right
coord_system.unitScale = 1.0

result = lib.CoreSdk_InitializeCoordinateSystemWithVUH(coord_system[0], True)
if result != SDKReturnCode.Success:
    print("Failed to initialize coordinate system")
    exit(1)

# Search for available hosts
loopback_only = False  # Set to False for networked search
result = lib.CoreSdk_LookForHosts(3, loopback_only)  # 3 second timeout

if result == SDKReturnCode.Success:
    # Get number of hosts found
    count = ffi.new("uint32_t*")
    lib.CoreSdk_GetNumberOfAvailableHostsFound(count)
    num_hosts = count[0]

    if num_hosts > 0:
        # Get host list
        hosts_array = ffi.new("ManusHost[]", num_hosts)
        lib.CoreSdk_GetAvailableHostsFound(hosts_array, num_hosts)

        # Connect to first host
        result = lib.CoreSdk_ConnectToHost(hosts_array[0])
        if result == SDKReturnCode.Success:
            print("Connected to MANUS Core!")

Receiving Data via Callbacks

from manus_sdk import ManusSDK

sdk = ManusSDK()

# Define callback function
def on_raw_skeleton_data(stream_info):
    """Called when raw skeleton data is available"""
    print(f"Received {stream_info.skeletonsCount} skeleton(s)")

# Register callback
result = sdk.register_raw_skeleton_callback(on_raw_skeleton_data)
print(f"Callback registered: {result}")

# Keep program running to receive callbacks
import time
while True:
    time.sleep(0.1)

SDK Architecture

The Python SDK consists of:

Pre-compiled CFFI Extension (manus_sdk)

  • Native C library bindings for Windows (.pyd) and Linux (.so)
  • Available for Python 3.9, 3.10, 3.11, 3.12
  • Automatically selected based on your Python version
  • No compilation needed - just install and run

Wrapper Classes (manus_sdk.manus_wrapper)

  • High-level Python callback management
  • Enum definitions
  • Helper functions

Generated Enums (manus_sdk.generated._enums)

  • SDK enums (SDKReturnCode, Side, HandMotion, etc.)
  • Clean enum names (removes C prefixes)
  • Type-safe enum usage

Data Streams

The SDK provides several callback-based data streams:

Raw Skeleton Data

Joint positions and rotations from gloves. Contains: - Position (x, y, z) - Rotation (w, x, y, z quaternion)

Ergonomics Data

Finger joint angle information. Contains: - Spread angles (abduction/adduction) - MCP, PIP, DIP joint bends - Per-finger joint metrics (in degrees)

Landscape Data

System overview and device inventory. Contains: - Connected dongles - Connected gloves - User information - Skeleton configurations - System settings

Common Tasks

Prerequisites

The code snippets in this section assume the SDK has been properly initialized and connected to MANUS Core. Before using these examples, ensure you have:

  1. Called CoreSdk_InitializeCore() or CoreSdk_InitializeIntegrated()
  2. Set up a coordinate system with CoreSdk_InitializeCoordinateSystemWithVUH()
  3. Connected to a MANUS Core instance with CoreSdk_ConnectToHost()

Set Coordinate System

from manus_sdk import lib, ffi
from manus_sdk.generated._enums import AxisView, AxisPolarity, Side

# Create coordinate system struct
coord_system = ffi.new("CoordinateSystemVUH*")
coord_system.view = AxisView.XFromViewer
coord_system.up = AxisPolarity.PositiveZ
coord_system.handedness = Side.Right
coord_system.unitScale = 1.0

# Initialize coordinate system
result = lib.CoreSdk_InitializeCoordinateSystemWithVUH(coord_system[0], True)

Get Glove Information

from manus_sdk import lib, ffi

# Get number of dongles
dongle_count = ffi.new("uint32_t*")
lib.CoreSdk_GetNumberOfDongles(dongle_count)

# Get dongle info
dongles = ffi.new("ManusHost[]", dongle_count[0])
lib.CoreSdk_GetDongleList(dongles, dongle_count[0])

Process Raw Skeleton Data

from manus_sdk import lib, ffi

def on_raw_skeleton_callback(stream_info):
    """Handle raw skeleton stream"""
    for i in range(stream_info.skeletonsCount):
        # Get skeleton info
        info = ffi.new("RawSkeletonInfo*")
        lib.CoreSdk_GetRawSkeletonInfo(i, info)

        # Get skeleton nodes
        nodes_array = ffi.new("SkeletonNode[]", info[0].nodesCount)
        lib.CoreSdk_GetRawSkeletonData(i, nodes_array, info[0].nodesCount)

        # Access node data
        for j in range(info[0].nodesCount):
            node = nodes_array[j]
            pos = node.transform.position
            rot = node.transform.rotation
            print(f"Node {j}: pos=({pos.x}, {pos.y}, {pos.z})")

Important Notes

Thread Safety

Callbacks execute in SDK threads. If you need to access callback data from your main thread, use proper synchronization (e.g., threading.Lock, threading.Event).

Memory Management

CFFI data structures are references to C memory. When working with persistent data, convert CFFI structs to Python dictionaries or native types to avoid memory reuse issues.

Next Steps

  1. Run the Minimal Client: Start with examples/minimal_client.py for basic usage
  2. Explore the SDK Client: Try examples/sdk_client.py for advanced features
  3. Review Examples: Study the example code to understand callback patterns
  4. Build Your Application: Adapt the examples to your use case

Troubleshooting

"Cannot import _manus_sdk"

  • Ensure you have the correct Python version (3.9, 3.10, 3.11, or 3.12)
  • Verify proper installation: pip install -e .
  • Verify installation: python -c "from manus_sdk import lib, ffi; print('OK')"

"Failed to initialize SDK"

  • Verify MANUS Core is running (for Local/Remote modes)
  • Try Integrated mode first to verify SDK is working

Support

For issues or questions:

  1. Check the troubleshooting section above
  2. Review example code in examples/
  3. Check the C++ SDK documentation for API reference
  4. Examine SDK header files in the C++ SDK for detailed function signatures