For the complete documentation index, see llms.txt. This page is also available as Markdown.

Coordinate Systems

MultiSet VPS returns poses in left-handed Y-up (Unity, the default) or right-handed Y-up (ARKit, ARCore, WebXR) coordinates via the isRightHanded flag.

Overview

Every successful localization returns a 6-DoF pose: a position (x, y, z) in meters and a rotation quaternion (x, y, z, w), both expressed in the map's coordinate space.

MultiSet supports two coordinate conventions for that pose, and both are Y-up:

Convention
Flag
Ecosystem

Left-handed, Y-up (LHS)

isRightHanded: false (default)

Unity, MultiSet Quest SDK, MultiSet App

Right-handed, Y-up (RHS)

isRightHanded: true

ARKit (iOS), ARCore (Android), WebXR, Three.js, OpenGL

LHS is the map's native frame: it is how poses are stored internally, and it is what you get when the flag is omitted. Setting isRightHanded: true asks the server to convert the pose before returning it.

The two frames share the same origin, the same up axis, and the same scale. They differ by a mirror across the YZ plane: the X axis is negated. The same physical camera pose therefore has identical y and z values in both, with an opposite sign on x.

Two coordinate frames side by side. Left: left-handed Y-up, isRightHanded false, the default, used by Unity SDK, Quest SDK and MultiSet App, with a camera at position 3.00, 1.60, 5.50 and rotation 0.00, 0.38, 0.00, 0.92. Right: right-handed Y-up, isRightHanded true, used by iOS ARKit, Android ARCore and WebXR or Three.js, with the same physical camera at position -3.00, 1.60, 5.50 and rotation 0.00, -0.38, 0.00, 0.92. The frames are mirrored across the YZ plane: negate x on position, negate y and z on the rotation quaternion.
The same physical camera pose, described in both conventions

Which convention should I use?

Platform
Frame it works in
What to do

Unity SDK

Left-handed, Y-up

Nothing. The SDK uses the default and places content directly.

MultiSet Quest SDK

Left-handed, Y-up

Nothing. Unity based, so the default applies.

iOS native (ARKit)

Right-handed, Y-up

Send isRightHanded: true

Android native (ARCore)

Right-handed, Y-up

Send isRightHanded: true

WebXR SDK (Three.js / Needle)

Right-handed, Y-up

Send isRightHanded: true (the WebXR SDK already defaults to it)

Custom REST integration

Your choice

Pick the one that matches your renderer or engine

If your stack is right-handed but not Y-up (for example ROS, which is right-handed Z-up), request the RHS Y-up pose and apply your own axis swap on top of it.


Setting the flag

isRightHanded is optional on every query endpoint and defaults to false.

Endpoint
Body type
Value to send

POST /vps/map/query

JSON

"isRightHanded": true

POST /vps/map/query-form

form-data

isRightHanded=true (string)

POST /vps/map/multi-image-query

form-data

isRightHanded=true (string)

POST /vps/object/query

form-data

isRightHanded=true (string)


Example: the same query in both conventions

Left-handed (default)

Drop this straight into a Unity Transform:

Right-handed

Drop this straight into a Three.js object:

The same request as form-data:


Converting a pose yourself

If you receive a pose in one convention and need the other, mirror it across the YZ plane: negate position.x, negate rotation.y and rotation.z, and leave everything else alone. The operation is its own inverse, so the same function converts in both directions.


What isRightHanded does not change

The flag governs the pose the API returns. Several other values are always expressed in the map's native left-handed frame, no matter what you set:

Value
Frame
Notes

Always LHS

Convert an RHS position to LHS before sending it as a hint

Unaffected

A Y-axis band, and Y is identical in both conventions

Unaffected

Latitude, longitude, and altitude. The server converts it to LHS internally

GeoPose response

Unaffected

The server un-mirrors the pose before georeferencing, so GeoPose is the same either way

Georeference API local coordinates

Always LHS

Alignment points must be supplied in LHS

Simulation data capture poses

Always LHS

Convert RHS captures before uploading the manifest

Multi frame query

The multi frame query also takes a per-frame trackingPose from your local SLAM session. These are fused with the per-image estimates, so send them in the same convention you declared with isRightHanded: RHS tracking poses with isRightHanded: true, LHS tracking poses with the default. The trackingPose echoed back in the response is your input, returned unchanged.

Object Tracking query

Object Tracking uses the same flag. It applies to the detected object's pose in the camera frame: LHS by default, RHS when isRightHanded: true.

Last updated

Was this helpful?