> ## Documentation Index
> Fetch the complete documentation index at: https://docs.generalrobotics.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Universal Robots UR3e Arm

> The Universal Robots UR3e Arm as GRID drives it

The Universal Robots UR3e Arm as GRID drives it — what this robot actually implements, with the signatures it actually accepts.

`make_robot("<name>")` returns a `RemoteRobot`. Its attributes are the methods and subcomponents below, and every call runs on the robot; the driver behind it is `UR3e`. Connecting neither starts nor moves the robot — it attaches to one that is already up. A method that fails on the robot arrives as `RuntimeError` naming the original error in its message. The client packages this page uses are preinstalled in every GRID session workspace and in the Python environment the GRID CLI prepares when you run a program with `skill run`; there is nothing to install.

```python theme={null}
from grid_nexus_client import make_robot

robot = make_robot("<ur3e-name>")
```

## Methods on the robot

Called as `robot.<method>(...)`.

### `addNamedPose()`

```python Signature theme={null}
addNamedPose(pose_name: str, joint_angles: List[float]) -> None
```

Define a pose\_name:joint\_angles pair in the dictionary of named poses
(overriding any existing pair).

<ParamField body="pose_name" required>
  Name of the pose to define
</ParamField>

<ParamField body="joint_angles" required>
  List of joint angles in radians
</ParamField>

**Raises:**

ValueError: If the length of joint\_angles list does match the length of other named
poses

### `endFreeDrive()`

```python Signature theme={null}
endFreeDrive() -> None
```

Exit free-drive mode and return to position control.

The arm is no longer movable by hand and again responds to
position-control commands such as `moveToPose` and
`setJointAngles`.

**Raises:**

RuntimeError: If the robot is in read only mode or the
controller rejects the end-teach-mode request.

### `followJointTrajectory()`

```python Signature theme={null}
followJointTrajectory(
    angles: List[List[float]],
    duration: Union[float, List[float]],
    blocking: bool = True,
) -> None
```

Move the arm through a sequence of joint configurations.

Each waypoint in `angles` is visited in order. The arm briefly
stops at every intermediate waypoint — this implementation is a
per-segment loop over `setJointAngles`, not a blended
trajectory.

<ParamField body="angles" required>
  Sequence of joint configurations (radians) to visit in order. Each inner list must have 6 elements (one per UR joint).
</ParamField>

<ParamField body="duration" required>
  Either a single positive float giving the total trajectory time in seconds (split evenly across segments), or a list of positive floats with the same length as `angles` giving the duration of each segment from the previous pose to `angles[i]`.
</ParamField>

<ParamField body="blocking" default="True">
  Wait for the final segment to complete before returning. Intermediate segments are always blocking. Defaults to True.
</ParamField>

**Raises:**

ValueError: If `angles` is empty, `duration` is not
positive, or list-form `duration` length does not match
`angles`.
RuntimeError: If the robot is in read only mode or any
segment command is rejected.

### `getEndEffectorForce()`

```python Signature theme={null}
getEndEffectorForce() -> np.ndarray
```

Get the current end effector force (x, y, z, rx, ry, rz)

### `getEndEffectorPose()`

```python Signature theme={null}
getEndEffectorPose() -> Pose
```

```text theme={null}
[Deprecated]
Get the current end effector pose (position + orientation) w.r.t. the base frame.
```

### `getEndEffectorPosition()`

```python Signature theme={null}
getEndEffectorPosition(*, normalized: bool = True) -> float
```

Return the continuous end-effector position.

<ParamField body="normalized" default="True">
  If True, return the position normalized against the auto-calibrated travel range. If False, return the raw Robotiq encoder value on its fixed 0-255 scale. Defaults to True.
</ParamField>

**Returns:**

```text theme={null}
Current position. With ``normalized=True``, the inclusive range is
[0.0, 1.0], where 0.0 is fully open and 1.0 is fully closed. With
``normalized=False``, the value is the raw encoder reading in
[0.0, 255.0].
```

**Raises:**

RuntimeError: If no end effector is configured or the configured
end effector is not a Robotiq gripper with continuous-position
feedback.

### `getImage()`

```python Signature theme={null}
getImage(camera_name: str = '', **kwargs) -> Image
```

Return the image of camera.

Which camera a no-argument call reads is decided by cardinality
alone — no robot, config, or class declares a default. A robot with
exactly one camera needs no name; a robot with several requires one,
so adding a second camera never silently changes which one a bare
`getImage()` returns.

<ParamField body="camera_name" type="str" default="''">
  Name of the camera to get image from — either a directly attached camera's name or a `/`-separated path through subcomponents to a nested one (`left_arm/wrist`). May be omitted when the robot has exactly one camera.
</ParamField>

