UBTECH Alpha Servos UBT-12HC icon UBTECH Alpha Servos UBT-12HC — Control UBTECH Alpha UBT-12HC smart servos via ARC using EZ-B v4/IoTiny UART, assign virtual ports, set baud, custom bits and position mapping. Try it →
 
Meta Quest Robot Robot Skill

Meta Quest Robot

by Synthiam Inc

Meta Quest teleoperation for ARCx: stereo video, head-tracked neck, 3D arm control, hand/finger tracking, driving, buttons, safety, haptics

Requires ARCx v1 (Updated 10/12/2026)
Tags: Remote Control Servo Virtual Reality
Compatible with: Compatible with Microsoft Windows 10 or 11 Windows Compatible with ARM Linux (Raspberry pi, etc) ARM Compatible with Linux Linux Compatible with MacOS MacOS

How to add the Meta Quest Robot robot skill

  1. Load the most recent release of ARCx on a compatible operating system (Get ARCx).
  2. Press the + Skills menu from the top menu bar in ARCx.
  3. Choose any of these category tabs, the robot skill appears in each of them: Remote Control, Servo, Virtual Reality.
  4. Press the Meta Quest Robot icon to add the robot skill to your project.

Don't have a robot yet?

Follow the Getting Started Guide to build a robot and use the Meta Quest Robot robot skill.


How to use the Meta Quest Robot robot skill

Become the robot with a Meta Quest headset. Look through the robot's cameras in stereo, and the robot's head turns with yours. Reach out with a controller or your bare hand and the robot's arm reaches with you, in real 3D space, whatever arm it has. Curl your fingers and the robot's fingers curl. Drive with a thumbstick, and run a script from any button.

This is the ARCx version of ARC's Oculus Quest Robot, rebuilt around ARCx's kinematics. The ARC version moved servos straight from numbers squashed into servo positions on the headset; this one receives the headset's real positions (in millimetres) and rotations, and does the robotics in ARCx: true head angles in degrees, arms driven through any kinematic chain, finger curl worked out from the hand skeleton and calibrated to your hand, safety stops, and feedback to the headset.

The skill window with a headset connected

What you need

  • A Meta Quest headset (Quest 2, Quest 3, Quest 3S or Quest Pro) with the ARCx Quest Robot app. This is a new app that only works with ARCx; the old "Quest Robot Controller" app for ARC does not.
  • The headset and the ARCx computer on the same network. 5 GHz Wi-Fi gives the smoothest video.
  • One or two camera robot skills for the view (optional - the headset controls the robot without video).
  • For arms in 3D, a kinematics robot skill such as Kinematics Service describing each arm as a named chain. Without one, an arm can still follow your hand on three plain servos.
  • For driving, a movement panel in the project.

Connecting the headset

  1. The window lists this computer's addresses and the port (8082 unless changed). Allow that port through the computer's firewall.
  2. Start the ARCx Quest Robot app, enter one of the addresses and the port, and choose Connect Single (one screen in front of you) or Connect Dual (stereo, one image per eye).
  3. The window turns green: Active. The direction you face when you connect is the robot's forward; press the left thumbstick at any time to make wherever you face now the robot's forward again (recentre).

The app's Open ARCx button opens ARCx itself in the Quest's browser, so you can change settings without taking the headset off.

The window

The buttons along the top:

Button What it does
Pause / Resume Nothing moves from the headset while paused; the video keeps playing.
Recentre The direction the user faces becomes the robot's forward, and the head servos centre.
Open Hands / Fists Calibrate finger curl to this user's hands (see Fingers).
Unlink Hang up on the headset.

Below them: the status (Active, Paused, Tracking lost, Headset not worn, Headset menu open...), the headset's tracking rate, the video frame rate and bandwidth, the head's yaw, pitch and roll, and a card for each hand showing what is tracking it (a controller or a bare hand), where it is in millimetres, the trigger and grip, the arm's state and each finger's curl.

Head settings

