Robot¶
A kinematic model loaded from URDF, Xacro, or a USD articulation. A Robot is
immutable and holds no scene state — joint values live in the
Scene that owns it, so the same model can be added to a scene more
than once.
import botrail as bt
robot = bt.Robot.from_urdf("arm.urdf")
robot = bt.Robot.from_xacro("arm.urdf.xacro") # expanded without ROS
robot = bt.Robot.from_usd("franka.usd") # Isaac Sim articulations
Robot
¶
A parsed robot model (kinematic tree + geometry). Immutable.
allowed_collisions
property
¶
The link pairs declared to be allowed to touch, by name: the
package's own and those added with allow_collisions.
flange_link
property
¶
Declared tool-mounting face (catalog frames.flange_frame; after
attach_tool, the mounted tool's onward flange if it has one).
attach_tool uses it when flange is omitted.
grasp_frames
property
¶
Declared grasp-surface frames (catalog frames.grasp_frames): the
fingertips of a hand, the pads of a gripper — where the product
says it holds things. Empty when the source declares none; after
attach_tool the mounted tool's ride along.
groups
property
¶
The planning groups — the arms — by name: what every group=
argument addresses. A single-arm robot has one ("arm", every
joint, tipped at tcp_link); a dual-arm robot has one per arm.
Declared by the catalog manifest or define_group, else read off
the kinematic tree: each moving branch of a body is a group, tipped
at the branch's own tool mount rather than at a fingertip.
joint_limits
property
¶
Per actuated joint: (lower, upper) or None for continuous joints.
mimic_joints
property
¶
Joints that follow another joint (URDF <mimic>, USD
PhysxMimicJointAPI) instead of carrying a DOF of their own:
{joint: (source joint, multiplier, offset)}. Their value is
multiplier * <source position> + offset, and they never appear in
joint_names or in a joint position vector.
mount_link
property
¶
Declared mounting face when this model is a tool (catalog
frames.mount_frame). attach_tool uses it when mount is
omitted, falling back to the tool's root link.
tcp_link
property
¶
Default end-effector link name: the TCP declared by a tool
attachment or catalog manifest when present, otherwise the deepest
leaf in the kinematic tree. A robot declared to have several arms
has no single TCP — ask group(name).tip.
allow_collisions
method descriptor
¶
Declares link pairs that may touch — an SRDF's disable_collisions
— and returns the robot with them added; the input is not modified.
A scene already allows adjacent links and pairs that touch in nearly
every pose on its own; this is for what only the machine's maker can
say: the bulky torso capsules of a whole-body machine overlap in
most poses, and that is the design. A catalog package carries its
own (self_collision.allowed_pairs).
attach_tool
method descriptor
¶
attach_tool(
tool,
flange=None,
mount=None,
offset_position=None,
offset_quaternion=None,
tcp=None,
prefix=None,
group=None,
)
Welds a tool (end-effector) onto this robot's flange and returns the composite robot; neither input is modified. The DOF vector becomes this robot's joints followed by the tool's, mimic joints included.
flange defaults to the robot's declared flange_link and mount
to the tool's declared mount_link (catalog manifests declare
both), falling back to the tool's root — so catalog parts attach
with no arguments, and a coupling's outward face becomes the
composite's flange for the next attach_tool in the stack.
offset places the mount relative to the flange (e.g. a coupling's
thickness); the mount must resolve to the tool's root link. tcp
names a tool link to become the composite's tcp_link — otherwise a
TCP declared on the tool carries over, falling back to the
deepest-leaf heuristic. When both models share a link/joint name,
pass prefix to namespace the tool's names.
robot = ur5e.attach_tool(coupling).attach_tool(gripper) # catalog parts
robot = ur5e.attach_tool(
gripper, flange="flange", mount="robotiq_arg2f_base_link",
offset_position=(0, 0, 0.0139), tcp="tcp",
)
group names the arm the tool goes on: its
declared flange is the default flange, and its TCP becomes the
tool's. Without it, a flange on one of the arms says which.
define_group
method descriptor
¶
Declares (or redeclares, by name) a planning group and returns the
robot carrying it; this robot is not modified. tip is the link a
motion of the group places — an arm's TCP. joints names the
actuated joints it drives; omitted, they are the joints on tip's
chain minus those of any group tipped above it (a waist declared as
a group of its own stays out of the arm). flange names the arm's
tool-mounting face, which attach_tool(..., group=) uses.
The first declaration replaces the derived groups outright: from then on the declaration is the truth, and an arm not declared is not a group.
dual_arm
staticmethod
¶
dual_arm(
left,
right,
left_position=None,
left_quaternion=None,
right_position=None,
right_quaternion=None,
body=None,
left_mount=None,
right_mount=None,
)
Two arms on one body, as a single robot with the groups left and
right (link and joint names prefixed left_ / right_): the
dual-arm a single controller drives. body is the torso the arms
bolt to — omitted, a bare frame named after the left arm — and
left_mount / right_mount name the body links the arm roots go
on (the body's root by default) at the given poses. Tools then
attach per arm: attach_tool(gripper, group="left").
from_catalog
staticmethod
¶
Loads a robot or tool from the botrail model catalog (the Hugging
Face dataset botrail/botrail-catalog) by id — exact
(robotiq/2f/2f-85/r1) or any unambiguous shorthand (2f-85,
robotiq/2f-85). Needs the optional dependency huggingface_hub
(pip install botrail[catalog]).
revision pins a dataset commit SHA; without it the newest catalog
is fetched and the resolved SHA is recorded in the robot's source,
so saved projects and generated scripts replay bit-identically.
Downloads land in the standard Hugging Face cache. format forces
"urdf" or "usd"; by default the URDF is preferred. A TCP the
package manifest declares (frames.tcp_default) becomes tcp_link.
Packages distributed as recipe_only/metadata_only raise with a
pointer to building them locally.
from_package
staticmethod
¶
Loads a locally built catalog package directory containing manifest.yaml.
Preserves its product ID, frames, BOM and mounting declarations. The
revision is local-sha256:
from_urdf
staticmethod
¶
Loads a robot from a URDF file. Mesh paths are resolved relative to
the file; package:// URIs are resolved heuristically.
from_usd
staticmethod
¶
Imports a robot from a USD articulation (UsdPhysics joints and rigid
bodies, e.g. Isaac Sim assets). Link/joint names are the prim paths;
revolute limits are converted from degrees, distances from the
stage's metersPerUnit, and Y-up stages are re-modeled as Z-up.
articulation_root defaults to the first prim carrying
PhysicsArticulationRootAPI; search_paths resolve external
(omniverse://) references against local directories.
from_xacro
staticmethod
¶
Expands a Xacro file (no ROS required) and loads the resulting URDF.
group
method descriptor
¶
One planning group: its joints, tip (TCP) link, flange and base.
ik
method descriptor
¶
ik(
position,
quaternion=None,
link=None,
seed=None,
max_iters=100,
restarts=None,
group=None,
centering=None,
)
Solves inverse kinematics. With quaternion=None only the position
is matched. link defaults to the TCP link, seed to the neutral
configuration. When the seeded solve does not converge, up to
restarts further attempts run from deterministically generated
seeds (limits midpoint first, then fixed-seed uniform samples within
the limits) — the same call always returns the same answer. Pass
restarts=0 to solve strictly from the given seed. Always returns
the best configuration found; check result.converged.
group names the arm to solve with (its tip is the default link);
the joints of any other arm stay at the seed. centering is how
strongly a redundant arm's free joints are drawn toward mid-range
once the pose is met (default 0.1): 0 leaves them where the seed
had them, so the answer lands next to the seed — what teaching a
pose from a near one, or a step along a path, wants.
joint_values
method descriptor
¶
Value of every joint at positions, keyed by joint name: the DOF
value for actuated joints, the mimic relation for driven ones, and
0 for fixed joints.
mount
method descriptor
¶
Bolts part — a manipulator — onto this robot's link at as an
arm of its own, and returns the composite; neither input is
modified. The part's root goes on at at the offset; prefix
namespaces its link and joint names (required when the names
collide — two of the same arm). The arm becomes a planning group
named group (the prefix without its trailing _ by default) with
the part's TCP and flange, so tools then attach per arm:
attach_tool(gripper, group="left"). See dual_arm for the
two-arm shorthand.
IkResult¶
Returned by Robot.ik and
Scene.set_tcp_target. The solver is
best-effort: it applies the closest configuration it reached, so always check
converged before trusting the pose.
IkResult
¶
catalog_package¶
The catalog holds more than robots. A workpiece or a fixture is meshes and a
manifest, with no articulation to build a Robot from, so this resolves the
same product ids to a downloaded package directory and leaves the loading to
the caller — see the catalog section.
catalog_package
builtin
¶
The catalog package directory for query, downloaded whole.
Not every catalog package is a robot. A body-in-white is a pile of
collision meshes that a cell loads as obstacles, and a fixture is a
mesh plus a frame — both want the package on disk, not a RobotModel.
Returning the directory keeps those callers off huggingface_hub
internals and, more to the point, off a hand-written snapshot path
that silently stops matching when the dataset moves.