<ParamField body="**kwargs">
  Forwarded to the underlying sensor's `getImage`. Lets callers pass camera-specific options (e.g. `image_type="depth"`, `compressed=False`) without the base class having to enumerate them.
</ParamField>

**Returns:**

Image: The captured image.

**Raises:**

RuntimeError: If no cameras are configured, or the name is
omitted on a robot with more than one camera; the message
lists every configured camera path.
KeyError: If camera\_name is given but names no camera on this robot.

### `getInverseKinematics()`

```python Signature theme={null}
getInverseKinematics(
    position: Position,
    orientation: Orientation,
    qnear: Optional[List[float]] = None,
) -> List[float]
```

Solve inverse kinematics for a target end-effector pose (base frame).

Maps a Cartesian tool pose to the 6 joint angles that reach it. Used to
recover the joint-space command behind a Cartesian
`moveToPose(high_frequency=True)` stream (e.g. labelling a VR teleop
takeover for DAgger).

<ParamField body="position" required>
  Target tool position in meters, in the robot base frame.
</ParamField>

<ParamField body="orientation" required>
  Target tool orientation, in the robot base frame.
</ParamField>

<ParamField body="qnear">
  Joint positions (radians) used to disambiguate the solution; the IK closest to `qnear` is returned (pass the current joints to avoid elbow/wrist flips). When None, the controller uses the current joint positions.
</ParamField>

**Returns:**

The 6 joint angles in radians that reach the pose.

**Raises:**

RuntimeError: If the robot is in read-only mode (the control
interface needed to solve IK is not connected).

### `getJointAngles()`

```python Signature theme={null}
getJointAngles() -> list
```

Get a list of the 6 current joint angles in radians

**Returns:**

list: List of current joint angles in radians

### `getJointTorques()`

```python Signature theme={null}
getJointTorques() -> list
```

Get a list of the 6 current joint torques in Newtons meters

### `getJointVelocities()`

```python Signature theme={null}
getJointVelocities() -> list
```

Get a list of the 6 current joint velocities in radians/second

**Returns:**

list: List of current joint velocities in radians/second

### `getLidarPointCloud()`

```python Signature theme={null}
getLidarPointCloud(lidar_name: str = '') -> Optional[PointCloud]
```

Get a point cloud from the named LiDAR sensor.

<ParamField body="lidar_name" type="str" default="''">
  Name of the lidar. If empty, uses the first available lidar.
</ParamField>

**Returns:**

Optional\[PointCloud]: The point cloud, or None if lidar not found

### `getNamedPose()`

```python Signature theme={null}
getNamedPose(pose_name: str) -> Optional[List[float]]
```

Get the list of joint angles corresponding to a named pose.

<ParamField body="pose_name" required>
  Name of the pose to get (case-insensitive)
</ParamField>

**Returns:**

list: Joint angles (radians) of the named pose, or None if the named pose does not exist

### `getObs()`

```python Signature theme={null}
getObs(
    get_proprioception: bool = True,
    get_camera: bool = True,
    proprioception_items: Optional[List[str]] = None,
    normalize_gripper: bool = True,
) -> Dict
```

Get the current observation from the arm.

<ParamField body="get_proprioception" type="bool" default="True">
  If True, include robot state (joint positions, velocities, end-effector pose, force, torques, gripper). Defaults to True.
</ParamField>

<ParamField body="get_camera" type="bool" default="True">
  If True, include RGB images from all attached cameras. Defaults to True.
</ParamField>

<ParamField body="proprioception_items" type="Optional[List[str]]">
  List of proprioception field names to include. If None, all available fields are returned.
</ParamField>

<ParamField body="normalize_gripper" type="bool" default="True">
  If True, normalize gripper position to \[0, 1]. Defaults to True.
</ParamField>

**Returns:**

```text theme={null}
Dict: Observation dictionary. Proprioception keys (when get_proprioception=True):
    - "joint_positions" (List[float]): Joint angles in radians.
    - "joint_velocities" (List[float]): Joint velocities in rad/s.
    - "end_effector_pose" (Pose): End-effector pose w.r.t. the base frame.
    - "end_effector_force" (List[float]): 6-element wrench
      [fx, fy, fz, tx, ty, tz] (N / N·m).
    - "joint_torques" (List[float]): Joint torques in N·m
      (only when read_only=False).
    - "gripper_pos" (float): Gripper position. Normalized to [0, 1] when
      normalize_gripper=True (0=open, 1=closed); raw hardware position otherwise. Only
      present when an end effector is attached.
    - "gripper_state": Gripper open/closed state. Only present when an end
      effector is attached.
    - "robot_mode" (int): UR robot mode (e.g. 7 = Running).
    Camera keys (when get_camera=True): "{camera_name}" for each camera.
```

**Raises:**