Your head's real angles move the robot's neck. Choose the yaw (turn), pitch (nod) and roll (tilt) servos, and for each a range: how many degrees you turn to take the servos from the middle to their end. Set the range to the neck's real travel (a 180 degree pan servo is 90) and the view moves one to one with your head, which is what makes it comfortable. Turning left, looking up and tilting your right ear down each move towards the servo's maximum; tick Invert on a servo that goes the wrong way.

Hold Head While Driving keeps the view still while the robot drives. Smoothing takes the shake out of the head and the arms; 0 is the most responsive.

Arms

Arm settings

Each hand (Left Hand and Right Hand tabs) can drive an arm in one of two ways.

Kinematics (3D position) - pick the arm's kinematic chain. Your hand's movement in millimetres is sent to the chain, and the kinematics robot skill works out every joint. It works with any arm the kinematics skill can describe, from a 3-joint hobby arm to a 6-joint arm, and it respects that skill's joint limits and floor.

The arm follows your hand with a clutch, as teleoperated surgical and industrial robots do:

  • Hold the grip (the default): the arm follows only while you squeeze the controller's grip. Let go and the arm stays put while you move your hand somewhere comfortable; squeeze again and carry on, so you can reach further than one arm's length by "ratcheting". With a bare hand, pinch your middle finger to your thumb instead.
  • Squeeze the grip to toggle: squeeze once to start following and again to stop.
  • Always follow: whenever the hand is tracked.

When the clutch engages, the skill remembers where your hand and the robot's gripper are, and from then on the gripper moves by however much your hand moves. You never have to line your hand up with the robot's, and the arm never jumps.

Setting What it does
Tracked By The controller, the bare hand, or the controller when it is tracked and the bare hand when you put it down.
Motion Scale Millimetres the arm moves per millimetre of hand. 0.5 for fine work, 2 for a big robot.
Follow Hand Rotation Also turn the gripper as your wrist turns, for chains that can control orientation (usually 5 or 6 joints).
Max Speed The fastest the arm's target may move. A flick of the wrist is spread out so the arm is never asked to jump.
Deadband The hand must move this far before the arm is sent a new target, so a resting hand's tremor does not keep the servos hunting.
Moves Per Second How often the arm is sent a new target.
Workspace Fence A box, in the arm's own frame, the target can never leave: keep the gripper off the table and away from the robot's body.

The controller buzzes when the clutch picks up and lets go, and rumbles while your hand is somewhere the arm cannot reach, so you feel the edge of its workspace.

Servos (forward, left, up) - no kinematics: how far your hand is forward, to the left and up from where it was when you recentred each move a servo. For simple robots, and for projects coming from ARC.

Gripper and fingers

The index trigger positions the gripper servos from their minimum (released) to their maximum (fully pulled). With a bare hand, pinching your index finger to your thumb does the same.

Each of the five fingers has its own servos, from their minimum (straight) to their maximum (curled). With hand tracking, the headset measures how much each of your fingers bends at every knuckle. With a controller, the index trigger curls the index finger, the grip curls the other three, and resting your thumb on a button or the thumb rest curls the thumb.

Everyone's hands are different, so calibrate: put the controllers down, have the user hold both hands up in front of the headset, open and flat, and press Open Hands; then fists, and press Fists. Save the project to keep it. The numbers are also on the hand tabs to adjust by hand.

Driving

The left (or right) thumbstick drives through the project's movement panel: forward and back set the speed, pushing sideways while moving steers, and sideways alone spins in place. Max Turn Speed is separate and lower by default, because spinning quickly is the fastest way to make someone feel sick in VR. The other thumbstick can move two servos of its own.

Buttons

Button scripts

Every button can run a script when pressed and when released: A and B (right controller), X and Y (left controller), pressing either thumbstick, the index triggers, the grips, and a bare hand's index-finger pinch. Press a button on the headset while this tab is open and its row lights up. The recentre button (the left thumbstick unless changed) and an optional pause button do only that. There are also scripts for the headset connecting and disconnecting. The left controller's menu button belongs to the app: it opens the app's menu, and the robot holds still while it is open.

Safety

