[isaacsim.robot_motion.controllers] controllers#
Version: 0.3.2
Overview#
The isaacsim.robot_motion.controllers extension provides portable, GPU-accelerated robot motion
controllers that implement the
BaseController
interface from isaacsim.robot_motion.experimental.motion_generation.
Each controller reads its setpoint from a named control-point site in
setpoint_state.sites and writes joint velocity and position targets into the returned
RobotState. On a CUDA device the projection and kinematics are captured into a CUDA graph
at construction time, keeping per-step overhead to a pair of device-to-device copies plus a
graph launch.
Controllers#
DifferentialDriveController
converts a control-point velocity setpoint into left and right wheel angular velocity targets
using the differential drive kinematic model:
omega_L = (2 * v - omega * wheel_base) / (2 * wheel_radius)
omega_R = (2 * v + omega * wheel_base) / (2 * wheel_radius)
Linear speed v and yaw rate omega are extracted from the site by projecting the 3D
linear and angular velocity vectors onto configurable forward_direction and
rotation_direction unit vectors.
AckermannController
converts a control-point linear-velocity setpoint into steerable-wheel angular velocities,
steering-angle position targets, and (optionally) non-steerable-wheel angular velocities,
using the Ackermann kinematic model. The setpoint encodes speed v and body turning angle
θ as the velocity vector [v·cos θ, v·sin θ, 0]. Alternatively, direct_command=True
allows passing linear_speed and turning_angle as keyword arguments directly to
forward(), bypassing the velocity-vector projection step.
HolonomicController
converts a control-point body twist setpoint [vx, vy, wz] into per-wheel angular velocity
targets for mecanum-wheeled robots using closed-form
inverse kinematics:
phi_dot_i = K_i * (M[i, :] @ [vx, vy, wz])
The kinematic matrix M (N × 3) and conversion diagonal K (N,) are precomputed at
construction from the authored wheel positions, orientations, radii, and mecanum roller
angles, after transforming that geometry into the command-site frame given by
command_site_position and command_site_quaternion — so the wheels may be measured in
whatever frame is convenient and the site moved independently of them. Wheel geometry is
conveniently obtained from USD assets via
HolonomicRobotUsdSetup.get_holonomic_controller_params(). Planar linear speed and yaw
rate are clamped independently before the matrix multiply; per-wheel speed is clamped after.
Example#
import math
import isaacsim.robot_motion.controllers as ctrl
import isaacsim.robot_motion.experimental.motion_generation as mg
import warp as wp
# --- Differential drive ---
dd_controller = ctrl.DifferentialDriveController(
robot_joint_space=robot.dof_names,
left_wheel_joint="left_wheel_joint",
right_wheel_joint="right_wheel_joint",
wheel_radius=0.03,
wheel_base=0.1125,
)
dd_setpoint = mg.RobotState(
sites=mg.SpatialState.from_name(
spatial_space=["control_point"],
linear_velocities=(["control_point"], wp.array([[0.2, 0.0, 0.0]], dtype=wp.float32)),
angular_velocities=(["control_point"], wp.array([[0.0, 0.0, 1.0]], dtype=wp.float32)),
)
)
desired_state = dd_controller.forward(estimated_state, dd_setpoint, t)
# --- Ackermann ---
ack_controller = ctrl.AckermannController(
robot_joint_space=robot.dof_names,
left_steerable_wheel_joint="front_left_wheel",
right_steerable_wheel_joint="front_right_wheel",
left_steering_joint="front_left_steering",
right_steering_joint="front_right_steering",
steerable_wheel_radius=0.3,
wheel_base=1.5,
track_width=1.2,
)
v, theta = 1.0, 0.3 # speed [m/s], turning angle [rad]
ack_setpoint = mg.RobotState(
sites=mg.SpatialState.from_name(
spatial_space=["control_point"],
linear_velocities=(
["control_point"],
wp.array([[v * math.cos(theta), v * math.sin(theta), 0.0]], dtype=wp.float32),
),
)
)
desired_state = ack_controller.forward(estimated_state, ack_setpoint, t)
# --- Holonomic (omni / mecanum) ---
holo_controller = ctrl.HolonomicController(
robot_joint_space=robot.dof_names,
wheel_joint_names=["axle_0_joint", "axle_1_joint", "axle_2_joint"],
wheel_radius=wheel_radius, # from HolonomicRobotUsdSetup
wheel_positions=wheel_positions, # from HolonomicRobotUsdSetup
wheel_orientations=wheel_orientations,
mecanum_angles=[90.0, 90.0, 90.0], # 90° = omni; 45°/135° = standard mecanum
)
holo_setpoint = mg.RobotState(
sites=mg.SpatialState.from_name(
spatial_space=["control_point"],
linear_velocities=(["control_point"], wp.array([[0.4, 0.0, 0.0]], dtype=wp.float32)),
angular_velocities=(["control_point"], wp.array([[0.0, 0.0, 0.0]], dtype=wp.float32)),
)
)
desired_state = holo_controller.forward(estimated_state, holo_setpoint, t)
Integration#
This extension depends on isaacsim.robot_motion.experimental.motion_generation for the
BaseController interface and state types.
Enable Extension#
The extension can be enabled (if not already) in one of the following ways:
Define the next entry as an application argument from a terminal.
APP_SCRIPT.(sh|bat) --enable isaacsim.robot_motion.controllers
Define the next entry under [dependencies] in an experience (.kit) file or an extension configuration (extension.toml) file.
[dependencies]
"isaacsim.robot_motion.controllers" = {}
Open the Window > Extensions menu in a running application instance and search for isaacsim.robot_motion.controllers.
Then, toggle the enable control button if it is not already active.
Python API#
Controllers
Single-robot Ackermann steering controller. |
|
Single-robot differential drive controller. |
|
Holonomic (omni / mecanum) drive controller. |
Controllers#
- class AckermannController(
- *,
- robot_joint_space: list[str],
- left_steerable_wheel_joint: str,
- right_steerable_wheel_joint: str,
- left_steering_joint: str,
- right_steering_joint: str,
- steerable_wheel_radius: float,
- wheel_base: float,
- track_width: float,
- left_non_steerable_wheel_joint: str | None = None,
- right_non_steerable_wheel_joint: str | None = None,
- non_steerable_wheel_radius: float | None = None,
- non_steerable_track_width: float | None = None,
- max_linear_speed: float | None = None,
- max_turning_angle: float | None = None,
- steerable_wheels_at_rear: bool = False,
- direct_command: bool = False,
- linear_speed_kwarg: str = 'linear_speed',
- turning_angle_kwarg: str = 'turning_angle',
- control_point_name: str = 'control_point',
- forward_direction: list[float] | ndarray | array = (1.0, 0.0, 0.0),
- rotation_direction: list[float] | ndarray | array = (0.0, 0.0, 1.0),
- device: Device | str | None = None,
Bases:
BaseControllerSingle-robot Ackermann steering controller.
Converts a control-point linear-velocity setpoint into:
Steerable-wheel angular velocities and steering-angle position targets.
Non-steerable-wheel angular velocities (if any).
The setpoint must be a real velocity vector at the control point. For a vehicle travelling at total speed
vwith body turning angleθ, the site’slinear_velocityshould be[v·cos θ, v·sin θ, 0]in the body frame.The controller recovers speed and angle by projection onto the body axes:
v_x = dot(linear_velocity, forward_direction)v_y = dot(linear_velocity, lateral_direction)linear_speed = sign(v_x) · ‖[v_x, v_y]‖turning_angle = atan2(v_y, v_x)(forward,v_x > 0)turning_angle = atan2(-v_y, -v_x)(reversing,v_x ≤ 0)
where
lateral_direction = normalize(cross(rotation_direction, forward_direction)).Negating both components for reversing keeps
turning_anglein(-π/2, π/2). Positive turning angle steers to the left (counterclockwise from above with the defaultrotation_direction = [0, 0, 1]).Both direction vectors are normalized at construction time and must be at least 89.9 degrees apart.
- Parameters:
robot_joint_space – Ordered list of all joint names in the robot.
left_steerable_wheel_joint – Name of the left steerable wheel joint in
robot_joint_space(velocity target).right_steerable_wheel_joint – Name of the right steerable wheel joint in
robot_joint_space(velocity target).left_steering_joint – Name of the left steering joint in
robot_joint_space(position target — the physical steering angle of the wheel).right_steering_joint – Name of the right steering joint in
robot_joint_space(position target).steerable_wheel_radius – Radius of the steerable wheels [m].
wheel_base – Axle-to-axle distance, front to rear [m].
track_width – Lateral wheel-to-wheel distance [m].
left_non_steerable_wheel_joint – Name of the left non-steerable wheel joint in
robot_joint_space(velocity target). Must be provided together withright_non_steerable_wheel_joint. Its lateral offset is derived automatically as+non_steerable_track_width / 2.right_non_steerable_wheel_joint – Name of the right non-steerable wheel joint in
robot_joint_space(velocity target). Must be provided together withleft_non_steerable_wheel_joint. Its lateral offset is derived automatically as-non_steerable_track_width / 2.non_steerable_wheel_radius – Radius of the non-steerable wheels [m]. When
None, falls back tosteerable_wheel_radius.non_steerable_track_width – Lateral distance between the non-steerable wheels [m]. When
None, falls back totrack_width.max_linear_speed – Forward/backward speed limit [m/s]. When
None, no limit is applied.max_turning_angle – Steering angle clamp [rad]. Must be in
(0, π/2].steerable_wheels_at_rear – Pass
Truefor rear-wheel-steering vehicles (e.g. forklifts).direct_command – Pass
Trueto ignoresetpoint_stateinforward()and read speed and angle directly from kwargs instead.linear_speed_kwarg – Name of the
forward()kwarg that carries the signed total speed [m/s] in direct mode.turning_angle_kwarg – Name of the
forward()kwarg that carries the body turning angle [rad] in direct mode.control_point_name – Name of the site in
setpoint_state.sitesfrom whichlinear_velocityis read. Unused whendirect_command=True.forward_direction – Robot forward axis in the body frame. Normalized at construction.
rotation_direction – Yaw axis in the body frame. Normalized at construction. Must be at least 89.9° from
forward_direction. Used to derivelateral_directionasnormalize(cross(rotation_direction, forward_direction)).device – Warp device for internal buffers. Defaults to
wp.get_device().
- Raises:
ValueError – If either direction vector is zero, not 3-element, or the two directions are less than 89.9 degrees apart.
ValueError – If
steerable_wheel_radius,wheel_base, ortrack_widthis not strictly positive.ValueError – If
non_steerable_wheel_radiusis provided and not strictly positive.ValueError – If
non_steerable_track_widthis provided and not strictly positive.ValueError – If
max_linear_speedis provided and not strictly positive.ValueError – If
max_turning_angleis provided and not in(0, π/2].ValueError – If exactly one of
left_non_steerable_wheel_joint/right_non_steerable_wheel_jointis provided (both or neither required).ValueError – If any two of the required joint names are identical.
ValueError – If any required joint name is not in
robot_joint_space.
- forward(
- estimated_state: RobotState,
- setpoint_state: RobotState | None,
- t: float,
- **kwargs: object,
Compute wheel velocity and steering targets.
Dispatches to
_forward_direct()or_forward_site()depending on thedirect_commandflag set at construction.- Parameters:
estimated_state – Current estimated state of the robot. Not used by this controller but required by the
BaseControllerinterface.setpoint_state – Desired robot state containing the control-point site. Ignored when
direct_command=True.t – Current clock time [s].
**kwargs – In direct mode, must supply the kwargs named by
linear_speed_kwarg(signed total speed [m/s]) andturning_angle_kwarg(body turning angle [rad]).
- Returns:
RobotStatewhoseJointStateholds velocity targets for all wheel joints (steerable and non-steerable) in the order[left_steer, right_steer, left_ns, right_ns], and position targets for the two steering joints[left_steering, right_steering].Noneif required inputs are absent.
- reset(
- estimated_state: RobotState,
- setpoint_state: RobotState | None,
- t: float,
- **kwargs: object,
Reset the controller.
In non-direct mode the stored
prev_thetais zeroed so the next command starts with a clean steering history.- Parameters:
estimated_state – Current estimated state of the robot.
setpoint_state – Optional desired state of the robot.
t – Current clock time [s].
**kwargs – Unused; accepted for interface compatibility.
- Returns:
Always
True.
- class DifferentialDriveController(
- *,
- robot_joint_space: list[str],
- left_wheel_joint: str,
- right_wheel_joint: str,
- wheel_radius: float,
- wheel_base: float,
- control_point_name: str = 'control_point',
- forward_direction: list[float] | ndarray | array = (1.0, 0.0, 0.0),
- rotation_direction: list[float] | ndarray | array = (0.0, 0.0, 1.0),
- max_linear_speed: float | None = None,
- max_angular_speed: float | None = None,
- max_wheel_speed: float | None = None,
- device=None,
Bases:
BaseControllerSingle-robot differential drive controller.
Converts a control-point velocity setpoint into left / right wheel velocity commands using the differential drive kinematic model:
omega_L = (2 * v - omega * wheel_base) / (2 * wheel_radius) omega_R = (2 * v + omega * wheel_base) / (2 * wheel_radius)
The scalar commands are extracted from the named site in
setpoint_state.sitesby projection:v = dot(forward_direction, site.linear_velocity)omega = dot(rotation_direction, site.angular_velocity)
The control point is interpreted as the point midway between the two front wheels, which may differ from the robot’s root (e.g. centre of mass).
Both direction vectors are normalized at construction time and must be at least 89.9 degrees apart.
- Parameters:
robot_joint_space – Ordered list of all joint names in the robot.
left_wheel_joint – Name of the left wheel joint in
robot_joint_space.right_wheel_joint – Name of the right wheel joint in
robot_joint_space.wheel_radius – Wheel radius [m].
wheel_base – Lateral wheel-to-wheel distance [m].
control_point_name – Name of the site in
setpoint_state.sitesfrom which linear and angular velocities are read.forward_direction – Robot forward axis in the body frame. Normalized at construction.
rotation_direction – Yaw axis in the body frame. Normalized at construction. Must be at least 89.9° from
forward_direction.max_linear_speed – Forward/backward speed limit [m/s]. When
None, no limit is applied.max_angular_speed – Yaw-rate limit [rad/s]. When
None, no limit is applied.max_wheel_speed – Per-wheel angular velocity limit [rad/s]. When
None, no limit is applied.device – Warp device for internal buffers. When a CUDA device is used, a CUDA graph is captured at construction.
- Raises:
ValueError – If either direction vector is zero, not 3-element, or the two directions are less than 89.9 degrees apart.
ValueError – If
wheel_radiusorwheel_baseis not strictly positive.ValueError – If any of
max_linear_speed,max_angular_speed, ormax_wheel_speedis provided and not strictly positive.ValueError – If
left_wheel_jointorright_wheel_jointis not inrobot_joint_space.
- forward(
- estimated_state: RobotState,
- setpoint_state: RobotState | None,
- t: float,
- **kwargs: object,
Compute left and right wheel velocity targets from a control-point setpoint.
- Parameters:
estimated_state – Current estimated state of the robot. Not used by this controller but required by the
BaseControllerinterface.setpoint_state – Desired robot state. Must have a
sitesfield containing the named control point with both linear and angular velocities.t – Current clock time [s].
**kwargs – Unused; accepted for interface compatibility.
- Returns:
RobotStatewithJointStatevelocity targets for the two wheel joints, orNoneif the control point site or its velocities are absent.
- reset(
- estimated_state: RobotState,
- setpoint_state: RobotState | None,
- t: float,
- **kwargs: object,
Reset the controller.
This controller is stateless, so reset always succeeds immediately.
- Parameters:
estimated_state – Current estimated state of the robot.
setpoint_state – Optional desired state of the robot.
t – Current clock time [s].
**kwargs – Unused; accepted for interface compatibility.
- Returns:
Always
True.
- class HolonomicController(
- *,
- robot_joint_space: list[str],
- wheel_joint_names: list[str],
- wheel_radius: list | ndarray | None = None,
- wheel_positions: list | ndarray | None = None,
- wheel_orientations: list | ndarray | None = None,
- mecanum_angles: list | ndarray | None = None,
- wheel_axis: list | ndarray | None = None,
- command_site_position: list | ndarray | None = None,
- command_site_quaternion: list | ndarray | None = None,
- rotation_direction: list | ndarray | None = None,
- max_linear_speed: float | None = None,
- max_angular_speed: float | None = None,
- max_wheel_speed: float | None = None,
- control_point_name: str = 'control_point',
- device: Device | str | None = None,
Bases:
BaseControllerHolonomic (omni / mecanum) drive controller.
Converts a planar twist setpoint at a named command site into per-wheel angular velocities using the closed-form inverse kinematics of the wheel base, and returns them as a
RobotStatewhose joint state holds velocity targets for the wheel joints.The command is read from the named site in
setpoint_state.sitesand is interpreted as the twist of the command site:linear_velocityis the velocity of the site’s origin andangular_velocityis taken aboutrotation_direction.The command site is placed by
command_site_positionandcommand_site_quaternion, given in the same frame aswheel_positionsandwheel_orientations. The wheel geometry is transformed into the site frame at construction, so the wheels may be measured in whatever frame is convenient (a robot root, a USD centre-of-mass prim) and the site moved independently of them.rotation_directionis then expressed in the command-site frame, so the default[0, 0, 1]means “the site frame’s own +Z”.The kinematics are precomputed once at construction into two constant operators:
M(N×3) maps the command-site twist[v_u, v_v, w]to per-wheel no-slip-axis contact speedsuviau_i = a_iᵀ (v_c + ω × r_i).K(diagonal, length N) converts each contact speed to a wheel joint angular velocity:φ̇_i = u_i / (r_i · cos γ_i), whereγ_iis the roller offset angle (mecanum_angle_i − 90°).
On a CUDA device the full forward pass (project twist → clamp → matrix multiply) is captured into a CUDA graph at construction time. Each
forward()call then copies the live setpoint into staging buffers and launches the graph with no CPU–GPU round-trips.- Parameters:
robot_joint_space – The ordered list of joint names defining the joint space of the controlled robot (for example,
Articulation.dof_names).wheel_joint_names – Names of the wheel joints, one per wheel, ordered to match
wheel_positions[i]/wheel_orientations[i]/mecanum_angles[i]. Each name must be unique and present inrobot_joint_space.wheel_radius – Radius of each wheel (scalar broadcast to all wheels, or per-wheel array).
wheel_positions – Positions of each wheel, in the same frame as
command_site_position.wheel_orientations – Quaternion orientations of each wheel, in the same frame as
command_site_quaternion, in[w, x, y, z]order.mecanum_angles – Mecanum roller angle of each wheel in degrees, measured from the wheel axle (90 = omni / plain wheel, 45 or 135 = standard mecanum). This is the legacy
isaacmecanumwheel:angleconvention returned byHolonomicRobotUsdSetup, so it can be passed straight through. Scalar broadcast or per-wheel array.wheel_axis – Local rotation (spin) axis of the wheel joint.
command_site_position – Position of the command site, in the same frame as
wheel_positions. Defaults to the origin of that frame.command_site_quaternion – Orientation of the command site, in the same frame as
wheel_orientations, in[w, x, y, z]order. Defaults to identity, in which case the wheel frame is used as the command-site frame directly.rotation_direction – Yaw axis, expressed in the command-site frame. Defaults to that frame’s
[0, 0, 1].max_linear_speed – Maximum planar linear speed [m/s].
Nonemeans no limit.max_angular_speed – Maximum yaw rate [rad/s].
Nonemeans no limit.max_wheel_speed – Maximum individual wheel angular velocity [rad/s].
Nonemeans no limit. Applied independently per wheel after the matrix multiply; this can distort the commanded direction.control_point_name – Name of the site in
setpoint_state.sitesfrom which the twist command is read.device – Warp device for internal buffers. If the device is a CUDA device, a CUDA graph is captured at construction time.
- Raises:
ValueError – If
wheel_radius,wheel_positions, orwheel_orientationsisNone.ValueError – If
wheel_joint_namescontains duplicates, has a name not inrobot_joint_space, or does not have one entry per wheel.ValueError – If
rotation_directionis zero,command_site_positiondoes not have shape(3,), orcommand_site_quaterniondoes not have shape(4,)or is zero.ValueError – If any wheel’s axle is parallel to
rotation_direction(undefined rolling direction) or its mecanum angle is 0 or 180 degrees.ValueError – If any provided speed limit is not strictly positive.
- forward(
- estimated_state: RobotState,
- setpoint_state: RobotState | None,
- t: float,
- **kwargs: object,
Convert a command-site twist setpoint into per-wheel velocity targets.
- Parameters:
estimated_state – Current estimated state of the robot (unused).
setpoint_state – Desired robot state containing the named command-site with both linear and angular velocities.
t – Current clock time (unused).
**kwargs – Additional keyword arguments (unused).
- Returns:
RobotStatewhose joint state contains velocity targets for the wheel joints, orNoneif the command-site or its velocities are absent.
- reset(
- estimated_state: RobotState,
- setpoint_state: RobotState | None,
- t: float,
- **kwargs: object,
Reset the controller.
The holonomic controller is stateless, so this always succeeds.
- Parameters:
estimated_state – Current estimated state of the robot (unused).
setpoint_state – Desired setpoint state (unused).
t – Current clock time (unused).
**kwargs – Additional keyword arguments (unused).
- Returns:
Always
True.