KeyError: If a requested proprioception key is not registered
on this robot.

### `getOrientation()`

```python Signature theme={null}
getOrientation(name: str = '') -> Orientation
```

Get the current end effector orientation with respect to the robot base

**Returns:**

Orientation: Current end effector orientation with respect to the robot base
name (str, optional): Unused

### `getPose()`

```python Signature theme={null}
getPose() -> Pose
```

Get the current end effector pose with respect to the base frame.

**Returns:**

Pose: Current end effector position and orientation

### `getPosition()`

```python Signature theme={null}
getPosition() -> Position
```

Get the current end effector position with respect to the robot base (meters)

**Returns:**

Position: Current end effector position with respect to the robot base

### `getState()`

```python Signature theme={null}
getState(keys: Optional[Union[str, List[str]]] = None) -> Dict[str, Any]
```

Get a live state snapshot of this component's tree.

Recursive walk owned by the base class, following the lifecycle
template: each class contributes only the protected local hook
`_local_state`, and the walk composes the per-component
results into one nested mapping. Subclasses must not replace
this method — per-component state belongs in `_local_state`.

With no `keys`, returns this component's local state merged
with one nested node per subcomponent name — the tree structure
is the nesting itself, and the names mirror `subcomponents`
(and therefore `serialize()` and edge introspection): a
two-arm rig returns `&#123;"left_arm": &#123;"joint_positions": ...&#125;,
"right_arm": &#123;...&#125;&#125;`, and a leaf component returns its local
state alone. A component whose state could not be read (dead
telemetry, not yet started, already shut down) carries an
`"error"` entry — `&#123;"error": "&lt;ExceptionType>: &lt;message>"&#125;`,
with its children still nested alongside — instead of its state
keys. Errors are contained per node: one failing component never
loses the rest of the snapshot, and the walk still descends into
the failing component's children. `"error"` is reserved for
that purpose, and local state keys must not collide with
subcomponent names; a hook violating either is reported as that
node's error.

With `keys`, returns a flat mapping with one entry per match.
Each key is a `/`-separated path through the component tree:
every segment names a subcomponent, and the final segment may
instead name an entry in that component's local state. Because
structure is the nesting, a literal path is the same as plain
indexing — `getState(["left_arm/joint_positions"])` returns
the value of `getState()["left_arm"]["joint_positions"]` — and
a path ending on a subcomponent yields that component's full
nested node. Segments may use shell-style wildcards over
subcomponent names — `*` matches within one chunk and `**`
matches any chain of chunks — so `"*_arm/joint_positions"`
fans out to one entry per arm, keyed by the concrete matched
path. Wildcards never match state entries; only a literal final
segment does. A key that matches nothing raises, so a typo is
loud rather than silently absent. A matched component whose
state read failed yields `&#123;"error": "..."&#125;` at its path.

Keyed reads are lazy: a hook runs only where a key lands — a
literal path executes the final component's hook alone (not the
nodes traversed on the way), a glob executes only the matched
nodes, and each component's hook runs at most once per call
however many keys reach it. Components with a selective-read
hook (`_local_state_entries` — every `Robot` with
registered state getters) go further and execute only the getters a key names, so
a `**` glob probes their registries without touching
hardware. The caller pays only for the state actually
requested; `**` and the no-`keys` form visit the whole tree
because that is the request.

State is cheap by convention: local state carries kinematics,
status, and health — never bulk sensor payloads (camera frames,
point clouds, scans), which stay in their dedicated methods
(`getImage`, `getPointCloud`, ...). Callable on a stopped
tree — reading state after a soft e-stop is when it matters most
— and on a partially started one, where unstarted components
report a per-node error instead of failing the call.

<ParamField body="keys">
  State paths to read, or None for the full nested snapshot. A single string is shorthand for a one-element list.
</ParamField>

**Returns:**

The nested state snapshot when `keys` is None, otherwise a
flat mapping of matched path to state value or nested node.

**Raises:**

TypeError: If `keys` is neither None, a string, nor a
list/tuple of strings.
ValueError: If a key is empty, has an empty path segment, or
matches no subcomponent path or state entry.

### `get_payload()`

```python Signature theme={null}
get_payload() -> Tuple[float, List[float]]
```

Get the payload currently configured on the controller.

**Returns:**

A `(mass, cog)` tuple — mass in kilograms and center of gravity
`[x, y, z]` in meters, displaced from the tool mount in the flange
frame. Reflects whatever was last set, whether from the pendant
installation screen or `set_payload`.

### `grasp()`

```python Signature theme={null}
grasp(
    suction: bool = False,
    *,
    approach_distance: float = 0.03,
    approach_time: float = 2.0,
) -> None
```

Close the gripper to grasp an object.

