Skip to content

Rigs_UpdateRig

PATCH
/v1/accounts/{account}/rigs/{rig}
curl --request PATCH \
--url https://dev-api.qualiastudios.dev/v1/accounts/example/rigs/example \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <X-API-Key>' \
--data '{ "name": "example", "displayName": "example", "key": "example", "kind": "KIND_UNSPECIFIED", "robot": "example", "mounts": [ { "side": "SIDE_UNSPECIFIED", "trackerPose": { "xyz": [ 1 ], "rpy": [ 1 ] }, "openAngle": 1, "closedAngle": 1 } ], "etag": "example", "gripper": "example" }'

Edits a rig. An edit changes no dataset: ingest does not read this record. An upload is converted with the rig it declares (meta/ingest.toml [rig], else the built-in profile) and records that rig in its calibration document.

Nobody edits the built-in UMI rig (FAILED_PRECONDITION), except to give it a gripper: with an update_mask of exactly gripper and a gripper set, the account gets its own copy of the rig (no calibration) carrying it, and the response is that copy, a different rig name from the request. The copy takes the built-in’s place in the account’s list. If the account already has its own rig with that key, ALREADY_EXISTS: set the gripper on that rig.

account
required
string

The account id.

rig
required
string

The rig id.

updateMask
string format: field-mask

Which fields to change: display_name, robot, mounts, gripper. * is all of them, so an unset gripper clears the rig’s. An empty gripper in the mask removes the design from the rig (the design itself stays; it is a robot). The calibration is set only by ImportCalibration.

Media type application/json

A capture rig: what episodes are recorded with. An arm rig drives a fleet robot; a handheld (UMI) rig carries trackers whose fixed mount to each gripper root belongs here, not to any robot (QUA-2337). Episodes name their rig by key (Episode.rig).

The UMI handheld rig (key umi-handheld) is built in: every account lists and reads it under its own name, and nobody edits or deletes it (FAILED_PRECONDITION). An account rig with the same key takes its place, so an account records its own calibration of its UMI pair by creating one, or by setting a gripper on the built-in (UpdateRig), which makes that copy itself. An account may delete its copy; it then lists the built-in again, uncalibrated.

A handheld rig may carry the TCP calibration of its trackers (calibration) and the design of its gripper (gripper, a Robot of kind GRIPPER): the gripper’s URDF, with the calibration saying where on it the TCP is. Both are a record on the rig: importing or replacing either changes no dataset. Ingest reads only the calibration’s tracker_to_tcp, filename and derive_date; the gripper design and the calibration’s end-effector fields (ee_link, ee_to_tcp) are for display.

Served by fleet.

object
name

Accounts/{account}/rigs/{rig}

string
displayName
required

Human name.

string
key
required

What recordings carry as their rig id (meta/ingest.toml, LeRobot robot_type). Unique per account; 1 to 128 letters, digits, ’.’, ’_’, ’:’ or ’-’, starting with a letter or digit. Fixed at creation.

string
kind
required

Arm or handheld.

string format: enum
Allowed values: KIND_UNSPECIFIED ARM HANDHELD
robot

Arm rig: accounts/{account}/robots/{robot} it drives, so its episodes get forward kinematics on that robot’s model. A robot (not a gripper design) of the rig’s own account; deleting the robot clears it. A handheld rig has none.

string
mounts

Handheld rig: one mount per tracked hand, at least one, at most one per side. An arm rig has none.

Array<object>

One tracker’s fixed mount.

object
side
required

Which hand.

string format: enum
Allowed values: SIDE_UNSPECIFIED SIDE_LEFT SIDE_RIGHT
trackerPose
required

The fixed mount: the tracker’s pose in its gripper root’s frame (x along the fingers, y the way the jaw opens, z along the hinge): xyz in metres and rpy in radians like every Transform. meta/ingest.toml’s [rig.mount.] gives the same pose with rpy in degrees. Unset xyz or rpy read as zeros.

object
xyz

X, y, z in metres.

Array<number>
rpy

Roll, pitch, yaw in radians.

Array<number>
openAngle

The gripper’s closure calibration: the raw angle fully open.

number format: double
closedAngle

The raw angle shut.

number format: double
createTime

When it was created.

string format: date-time
updateTime

When it last changed.

string format: date-time
etag

Sent back on UpdateRig.

string
calibration

Handheld rig: where each tracker’s TCP is, from the last ImportCalibration. Unset until one is imported, and never set on the built-in rig. Not editable through UpdateRig.

object
filename
required

The uploaded file’s name, e.g. “tcp_calibration.json”.

string
deriveDate