Setting What it does
Tracking Timeout With no tracking from the headset for this long (Wi-Fi dropped, app closed), driving stops and the arms let go. 500 ms by default.
Stop When Headset Removed The headset's proximity sensor stops everything the moment it comes off.
Start Paused Nothing moves after the project loads until someone resumes.
Pause On Stop Button The ARCx stop button pauses the skill, so the headset cannot move the robot again until someone resumes on purpose.
Haptic Feedback The vibrations described above.

Driving is only ever stopped by this skill if this skill started it, so a script or another skill driving the robot is not interrupted.

Video

Connection and video

Choose the camera for the left eye and, for stereo, the right eye: two cameras side by side about 6 cm apart, like eyes, give real depth. With one camera both eyes see it. The newest frame is always the one sent and older ones are dropped, so a slow network lowers the frame rate rather than adding delay. Lower the JPEG quality or the width for weak Wi-Fi.

Variables

With Set Variables on (Safety tab), the headset's tracking is in global variables for scripts, all starting with the prefix (Quest):

Variables Meaning
$QuestConnected, $QuestPaused, $QuestActive, $QuestWorn true or false
$QuestHeadYaw, $QuestHeadPitch, $QuestHeadRoll Degrees: yaw positive left, pitch positive up, roll positive tilting the right ear down
$QuestLeftX, $QuestLeftY, $QuestLeftZ The left hand in millimetres forward, left and up of where your head was at the last recentre
$QuestLeftRoll, $QuestLeftPitch, $QuestLeftYaw The left hand's orientation in degrees
$QuestLeftTrigger, $QuestLeftGrip 0 to 1 (a bare hand: the index and middle finger pinches)
$QuestLeftStickX, $QuestLeftStickY -1 to 1
$QuestLeftThumb ... $QuestLeftPinky Finger curl, 0 straight to 1 curled
$QuestLeftSource, $QuestLeftArmEngaged Controller, Hand or None; whether the arm is following
$QuestButtonA ... $QuestButtonRightPinch true while held

The same for Right. Positions use the ARCx kinematics frame (+X forward, +Y left, +Z up), so a script can pass them straight to a kinematic chain.

Talking back to the user

A script can show text in front of the user and vibrate the controllers through this skill's control commands, for example to say "Battery low" or to buzz when a sensor sees something. AI assistants connected to ARCx get the same as tools, plus one that reads everything the headset is tracking.

Custom UI

The Quest Status widget shows whether the headset is connected and what it is doing, with Pause and Recentre buttons, for your own control panel screens.


Control Commands for the Meta Quest Robot robot skill

There are Control Commands available for this robot skill which allows the skill to be controlled programmatically from scripts or other robot skills. These commands enable you to automate actions, respond to sensor inputs, and integrate the robot skill with other systems or custom interfaces. If you're new to the concept of Control Commands, we have a comprehensive manual available here that explains how to use them, provides examples to get you started and make the most of this powerful feature.

Control Command Manual

This robot skill has 14 control commands, listed below. Send them from a JavaScript or Python script, from Blockly, or from another robot skill.

The first value is always the window title, which is the name in the title bar of the robot skill on your workspace. It starts out as Meta Quest Robot, which is what every example below uses. If you rename the robot skill, or add a second copy of it to the project, use the title as it appears on that window instead.

ControlCommand() can be shortened to CC(), and both spellings work in JavaScript and in Python. The examples are JavaScript; Python is the same call, except that true and false are written True and False.

CalibrateFists

Remember the user's tracked hands, closed in fists, as fully curled fingers. Returns how many hands were tracked.

Syntax

ControlCommand("Meta Quest Robot", "CalibrateFists")

Returns: Integer [-2,147,483,648 to 2,147,483,647]

Example

var result = ControlCommand("Meta Quest Robot", "CalibrateFists");

CalibrateOpenHands

Remember the user's tracked hands, held open and flat, as straight fingers. Returns how many hands were tracked.

Syntax

ControlCommand("Meta Quest Robot", "CalibrateOpenHands")

Returns: Integer [-2,147,483,648 to 2,147,483,647]

Example

var result = ControlCommand("Meta Quest Robot", "CalibrateOpenHands");

DisconnectHeadset

Hang up on the connected headset. The app can connect again.

Syntax

ControlCommand("Meta Quest Robot", "DisconnectHeadset")