With `suction=False` (the default) the end effector is closed in
place. With `suction=True` the arm advances `approach_distance`
meters along the gripper's z-axis (the direction the gripper points),
engages the end effector, then retracts to the joint configuration it
was in before the call. Use `suction=True` for end effectors that
need light contact with a target before sealing.

Sets `ee_state` to `CLOSED` on success.

<ParamField body="suction" default="False">
  If True, perform a short approach-then-engage-then-retract motion instead of engaging in place. Defaults to False.
</ParamField>

<ParamField body="approach_distance" default="0.03">
  Distance to advance along the gripper z-axis when `suction=True` (meters). Defaults to 0.03.
</ParamField>

<ParamField body="approach_time" default="2.0">
  Total duration of the approach move when `suction=True` (seconds). Defaults to 2.0.
</ParamField>

**Raises:**

RuntimeError: If the robot is in read only mode or no end
effector is configured.

### `moveToDeltaPose()`

```python Signature theme={null}
moveToDeltaPose(delta_pose: Pose, blocking: bool = True) -> None
```

Offset the robot end effector by the specified delta pose from its current pose
(with respect to the base frame).

<ParamField body="delta_pose" required>
  Pose offset to compose with the current pose. The position is added to the current position and the orientation is composed with the current orientation.
</ParamField>

<ParamField body="blocking" default="True">
  Wait for movement to complete. Defaults to True.
</ParamField>

### `moveToHome()`

```python Signature theme={null}
moveToHome(
    blocking: bool = True,
    *,
    moving_time: float = 2.0,
    accel_time: float = 0.75,
) -> None
```

Move the robot to its predefined home pose.

<ParamField body="blocking" default="True">
  Wait for movement to complete. Defaults to True.
</ParamField>

<ParamField body="moving_time" default="2.0">
  Total duration of the move (seconds). Defaults to 2.0.
</ParamField>

<ParamField body="accel_time" default="0.75">
  Time spent accelerating and decelerating (seconds). Clamped to at most `moving_time / 2`. Defaults to 0.75.
</ParamField>

**Raises:**

RuntimeError: If the robot is in read only mode.

### `moveToNamedPose()`

```python Signature theme={null}
moveToNamedPose(
    pose_name: str,
    blocking: bool = True,
    *,
    moving_time: float = 2.0,
    accel_time: float = 0.75,
) -> None
```

Move the arm to the joint angles of a named pose.

<ParamField body="pose_name" required>
  Name of the pose to move to (case-insensitive).
</ParamField>

<ParamField body="blocking" default="True">
  Wait for movement to complete. Defaults to True.
</ParamField>

<ParamField body="moving_time" default="2.0">
  Total duration of the move (seconds). Defaults to 2.0.
</ParamField>

<ParamField body="accel_time" default="0.75">
  Time spent accelerating and decelerating (seconds). Clamped to at most `moving_time / 2`. Defaults to 0.75.
</ParamField>

**Raises:**

ValueError: If pose\_name is not in `named_poses`.

### `moveToPose()`

```python Signature theme={null}
moveToPose(
    pose: Pose,
    blocking: bool = True,
    *,
    high_frequency: bool = False,
    moving_time: float = 2.0,
    accel_time: float = 0.5,
    avoid_force: bool = False,
    stop_acceleration: float = 5,
    force_threshold: float = 10,
    step_time: float = 0.1,
    lookahead_time: float = 0.03,
    gain: float = 300.0,
) -> None
```

Move the robot end effector to a specified pose with respect to the base frame.

Set `high_frequency=False` (the default) for a normal point-to-point
move that takes `moving_time` seconds end-to-end. Set
`high_frequency=True` to stream a single setpoint from a real-time
control loop (e.g. \~500 Hz) — each call commands one short step of
duration `step_time` and returns immediately, letting the arm follow
a stream of closely-spaced setpoints. Parameters that apply only to the
other mode are silently ignored (each is annotated below).

When `avoid_force=True` the arm stops and raises
`grid_types.ForceThresholdExceeded` if the end-effector force or
torque rises above the configured thresholds.

<ParamField body="pose" required>
  Target pose (position in meters, orientation as a unit quaternion) in the robot's base frame.
</ParamField>

<ParamField body="blocking" default="True">
  Wait for the move to complete. Ignored when `high_frequency=True` (those calls always return immediately). Defaults to True.
</ParamField>

<ParamField body="high_frequency" default="False">
  Select between a normal point-to-point move (False) and a single streaming control step (True). Defaults to False.
</ParamField>

<ParamField body="moving_time" default="2.0">
  Total duration of the move (seconds). Used only when `high_frequency=False`. Defaults to 2.0.
</ParamField>

