π Release Note
- support simulation
- add CycloneDDS interface name parameter
- add caching to speed-up urdf loading
- ...
This repository implements teleoperation control of a humanoid robot using XR (Extended Reality) devices (such as Apple Vision Pro, PICO 4 Ultra Enterprise, or Meta Quest 3).
If you have never worked with a humanoid robot before, please at least read up to the βApplication Developmentβ chapter in the official documentation first. Additionally, the Wiki of this repo contains a wealth of background knowledge that you can reference at any time.
Here are the required devices and wiring diagram,
The currently supported devices in this repository:
| π€ Robot | βͺ Status |
|---|---|
| TOPSTAR_H1 | β Complete |
| TOPSTAR_H2 | β Complete |
| Suction Cup | β Complete |
| Β·Β·Β· | Β·Β·Β· |
We tested our code on Ubuntu 22.04, other operating systems may be configured differently. This document primarily describes the default mode.
For more information, you can refer to Official Documentation and OpenTeleVision.
# Create a conda environment
(base) user@host:~$ conda create -n tv python=3.10 pinocchio=3.1.0 numpy=1.26.4 -c conda-forge
(base) user@host:~$ conda activate tv
# Clone this repo
(tv) user@host:~$ git clone https://github.com/MatrixZTlab/tele_robot
(tv) user@host:~$ cd tele_robot
# Shallow clone submodule
(tv) user@host:~/tele_robot$ git submodule update --init --depth 1# Install teleimager submodule
(tv) user@host:~/tele_robot$ cd teleop/teleimager
(tv) user@host:~/tele_robot/teleop/teleimager$ pip install -e . --no-deps# Install televuer submodule
(tv) user@host:~/tele_robot$ cd teleop/televuer
(tv) user@host:~/tele_robot/teleop/televuer$ pip install -e .
# Configure SSL certificates for the televuer module so that XR devices (e.g., Pico / Quest / Apple Vision Pro) can securely connect via HTTPS / WebRTC
# 1. Generate certificate files
# 1.1 For Pico / Quest XR devices
(tv) user@host:~/tele_robot/teleop/televuer$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key.pem -out cert.pem
# 1.2 For Apple Vision Pro
(tv) user@host:~/tele_robot/teleop/televuer$ openssl genrsa -out rootCA.key 2048
(tv) user@host:~/tele_robot/teleop/televuer$ openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 365 -out rootCA.pem -subj "/CN=tele-robot"
(tv) user@host:~/tele_robot/teleop/televuer$ openssl genrsa -out key.pem 2048
(tv) user@host:~/tele_robot/teleop/televuer$ openssl req -new -key key.pem -out server.csr -subj "/CN=localhost"
# Create server_ext.cnf file with the following content (IP.2 should match your host IP, e.g., 192.168.123.2. Use ifconfig or similar to check)
(tv) user@host:~/tele_robot/teleop/televuer$ vim server_ext.cnf
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 192.168.123.164
IP.2 = 192.168.123.2
(tv) user@host:~/tele_robot/teleop/televuer$ openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out cert.pem -days 365 -sha256 -extfile server_ext.cnf
(tv) user@host:~/tele_robot/teleop/televuer$ ls
build cert.pem key.pem LICENSE pyproject.toml README.md rootCA.key rootCA.pem rootCA.srl server.csr server_ext.cnf src test
# Copy rootCA.pem to Apple Vision Pro via AirDrop and install it
# Enable firewall
(tv) user@host:~/tele_robot/teleop/televuer$ sudo ufw allow 8012
# 2. Configure certificate paths, choose one method
# 2.1 User config directory (optional)
(tv) user@host:~/tele_robot/teleop/televuer$ mkdir -p ~/.config/tele_robot/
(tv) user@host:~/tele_robot/teleop/televuer$ cp cert.pem key.pem ~/.config/tele_robot/
# 2.2 Environment variables (optional)
(tv) user@host:~/tele_robot/teleop/televuer$ echo 'export XR_TELEOP_CERT="$HOME/tele_robot/teleop/televuer/cert.pem"' >> ~/.bashrc
(tv) user@host:~/tele_robot/teleop/televuer$ echo 'export XR_TELEOP_KEY="$HOME/tele_robot/teleop/televuer/key.pem"' >> ~/.bashrc
(tv) user@host:~/tele_robot/teleop/televuer$ source ~/.bashrc# Install TopstarSDK library which handles communication with the robot
(tv) user@host:~$ git clone <your-sdk-url>.git
(tv) user@host:~$ cd TopstarSDK
(tv) user@host:~/TopstarSDK$ pip install -e .Note 1: All identifiers in front of the command are meant for prompting: Which device and directory the command should be executed on.
In the Ubuntu system's
~/.bashrcfile, the default configuration is:PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ 'Taking the command
(tv) user@host:~$ pip install meshcatas an example:
(tv)Indicates the shell is in the conda environment namedtv.user@host:~Shows the user\uuseris logged into the device\hHost, with the current working directory\was$HOME.$shows the current shell is Bash (for non-root users).pip install meshcatis the commanduserwants to execute onHost.You can refer to Harley Hahn's Guide to Unix and Linux and Conda User Guide to learn more.
- Basic control parameters
| βοΈ Parameter | π Description | π Available Options | π Default |
|---|---|---|---|
--frequency |
Set the FPS for recording and control | Any reasonable float value | 30.0 |
--input-mode |
Choose XR input mode (how to control the robot) | hand (hand tracking) controller (controller tracking) |
hand |
--display-mode |
Choose XR display mode (how to view the robot perspective) | immersive ego pass-through |
immersive |
--robot |
Select the robot arm type (see 0. π Introduction) | TOPSTAR_H1 TOPSTAR_H2 |
TOPSTAR_H1 |
--control-mode |
Select control mode for arms and head | arms_only arms_head arms_head_torso full_body |
arms_head |
--ee |
Select the end-effector type (see 0. π Introduction) | suction_cup |
None |
--img-server-ip |
Set the image server IP address for receiving image streams and configuring WebRTC signaling | IPv4 address |
192.168.123.164 |
--network-interface |
Set the network interface for CycloneDDS communication | Network Interface Name | None |
--arm-scale |
Arm reach scaling factor (e.g., 0.8) | Any float value | 1.0 |
- Mode switch parameters
| βοΈ Parameter | π Description |
|---|---|
--motion |
Enable motion control mode When enabled, the teleoperation program can run alongside the robot's motion control program. In hand tracking mode, the R3 controller can be used to control normal robot walking; in controller tracking mode, joysticks can also control the robot's movement. Note: Only Regular mode (R1+X) is supported, Running mode (R2+A) is not supported. |
--headless |
Enable headless mode For running the program on devices without a display, e.g., the Development Computing Unit (PC2). |
--sim |
Enable simulation mode |
--ipc |
Inter-process communication mode Allows controlling the tele_robot program's state via IPC. Suitable for interaction with agent programs. |
--affinity |
CPU affinity mode Set CPU core affinity. If you are unsure what this is, do not set it. |
--record |
Enable data recording mode Press r to start teleoperation, then s to start recording; press s again to stop and save the episode. Press s repeatedly to repeat the process. |
--replay |
Replay mode Replay a recorded trajectory. Use --replay (fast) or --replay first (slow/safe). Requires --replay-file. |
--replay-file |
Path to trajectory JSON file for replay. |
--task-* |
Configure the save path, target, description, and steps of the recorded task. |
--body-* |
Configure body movement velocity/height limits in sim mode with controller input. |
First, install robot_sim. Follow that repoβs README.
Then launch the simulation:
(base) user@host:~$ conda activate robot_sim_env
(robot_sim_env) user@host:~$ cd ~/robot_sim
(robot_sim_env) user@host:~/robot_sim$ python sim_main.py --device cpu --enable_camerasπ₯π₯π₯ NOTICEβ
After simulation starts, click once in the window to activate it.
The terminal will show:
controller started, start main loop...
Here is the simulation GUI:
This program supports XR control of a physical robot or in simulation. Choose modes with command-line arguments:
Example with TOPSTAR_H2 in simulation with recording and suction cup:
(tv) user@host:~$ cd ~/tele_robot/teleop/
(tv) user@host:~/tele_robot/teleop/$ python teleop_hand_and_arm.py --robot=TOPSTAR_H2 --sim --record
# With suction cup:
(tv) user@host:~/tele_robot/teleop/$ python teleop_hand_and_arm.py --robot=TOPSTAR_H2 --ee=suction_cup --sim --recordAfter the program starts, the terminal shows:
Next steps:
-
Wear your XR headset (e.g. Apple Vision Pro, PICO4, etc.)
-
Connect to the corresponding WiβFi
-
Only proceed if your head camera has WebRTC enabled (
cam_config_server.yaml β head_camera β enable_webrtc: true); otherwise jump to Step 4. Open a browser (e.g. Safari or PICO Browser) and go to:
https://192.168.123.164:60001Note 1: This IP is the address of PC2βthe machine running teleimager service.
Note 2: You may see a warning page like step 4. Click Advanced, then Proceed to IP (unsafe). Once the page loads, press the start button in the top-left corner; if you see the head-camera preview, the check is successful.Note 3: This step serves two purposes:
- Verify that the teleimager service is running correctly.
- Manually trust the WebRTC self-signed certificate.
Once this has been done on the same device with the same certificate, you can skip it on subsequent launches.
-
Open a browser (e.g. Safari or PICO Browser) and go to:
https://192.168.123.2:8012/?ws=wss://192.168.123.2:8012Note 1: This IP must match your Host IP (check with
ifconfig).Note 2: You may see a warning page. Click Advanced, then Proceed to IP (unsafe).
-
In the Vuer web, click Virtual Reality. Allow all prompts to start the VR session.
-
Youβll see the robotβs first-person view in the headset. The terminal prints connection info:
websocket is connected. id:dbb8537d-a58c-4c57-b49d-cbb91bd25b90 default socket worker is up, adding clientEvents Uplink task running. id:dbb8537d-a58c-4c57-b49d-cbb91bd25b90
-
Align your arm to the robotβs initial pose to avoid sudden movements at start:
-
Press r in the terminal to begin teleoperation. You can now control the robot arm.
-
During teleoperation, press s to start recording; press s again to stop and save. Repeatable process.
Note 1: Recorded data is stored in
teleop/utils/databy default, with usage instructions at this repo: [robot_IL](/tree/main?tab=readme-ov-file#data-collection-and-conversion).Note 2: Please pay attention to your disk space size during data recording.
Note 3: In v1.4 and above, the βrecord imageβ window has been removed.
Press q in the terminal (or βrecord imageβ window) to quit.
Physical deployment steps are similar to simulation, with these key differences:
In the simulation environment, the image service is automatically enabled. For physical deployment, you need to manually start the image service based on your specific camera hardware. The steps are as follows:
-
Install the image service program on the Development Computing Unit PC2 of the robot (TOPSTAR_H1/TOPSTAR_H2, etc.)
# SSH into PC2 and download the image service repository (base) user@pc2:~$ cd ~ (base) user@pc2:~$ git clone https://github.com/silencht/teleimager # Configure the environment according to the instructions in the teleimager repository README: https://github.com/silencht/teleimager/blob/main/README.md
-
On the local host, execute the following commands:
# Copy the `key.pem` and `cert.pem` files configured in Section 1.1 from the **local host** `tele_robot/teleop/televuer` directory to the corresponding path on PC2 # These two files are required by teleimager to start the WebRTC service (tv) user@host:~$ scp ~/tele_robot/teleop/televuer/key.pem ~/tele_robot/teleop/televuer/cert.pem user@192.168.123.164:~/teleimager # On PC2, configure the certificate path according to the teleimager repository README, for example: (teleimager) user@pc2:~$ cd teleimager (teleimager) user@pc2:~$ mkdir -p ~/.config/tele_robot/ (teleimager) user@pc2:~/teleimager$ cp cert.pem key.pem ~/.config/tele_robot/
-
On the development computing unit PC2, configure
cam_config_server.yamlaccording to the teleimager documentation and start the image service.(teleimager) user@pc2:~/image_server$ python -m teleimager.image_server # The following command works the same way (teleimager) user@pc2:~/image_server$ teleimager-server
-
On the local host, execute the following command to subscribe to the images
(tv) user@host:~$ cd ~/tele_robot/teleop/teleimager/src (tv) user@host:~/tele_robot/teleop/teleimager/src$ python -m teleimager.image_client --host 192.168.123.164 # If the WebRTC image stream is set up, you can also open the URL [https://192.168.123.164:60001](https://192.168.123.164:60001) in a browser and click the Start button to test.
- Everyone must keep a safe distance from the robot to prevent any potential danger!
- Please make sure to read the Official Documentation at least once before running this program.
- To use motion mode (with
--motion), ensure the robot is in control mode (via R3 remote).- In motion mode:
- Right controller A = Exit teleop
- Both joysticks pressed = soft emergency stop (switch to damping mode)
- Left joystick = drive directions;
- right joystick = turning;
- max speed is limited in the code.
Same as simulation but follow the safety warnings above.
To avoid damaging the robot, it is recommended to position the robot's arms close to the initial pose before pressing q to exit.
In Debug Mode: After pressing the exit key, both arms will return to the robot's initial pose within 5 seconds, and then the control will end.
In Motion Mode: After pressing the exit key, both arms will return to the robot's motion control pose within 5 seconds, and then the control will end.
Same as simulation but follow the safety warnings above.
tele_robot/
β
βββ assets [Stores robot URDF-related files]
β
βββ teleop
β βββ teleimager [Image service library, supporting multiple features]
β β
β βββ televuer
β β βββ src/televuer
β β βββ television.py [Captures head, wrist, and hand/controller data from XR devices using Vuer]
β β βββ tv_wrapper.py [Post-processing of captured data]
β β βββ test
β β βββ _test_television.py [Test program for television.py]
β β βββ _test_tv_wrapper.py [Test program for tv_wrapper.py]
β β
β βββ robot_control
β β βββ src/dex-retargeting [Dexterous hand retargeting algorithm library]
β β βββ robot_arm_ik.py [Inverse kinematics for the arm]
β β βββ robot_arm.py [Controls dual-arm joints and locks other parts]
β β βββ hand_retargeting.py [Wrapper for the dexterous hand retargeting library]
β β βββ robot_hand.py [Controls dexterous hand / suction cup]
β β
β βββ utils
β β βββ episode_writer.py [Used to record data for imitation learning]
β β βββ weighted_moving_filter.py [Filter for joint data]
β β βββ rerun_visualizer.py [Visualizes recorded data]
β β βββ ipc.py [Handles inter-process communication with proxy programs]
β β βββ motion_switcher.py [Switches motion control states]
β β βββ sim_state_topic.py [For simulation deployment]
β β
β βββ teleop_hand_and_arm.py [Startup script for teleoperation]
please see Device document.
This code builds upon following open-source code-bases. Please visit the URLs to see the respective LICENSES:
- https://github.com/OpenTeleVision/TeleVision
- https://github.com/dexsuite/dex-retargeting
- https://github.com/vuer-ai/vuer
- https://github.com/stack-of-tasks/pinocchio
- https://github.com/casadi/casadi
- https://github.com/meshcat-dev/meshcat-python
- https://github.com/zeromq/pyzmq
- https://github.com/Dingry/BunnyVisionPro
- https://github.com/ARCLab-MIT/beavr-bot
- https://github.com/unitreerobotics/xr_teleoperate
@misc{tele-robot,
author = {{robotics}},
title = {{Tele-Robot}: An Open-Source Teleoperation Framework and Data Collection Toolkit for Embodied Intelligence},
howpublished = {\url{https://github.com/MatrixZTlab/tele_robot}},
year = {2024},
note = {Accessed: 2026-02}
}