Skip to main content

Making of: Santa's Little Helpers - Orchestrating UR7 and Unitree Go2

12/24/2025
By Cyberwave Team
Making of: Santa's Little Helpers - Orchestrating UR7 and Unitree Go2

This holiday season, we put together a special demonstration showing what Cyberwave does best: seamlessly orchestrating heterogeneous robots working together. The result is our Christmas video, featuring a UR7 collaborative robot arm loading gift packages onto a Unitree Go2 quadruped robot.

Watch the full video on our YouTube channel.

The Setup

The demonstration brings together two very different robots:

  • Universal Robots UR7: A 6-axis collaborative robot arm equipped with a vacuum gripper for precise pick-and-place operations
  • Unitree Go2: A quadruped robot that serves as the mobile delivery platform

Both robots are connected to the Cyberwave platform through a Cyberwave Edge device, which handles real-time communication and state synchronization via MQTT.

How It Works

The magic happens through Cyberwave's unified API. Instead of writing separate integration code for each robot's proprietary SDK, we define high-level behaviors that the platform translates into robot-specific commands.

Here's how you can connect to multiple assets and coordinate their movements:

1. Initialize the Cyberwave Client

from cyberwave import Cyberwave

# Initialize the client with your credentials
client = Cyberwave(
    api_key="your_api_key",
    mqtt_host="mqtt.cyberwave.com",
    mqtt_port=1883
)

# Connect to MQTT for real-time control
client.mqtt.connect()

2. Create Digital Twins for Both Robots

# Create twins for both robots in the same environment
ur7_twin = client.twin("universal-robots/ur7", environment_id="your_env_id")
go2_twin = client.twin("unitree/go2", environment_id="your_env_id")

print(f"UR7 Twin UUID: {ur7_twin.uuid}")
print(f"Go2 Twin UUID: {go2_twin.uuid}")

3. Coordinate Multi-Robot Movements

from cyberwave import SOURCE_TYPE_TELE

# Define UR7 positions for pick and place
PICK_POSITION = {
    "elbow_joint": -2.41,
    "shoulder_lift_joint": -1.31,
    "shoulder_pan_joint": 0.86,
    "wrist_1_joint": -0.98,
    "wrist_2_joint": 1.56,
    "wrist_3_joint": -0.70,
    "ee_fixed_joint": -0.5  # Vacuum off
}

PLACE_POSITION = {
    "elbow_joint": -1.35,
    "shoulder_lift_joint": -2.46,
    "shoulder_pan_joint": -1.29,
    "wrist_1_joint": -0.89,
    "wrist_2_joint": 1.57,
    "wrist_3_joint": -2.95,
    "ee_fixed_joint": 0.5  # Vacuum on
}

# Move UR7 to pick position
client.mqtt.update_joints_state(
    twin_uuid=ur7_twin.uuid,
    joint_positions=PICK_POSITION,
    source_type=SOURCE_TYPE_TELE
)

# Command Go2 to approach position
go2_twin.move(x=0.5, y=0.0, yaw=0.0)  # Move forward

4. Verify Position and Synchronize

import time

def wait_for_robot_position(client, twin_uuid, target_positions, tolerance=0.02, timeout=15):
    """Wait for the robot to reach target position."""
    start_time = time.time()
    
    while time.time() - start_time < timeout:
        # Check current position via MQTT state updates
        # The edge device continuously publishes joint states
        time.sleep(0.1)
        
        # Position verification logic here
        # Returns True when all joints are within tolerance
        
    return False

# Wait for UR7 to reach pick position before activating gripper
if wait_for_robot_position(client, ur7_twin.uuid, PICK_POSITION):
    # Activate vacuum gripper
    client.mqtt.update_joints_state(
        twin_uuid=ur7_twin.uuid,
        joint_positions={"ee_fixed_joint": 0.5},  # Vacuum on
        source_type=SOURCE_TYPE_TELE
    )

The Complete Orchestration Flow

The Christmas video demonstrates a full pick-and-place cycle:

  1. UR7 moves to home position - The arm starts from a safe zero position
  2. UR7 approaches the package - Precise positioning above the gift box
  3. Vacuum gripper activates - The package is securely gripped
  4. UR7 lifts and transfers - The arm moves the package toward the Go2
  5. Package placement - The gift is carefully placed on the Go2's back
  6. Vacuum release - A brief delay ensures clean release
  7. UR7 returns home - The arm returns to ready position
  8. Go2 walks away - The quadruped delivers the package

Why This Matters

This demonstration showcases several key capabilities of the Cyberwave platform:

  • Vendor-agnostic control: One API works with both Universal Robots and Unitree hardware
  • Real-time synchronization: MQTT-based communication ensures robots stay coordinated
  • State verification: The platform confirms robot positions before proceeding to the next step
  • Edge computing: Low-latency control through the Cyberwave Edge device

Try It Yourself

The complete source code for the UR7 control sequence is available in our SDK examples as ur7-santas-little-helper.py. To get started:

# Install the Cyberwave SDK
pip install cyberwave

# Set your credentials
export CYBERWAVE_API_KEY=your_api_key
export CYBERWAVE_TWIN_UUID=your_twin_uuid

# Run the example
python examples/ur7-santas-little-helper.py

What's Next

This is just the beginning. We're working on higher-level coordination primitives that will make multi-robot workflows even simpler to define. Imagine describing a task like "pick package from station A and deliver to station B" and having the platform automatically orchestrate the robots involved.

Happy holidays from the Cyberwave team. We look forward to building the future of robotics with you in 2026.

Questions or want to try Cyberwave with your robots? Get in touch or explore our documentation.