Robots_UpdateRobot
const url = 'https://dev-api.qualiastudios.dev/v1/accounts/example/robots/example';const options = { method: 'PATCH', headers: {'X-API-Key': '<X-API-Key>', 'Content-Type': 'application/json'}, body: '{"name":"example","displayName":"example","robotType":"example","serialNumber":"example","etag":"example","kind":"KIND_UNSPECIFIED","owner":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PATCH \ --url https://dev-api.qualiastudios.dev/v1/accounts/example/robots/example \ --header 'Content-Type: application/json' \ --header 'X-API-Key: <X-API-Key>' \ --data '{ "name": "example", "displayName": "example", "robotType": "example", "serialNumber": "example", "etag": "example", "kind": "KIND_UNSPECIFIED", "owner": "example" }'Edits display_name, robot_type or serial_number. Not the kind.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”The account id.
The robot id.
Query Parameters
Section titled “Query Parameters ”Which fields to change: display_name, robot_type, serial_number.
Request Body required
Section titled “Request Body required ”A robot the account keeps (fleet.robots). Episodes can be recorded on it (Dataset.source_robot) and played on it (Dataset.target_robot).
A gripper design (kind GRIPPER) is the same record: a URDF of one gripper
with the TCP of each hand on it (gripper_tcp, QUA-3188), which is also what
a handheld rig’s trackers are calibrated to and what Rig.gripper points at
(ML-316). Everything that takes a robot name works on it (upload, model,
delete), but it is no robot: ListRobots leaves it out unless asked for
grippers, so it is never the default target, and Robot.config_digest is
always empty (its RobotModel keeps one), so no reach result is keyed by it.
It lives in one workspace. ListRobots with kind = GRIPPER makes the
workspace’s “UMI handheld” gripper (rig_key “umi-handheld”) on first ask: an
ordinary row, editable and deletable like any other.
A robot carries a gripper on its flanges (carried_gripper), set with
SetRobotGripper, and owns it: attaching a gripper copies its URDF, TCP and jaw
into a gripper design of the robot’s own (owner names the robot), so editing
it changes that robot only. An owned gripper is carried by its owner alone, is
included when listing grippers as a source to copy, is deleted with its robot,
by detaching it, or by DeleteRobot on the gripper, and
needs robots:write to change (a workspace-level gripper, such as the
handheld’s, needs rigs:write). Everything that takes a gripper name works on
it (GetRobot, the model, SetGripperTcp, ImportGripperCalibration).
Served by fleet.
object
Accounts/{account}/robots/{robot}
Unique per account.
The robot type key (fleet.robot_type.key), e.g. “openarm”, “franka_fr3”. Empty for a robot defined only by an imported URDF.
Serial number, free text.
Whether the robot has a model (URDF) configured.
RobotModel.config_digest, empty without a model: what reach results are keyed by. Always empty for a gripper design.
When it was registered.
When it last changed.
Sent back on UpdateRobot.
Robot or gripper design. Set by CreateRobot (unset is ROBOT) and never changed.
Kind GRIPPER only: its TCPs.
object
The hands that have a TCP: none, one or both sides.
One hand’s TCP.
object
Which hand.
The link of the gripper’s URDF that tcp is expressed in, with the
side resolved (“openarm_left_ee_base_link”). Empty when the hand has
only a tracker_to_tcp.
The TCP’s pose in link’s frame. Empty when the hand has none.
object
M[0..3] is the first row, m[12..15] the last.
The TCP’s pose in the tracker’s frame: what uploads are resolved with. Unset when the hand has none, so it serves robots only. (— api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: a transform is named by its direction, as TcpCalibration.Hand.tracker_to_tcp is. —)
object
X, y, z in metres.
Roll, pitch, yaw in radians.
The hands’ tracker_to_tcp as a calibration, the form
Datasets.ResolvePoses takes. Set only when resolves_uploads.
object
The uploaded file’s name, e.g. “tcp_calibration.json”.
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.
Both hands, left then right.
One hand’s transform.
object
Which hand.
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
X, y, z in metres.
Roll, pitch, yaw in radians.
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
X, y, z in metres.
Roll, pitch, yaw in radians.
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_
The ingest rig kind this gripper stands for, e.g. “umi-handheld”: what
Dataset.poses_rig names. Unique among workspace-level grippers. Empty for
a gripper that stands for none, and for the gripper a robot owns (see
source_rig_key); a TCP on it serves robots only.
The calibration file’s name, or “tcp-matrix:
“YYYY-MM-DD”: the file’s, or the day the matrix was set (UTC). Empty when a file gave none.
Whether the gripper’s URDF changed since a TCP in a link was set: a re-import changed its digest or took the link away. A stale TCP is shown with a warning and is never composed into a robot’s arm; set it again, every hand that has one in the same call.
Robots can use it: every hand has its TCP in a link and it is not stale.
Uploads can be resolved with it: both hands have a tracker_to_tcp, and
the calibration has a file name and a date.
Sent back on SetGripperTcp and ImportGripperCalibration.
The rig_key of the gripper this one was copied from, e.g.
“umi-handheld”, for the gripper a robot owns; empty otherwise. It says
the gripper is a copy of that rig’s gripper (and so has its controller to
TCP transform), which a copy cannot claim as its own rig_key: uploads are
resolved with the gripper that holds the key.
Kind ROBOT only: the gripper it carries, if any.
object
Accounts/{account}/robots/{robot} of kind GRIPPER, in the robot’s
workspace: the robot’s own gripper (its owner is the robot).
One per arm side the gripper is mounted on.
Where a gripper’s hand link sits on one arm.
object
Which arm.
The robot’s link the gripper hangs off: it must be joined to the arm’s
hand_link by fixed joints only.
The pose of the gripper’s hand link (its TCP link) in parent_link’s
frame. Ignored when baked. The mount is for the link the hand’s TCP is
in when it is set, which must exist then; a TCP set in another link
later composes nothing until the mount is set again.
object
M[0..3] is the first row, m[12..15] the last.
The robot’s own URDF already has the gripper built in, as the gripper
design has it: the mount is the identity on the robot’s link of the
gripper’s link name. The server checks that the two URDFs agree on where
that link is (FAILED_PRECONDITION when they do not) and sets
parent_link and matrix itself.
The mount was filled in by a guess and has not been confirmed.
Sent back on SetRobotGripper.
The gripper’s display name (the one it was copied from), so a robot can say “gripper: KIWI gripper pair” without reading the gripper.
Kind GRIPPER only: accounts/{account}/robots/{robot} of the robot that
owns this gripper. Empty for a workspace-level gripper (the handheld’s, or
a library gripper). Set on CreateRobot (with kind GRIPPER) to make the
named robot’s own gripper, which that robot carries from then on (with no
mounts); never changed after.
(— api-linter: core::0121::no-mutable-cycles=disabled
aip.dev/not-precedent: owner is set once, on CreateRobot, and
never changed (it is IMMUTABLE), so the Robot to Robot reference
cannot form a cycle: a gripper names the robot that owns it, and a
robot never has an owner. —)
The server supports exact staged gripper copy and fenced replacement. Absent on older servers; clients must not assume those guarantees.
The sha256 (lowercase hex) of the robot’s thumbnail, a picture of its model at the default pose that fleet draws when the model is imported (the bytes are GetRobotThumbnail’s). Empty when it has none yet, or when the model was replaced since it was drawn, so a replaced model never shows its old picture.
Responses
Section titled “ Responses ”OK
A robot the account keeps (fleet.robots). Episodes can be recorded on it (Dataset.source_robot) and played on it (Dataset.target_robot).
A gripper design (kind GRIPPER) is the same record: a URDF of one gripper
with the TCP of each hand on it (gripper_tcp, QUA-3188), which is also what
a handheld rig’s trackers are calibrated to and what Rig.gripper points at
(ML-316). Everything that takes a robot name works on it (upload, model,
delete), but it is no robot: ListRobots leaves it out unless asked for
grippers, so it is never the default target, and Robot.config_digest is
always empty (its RobotModel keeps one), so no reach result is keyed by it.
It lives in one workspace. ListRobots with kind = GRIPPER makes the
workspace’s “UMI handheld” gripper (rig_key “umi-handheld”) on first ask: an
ordinary row, editable and deletable like any other.
A robot carries a gripper on its flanges (carried_gripper), set with
SetRobotGripper, and owns it: attaching a gripper copies its URDF, TCP and jaw
into a gripper design of the robot’s own (owner names the robot), so editing
it changes that robot only. An owned gripper is carried by its owner alone, is
included when listing grippers as a source to copy, is deleted with its robot,
by detaching it, or by DeleteRobot on the gripper, and
needs robots:write to change (a workspace-level gripper, such as the
handheld’s, needs rigs:write). Everything that takes a gripper name works on
it (GetRobot, the model, SetGripperTcp, ImportGripperCalibration).
Served by fleet.
object
Accounts/{account}/robots/{robot}
Unique per account.
The robot type key (fleet.robot_type.key), e.g. “openarm”, “franka_fr3”. Empty for a robot defined only by an imported URDF.
Serial number, free text.
Whether the robot has a model (URDF) configured.
RobotModel.config_digest, empty without a model: what reach results are keyed by. Always empty for a gripper design.
When it was registered.
When it last changed.
Sent back on UpdateRobot.
Robot or gripper design. Set by CreateRobot (unset is ROBOT) and never changed.
Kind GRIPPER only: its TCPs.
object
The hands that have a TCP: none, one or both sides.
One hand’s TCP.
object
Which hand.
The link of the gripper’s URDF that tcp is expressed in, with the
side resolved (“openarm_left_ee_base_link”). Empty when the hand has
only a tracker_to_tcp.
The TCP’s pose in link’s frame. Empty when the hand has none.
object
M[0..3] is the first row, m[12..15] the last.
The TCP’s pose in the tracker’s frame: what uploads are resolved with. Unset when the hand has none, so it serves robots only. (— api-linter: core::0140::prepositions=disabled aip.dev/not-precedent: a transform is named by its direction, as TcpCalibration.Hand.tracker_to_tcp is. —)
object
X, y, z in metres.
Roll, pitch, yaw in radians.
The hands’ tracker_to_tcp as a calibration, the form
Datasets.ResolvePoses takes. Set only when resolves_uploads.
object
The uploaded file’s name, e.g. “tcp_calibration.json”.
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.
Both hands, left then right.
One hand’s transform.
object
Which hand.
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
X, y, z in metres.
Roll, pitch, yaw in radians.
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
X, y, z in metres.
Roll, pitch, yaw in radians.
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_
The ingest rig kind this gripper stands for, e.g. “umi-handheld”: what
Dataset.poses_rig names. Unique among workspace-level grippers. Empty for
a gripper that stands for none, and for the gripper a robot owns (see
source_rig_key); a TCP on it serves robots only.
The calibration file’s name, or “tcp-matrix:
“YYYY-MM-DD”: the file’s, or the day the matrix was set (UTC). Empty when a file gave none.
Whether the gripper’s URDF changed since a TCP in a link was set: a re-import changed its digest or took the link away. A stale TCP is shown with a warning and is never composed into a robot’s arm; set it again, every hand that has one in the same call.
Robots can use it: every hand has its TCP in a link and it is not stale.
Uploads can be resolved with it: both hands have a tracker_to_tcp, and
the calibration has a file name and a date.
Sent back on SetGripperTcp and ImportGripperCalibration.
The rig_key of the gripper this one was copied from, e.g.
“umi-handheld”, for the gripper a robot owns; empty otherwise. It says
the gripper is a copy of that rig’s gripper (and so has its controller to
TCP transform), which a copy cannot claim as its own rig_key: uploads are
resolved with the gripper that holds the key.
Kind ROBOT only: the gripper it carries, if any.
object
Accounts/{account}/robots/{robot} of kind GRIPPER, in the robot’s
workspace: the robot’s own gripper (its owner is the robot).
One per arm side the gripper is mounted on.
Where a gripper’s hand link sits on one arm.
object
Which arm.
The robot’s link the gripper hangs off: it must be joined to the arm’s
hand_link by fixed joints only.
The pose of the gripper’s hand link (its TCP link) in parent_link’s
frame. Ignored when baked. The mount is for the link the hand’s TCP is
in when it is set, which must exist then; a TCP set in another link
later composes nothing until the mount is set again.
object
M[0..3] is the first row, m[12..15] the last.
The robot’s own URDF already has the gripper built in, as the gripper
design has it: the mount is the identity on the robot’s link of the
gripper’s link name. The server checks that the two URDFs agree on where
that link is (FAILED_PRECONDITION when they do not) and sets
parent_link and matrix itself.
The mount was filled in by a guess and has not been confirmed.
Sent back on SetRobotGripper.
The gripper’s display name (the one it was copied from), so a robot can say “gripper: KIWI gripper pair” without reading the gripper.
Kind GRIPPER only: accounts/{account}/robots/{robot} of the robot that
owns this gripper. Empty for a workspace-level gripper (the handheld’s, or
a library gripper). Set on CreateRobot (with kind GRIPPER) to make the
named robot’s own gripper, which that robot carries from then on (with no
mounts); never changed after.
(— api-linter: core::0121::no-mutable-cycles=disabled
aip.dev/not-precedent: owner is set once, on CreateRobot, and
never changed (it is IMMUTABLE), so the Robot to Robot reference
cannot form a cycle: a gripper names the robot that owns it, and a
robot never has an owner. —)
The server supports exact staged gripper copy and fenced replacement. Absent on older servers; clients must not assume those guarantees.
The sha256 (lowercase hex) of the robot’s thumbnail, a picture of its model at the default pose that fleet draws when the model is imported (the bytes are GetRobotThumbnail’s). Empty when it has none yet, or when the model was replaced since it was drawn, so a replaced model never shows its old picture.
Example
{ "kind": "KIND_UNSPECIFIED", "gripperTcp": { "hands": [ { "side": "SIDE_UNSPECIFIED" } ], "calibration": { "hands": [ { "side": "SIDE_UNSPECIFIED" } ] } }, "carriedGripper": { "mounts": [ { "side": "SIDE_UNSPECIFIED" } ] }}default
Section titled “default ”Default error response
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
The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
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.
A list of messages that carry the error details. There is a common set of message types for APIs to use.
Contains an arbitrary serialized message along with a @type that describes the type of the serialized message.
object
The type of the serialized message.
Example generated
{ "code": 1, "message": "example", "details": [ { "@type": "example" } ]}