When the calibration was made, “YYYY-MM-DD”: the leading date of the file’s calibrated or else its derived text. Empty when the file gives none.

string
hands
required

Both hands, left then right.

Array<object>

One hand’s transform.

object
side
required

Which hand.

string format: enum
Allowed values: SIDE_UNSPECIFIED SIDE_LEFT SIDE_RIGHT
trackerToTcp
required

The TCP’s pose in the tracker’s frame: xyz in metres and rpy in radians (URDF convention, extrinsic XYZ), the file’s rotation matrix converted. A rotation whose pitch is within a hair of +-90 degrees has no unique roll and yaw; it is stored with roll 0. (— api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: a transform is named by its direction, as the calibration file’s own controller_to_tcp is. —)

object
xyz

X, y, z in metres.

Array<number>
rpy

Roll, pitch, yaw in radians.

Array<number>
eeToTcp

The same TCP in the frame of the gripper design’s ee_link for this hand, in the form of tracker_to_tcp (so the same pitch limit). Display only. Set with ee_link or not at all, and only when it composes with the file’s controller_to_ee to the file’s controller_to_tcp, which is what makes the TCP drawn the TCP used. (— api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: a transform is named by its direction, as the calibration file’s own ee_to_tcp is. —)

object
xyz

X, y, z in metres.

Array<number>
rpy

Roll, pitch, yaw in radians.

Array<number>
eeLink

The link of the rig’s gripper design that Hand.ee_to_tcp is a pose in, with {side} for “left” or “right” (the gripper joint’s convention in RobotModel.Gripper), e.g. “openarm_{side}_ee_base_link”. Read from the file’s own description of its end-effector frame. Empty when the file names none, lacks the end-effector poses, or they disagree with its controller_to_tcp (then no ee_to_tcp is set either). Display only.

ee_to_tcp is drawn in this link’s own frame, which must be the plain end-effector frame the file means. An export whose link sits elsewhere draws the TCP off by the difference: an OpenArm exported with the xacro default collapse_internal_empty_links puts openarm__ee_base_link at link7, 20.5 mm behind the frame the calibration is in.

string
builtin

Whether this is a built-in rig (the UMI handheld rig): read only, the same in every account. Setting a gripper on one makes the account’s own copy.

boolean
gripper

Handheld rig: accounts/{account}/robots/{robot} of kind GRIPPER, the design of its gripper (a URDF, imported as a robot model). A design of the rig’s own account; deleting the design clears it. A design lives in one workspace, like any robot, and a rig in none, so this may name a design of any workspace of the account, and Robots.GetRobot finds it only from that workspace. Set with UpdateRig (CreateRig refuses it); on the built-in rig that makes the account’s own copy, uncalibrated. An arm rig has none; it names a robot.

string

OK

Media type application/json

A capture rig: what episodes are recorded with. An arm rig drives a fleet robot; a handheld (UMI) rig carries trackers whose fixed mount to each gripper root belongs here, not to any robot (QUA-2337). Episodes name their rig by key (Episode.rig).

The UMI handheld rig (key umi-handheld) is built in: every account lists and reads it under its own name, and nobody edits or deletes it (FAILED_PRECONDITION). An account rig with the same key takes its place, so an account records its own calibration of its UMI pair by creating one, or by setting a gripper on the built-in (UpdateRig), which makes that copy itself. An account may delete its copy; it then lists the built-in again, uncalibrated.

A handheld rig may carry the TCP calibration of its trackers (calibration) and the design of its gripper (gripper, a Robot of kind GRIPPER): the gripper’s URDF, with the calibration saying where on it the TCP is. Both are a record on the rig: importing or replacing either changes no dataset. Ingest reads only the calibration’s tracker_to_tcp, filename and derive_date; the gripper design and the calibration’s end-effector fields (ee_link, ee_to_tcp) are for display.

Served by fleet.

object
name

Accounts/{account}/rigs/{rig}

string
displayName
required

Human name.

string
key
required

What recordings carry as their rig id (meta/ingest.toml, LeRobot robot_type). Unique per account; 1 to 128 letters, digits, ’.’, ’_’, ’:’ or ’-’, starting with a letter or digit. Fixed at creation.

string
kind
required

Arm or handheld.

string format: enum
Allowed values: KIND_UNSPECIFIED ARM HANDHELD
robot

Arm rig: accounts/{account}/robots/{robot} it drives, so its episodes get forward kinematics on that robot’s model. A robot (not a gripper design) of the rig’s own account; deleting the robot clears it. A handheld rig has none.

string
mounts

Handheld rig: one mount per tracked hand, at least one, at most one per side. An arm rig has none.

Array<object>

One tracker’s fixed mount.

