Implementation:ARISE Initiative Robosuite OperationalSpaceController
| Knowledge Sources | |
|---|---|
| Domains | Robotics, Control |
| Last Updated | 2026-02-15 07:00 GMT |
Overview
Concrete tool for controlling a robot arm's end effector via operational space control (OSC) provided by robosuite.
Description
The OperationalSpaceController class implements the Operational Space Control framework originally described by Oussama Khatib (1987). It computes joint torques that produce desired task-space forces and torques at the end effector, enabling direct Cartesian position and orientation control of the robot arm. The controller extends the abstract Controller base class.
The controller accepts 6-DOF actions (position + orientation) or 3-DOF actions (position only), which can be either delta or absolute commands expressed in either the robot base frame or the world frame. It computes position and orientation errors, multiplies them by configurable stiffness (kp) and damping (kd) gains, and projects the resulting wrench through the task-space dynamics (lambda matrices) to produce joint torques. Null-space torques are added to bias the arm toward its initial configuration without affecting end-effector behavior.
The controller supports three impedance modes: "fixed" (constant gains), "variable" (both kp and damping_ratio are part of the action space), and "variable_kp" (only kp is variable, with critically damped behavior). Position and orientation interpolators can be provided for smooth trajectory tracking between discrete policy actions. The uncouple_pos_ori flag controls whether positional and orientational torque components are decoupled through separate lambda matrices.
Usage
Use the OperationalSpaceController when you need compliant, torque-level task-space control of a robot arm. It is ideal for contact-rich manipulation tasks where impedance behavior matters, or for research requiring variable stiffness/damping. It is instantiated through the controller factory with names "OSC_POSE" (6-DOF) or "OSC_POSITION" (3-DOF position only).
Code Reference
Source Location
- Repository: ARISE_Initiative_Robosuite
- File: robosuite/controllers/parts/arm/osc.py
- Lines: 1-584
Signature
class OperationalSpaceController(Controller):
def __init__(
self,
sim,
ref_name,
joint_indexes,
actuator_range,
input_max=1,
input_min=-1,
output_max=(0.05, 0.05, 0.05, 0.5, 0.5, 0.5),
output_min=(-0.05, -0.05, -0.05, -0.5, -0.5, -0.5),
kp=150,
damping_ratio=1,
impedance_mode="fixed",
kp_limits=(0, 300),
damping_ratio_limits=(0, 100),
policy_freq=20,
position_limits=None,
orientation_limits=None,
interpolator_pos=None,
interpolator_ori=None,
control_ori=True,
input_type="delta",
input_ref_frame="base",
uncouple_pos_ori=True,
lite_physics=True,
**kwargs,
): ...
def set_goal(self, action): ...
def run_controller(self) -> np.array: ...
def update_origin(self, origin_pos, origin_ori): ...
def update_initial_joints(self, initial_joints): ...
def reset_goal(self, goal_update_mode="achieved"): ...
def compute_goal_pos(self, delta, goal_update_mode=None) -> np.array: ...
def compute_goal_ori(self, delta, goal_update_mode=None) -> np.array: ...
def world_to_origin_frame(self, vec) -> np.array: ...
def goal_origin_to_eef_pose(self) -> np.array: ...
def set_goal_update_mode(self, goal_update_mode): ...
def delta_to_abs_action(self, delta_ac, goal_update_mode) -> np.array: ...
@property
def control_limits(self) -> tuple: ...
@property
def name(self) -> str: ... # Returns "OSC_POSE" or "OSC_POSITION"
Import
from robosuite.controllers.parts.arm.osc import OperationalSpaceController
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| sim | MjSim | Yes | MuJoCo simulator instance for state updates |
| ref_name | str | Yes | Name of the end effector site in the robot XML |
| joint_indexes | dict | Yes | Dictionary with keys 'joints', 'qpos', 'qvel' mapping to index lists
|
| actuator_range | 2-tuple of array | Yes | (low, high) joint actuator torque limits |
| input_max | float or Iterable | No | Maximum input action value, clipping threshold (default: 1) |
| input_min | float or Iterable | No | Minimum input action value, clipping threshold (default: -1) |
| output_max | float or Iterable | No | Maximum scaled output (default: (0.05, 0.05, 0.05, 0.5, 0.5, 0.5)) |
| output_min | float or Iterable | No | Minimum scaled output (default: (-0.05, -0.05, -0.05, -0.5, -0.5, -0.5)) |
| kp | float or Iterable | No | Proportional gain for position/orientation error (default: 150) |
| damping_ratio | float or Iterable | No | Damping ratio used to compute derivative gain kd (default: 1) |
| impedance_mode | str | No | One of "fixed", "variable", "variable_kp" (default: "fixed")
|
| kp_limits | 2-tuple | No | Min/max range for variable kp values (default: (0, 300)) |
| damping_ratio_limits | 2-tuple | No | Min/max range for variable damping_ratio (default: (0, 100)) |
| policy_freq | int | No | Policy action frequency in Hz (default: 20) |
| position_limits | 2-list or None | No | Cartesian position clipping limits in meters |
| orientation_limits | 2-list or None | No | Orientation clipping limits in radians |
| interpolator_pos | Interpolator | No | Interpolator for smooth position trajectory between actions |
| interpolator_ori | Interpolator | No | Interpolator for smooth orientation trajectory between actions |
| control_ori | bool | No | Whether to control orientation in addition to position (default: True) |
| input_type | str | No | "delta" for relative or "absolute" for absolute commands (default: "delta")
|
| input_ref_frame | str | No | "base" or "world" reference frame for actions (default: "base")
|
| uncouple_pos_ori | bool | No | Whether to decouple positional and orientational torques (default: True) |
| lite_physics | bool | No | Whether to optimize MuJoCo forward calls (default: True) |
Outputs
| Name | Type | Description |
|---|---|---|
| torques | np.array | Joint torques to be applied, including gravity compensation and null-space terms |
| name | str | Controller identifier: "OSC_POSE" or "OSC_POSITION"
|
| control_limits | tuple(np.array, np.array) | (min, max) action limits, which vary based on impedance mode |
Usage Examples
# Typical usage via the controller factory
from robosuite.controllers.parts.controller_factory import arm_controller_factory
controller_params = {
"sim": sim,
"ref_name": "gripper0_grip_site",
"joint_indexes": {
"joints": [0, 1, 2, 3, 4, 5, 6],
"qpos": [0, 1, 2, 3, 4, 5, 6],
"qvel": [0, 1, 2, 3, 4, 5, 6],
},
"actuator_range": (np.array([-87]*7), np.array([87]*7)),
"policy_freq": 20,
"ndim": 7,
"interpolation": "linear",
"ramp_ratio": 0.2,
}
# Create OSC controller with both position and orientation control
controller = arm_controller_factory("OSC_POSE", controller_params)
# Set a delta goal: small displacement in x, no orientation change
action = np.array([0.01, 0.0, 0.0, 0.0, 0.0, 0.0])
controller.set_goal(action)
# Compute torques for the current timestep
torques = controller.run_controller()
# For position-only control:
controller_pos = arm_controller_factory("OSC_POSITION", controller_params)
action_pos = np.array([0.01, 0.0, 0.0])
controller_pos.set_goal(action_pos)
torques_pos = controller_pos.run_controller()