Robot
Robot model backed by Warp.
Examples
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> q = wp.from_numpy(np.array([0.0, -1.2, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0]), dtype=wp.float32)
>>> state = robot.state(q=q)
>>> state = robot.forward_kinematics(state)
>>> hand_idx = robot.spec.link_names.index("panda_hand")
>>> link_pose = state.T_world_link[:, hand_idx]
>>> expected = np.array([6.0860e-02, -4.7547e-12, 7.6373e-01, 0.0382, 0.9193, 0.3808, 0.0922], dtype=np.float32)
>>> expected = wp.from_numpy(expected, dtype=wp_vec7)
>>> np.allclose(se3_to_matrix(link_pose).numpy(), se3_to_matrix(expected).numpy(), atol=1e-4)
Trueimport numpy as np
import warp as wp
from robokit.robo.robot import Robot
from robokit.lie.se3 import se3_to_matrix
from robokit.utils.warp_utils import wp_vec7
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
q = wp.from_numpy(np.array([0.0, -1.2, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0]), dtype=wp.float32)
state = robot.state(q=q)
state = robot.forward_kinematics(state)
hand_idx = robot.spec.link_names.index("panda_hand")
link_pose = state.T_world_link[:, hand_idx]
expected = np.array([6.0860e-02, -4.7547e-12, 7.6373e-01, 0.0382, 0.9193, 0.3808, 0.0922], dtype=np.float32)
expected = wp.from_numpy(expected, dtype=wp_vec7)
np.allclose(se3_to_matrix(link_pose).numpy(), se3_to_matrix(expected).numpy(), atol=1e-4)Load a robot model from a URDF/MJCF path, description string, or parsed yourdfpy.URDF.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> robot.spec.num_actuated_joints
8from robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
robot.spec.num_actuated_jointsURDF/MJCF file path, description string, or already-parsed yourdfpy.URDF.
Load link visual/collision meshes.
Directory to resolve mesh files against.
Load collision spheres from collision_spheres_path.
YAML file with per-link collision spheres and optional self_collision_link_buffers.
Base link; defaults to the URDF root.
End-effector link name(s).
YAML file with link pairs self-collision terms skip.
The loaded robot model.
Build a robot state for the given joint positions (defaults to zero_q).
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> robot.state().q.shape
(1, 8)from robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
robot.state().q.shapeCompute forward kinematics for given joint positions; returns a state with all link transforms.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> q = wp.from_numpy(np.array([0.0, -1.2, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0]), dtype=wp.float32)
>>> state = robot.state(q=q)
>>> state = robot.forward_kinematics(state)
>>> hand_idx = robot.spec.link_names.index("panda_hand")
>>> link_pose = state.T_world_link[:, hand_idx]
>>> expected = np.array([6.0860e-02, -4.7547e-12, 7.6373e-01, 0.0382, 0.9193, 0.3808, 0.0922], dtype=np.float32)
>>> expected = wp.from_numpy(expected, dtype=wp_vec7)
>>> np.allclose(se3_to_matrix(link_pose).numpy(), se3_to_matrix(expected).numpy(), atol=1e-4)
True
>>> T_world_base = wp.from_numpy(np.array([1.0, 2.0, 3.0, 0.7071, 0.0, 0.7071, 0.0]), dtype=wp_vec7)
>>> state = robot.state(q=q, T_world_base=T_world_base)
>>> state = robot.forward_kinematics(state)
>>> link_pose = state.T_world_link[:, hand_idx]
>>> expected = np.array([1.76371783, 2.0, 2.93915576, -0.24222432, 0.71524162, 0.29626278, -0.58478125], dtype=np.float32)
>>> expected = wp.from_numpy(expected, dtype=wp_vec7)
>>> np.allclose(se3_to_matrix(link_pose).numpy(), se3_to_matrix(expected).numpy(), atol=1e-4)
Trueimport numpy as np
import warp as wp
from robokit.robo.robot import Robot
from robokit.lie.se3 import se3_to_matrix
from robokit.utils.warp_utils import wp_vec7
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
q = wp.from_numpy(np.array([0.0, -1.2, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0]), dtype=wp.float32)
state = robot.state(q=q)
state = robot.forward_kinematics(state)
hand_idx = robot.spec.link_names.index("panda_hand")
link_pose = state.T_world_link[:, hand_idx]
expected = np.array([6.0860e-02, -4.7547e-12, 7.6373e-01, 0.0382, 0.9193, 0.3808, 0.0922], dtype=np.float32)
expected = wp.from_numpy(expected, dtype=wp_vec7)
np.allclose(se3_to_matrix(link_pose).numpy(), se3_to_matrix(expected).numpy(), atol=1e-4)
T_world_base = wp.from_numpy(np.array([1.0, 2.0, 3.0, 0.7071, 0.0, 0.7071, 0.0]), dtype=wp_vec7)
state = robot.state(q=q, T_world_base=T_world_base)
state = robot.forward_kinematics(state)
link_pose = state.T_world_link[:, hand_idx]
expected = np.array([1.76371783, 2.0, 2.93915576, -0.24222432, 0.71524162, 0.29626278, -0.58478125], dtype=np.float32)
expected = wp.from_numpy(expected, dtype=wp_vec7)
np.allclose(se3_to_matrix(link_pose).numpy(), se3_to_matrix(expected).numpy(), atol=1e-4)Compute forward kinematics as 4x4 matrices for NumPy arrays, without an autograd round trip.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> q = np.zeros((1, robot.spec.num_actuated_joints), dtype=np.float32)
>>> robot.forward_kinematics_via_matrix_numpy(q).shape
(1, 13, 4, 4)import numpy as np
from robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
q = np.zeros((1, robot.spec.num_actuated_joints), dtype=np.float32)
robot.forward_kinematics_via_matrix_numpy(q).shapeCompute world link poses as translation-first 7D poses for NumPy arrays.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> q = np.zeros((1, robot.spec.num_actuated_joints), dtype=np.float32)
>>> robot.forward_kinematics_numpy(q).shape
(1, 13, 7)import numpy as np
from robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
q = np.zeros((1, robot.spec.num_actuated_joints), dtype=np.float32)
robot.forward_kinematics_numpy(q).shapeCompute the whole-body center of mass in world frame for NumPy arrays.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> q = np.zeros((1, robot.spec.num_actuated_joints), dtype=np.float32)
>>> np.allclose(robot.compute_center_of_mass_numpy(q)[0], [0.0232, 0.0061, 0.6062], atol=1e-4)
Trueimport numpy as np
from robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
q = np.zeros((1, robot.spec.num_actuated_joints), dtype=np.float32)
np.allclose(robot.compute_center_of_mass_numpy(q)[0], [0.0232, 0.0061, 0.6062], atol=1e-4)Store robot joint Jacobians in state for state.get_link_jacobian().
Base layouts:
- Fixed base: joint columns only.
- Floating base: prepend J_base, giving shape [batch, 6, 6 + num_dofs].
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> T_world_base = wp.from_numpy(np.array([1.0, 2.0, 3.0, 0.7071, 0.0, 0.7071, 0.0]), dtype=wp_vec7)
>>> q = wp.from_numpy(np.array([0.0, -1.2, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0]), dtype=wp.float32)
>>> state = robot.state(q=q, T_world_base=T_world_base)
>>> state = robot.compute_motion_subspace(state)
>>> J = state.get_link_jacobian(robot.spec.link_names.index("panda_hand"), "body")
>>> np.allclose(J.numpy()[0, 0, :6], np.array([0.693, 0.7071, 0.1405, -0.54, 0.5207, 0.043], dtype=np.float32), atol=1e-4)
True
>>> J = state.get_link_jacobian(robot.spec.link_names.index("panda_hand"), "spatial")
>>> np.allclose(J.numpy()[0, 0, 6:], np.array([0.0001, -3., 1.8641, 3.2647, -1.4346, 3.0467, -0.3974, 0.], dtype=np.float32), atol=1e-3)
True
>>> np.allclose(J.numpy()[0, 0, :6], np.array([0.0001, 0., 1., -2., -3., 0.0001], dtype=np.float32), atol=1e-3)
Trueimport numpy as np
import warp as wp
from robokit.robo.robot import Robot
from robokit.utils.warp_utils import wp_vec7
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
T_world_base = wp.from_numpy(np.array([1.0, 2.0, 3.0, 0.7071, 0.0, 0.7071, 0.0]), dtype=wp_vec7)
q = wp.from_numpy(np.array([0.0, -1.2, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0]), dtype=wp.float32)
state = robot.state(q=q, T_world_base=T_world_base)
state = robot.compute_motion_subspace(state)
J = state.get_link_jacobian(robot.spec.link_names.index("panda_hand"), "body")
np.allclose(J.numpy()[0, 0, :6], np.array([0.693, 0.7071, 0.1405, -0.54, 0.5207, 0.043], dtype=np.float32), atol=1e-4)
J = state.get_link_jacobian(robot.spec.link_names.index("panda_hand"), "spatial")
np.allclose(J.numpy()[0, 0, 6:], np.array([0.0001, -3., 1.8641, 3.2647, -1.4346, 3.0467, -0.3974, 0.], dtype=np.float32), atol=1e-3)
np.allclose(J.numpy()[0, 0, :6], np.array([0.0001, 0., 1., -2., -3., 0.0001], dtype=np.float32), atol=1e-3)Compute the whole-body center of mass in world frame into state.com_world.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> state = robot.compute_center_of_mass(robot.state())
>>> np.allclose(state.com_world.numpy()[0], [0.0232, 0.0061, 0.6062], atol=1e-4)
Trueimport numpy as np
from robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
state = robot.compute_center_of_mass(robot.state())
np.allclose(state.com_world.numpy()[0], [0.0232, 0.0061, 0.6062], atol=1e-4)Compute the collision sphere centers in world frame.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> state = robot.state()
>>> robot.transform_collision_spheres(state) is state # no collision spheres loaded
Truefrom robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
state = robot.state()
robot.transform_collision_spheres(state) is state # no collision spheres loadedThe robot state.
The robot state with updated collision sphere centers.
Compute the per-link capsule segment endpoints (a, b) in world frame.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> state = robot.state()
>>> robot.transform_collision_capsules(state) is state # no link capsules loaded
Truefrom robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
state = robot.state()
robot.transform_collision_capsules(state) is state # no link capsules loadedCompute differentiable forward kinematics as 4x4 matrices for torch tensors.
Example
>>> import torch
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> T_world_link = robot.forward_kinematics_via_matrix_torch(torch.zeros(robot.spec.num_actuated_joints))
>>> T_world_link.shape
torch.Size([13, 4, 4])from robokit.robo.robot import Robot
import torch
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
T_world_link = robot.forward_kinematics_via_matrix_torch(torch.zeros(robot.spec.num_actuated_joints))
T_world_link.shapeTransform local points attached to links to world frame.
Example
>>> import torch
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> T_world_link = robot.forward_kinematics_via_matrix_torch(torch.zeros(robot.spec.num_actuated_joints))
>>> points = robot.transform_link_points_torch(T_world_link, torch.zeros(2, 3), torch.tensor([0, 1]))
>>> points.shape
torch.Size([2, 3])from robokit.robo.robot import Robot
import torch
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
T_world_link = robot.forward_kinematics_via_matrix_torch(torch.zeros(robot.spec.num_actuated_joints))
points = robot.transform_link_points_torch(T_world_link, torch.zeros(2, 3), torch.tensor([0, 1]))
points.shapeLink transforms in world frame [..., num_links, 4, 4]
Local points in link frames [num_points, 3]
Link index for each point [num_points]
World-frame points [..., num_points, 3]
Expand actuated joint values to all joints (mimic joints follow their controlling joint).
Example
>>> import torch
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> robot.map_to_full_joint_values_torch(torch.zeros(robot.spec.num_actuated_joints)).shape
torch.Size([12])from robokit.robo.robot import Robot
import torch
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
robot.map_to_full_joint_values_torch(torch.zeros(robot.spec.num_actuated_joints)).shapeSample joint positions uniformly within the actuated joint limits.
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> robot = Robot.load(load_robot_description("panda_description"))
>>> robot.sample_q(num_samples=3, rng=np.random.default_rng(0)).shape
(3, 8)import numpy as np
from robokit.robo.robot import Robot
from robot_descriptions.loaders.yourdfpy import load_robot_description
robot = Robot.load(load_robot_description("panda_description"))
robot.sample_q(num_samples=3, rng=np.random.default_rng(0)).shapeRobot specification.
Examples
>>> spec = RobotSpec.parse("tests/fixtures/wx250s.urdf")
>>> spec.num_actuated_joints
8
>>> spec.num_links
14from robokit.robo.robot_spec import RobotSpec
spec = RobotSpec.parse("tests/fixtures/wx250s.urdf")
spec.num_actuated_joints
spec.num_linksName of the robot.
Robot description
Format of the robot description.
Names of all joints, including actuated, mimic and fixed joints.
Names of non-fixed joints, including actuated and mimic joints.
Names of actuated joints.
Types of all joints, see JointType.
Axes of all joints, [x, y, z].
Twists of all joints, [linear (x, y, z), angular (x, y, z)].
Indices of actuated joints, -1 for mimic and non-actuated joints.
Indices of parent joints, -1 for joints attached to the base link.
Transforms of parent joints, [pos (x, y, z), quat (w, x, y, z)].
Indices of mimicked actuated joints, -1 for non-mimic joints.
Multipliers of mimicked actuated joints, 1.0 for non-mimic joints.
Offsets of mimicked actuated joints, 0.0 for non-mimic joints.
Limits of all joints, [lower, upper].
Velocity limits of all joints.
Limits of actuated joints, [lower, upper].
Velocity limits of actuated joints.
Names of all links.
Indices of parent joints of all links, -1 for the base link.
Base link name (root of the parsed kinematic tree).
End-effector (leaf) link names of the parsed kinematic tree.
Visual geometries of all links.
Collision geometries of all links.
Collision sphere centers in link-local coordinates.
Collision sphere radii.
Link indices (in link_names) for each collision sphere.
Load ignored self-collision link pairs verbatim from self_collision_ignore_path, or return none.
Mass of each link (0.0 if no inertial data).
Center of mass position in link-local frame.
Baked capsule endpoints from link_capsules_path; unset means fit them from the collision meshes.
Baked capsule radii from link_capsules_path.
Per-link self-collision radius inflation from the collision-sphere YAML; world radii stay unchanged.
Parse an MJCF robot: hinge/slide joints, equality mimics; the world body stays if kept or a root has joints. A hinge with an anchor (jnt_pos) turns at a synthetic <body>_anchor link, then a fixed joint shifts back.
Transforms of parent joints as 4x4 matrices.
Names of mimic joints.
Per-link bounding sphere centers in link-local coordinates (broad-phase filter).
Per-link bounding sphere radii (broad-phase filter).
Per-link capsule segment endpoints (a, b) in link-local coordinates; zeros for links without a capsule.
Per-link capsule radii; 0.0 for links without a capsule.
Mapping from all joints to actuated joints.
Boolean mask for ancestor joints of links.
Boolean mask for ancestor links of links.
Link geometry: a single concatenated mesh, or the raw trimesh.Scene when return_mesh=False.
Per-link geometry: concatenated meshes or trimesh.Scenes when return_mesh=False (needs load_meshes=True).
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> spec = RobotSpec.parse(load_robot_description("panda_description"), load_meshes=True)
>>> "panda_hand" in spec.get_link_meshes()
Truefrom robokit.robo.robot_spec import RobotSpec
from robot_descriptions.loaders.yourdfpy import load_robot_description
spec = RobotSpec.parse(load_robot_description("panda_description"), load_meshes=True)
"panda_hand" in spec.get_link_meshes()Cached Warp spec tensors for device (build on miss).
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> spec = RobotSpec.parse(load_robot_description("panda_description"))
>>> spec.get_tensors() is spec.get_tensors()
Truefrom robokit.robo.robot_spec import RobotSpec
from robot_descriptions.loaders.yourdfpy import load_robot_description
spec = RobotSpec.parse(load_robot_description("panda_description"))
spec.get_tensors() is spec.get_tensors()Cached torch spec tensors for device (build on miss).
Example
>>> from robot_descriptions.loaders.yourdfpy import load_robot_description
>>> spec = RobotSpec.parse(load_robot_description("panda_description"))
>>> spec.get_tensors_torch() is spec.get_tensors_torch()
Truefrom robokit.robo.robot_spec import RobotSpec
from robot_descriptions.loaders.yourdfpy import load_robot_description
spec = RobotSpec.parse(load_robot_description("panda_description"))
spec.get_tensors_torch() is spec.get_tensors_torch()(batch, tangent_dim) velocities that integrate moves each element by to reach other's.
Integrate the state by a tangent-space velocity, optionally reporting the move the limits let through.
Clamp joints while preserving masked coordinates; record_tape=False excludes projection from tape.
Elements offset to offset + batch_size of every buffer, sharing storage.
Zero-copy view folding the frame axis into the batch axis so per-pose kernels run unchanged.
Optimized accept: copies q, and the forward kinematics this state already had (1 kernel).