object
side
required

Which hand.

string format: enum
Allowed values: SIDE_UNSPECIFIED SIDE_LEFT SIDE_RIGHT
trackerPose
required

The fixed mount: the tracker’s pose in its gripper root’s frame (x along the fingers, y the way the jaw opens, z along the hinge): xyz in metres and rpy in radians like every Transform. meta/ingest.toml’s [rig.mount.] gives the same pose with rpy in degrees. Unset xyz or rpy read as zeros.

object
xyz

X, y, z in metres.

Array<number>
rpy

Roll, pitch, yaw in radians.

Array<number>
openAngle

The gripper’s closure calibration: the raw angle fully open.

number format: double
closedAngle

The raw angle shut.

number format: double
createTime

When it was created.

string format: date-time
updateTime

When it last changed.

string format: date-time
etag

Sent back on UpdateRig.

string
calibration

Handheld rig: where each tracker’s TCP is, from the last ImportCalibration. Unset until one is imported, and never set on the built-in rig. Not editable through UpdateRig.

object
filename
required

The uploaded file’s name, e.g. “tcp_calibration.json”.

string
deriveDate

When the calibration was made, “YYYY-MM-DD”: the leading date of the file’s calibrated or else its derived text. Empty when the file gives none.

string
hands
required

Both hands, left then right.

Array<object>

One hand’s transform.

object
side
required

Which hand.

string format: enum
Allowed values: SIDE_UNSPECIFIED SIDE_LEFT SIDE_RIGHT
trackerToTcp
required

The TCP’s pose in the tracker’s frame: xyz in metres and rpy in radians (URDF convention, extrinsic XYZ), the file’s rotation matrix converted. A rotation whose pitch is within a hair of +-90 degrees has no unique roll and yaw; it is stored with roll 0. (— api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: a transform is named by its direction, as the calibration file’s own controller_to_tcp is. —)

object
xyz

X, y, z in metres.

Array<number>
rpy

Roll, pitch, yaw in radians.

Array<number>
eeToTcp

The same TCP in the frame of the gripper design’s ee_link for this hand, in the form of tracker_to_tcp (so the same pitch limit). Display only. Set with ee_link or not at all, and only when it composes with the file’s controller_to_ee to the file’s controller_to_tcp, which is what makes the TCP drawn the TCP used. (— api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: a transform is named by its direction, as the calibration file’s own ee_to_tcp is. —)

object
xyz

X, y, z in metres.

Array<number>
rpy

Roll, pitch, yaw in radians.

Array<number>
eeLink

The link of the rig’s gripper design that Hand.ee_to_tcp is a pose in, with {side} for “left” or “right” (the gripper joint’s convention in RobotModel.Gripper), e.g. “openarm_{side}_ee_base_link”. Read from the file’s own description of its end-effector frame. Empty when the file names none, lacks the end-effector poses, or they disagree with its controller_to_tcp (then no ee_to_tcp is set either). Display only.

ee_to_tcp is drawn in this link’s own frame, which must be the plain end-effector frame the file means. An export whose link sits elsewhere draws the TCP off by the difference: an OpenArm exported with the xacro default collapse_internal_empty_links puts openarm__ee_base_link at link7, 20.5 mm behind the frame the calibration is in.

string
builtin

Whether this is a built-in rig (the UMI handheld rig): read only, the same in every account. Setting a gripper on one makes the account’s own copy.

boolean
gripper

Handheld rig: accounts/{account}/robots/{robot} of kind GRIPPER, the design of its gripper (a URDF, imported as a robot model). A design of the rig’s own account; deleting the design clears it. A design lives in one workspace, like any robot, and a rig in none, so this may name a design of any workspace of the account, and Robots.GetRobot finds it only from that workspace. Set with UpdateRig (CreateRig refuses it); on the built-in rig that makes the account’s own copy, uncalibrated. An arm rig has none; it names a robot.

string
Example
{
"kind": "KIND_UNSPECIFIED",
"mounts": [
{
"side": "SIDE_UNSPECIFIED"
}
],
"calibration": {
"hands": [
{
"side": "SIDE_UNSPECIFIED"
}
]
}
}

Default error response

Media type application/json

The Status type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by gRPC. Each Status message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the API Design Guide.

object
code

The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].

integer format: int32
message

A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.

string
details

A list of messages that carry the error details. There is a common set of message types for APIs to use.

Array<object>

Contains an arbitrary serialized message along with a @type that describes the type of the serialized message.

object
@type

The type of the serialized message.

string
key
additional properties
any
Example generated
{
"code": 1,
"message": "example",
"details": [
{
"@type": "example"
}
]
}