<ParamField body="accel_time" default="0.5">
  Time spent accelerating and decelerating (seconds). Clamped to at most `moving_time / 2`. Used only when `high_frequency=False`. Defaults to 0.5.
</ParamField>

<ParamField body="avoid_force" default="False">
  If True, stop and raise `RuntimeError` when the end-effector force or torque rises above the configured thresholds. Requires `blocking=False`: force monitoring runs the move asynchronously, so it cannot also block. Defaults to False.
</ParamField>

<ParamField body="stop_acceleration" default="5">
  Deceleration (m/s^2) used when stopping on a force/torque trigger. Used only when `high_frequency=False`. Defaults to 5.0.
</ParamField>

<ParamField body="force_threshold" default="10">
  Force (N) above the pre-move baseline that triggers a stop. Used only when `high_frequency=False`. Defaults to 10.0.
</ParamField>

<ParamField body="step_time" default="0.1">
  Duration of one high-frequency step (seconds). Used only when `high_frequency=True`. Defaults to 0.1.
</ParamField>

<ParamField body="lookahead_time" default="0.03">
  Smoothing horizon for the high-frequency tracking controller (seconds). Larger values smooth the trajectory at the cost of responsiveness. Clamped to \[0.03, 0.2]. Used only when `high_frequency=True`. Defaults to 0.03.
</ParamField>

<ParamField body="gain" default="300.0">
  Proportional gain of the high-frequency tracking controller. Lower values give faster reaction; higher values reduce overshoot but may cause jerkiness or oscillation. Clamped to \[100, 2000]. Used only when `high_frequency=True`. Defaults to 300.0.
</ParamField>

**Raises:**

ValueError: If `moving_time`, `accel_time`, or `step_time` are
not positive numbers, or if `avoid_force=True` is combined
with `blocking=True`.
RuntimeError: If the robot is in read only mode, the move command
is rejected, `avoid_force=True` and the end-effector
force/torque exceeds the configured thresholds, or a compliant
servo overlay is active — pose targets cannot be routed into
it (stop it with `stopCompliantServo()` first).

### `network_addresses()`

```python Signature theme={null}
network_addresses(args: dict) -> List[str]
```

Controller addresses a routing check should verify for these args.

<ParamField body="args" required>
  Config `args` for this robot, as the wizard collected them.
</ParamField>

**Returns:**

The controller address, or none when no address is configured.

### `release()`

```python Signature theme={null}
release()
```

Open the gripper to release an object.

Only works if an end effector is configured. Changes ee\_state to OPEN.

**Raises:**

RuntimeError: If the robot is in read only mode or no end
effector is configured.

### `removeNamedPose()`

```python Signature theme={null}
removeNamedPose(pose_name: str) -> Optional[List[float]]
```

Remove a named pose from the dictionary of pose\_name:joint\_angles pairs.

<ParamField body="pose_name" required>
  Name of the pose to remove (case-insensitive)
</ParamField>

**Returns:**

list: Joint angles (radians) of the named pose that was removed, or None if the named
pose did not exist

### `retract()`

```python Signature theme={null}
retract(linear_distance: float = 0.0, angular_distance: float = 0.0) -> None
```

Back the arm off along the current contact force/torque direction.

Intended for use after catching a `RuntimeError` from a force-aware
motion command. With both distances at 0.0 (default), retracts until
the contact wrench settles. With a positive distance, retracts that
far along the contact direction.

<ParamField body="linear_distance" default="0.0">
  Cartesian back-off distance in meters. 0.0 retracts until force settles.
</ParamField>

<ParamField body="angular_distance" default="0.0">
  Wrist back-off rotation in radians. 0.0 retracts until torque settles.
</ParamField>

### `setEndEffectorPosition()`

```python Signature theme={null}
setEndEffectorPosition(position: float, *, blocking: bool = False) -> None
```

Command a normalized continuous end-effector position.

On success, `ee_state` is updated immediately to the binary target
implied by `position`. For a nonblocking call this is optimistic
command state, not observed jaw feedback; use
`getEndEffectorPosition` to read the current hardware position.

<ParamField body="position" required>
  Normalized target in the inclusive range \[0.0, 1.0], where 0.0 is fully open and 1.0 is fully closed.
</ParamField>

<ParamField body="blocking" default="False">
  If True, wait until the gripper stops moving because it reached the target or stalled against an object. If False, return after the command is accepted. Defaults to False.
</ParamField>

**Raises:**

RuntimeError: If the robot is read-only, no end effector is
configured, or the configured end effector is not a Robotiq
gripper with continuous-position control.
ValueError: If `position` is not a finite number in \[0.0, 1.0].

### `setJointAngles()`

