Tutorial
This tutorial walks you through the complete workflow of taking a C3D motion capture file and retargeting it onto a 3D character using the MyoSapiens Python SDK.
Prerequisites
Before starting, make sure you have:
- Python SDK installed
- API key configured
- A C3D motion capture file
- A markerset XML file that matches your C3D data
Step 1: Initialize the Client
Start by importing the SDK and initializing the client. Make sure you have your API key set as an environment variable (see Installation Guide):
import os
from myosdk import Client
# Initialize the client
client = Client(api_key=os.getenv("MYO_API_KEY"))
Step 2: Run a Retarget Job (Simplest Path)
The simplest way to retarget is to pass file paths directly. The SDK uploads them, runs the job, and waits for completion:
# One call: upload, process, wait, and optionally download
result = client.retarget(
tracker="path/to/your/motion.c3d",
markerset="path/to/your/markerset.xml",
export_glb=True, # Optional: get motion as GLB
stream_status=True, # Optional: print status updates
output_dir="out/", # Optional: auto-download when complete
)
print(f"Job completed! Processing time: {result.processing_time_seconds}s")
If you didn't use output_dir, download the outputs:
# Download all outputs to a directory
result.download_all("out/")
# Or download individual files
result.download_qpos("out/qpos.parquet")
result.download_xpos("out/xpos.parquet")
result.download_model("out/model.mjb")
result.download_motion("out/motion.glb") # Only if export_glb=True
See File Formats for details on each output (qpos = joint angles, xpos = joint positions in 3D space, model = MuJoCo model, motion = GLB).
Step 3: Alternative — More Control with create_retarget_job
If you want to stream status or manage the job manually:
# Block by default but stream status
result = client.create_retarget_job(
tracker="path/to/motion.c3d",
markerset="path/to/markerset.xml",
export_glb=True,
stream_status=True,
on_status=lambda e: print(f"Status: {e.status}"),
)
result.download_all("out/")
Non-blocking (manual control):
job = client.create_retarget_job(
tracker="path/to/motion.c3d",
markerset="path/to/markerset.xml",
export_glb=True,
block_until_complete=False,
)
for event in job.stream():
print(f"Status: {event.status}")
result = job.wait(timeout=600)
result.download_all("out/")
Step 4: Use the Outputs
The outputs are Parquet (qpos, xpos), MuJoCo binary (model), and optionally GLB (motion). Example with Parquet:
import pandas as pd
# Load qpos (joint angles)
qpos_df = pd.read_parquet("out/qpos.parquet")
print(f"qpos: {qpos_df.shape}")
# Load xpos (joint positions in 3D space)
xpos_df = pd.read_parquet("out/xpos.parquet")
print(f"xpos: {xpos_df.shape}")
See File Formats for full details on output structure and usage.
Complete Example with Error Handling
Here's the full script with error handling:
import os
from myosdk import Client
from myosdk.exceptions import ApiError, InsufficientCreditsError
client = Client(api_key=os.getenv("MYO_API_KEY"))
try:
print("Creating retarget job...")
result = client.retarget(
tracker="motion.c3d",
markerset="markerset.xml",
export_glb=True,
stream_status=True,
)
print(f"Job completed! Processing time: {result.processing_time_seconds}s")
print("Downloading outputs...")
result.download_all("out/")
print("Done! Outputs saved to out/")
except InsufficientCreditsError as e:
print(f"Insufficient credits: {e}")
except ApiError as e:
print(f"API error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
finally:
client.close()
Next Steps
Now that you've completed your first retargeting:
- Learn about retarget parameters for advanced configuration
- Check the SDK Reference for complete API documentation
- Review error handling for production applications
- See the API Reference for REST API documentation
- Learn more about Why Myo? and our approach to unified motion processing