Returns: nothing

Example

ControlCommand("Meta Quest Robot", "DisconnectHeadset");

GetHeadAngles

The user's head angles in degrees as [yaw, pitch, roll]: yaw positive turning left, pitch positive looking up, roll positive tilting the right ear down.

Syntax

ControlCommand("Meta Quest Robot", "GetHeadAngles")

Returns: Array of Double

Example

var result = ControlCommand("Meta Quest Robot", "GetHeadAngles");

IsConnected

Whether a headset running the ARCx Quest Robot app is connected.

Syntax

ControlCommand("Meta Quest Robot", "IsConnected")

Returns: Boolean [true or false]

Example

var result = ControlCommand("Meta Quest Robot", "IsConnected");

IsPaused

Whether the skill is paused.

Syntax

ControlCommand("Meta Quest Robot", "IsPaused")

Returns: Boolean [true or false]

Example

var result = ControlCommand("Meta Quest Robot", "IsPaused");

Pause

Pause: nothing on the robot moves from the headset (head, arms, fingers, driving) until resumed. The video keeps streaming.

Syntax

ControlCommand("Meta Quest Robot", "Pause")

Returns: nothing

Example

ControlCommand("Meta Quest Robot", "Pause");

PauseToggle

Pause when running, resume when paused. Returns true when now paused.

Syntax

ControlCommand("Meta Quest Robot", "PauseToggle")

Returns: Boolean [true or false]

Example

var result = ControlCommand("Meta Quest Robot", "PauseToggle");

Recenter

Make the direction the user faces now the robot's forward, and centre the head servos.

Syntax

ControlCommand("Meta Quest Robot", "Recenter")

Returns: nothing

Example

ControlCommand("Meta Quest Robot", "Recenter");

Resume

Resume after a pause.

Syntax

ControlCommand("Meta Quest Robot", "Resume")

Returns: nothing

Example

ControlCommand("Meta Quest Robot", "Resume");

SetLeftCamera

Show this camera robot skill (video source name) to the left eye, or to both eyes when there is no right camera. An empty name stops the video.

Syntax

ControlCommand("Meta Quest Robot", "SetLeftCamera", (String)videoSourceName)

Parameters

# Name Type What to pass
1 videoSourceName Text Your text, in quotes

Returns: nothing

Example

ControlCommand("Meta Quest Robot", "SetLeftCamera", "videoSourceName");

SetRightCamera

Show this camera robot skill (video source name) to the right eye for stereo. An empty name shows the left camera to both eyes.

Syntax

ControlCommand("Meta Quest Robot", "SetRightCamera", (String)videoSourceName)

Parameters

# Name Type What to pass
1 videoSourceName Text Your text, in quotes

Returns: nothing

Example

ControlCommand("Meta Quest Robot", "SetRightCamera", "videoSourceName");

ShowMessage

Float a line of text in front of the user in the headset for some seconds. Returns whether a headset is connected.

Syntax

ControlCommand("Meta Quest Robot", "ShowMessage", (String)text, (Number)seconds)

Parameters

# Name Type What to pass
1 text Text Your text, in quotes
2 seconds Number A number, without quotes

Returns: Boolean [true or false]

Example

var result = ControlCommand("Meta Quest Robot", "ShowMessage", "text", 0);

Vibrate

Vibrate the headset's controllers. controller is left, right or both; amplitude 0 to 1; durationMs 1 to 5000. Returns whether a headset is connected.

Syntax

ControlCommand("Meta Quest Robot", "Vibrate", (String)controller, (Number)amplitude, (Number)durationMs)

Parameters

# Name Type What to pass
1 controller Text Your text, in quotes
2 amplitude Number A number, without quotes
3 durationMs Number A number, without quotes

Returns: Boolean [true or false]

Example

var result = ControlCommand("Meta Quest Robot", "Vibrate", "controller", 0, 0);

This list is read out of the robot skill itself each time its package is uploaded, so it matches the published version (v1).


ARC Pro

Upgrade to ARC Pro

Get access to the latest features and updates before they're released. You'll have everything that's needed to unleash your robot's potential!