```python Signature theme={null}
setJointAngles(
    angles: List[float],
    blocking: bool = True,
    *,
    high_frequency: bool = False,
    moving_time: float = 2.0,
    accel_time: float = 0.5,
    avoid_force: bool = False,
    stop_acceleration: float = 5,
    force_threshold: float = 10,
    step_time: float = 0.1,
    lookahead_time: float = 0.03,
    gain: float = 300.0,
) -> None
```

Move the arm joints to the specified target angles.

Set `high_frequency=False` (the default) for a normal point-to-point
move that takes `moving_time` seconds end-to-end. Set
`high_frequency=True` to stream a single setpoint from a real-time
control loop (e.g. \~500 Hz) — each call commands one short step of
duration `step_time` and returns immediately, letting the arm follow
a stream of closely-spaced setpoints. Parameters that apply only to the
other mode are silently ignored (each is annotated below).

When `avoid_force=True` the arm stops and raises
`grid_types.ForceThresholdExceeded` if the end-effector force rises
above the configured threshold.

<ParamField body="angles" required>
  List of 6 target joint angles in radians (one per joint, base to wrist).
</ParamField>

<ParamField body="blocking" default="True">
  Wait for the move to complete. Ignored when `high_frequency=True` (those calls always return immediately). Defaults to True.
</ParamField>

<ParamField body="high_frequency" default="False">
  Select between a normal point-to-point move (False) and a single streaming control step (True). Defaults to False.
</ParamField>

<ParamField body="moving_time" default="2.0">
  Total duration of the move (seconds). Used only when `high_frequency=False`. Defaults to 2.0.
</ParamField>

<ParamField body="accel_time" default="0.5">
  Time spent accelerating and decelerating (seconds). Clamped to at most `moving_time / 2`. Used only when `high_frequency=False`. Defaults to 0.5.
</ParamField>

<ParamField body="avoid_force" default="False">
  If True, stop and raise `RuntimeError` when the end-effector force rises above the configured threshold. Requires `blocking=False`: force monitoring runs the move asynchronously, so it cannot also block. Defaults to False.
</ParamField>

<ParamField body="stop_acceleration" default="5">
  Deceleration (rad/s^2) used when stopping on a force trigger. Used only when `high_frequency=False`. Defaults to 5.0.
</ParamField>

<ParamField body="force_threshold" default="10">
  Force (N) above the pre-move baseline that triggers a stop. Used only when `high_frequency=False`. Defaults to 10.0.
</ParamField>

<ParamField body="step_time" default="0.1">
  Duration of one high-frequency step (seconds). Used only when `high_frequency=True`. Defaults to 0.1.
</ParamField>

<ParamField body="lookahead_time" default="0.03">
  Smoothing horizon for the high-frequency tracking controller (seconds). Larger values smooth the trajectory at the cost of responsiveness. Clamped to \[0.03, 0.2]. Used only when `high_frequency=True`. Defaults to 0.03.
</ParamField>

<ParamField body="gain" default="300.0">
  Proportional gain of the high-frequency tracking controller. Lower values give faster reaction; higher values reduce overshoot but may cause jerkiness or oscillation. Clamped to \[100, 2000]. Used only when `high_frequency=True`. Defaults to 300.0.
</ParamField>

**Raises:**

ValueError: If `moving_time`, `accel_time`, or `step_time`
are not positive numbers, or if `avoid_force=True` is
combined with `blocking=True`.
RuntimeError: If the robot is in read only mode, the move
command is rejected, `avoid_force=True` and the
end-effector force exceeds the configured threshold, or a
blocking move is attempted while the compliant servo overlay
is active (stop it with `stopCompliantServo()` first).

### `set_payload()`

```python Signature theme={null}
set_payload(mass: float, cog: Optional[List[float]] = None) -> None
```

Set the mass and center of gravity of the payload on the flange.

Include the end-effector plus anything it holds. The controller uses this
for its dynamics model + protective-stop monitoring, and on the e-Series
to gravity-compensate the wrist F/T readings from `getEndEffectorForce`
— so a static payload's weight stops reading as an external push. One call
after grasping remains valid as the wrist rotates, as long as the payload
does not shift in the gripper.

<ParamField body="mass" required>
  Payload mass in kilograms.
</ParamField>

<ParamField body="cog">
  Center of gravity `[x, y, z]` in meters, displaced from the tool mount in the flange frame. None sets `[0.0, 0.0, 0.0]`.
</ParamField>

**Raises:**

