Overview
Abstract base classes for robotic arms (RobotArm) and hands (RobotHand), plus shared joint observables (JointsObservables), defining the standard interface for all manipulator entities in the dm_control Composer framework.
Description
The manipulator base module establishes the architectural foundation for all robotic manipulator entities. RobotArm extends composer.Robot and provides concrete methods for joint position randomization and inverse kinematics (IK), while declaring abstract properties that subclasses must implement.
The randomize_arm_joints method computes valid sampling bounds from the MJCF model (handling both limited and unlimited hinge joints) and sets joint positions to uniform random values within those bounds. The set_site_to_xpos method uses the inverse_kinematics.qpos_from_site_pose solver to position the arm such that a specified site reaches a target Cartesian position and orientation. It supports multiple IK attempts with randomized initial conditions, and canonicalizes joint angles to valid ranges after each successful solve. The default target orientation is DOWN_QUATERNION (pointing vertically downward).
RobotHand extends composer.Robot and declares two abstract members: set_grasp(physics, close_factors) for controlling finger positions (where 0 means fully open and 1 means fully closed), and the tool_center_point property. JointsObservables provides standard joints_pos and joints_vel observables via MJCF feature bindings on the entity's joints.
Usage
Subclass RobotArm to create specific arm implementations (e.g., Jaco, Kinova), implementing the joints and wrist_site abstract properties. Subclass RobotHand for gripper implementations, implementing set_grasp and tool_center_point. These base classes enable interchangeable use of different arm/hand combinations in Composer manipulation tasks.
Code Reference
Source Location
Signature
DOWN_QUATERNION = np.array([0., 0.70710678118, 0.70710678118, 0.])
class RobotArm(composer.Robot, metaclass=abc.ABCMeta):
def _build_observables(self):
...
def randomize_arm_joints(self, physics, random_state):
...
def set_site_to_xpos(self, physics, random_state, site, target_pos,
target_quat=None, max_ik_attempts=10):
...
@property
@abc.abstractmethod
def joints(self):
...
@property
@abc.abstractmethod
def wrist_site(self):
...
class JointsObservables(composer.Observables):
def joints_pos(self):
...
def joints_vel(self):
...
class RobotHand(composer.Robot, metaclass=abc.ABCMeta):
@abc.abstractmethod
def set_grasp(self, physics, close_factors):
...
@property
@abc.abstractmethod
def tool_center_point(self):
...
Import
from dm_control.entities.manipulators import base
from dm_control.entities.manipulators.base import RobotArm, RobotHand
I/O Contract
Inputs (randomize_arm_joints)
| Name |
Type |
Required |
Description
|
| physics |
mujoco.Physics |
Yes |
The compiled physics instance
|
| random_state |
np.random.RandomState |
Yes |
Random number generator for sampling joint positions
|
Inputs (set_site_to_xpos)
| Name |
Type |
Required |
Description
|
| physics |
mujoco.Physics |
Yes |
The compiled physics instance
|
| random_state |
np.random.RandomState |
Yes |
Random number generator for IK retries
|
| site |
mjcf.Element or str |
Yes |
The site to position (element or full name string)
|
| target_pos |
array-like (3,) |
Yes |
Desired Cartesian position of the site
|
| target_quat |
array-like (4,) or None |
No |
Desired orientation as quaternion; defaults to DOWN_QUATERNION
|
| max_ik_attempts |
int |
No |
Maximum IK solver attempts (default 10)
|
Inputs (set_grasp)
| Name |
Type |
Required |
Description
|
| physics |
mjcf.Physics |
Yes |
The compiled physics instance
|
| close_factors |
float or list of floats |
Yes |
Grasp position per finger; 0 = fully open, 1 = fully closed
|
Outputs
| Name |
Type |
Description
|
| randomize_arm_joints |
None (side effect) |
Joint qpos values are set in-place on the physics instance
|
| set_site_to_xpos return |
bool |
True if IK succeeded, False otherwise
|
| joints_pos observable |
numpy.ndarray |
Array of joint position values (qpos)
|
| joints_vel observable |
numpy.ndarray |
Array of joint velocity values (qvel)
|
Abstract Properties
| Class |
Property/Method |
Return Type |
Description
|
RobotArm |
joints |
list of mjcf.Element |
The joint elements of the arm
|
RobotArm |
wrist_site |
mjcf.Element |
The wrist site element (used as attachment site)
|
RobotHand |
set_grasp |
None |
Sets finger positions based on close factors
|
RobotHand |
tool_center_point |
mjcf.Element |
The tool center point site element
|
Usage Examples
from dm_control.entities.manipulators import base
import numpy as np
# Subclass RobotArm for a specific arm implementation
class MyArm(base.RobotArm):
def _build(self):
# Load MJCF model and set up joints, sites, etc.
...
@property
def joints(self):
return self._joints
@property
def wrist_site(self):
return self._wrist_site
# Use the arm in a task
arm = MyArm()
rng = np.random.RandomState(42)
# Randomize joint positions within valid bounds
arm.randomize_arm_joints(physics, rng)
# Move arm so that wrist_site reaches a target position
success = arm.set_site_to_xpos(
physics, rng,
site=arm.wrist_site,
target_pos=[0.5, 0.0, 0.3],
target_quat=base.DOWN_QUATERNION,
max_ik_attempts=10
)
# Access standard observables
obs = arm.observables
joint_positions = obs.joints_pos(physics)
joint_velocities = obs.joints_vel(physics)
Related Pages