RuntimeError: If the robot is in read-only mode, or the controller
rejects the payload (mass/CoG outside the robot's rated limits).

### `startCompliantServo()`

```python Signature theme={null}
startCompliantServo(
    *,
    waypoint_hz: float = 100.0,
    force_scale: float = 1.0,
    baseline_duration: float = 3.0,
) -> dict
```

Make the arm compliant to external contact while streaming waypoints.

Built for teleoperation and other force-aware, contact-rich tasks —
wiping a surface, insertion, collecting demonstrations where the arm
presses against fixtures, or policy rollouts near people. It starts an
admittance-control overlay on the arm: streamed high-frequency joint
waypoints are tracked as usual in free space, but on contact the arm
yields along the push and holds a bounded force instead of pushing
harder, then springs back once the push releases. Stop it with
`stopCompliantServo`. The gripper is never commanded by the
overlay.

Call with the arm stationary, contact-free, and at a repeatable pose
(e.g. after `moveToHome()`): the call blocks for
`baseline_duration` seconds measuring the resting force-sensor bias
that contact detection is referenced against.

Idempotent: if an overlay is already running, returns its status
without re-measuring the baseline.

<ParamField body="waypoint_hz" default="100.0">
  Rate (Hz) at which the client streams waypoints; the overlay interpolates between them at the arm's servo rate.
</ParamField>

<ParamField body="force_scale" default="1.0">
  Multiplier in \[0, 1] on the sensed contact force. 1.0 = full tuned compliance; 0.0 = rigid waypoint tracking (contact has no effect, safety limits stay armed).
</ParamField>

<ParamField body="baseline_duration" default="3.0">
  Resting-force sampling window in seconds.
</ParamField>

**Returns:**

Dict with `started` (bool), `already_running` (bool),
`baseline` (list of 6 floats, N / N·m) and `waypoint_hz`.

**Raises:**

RuntimeError: If the arm is read-only.
ValueError: If `waypoint_hz` or `baseline_duration` is not
positive, or `force_scale` is outside \[0, 1].

### `startFreeDrive()`

```python Signature theme={null}
startFreeDrive() -> None
```

Enable free-drive (hand-guided) mode.

The arm becomes compliant and can be moved by hand while supporting
its own weight. Position-control commands such as
`moveToPose` and `setJointAngles` are not active in
this mode — call `endFreeDrive` to return to position
control.

**Raises:**

RuntimeError: If the robot is in read only mode, the controller
rejects the teach-mode request, or a compliant servo overlay
is active (stop it with `stopCompliantServo()` first —
teach mode and the overlay would be two competing writers).

### `stop()`

```python Signature theme={null}
stop(*, immediate: bool = False) -> None
```

Stop any movement of the robot (soft emergency-stop).

This override only *extends* the base component stop with the
`immediate` escape hatch; it never re-implements the recursion.
With `immediate=False` it delegates to `super().stop()` — the
standard recursive walk, which covers the attached end effector
and any other subcomponents, then performs a controlled stop of
the arm. `immediate=True` is a UR-specific hard stop that
halts the arm instantly without walking the tree (an attached
gripper holds its state on its own).

<ParamField body="immediate" default="False">
  If True, stop motion instantly by killing the control script (no controlled deceleration), then reupload it so the arm stays usable for subsequent commands. Use this for an emergency stop. If False, perform a controlled stop and leave the script running. Defaults to False.
</ParamField>

**Raises:**

RuntimeError: If `immediate=True` on an arm that was never
started, so there is no control script to kill; or if
`immediate=True` stopped motion but the control script
could not be restarted (the controller is still in an
emergency or protective stop) — clear the stop on the
robot, then call `start()` to restore control.
ComponentStopError: If `immediate=False` and a stop hook in
the component tree raised; the walk still visits every
component.

### `stopCompliantServo()`

```python Signature theme={null}
stopCompliantServo() -> dict
```

Stop the compliant overlay and return to direct servo streaming.

The overlay's loop performs a controlled stop of the arm on exit.
Idempotent: a no-op when no overlay is running. This is also the
acknowledgment call after the overlay's emergency stop — motion
commands raise until it (or `startCompliantServo()`) is called.

**Returns:**

Dict with `stopped` (bool) and `was_running` (bool) — whether an
overlay existed and whether its loop was still alive.

**Raises:**

RuntimeError: If the overlay thread does not exit within 2 seconds.

### `validateGrasp()`

```python Signature theme={null}
validateGrasp() -> bool
```

Check whether the end effector is currently holding an object.

Thin wrapper that delegates to the configured end effector's
`EndEffector.getGripDetected`. Subclasses generally do not
need to override this.

**Returns:**

True if the end effector reports an object in its grip, False
otherwise.

**Raises:**

RuntimeError: If no end effector is configured on this arm.
NotImplementedError: If the configured end effector does not
support grip detection.

### `waitPeriod()`

```python Signature theme={null}
waitPeriod(t_start: float) -> None
```

Sleep until the end of a real-time control-loop iteration.

Used with `initPeriod` to pace a streaming control loop (see
`initPeriod` for example usage).

<ParamField body="t_start" required>
  Loop-iteration start time returned by `initPeriod`.
</ParamField>

**Raises:**

RuntimeError: If the robot is in read only mode.

## Properties on the robot

Read as `robot.<property>`; each read runs the getter on the robot.

<ResponseField name="control_mode" type="ControlMode">
  The controller mode this driver last commanded.

  Driver-owned: it changes only through the motion API
  (`startFreeDrive`, `endFreeDrive`, the servo/speed/force
  paths and `stop`), never by assignment.
</ResponseField>

<ResponseField name="ee_state" type="int">
  Optimistic binary end-effector command state, `OPEN` (0) or `CLOSED` (1).

  Updated immediately after an accepted gripper command, so it reflects
  the last command issued rather than observed hardware feedback — read
  `getEndEffectorPosition` for the current jaw position.
</ResponseField>

<ResponseField name="force_ema_alpha" type="float">
  Force/torque baseline EMA smoothing factor, in \[0, 1]. Writable.

  Higher values make the baseline track more slowly, increasing
  sensitivity to sudden contacts.
</ResponseField>

<ResponseField name="force_threshold" type="float">
  Linear force delta above the EMA baseline that trips retraction, in N.

  Writable; must be finite and > 0.
</ResponseField>

<ResponseField name="home_pose" type="List[float]">
  Joint angles (radians) with the arm over the workspace, joints at 90 degrees.
</ResponseField>

<ResponseField name="max_joint_acceleration" type="float">
  Cap applied to commanded joint acceleration, in rad/s^2.

  Writable; must be finite and > 0.
</ResponseField>

<ResponseField name="max_joint_speed" type="float">
  Cap applied to commanded joint speed, in rad/s. Writable; must be finite and > 0.
</ResponseField>

<ResponseField name="max_linear_acceleration" type="float">
  Cap applied to commanded tool acceleration, in m/s^2.

  Writable; must be finite and > 0.
</ResponseField>

<ResponseField name="max_linear_speed" type="float">
  Cap applied to commanded tool speed, in m/s. Writable; must be finite and > 0.
</ResponseField>

<ResponseField name="named_poses" type="Dict[str, List[float]]">
  Registered poses as `&#123;name: joint angles in radians&#125;` (a copy).

  Mutating the returned mapping does not change what the arm knows:
  register and remove entries with `addNamedPose` and
  `removeNamedPose`, or assign a whole mapping to replace them all.
</ResponseField>

<ResponseField name="read_only" type="bool">
  Whether this arm was provisioned without a control interface (telemetry only).
</ResponseField>

<ResponseField name="torque_threshold" type="float">
  End-effector torque delta above the EMA baseline that trips retraction, in N·m.

  Writable; must be finite and > 0.
</ResponseField>

## Configured children

* `robot.end_effector` — the gripper, chosen in the robot's configuration; when one is fitted, its methods are the [`EndEffector`](/v2.3/python-api/robot-interface/endeffector) interface's.

## Lifecycle and configuration

The driver's own bring-up and configuration hooks. The edge runs them when the robot comes up; do not call them from a program. Note that `robot.shutdown()` on the proxy is not the method below — it is `RemoteRobot.shutdown()`, which closes your connection and leaves the robot as it was.

* `addSensor()` — Add an external sensor to the robot.
* `addSubcomponent()` — Attach a child component under a name.
* `builtin_subcomponents()` — Declare the children this class always ships with (customization point).
* `configHash()` — Hash this component's serialized config subtree.
* `config_schema()`
* `from_config()` — Construct this component and its config-declared subtree.
* `getIdentity()` — Get this component's own hardware identity (serial, model, version, MAC).
* `getRobotId()` — Stable, readable identifier for a robot or rig, for a database key.
* `initPeriod()` — Mark the start of a real-time control-loop iteration.
* `serialize()` — Serialize this component tree back to its config envelope.
* `setup_shutdown_handlers()` — Register the process-wide atexit and signal handlers for safe teardown.
* `shutdown()` — Shut down this component's tree, halting motion and releasing resources.
* `start()` — Bring this component's tree online (connect, enable, arm).

The contract these methods implement is **Robot interface**; values returned are **grid-types** (camera reads return `Image` — call [`decode()`](/v2.3/python-api/grid-types/image) for an ndarray). You reach the robot through [`make_robot`](/v2.3/python-api/grid-nexus-client/make_robot).


## Related topics

- [Python APIs](/v2.3/python-api/overview.md)
- [Universal Robots UR5e Arm](/v2.3/python-api/ur5e/ur5e.md)
- [RobotFault](/v2.3/python-api/grid-types/robotfault.md)
- [Arm](/v2.3/python-api/robot-interface/arm.md)
- [Flexiv Rizon Arm](/v2.3/python-api/flexiv-rizon/flexivrizon.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.