anvil.workcell
anvil.workcell
What a workcell is: its robot's arms, where each answers and which slots it owns, its cameras and keep-out boxes.
The configuration here is plain dataclasses, so an edit is an assignment:
arm.description.tuning.ee_pose.joints[3].kp = 20.0 is what that arm then runs under the ee_pose controller. Start
from a shipped preset, WorkcellConfig.OPENYAM_V1_SINGLE or WorkcellConfig.shipped(...), edit what your bench
differs in, and save it.
A RobotConfig and a WorkcellConfig are checked whole when they are built. An edit made afterwards, to them or to
anything they hold, is checked where the robot or workcell is next handed over: to a hw interface, a controller, a
Clearance, save, or a property such as RobotConfig.num_slots that has to work something out from it. A value
refused there raises anvil.InvalidArgumentError saying what is wrong with it, and nothing reaches the drives.
The release wheel drives only the arms Anvil ships: a robot whose arms' joints or excluded_pairs differ from the
shipped description of their variant, or whose URDF is not the one that variant ships, is refused when it is built,
the error naming what differs. Tuning, a joint's gravity correction among it, homing, the gripper, the mounts, the
cameras and the keep-out boxes stay yours to change.
Classes:
| Name | Description |
|---|---|
Correction |
A correction to one feedforward term of one joint: the term as computed, times |
JointDescription |
One joint of an arm: the motor driving it, the addresses it answers on, and how far and how fast it may go. |
GripAssist |
The grip assist: the feedforward torque that does the gripping, on top of the gripper's own gains. |
FingerSet |
A set of interchangeable fingers a gripper carries, one directory under the gripper's |
Gripper |
A gripper the stack drives: its one motor, the gains it holds a width at, and the map from jaw opening to angle. |
ExternalGripper |
A gripper the stack does not drive: your own, run by your code on the arm's bus beside the stack. |
Gains |
A drive's two gains for one joint. |
ControllerTuning |
How one controller drives an arm's chain joints: their gains and how fast it moves their targets. |
TuningDescription |
How each controller drives an arm's chain joints, as the |
ArmDescription |
One arm variant: what it physically is and how it is driven. |
Side |
Which arm of a robot an arm is, where that means something. |
ArmCount |
How many followers a shipped workcell stands: one, or a left and a right. |
Role |
What an arm does in a robot. |
ArmLayout |
Where one arm of a robot sits in the robot's slots, as |
RobotLayout |
What follows from a robot's arms rather than being stated with them, as |
ArmConfig |
One arm of a robot: its name, the bus it answers on, what it does, which side it is, and its description. |
Mount |
Where a robot stands one copy of its variant's unit: an OpenArm torso carrying both arms, or one yam arm. |
Stand |
What a robot's units stand on, as Anvil's CAD draws it. |
TimedWaypoint |
One point of a |
TimedWaypoints |
Timed waypoints over every slot of a robot: a run the robot plans, such as its homing. |
UrdfJoint |
One moving joint of a robot's composed URDF and the slot it follows, as |
RobotConfig |
The robot one run drives: its arms in slot order, the URDF they stand by, and where each copy of it is mounted. |
NearestPair |
Two links of a robot checked against each other and their gap, from |
NearestLink |
A link of the robot and its gap to a keep-out box, from |
KeepOutBox |
A box in the workcell the robot is kept out of: a table, a wall, a fixture. |
Clearance |
How near a robot's links come to one another and to keep-out boxes, posed from its motors' positions. |
CameraRole |
What a camera looks at. |
Lens |
The lens fitted to a camera, which cannot be read off the camera, so a workcell says which. |
CameraConfig |
One camera of a workcell: its name, the device it opens, the mode it streams, and where it is. |
Preset |
A shipped workcell's name and shape, from |
WorkcellConfig |
A workcell: its robot, the cameras it streams, and the boxes its robot is kept out of. |
Functions:
| Name | Description |
|---|---|
shipped_urdf |
Returns the URDF text a shipped variant carries: the unit a robot's |
realhand_gripper |
Returns the external gripper an arm states for the RealHand L6 bolted to it, as the hand's description gives it. |
shipped_finger_sets |
Returns every finger set Anvil ships for |
Correction
dataclass
Correction(scale: float = 1.0, offset_nm: float = 0.0)
A correction to one feedforward term of one joint: the term as computed, times scale, plus offset_nm.
A model off by a factor or by a constant torque is corrected here; the defaults send the term as computed. Checked
where the arm is next handed over: a scale that is negative or not a number, or an offset_nm that is not a
number, is refused there.
Attributes:
| Name | Type | Description |
|---|---|---|
scale |
float
|
What the term is multiplied by: 1 sends it as computed, 0 none of it. |
offset_nm |
float
|
What is added after scaling, in newton meters. |
scale
class-attribute
instance-attribute
scale: float = 1.0
What the term is multiplied by: 1 sends it as computed, 0 none of it.
offset_nm
class-attribute
instance-attribute
offset_nm: float = 0.0
What is added after scaling, in newton meters.
JointDescription
dataclass
JointDescription(
name: str,
motor: str,
model: str,
slave_id: int,
master_id: int,
limits_deg: tuple[float, float],
max_dps: float | None = None,
gravity: Correction = Correction(
scale=1.0, offset_nm=0.0
),
rest_pose_deg: float = 0.0,
reflected: bool = False,
)
One joint of an arm: the motor driving it, the addresses it answers on, and how far and how fast it may go.
How hard a controller drives the joint is that controller's section of the arm's ArmDescription.tuning. Every
field is checked where the arm is next handed over. In the release wheel the joints of a robot must be exactly
those of the shipped description of its variant, so an edit to any field here is refused there.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The joint's name, e.g. |
motor |
str
|
The assembly-side motor name, |
model |
str
|
The Damiao motor model driving it, as the descriptions name it, e.g. |
slave_id |
int
|
The CAN address the motor listens on, 0 to 255. |
master_id |
int
|
The CAN address the motor replies on, 0 to 255. |
limits_deg |
tuple[float, float]
|
Its travel as |
max_dps |
float | None
|
The fastest its target may move, in degrees per second; |
gravity |
Correction
|
The correction applied to the gravity feedforward torque; as computed unless stated. |
rest_pose_deg |
float
|
The posture IK pulls the joint toward, in degrees, in the joint's own frame. |
reflected |
bool
|
Whether the joint's direction negates between the left and right arms of a mirror-image build. |
name
instance-attribute
name: str
The joint's name, e.g. joint_1; a gripper's motor is gripper.
motor
instance-attribute
motor: str
The assembly-side motor name, J<number>, e.g. J5: what the bench tools print.
Any other form is refused.
model
instance-attribute
model: str
The Damiao motor model driving it, as the descriptions name it, e.g. DM8009.
One this build does not know is refused.
slave_id
instance-attribute
slave_id: int
The CAN address the motor listens on, 0 to 255.
master_id
instance-attribute
master_id: int
The CAN address the motor replies on, 0 to 255.
limits_deg
instance-attribute
limits_deg: tuple[float, float]
Its travel as (min, max), in degrees, in the joint's own frame.
A reflected joint negates it on the right arm.
max_dps
class-attribute
instance-attribute
max_dps: float | None = None
The fastest its target may move, in degrees per second; None leaves its speed unguarded.
Each controller's ControllerTuning.max_dps for the joint may not exceed it.
gravity
class-attribute
instance-attribute
gravity: Correction = Correction(scale=1.0, offset_nm=0.0)
The correction applied to the gravity feedforward torque; as computed unless stated.
rest_pose_deg
class-attribute
instance-attribute
rest_pose_deg: float = 0.0
The posture IK pulls the joint toward, in degrees, in the joint's own frame.
A reflected joint negates it on the right arm.
reflected
class-attribute
instance-attribute
reflected: bool = False
Whether the joint's direction negates between the left and right arms of a mirror-image build.
GripAssist
dataclass
GripAssist(
max_torque: float = 0.0,
stiffness: float = 0.0,
opening_scale: float = 1.0,
shut_torque: float = 0.0,
)
The grip assist: the feedforward torque that does the gripping, on top of the gripper's own gains.
Each tick, with x the jaw-opening error in meters, measured minus commanded, closing pulls
max_torque * tanh(stiffness * x / max_torque) toward shut, and opening pulls opening_scale times the same curve
toward open. Near the target that is stiffness * x; past the knee, 1.5 * max_torque / stiffness meters of
error, it sits at max_torque. A max_torque of 0 turns the assist off, leaving the gripper's own gains to move
the jaws: where kp is a few per cent of the assist, as on the Anvil gripper, they creep, at the pace kp against
kd sets. Every value must be a number of zero or more, checked where the arm is next handed over.
Attributes:
| Name | Type | Description |
|---|---|---|
max_torque |
float
|
The torque the curve saturates at, in newton meters. |
stiffness |
float
|
The curve's slope at zero error, in newton meters per meter of jaw opening. |
opening_scale |
float
|
Opening as a fraction of closing, torque, speed and slope together. |
shut_torque |
float
|
The least closing torque while the command asks the jaws shut, in newton meters. |
max_torque
class-attribute
instance-attribute
max_torque: float = 0.0
The torque the curve saturates at, in newton meters.
How hard the gripper squeezes, and so, against the drive's Gripper.kd, how fast the jaws close.
stiffness
class-attribute
instance-attribute
stiffness: float = 0.0
The curve's slope at zero error, in newton meters per meter of jaw opening.
How sharply the jaws stop on an object. Higher holds a width more tightly and hunts sooner; a gripper that hunts wants less.
opening_scale
class-attribute
instance-attribute
opening_scale: float = 1.0
Opening as a fraction of closing, torque, speed and slope together.
1 is the same both ways, 0.5 releases at half speed, 0 turns the opening assist off.
shut_torque
class-attribute
instance-attribute
shut_torque: float = 0.0
The least closing torque while the command asks the jaws shut, in newton meters.
So a gripper closing on nothing holds itself shut.
FingerSet
dataclass
FingerSet(name: str, urdf: str | None = None)
A set of interchangeable fingers a gripper carries, one directory under the gripper's fingers/.
shipped_finger_sets lists the ones Anvil ships for a gripper; set one as a Gripper.fingers to swap to it.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The set's name, its directory under |
urdf |
str | None
|
The URDF fragment |
name
instance-attribute
name: str
The set's name, its directory under fingers/, e.g. fine_tip.
urdf
class-attribute
instance-attribute
urdf: str | None = None
The URDF fragment RobotConfig.composed_urdf lays over the gripper's own; None for the set shipped as name.
The printed finger on each carrier and the tool frame their tips set.
Gripper
dataclass
Gripper(
family: str,
version: int,
joint: JointDescription,
kp: float,
kd: float,
closed_deg: float,
open_deg: float,
opening_m: float,
urdf: str | None = None,
fingers: FingerSet | None = None,
grip_assist: GripAssist = GripAssist(
max_torque=0.0,
stiffness=0.0,
opening_scale=1.0,
shut_torque=0.0,
),
mass_kg: float = 0.0,
com_m: tuple[float, float, float] = (0.0, 0.0, 0.0),
inertia_kgm2: tuple[
float, float, float, float, float, float
] = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
alternate_motor: str | None = None,
)
A gripper the stack drives: its one motor, the gains it holds a width at, and the map from jaw opening to angle.
Every width the stack commands is the opening between the jaws, from 0 shut to opening_m fully open, mapped
linearly onto the motor angles closed_deg and open_deg. The gripper holds a width the same way under every
controller. A shipped description comes with its gripper filled in; a gripper Anvil does not ship needs its own
urdf.
Checked where the arm carrying it is next handed over: an opening_m that is not more than zero, a closed_deg or
open_deg outside joint's limits, a mass that is negative or not a number, a grip_assist value below zero, and
a urdf that is not a gripper fragment, or that fingers does not lay over, are refused there.
Attributes:
| Name | Type | Description |
|---|---|---|
family |
str
|
The gripper family, e.g. |
version |
int
|
The hardware revision, e.g. |
joint |
JointDescription
|
The motor driving the fingers. |
kp |
float
|
The drive's position gain, in newton meters per radian of motor angle error. |
kd |
float
|
The drive's velocity gain, in newton meters per radian per second of motor speed error. |
closed_deg |
float
|
The motor angle with the jaws shut, in degrees. |
open_deg |
float
|
The motor angle with the jaws open by |
opening_m |
float
|
The jaw opening at full travel, in meters, between the jaws: what every commanded width is measured against. |
urdf |
str | None
|
The unit's own URDF fragment, its |
fingers |
FingerSet | None
|
The finger set laid over |
grip_assist |
GripAssist
|
The feedforward torque that does the gripping. |
mass_kg |
float
|
The unit's mass, in kilograms. |
com_m |
tuple[float, float, float]
|
The unit's center of mass, in meters, in the frame of the link its fingers hang from. |
inertia_kgm2 |
tuple[float, float, float, float, float, float]
|
The unit's inertia about its center of mass, in kilogram square meters, as |
alternate_motor |
str | None
|
The motor name some units of this gripper were flashed as instead, e.g. |
gripper_map |
GripperMap
|
Map from a commanded jaw opening to the motor angle, linear between the shut and open angles. |
family
instance-attribute
family: str
The gripper family, e.g. anvil-gripper.
version
instance-attribute
version: int
The hardware revision, e.g. 1.
kp
instance-attribute
kp: float
The drive's position gain, in newton meters per radian of motor angle error.
kd
instance-attribute
kd: float
The drive's velocity gain, in newton meters per radian per second of motor speed error.
closed_deg
instance-attribute
closed_deg: float
The motor angle with the jaws shut, in degrees.
open_deg
instance-attribute
open_deg: float
The motor angle with the jaws open by opening_m, in degrees.
opening_m
instance-attribute
opening_m: float
The jaw opening at full travel, in meters, between the jaws: what every commanded width is measured against.
urdf
class-attribute
instance-attribute
urdf: str | None = None
The unit's own URDF fragment, its gripper.urdf, or None for the one its family and version ship.
RobotConfig.composed_urdf grafts it onto the hand link the arm ends at. It carries the tool frame and the two
finger joints the motor turns.
fingers
class-attribute
instance-attribute
fingers: FingerSet | None = None
The finger set laid over urdf, for a unit whose fingers are interchangeable.
None for one whose fingers are its own. A shipped arm carries the set its gripper ships with unless its
arm.yaml names another.
grip_assist
class-attribute
instance-attribute
grip_assist: GripAssist = GripAssist(
max_torque=0.0,
stiffness=0.0,
opening_scale=1.0,
shut_torque=0.0,
)
The feedforward torque that does the gripping.
mass_kg
class-attribute
instance-attribute
mass_kg: float = 0.0
The unit's mass, in kilograms.
The arm's URDF carries none of it; RobotConfig.composed_urdf adds it to the link the fingers hang from. A
gripper stated without it weighs nothing.
com_m
class-attribute
instance-attribute
com_m: tuple[float, float, float] = (0.0, 0.0, 0.0)
The unit's center of mass, in meters, in the frame of the link its fingers hang from.
inertia_kgm2
class-attribute
instance-attribute
inertia_kgm2: tuple[
float, float, float, float, float, float
] = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
The unit's inertia about its center of mass, in kilogram square meters, as (ixx, ixy, ixz, iyy, iyz, izz).
alternate_motor
class-attribute
instance-attribute
alternate_motor: str | None = None
The motor name some units of this gripper were flashed as instead, e.g. J7, or None for none.
A shipped arm's arm.yaml names it, as the OpenYAM's does, never the gripper's own description. The motor is then
driven at that name's addresses, slave n and master n + 0x10 for J<n>, on a link where the gripper's own
address is silent and that one answers; and a record numbered as it places the arm as a follower. An address a
chain joint uses, or a name not J<number>, is refused where the arm is next handed over.
gripper_map
property
gripper_map: GripperMap
Map from a commanded jaw opening to the motor angle, linear between the shut and open angles.
Built from the gripper as it is now; an edit after reading it does not change the map read.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The gripper is one the class docstring says is refused. |
ExternalGripper
dataclass
ExternalGripper(
can_ids: list[int] = [],
mass_kg: float = 0.0,
com_m: tuple[float, float, float] = (0.0, 0.0, 0.0),
inertia_kgm2: tuple[
float, float, float, float, float, float
] = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
)
A gripper the stack does not drive: your own, run by your code on the arm's bus beside the stack.
Set one as ArmDescription.gripper in place of a Gripper. It takes no slot and adds no URDF, so the arm's chain
ends at its hand flange, which carries the mass stated here. Checked where the arm is next handed over: a CAN ID
past 0x7FF, one stated twice or one the arm's motors use, and a mass that is negative or not a number, are refused
there.
Attributes:
| Name | Type | Description |
|---|---|---|
can_ids |
list[int]
|
The standard 11-bit CAN IDs your code sends and answers on, on the arm's bus. |
mass_kg |
float
|
The gripper's mass, in kilograms; 0 weighs nothing. |
com_m |
tuple[float, float, float]
|
Its center of mass, in meters, in the frame of the |
inertia_kgm2 |
tuple[float, float, float, float, float, float]
|
Its inertia about its center of mass, in kilogram square meters, as |
can_ids
class-attribute
instance-attribute
can_ids: list[int] = []
The standard 11-bit CAN IDs your code sends and answers on, on the arm's bus.
mass_kg
class-attribute
instance-attribute
mass_kg: float = 0.0
The gripper's mass, in kilograms; 0 weighs nothing.
com_m
class-attribute
instance-attribute
com_m: tuple[float, float, float] = (0.0, 0.0, 0.0)
Its center of mass, in meters, in the frame of the hand link it bolts to.
inertia_kgm2
class-attribute
instance-attribute
inertia_kgm2: tuple[
float, float, float, float, float, float
] = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
Its inertia about its center of mass, in kilogram square meters, as (ixx, ixy, ixz, iyy, iyz, izz).
Gains
dataclass
Gains(kp: float, kd: float)
A drive's two gains for one joint.
The drive applies kp * (position target - measured position) + kd * (velocity target - measured velocity),
plus the feedforward torque. Each must be a number of zero or more, checked where the arm is next handed over.
Attributes:
| Name | Type | Description |
|---|---|---|
kp |
float
|
Position gain, in newton meters per radian. |
kd |
float
|
Velocity gain, in newton meters per radian per second. |
kp
instance-attribute
kp: float
Position gain, in newton meters per radian.
kd
instance-attribute
kd: float
Velocity gain, in newton meters per radian per second.
ControllerTuning
dataclass
ControllerTuning(
joints: list[Gains],
max_dps: list[float],
tcp_max_mps: float,
)
How one controller drives an arm's chain joints: their gains and how fast it moves their targets.
Checked where the arm is next handed over: joints and max_dps must each hold exactly one entry per chain joint,
and every speed must be more than zero.
Attributes:
| Name | Type | Description |
|---|---|---|
joints |
list[Gains]
|
The gains of each chain joint, in chain order. |
max_dps |
list[float]
|
The fastest the controller moves each chain joint's target, in degrees per second, in chain order. |
tcp_max_mps |
float
|
The fastest the controller moves the arm's tool frame, in meters per second. |
max_dps
instance-attribute
max_dps: list[float]
The fastest the controller moves each chain joint's target, in degrees per second, in chain order.
Never past the joint's own JointDescription.max_dps.
tcp_max_mps
instance-attribute
tcp_max_mps: float
The fastest the controller moves the arm's tool frame, in meters per second.
TuningDescription
dataclass
TuningDescription(
joint: ControllerTuning,
joint_trajectory: ControllerTuning,
ee_pose: ControllerTuning,
leader_follower: ControllerTuning,
)
How each controller drives an arm's chain joints, as the tuning.yaml beside its arm.yaml states it.
One complete section per controller, nothing shared between them. An edit before a controller is built, such as
arm.description.tuning.ee_pose.joints[6].kp = 15.0, is what that controller then runs; once it is running, its
handle's configure is how a gain moves.
Attributes:
| Name | Type | Description |
|---|---|---|
joint |
ControllerTuning
|
The |
joint_trajectory |
ControllerTuning
|
The |
ee_pose |
ControllerTuning
|
The |
leader_follower |
ControllerTuning
|
The |
joint_trajectory
instance-attribute
joint_trajectory: ControllerTuning
The anvil.control.JointTrajectoryController's section.
leader_follower
instance-attribute
leader_follower: ControllerTuning
The anvil.control.LeaderFollowerController's section, for the followers; it drives the leaders limp.
ArmDescription
dataclass
ArmDescription(
family: str,
version: int,
joints: list[JointDescription],
gripper: Gripper | ExternalGripper,
tuning: TuningDescription,
home: dict[str, Any] | None = None,
excluded_pairs: list[tuple[str, str]] = [],
)
One arm variant: what it physically is and how it is driven.
Where it stands is the RobotConfig's business. The shipped variants are class attributes,
ArmDescription.OPENARM_V2, each built fresh on every access with nothing read from disk; shipped takes the
variant as text, and read takes a description directory of your own. Every field holds the object itself, so an
edit through one is what an arm carrying this description then runs. Checked where the arm is next handed over: no
chain joint or more than anvil.kinematics.MAX_DOF, a motor not named J<number>, a joint or tuning refused as its
class says, a gripper refused as its class says, or a home its field says is refused.
Methods:
| Name | Description |
|---|---|
shipped |
Returns the shipped arm |
read |
Reads the arm |
shipped_home |
Returns the homing run the variant ships with, its grips opened to the same share of the gripper it carries. |
to_json |
Returns the description as JSON, the form |
from_json |
Builds a description from the JSON |
Attributes:
| Name | Type | Description |
|---|---|---|
family |
str
|
The arm family, e.g. |
version |
int
|
The hardware revision, e.g. |
joints |
list[JointDescription]
|
The chain joints, in order; the gripper's motor is not among them. |
gripper |
Gripper | ExternalGripper
|
The gripper the arm carries: a |
tuning |
TuningDescription
|
The gains and speeds each controller drives the chain joints at. |
home |
dict[str, Any] | None
|
The homing run, as the left or only arm sees it: the one the variant ships with, or one a workcell taught. |
excluded_pairs |
list[tuple[str, str]]
|
Pairs of the arm's links, by its own URDF names, that |
OPENARM_V1 |
The OpenArm v1, built fresh on every access. |
|
OPENARM_V2 |
The OpenArm v2, built fresh on every access. |
|
OPENYAM_V1 |
The OpenYAM v1, built fresh on every access. |
|
OPENYAM_V2 |
The OpenYAM v2, built fresh on every access. |
|
YAM_V1 |
The YAM v1, built fresh on every access. |
|
variant |
str
|
The variant, |
num_slots |
int
|
Slots one such arm owns in a robot: one per chain joint, then one for a |
gripper_map |
GripperMap | None
|
|
family
instance-attribute
family: str
The arm family, e.g. openarm.
version
instance-attribute
version: int
The hardware revision, e.g. 2.
joints
instance-attribute
joints: list[JointDescription]
The chain joints, in order; the gripper's motor is not among them.
gripper
instance-attribute
gripper: Gripper | ExternalGripper
The gripper the arm carries: a Gripper the stack drives, or an ExternalGripper your own code drives.
tuning
instance-attribute
tuning: TuningDescription
The gains and speeds each controller drives the chain joints at.
home
class-attribute
instance-attribute
home: dict[str, Any] | None = None
The homing run, as the left or only arm sees it: the one the variant ships with, or one a workcell taught.
{"tcp_speed_mps": float, "rows": [...]}, each row {"q_deg": [...], "grip_m": float, "tcp_speed_mps": float |
None}. The first row is the park pose, where the arm sits while the robot is off; the last is the home pose, where
homing leaves it ready to work; the rows between are waypoints. Every shipped run is authored for an arm standing
upright. Teach your own from RobotConfig.home_rows_at, as a unit hung or on a wall has to, and go back
with shipped_home. None for an arm that ships none, which RobotConfig.home_trajectory then refuses.
Refused for a tcp_speed_mps that is not positive and finite, no rows, or a row that does not state one angle per
chain joint inside its limits, whose grip is outside the gripper's opening, or whose own tcp_speed_mps is not
positive and finite.
excluded_pairs
class-attribute
instance-attribute
excluded_pairs: list[tuple[str, str]] = []
Pairs of the arm's links, by its own URDF names, that Clearance never checks one against the other.
Their collision meshes overlap however it stands.
OPENARM_V1
class-attribute
instance-attribute
OPENARM_V1
The OpenArm v1, built fresh on every access.
OPENARM_V2
class-attribute
instance-attribute
OPENARM_V2
The OpenArm v2, built fresh on every access.
OPENYAM_V1
class-attribute
instance-attribute
OPENYAM_V1
The OpenYAM v1, built fresh on every access.
OPENYAM_V2
class-attribute
instance-attribute
OPENYAM_V2
The OpenYAM v2, built fresh on every access.
YAM_V1
class-attribute
instance-attribute
YAM_V1
The YAM v1, built fresh on every access.
variant
property
variant: str
The variant, family/vN, e.g. openyam/v1: the name the sim and shipped know the arm by.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The description is one the class docstring says is refused. |
num_slots
property
num_slots: int
Slots one such arm owns in a robot: one per chain joint, then one for a Gripper the stack drives.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The description is one the class docstring says is refused. |
gripper_map
property
gripper_map: GripperMap | None
Gripper.gripper_map of the gripper the stack drives; None for an external gripper.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The gripper is one |
shipped
staticmethod
shipped(variant: str) -> ArmDescription
Returns the shipped arm variant names, built fresh: for a caller that has the variant as text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variant
|
str
|
The variant, |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
Anvil ships no such variant; the message lists the ones it does. |
read
staticmethod
read(root: str, variant: str) -> ArmDescription
Reads the arm <root>/arms/<variant>/arm.yaml describes, with its tuning, homing and gripper.
How a description the SDK was not built with gets in: root is a directory laid out as Anvil's descriptions
are. The arm is joined to the gripper its arm.yaml names under <root>/grippers/, the tuning.yaml beside
it, and the home.yaml and collision.yaml beside it where they exist. The release wheel refuses a robot
built from a description that differs from the shipped one; see the module docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str
|
The directory holding |
required |
variant
|
str
|
The variant, |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
A file could not be read, a missing one included, or does not describe an arm this SDK can use; the message names the file. |
shipped_home
shipped_home() -> dict[str, Any] | None
Returns the homing run the variant ships with, its grips opened to the same share of the gripper it carries.
What a description whose home was taught goes back to: description.home = description.shipped_home().
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
The run in the shape |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
Anvil ships no such variant, or the description is one the class docstring says is refused. |
to_json
to_json() -> str
Returns the description as JSON, the form from_json reads back.
from_json
classmethod
from_json(wire: str) -> Self
Builds a description from the JSON to_json wrote, checked as it is when handed over.
JSON an older release wrote reads as it was written: a field added since takes its default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wire
|
str
|
The JSON text. |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
|
Side
Bases: StrEnum
Which arm of a robot an arm is, where that means something.
The left or the right of a pair, or of a mirror-image build even alone. The only arm of its role in a symmetric build, a lone yam or either arm of a single leader and follower, has no side.
Attributes:
| Name | Type | Description |
|---|---|---|
LEFT |
The left arm, which takes the lower slots of its role. |
|
RIGHT |
The right arm. |
LEFT
class-attribute
instance-attribute
LEFT
The left arm, which takes the lower slots of its role.
RIGHT
class-attribute
instance-attribute
RIGHT
The right arm.
ArmCount
Bases: StrEnum
How many followers a shipped workcell stands: one, or a left and a right.
Attributes:
| Name | Type | Description |
|---|---|---|
SINGLE |
One follower, with no side. |
|
BIMANUAL |
A left and a right follower. |
SINGLE
class-attribute
instance-attribute
SINGLE
One follower, with no side.
BIMANUAL
class-attribute
instance-attribute
BIMANUAL
A left and a right follower.
Role
Bases: StrEnum
What an arm does in a robot.
Followers take the lower slots, so adding leaders moves no follower's slots.
Attributes:
| Name | Type | Description |
|---|---|---|
LEADER |
Moved by hand; its measured state becomes the command of the follower on its side. |
|
FOLLOWER |
Driven to a command. |
LEADER
class-attribute
instance-attribute
LEADER
Moved by hand; its measured state becomes the command of the follower on its side.
Its URDF names carry a leader_ prefix ahead of its side.
FOLLOWER
class-attribute
instance-attribute
FOLLOWER
Driven to a command.
ArmLayout
dataclass
ArmLayout(
first_slot: int,
num_slots: int,
chain_slots: tuple[int, ...],
gripper_slot: int | None,
tcp_link: str,
)
Where one arm of a robot sits in the robot's slots, as RobotConfig.layout worked it out.
Attributes:
| Name | Type | Description |
|---|---|---|
first_slot |
int
|
The first slot the arm owns. |
num_slots |
int
|
How many slots it owns: its chain joints, then its gripper where the stack drives one. |
chain_slots |
tuple[int, ...]
|
The slot of each chain joint, in description order. |
gripper_slot |
int | None
|
The slot of its gripper motor, the last it owns; |
tcp_link |
str
|
The URDF link its chain ends at: the gripper's tool frame, or the |
first_slot
instance-attribute
first_slot: int
The first slot the arm owns.
num_slots
instance-attribute
num_slots: int
How many slots it owns: its chain joints, then its gripper where the stack drives one.
chain_slots
instance-attribute
chain_slots: tuple[int, ...]
The slot of each chain joint, in description order.
gripper_slot
instance-attribute
gripper_slot: int | None
The slot of its gripper motor, the last it owns; None for an external gripper, which owns none.
tcp_link
instance-attribute
tcp_link: str
The URDF link its chain ends at: the gripper's tool frame, or the hand flange for an external gripper.
RobotLayout
dataclass
RobotLayout(
variant: str,
num_slots: int,
slot_summary: str,
slot_names: tuple[str, ...],
slot_travel_rad: tuple[tuple[float, float], ...],
arms: tuple[ArmLayout, ...],
)
What follows from a robot's arms rather than being stated with them, as RobotConfig.layout worked it out.
A snapshot: reading it costs nothing, and an edit to the robot after it was taken does not change it.
Attributes:
| Name | Type | Description |
|---|---|---|
variant |
str
|
The variant the arms share, e.g. |
num_slots |
int
|
Slots the arms occupy: the |
slot_summary |
str
|
The arms and the slots they own, for an operator's log: |
slot_names |
tuple[str, ...]
|
Each slot by what it drives, in slot order. |
slot_travel_rad |
tuple[tuple[float, float], ...]
|
Each slot's travel as |
arms |
tuple[ArmLayout, ...]
|
One per arm, in the robot's order. |
variant
instance-attribute
variant: str
The variant the arms share, e.g. openyam/v1.
num_slots
instance-attribute
num_slots: int
Slots the arms occupy: the num_joints of an anvil.control.JointState or anvil.control.RobotCommand.
slot_summary
instance-attribute
slot_summary: str
The arms and the slots they own, for an operator's log: left owns slots 0..8, right owns slots 8..16.
Each range is half-open: 0..8 is slots 0 to 7.
slot_names
instance-attribute
slot_names: tuple[str, ...]
Each slot by what it drives, in slot order.
The arm's name, then the joint's or gripper, e.g. "left joint_3", "left gripper".
slot_travel_rad
instance-attribute
slot_travel_rad: tuple[tuple[float, float], ...]
Each slot's travel as (lower, upper), in radians, in slot order.
A chain joint's limits from the arm's description, negated on the right arm for a JointDescription.reflected
joint; a gripper motor's between its shut and open angles.
ArmConfig
dataclass
ArmConfig(
name: str,
bus: str,
description: ArmDescription,
side: Side | None = None,
role: Role = Role.FOLLOWER,
bus_overridden: bool = False,
)
One arm of a robot: its name, the bus it answers on, what it does, which side it is, and its description.
Put it in a RobotConfig to give it slots; the slot properties ask that robot, so they follow any edit to it.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Its name, unique in the robot: what logs, errors and |
bus |
str
|
The bus its motors answer on, e.g. |
description |
ArmDescription
|
Everything the arm physically is and how it is driven, as the object itself. |
side |
Side | None
|
|
role |
Role
|
What the arm does in the robot. |
bus_overridden |
bool
|
Whether an operator set |
num_slots |
int
|
Slots the arm owns: one per chain joint, then one for a |
first_slot |
int | None
|
The first slot the arm owns in the robot it was last put in; |
chain_slots |
list[int]
|
The slot of each chain joint, in description order. |
gripper_slot |
int | None
|
The slot of its gripper motor, the last one it owns; |
name
instance-attribute
name: str
Its name, unique in the robot: what logs, errors and RobotLayout.slot_names call it.
bus
instance-attribute
bus: str
The bus its motors answer on, e.g. "follower_l", resolved against the CAN links the host has.
Where the drives' identity records name a link, they decide and this is the fallback, unless bus_overridden; where
it resolves to no link with drives, the arm is guessed onto one that has them, as anvil.hw.buses says.
description
instance-attribute
description: ArmDescription
Everything the arm physically is and how it is driven, as the object itself.
So arm.description.tuning.ee_pose.joints[3].kp = 20.0 is what this arm then runs.
side
class-attribute
instance-attribute
side: Side | None = None
Side.LEFT or Side.RIGHT in a robot with more than one arm of its role, or for a mirror-image build.
None for the only arm of its role in a symmetric build. Any other choice is refused where the robot is built.
bus_overridden
class-attribute
instance-attribute
bus_overridden: bool = False
Whether an operator set bus by hand over what the drives' identity records say.
The arm then stays on bus, and the readiness check only warns where its records disagree.
num_slots
property
num_slots: int
Slots the arm owns: one per chain joint, then one for a Gripper the stack drives.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The description is one |
first_slot
property
first_slot: int | None
The first slot the arm owns in the robot it was last put in; None until it is in a RobotConfig.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
That robot, as edited since, is one |
chain_slots
property
chain_slots: list[int]
The slot of each chain joint, in description order.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot the arm is in, as edited since, is one |
OperationError
|
The arm is in no |
gripper_slot
property
gripper_slot: int | None
The slot of its gripper motor, the last one it owns; None for an external gripper, which owns none.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot the arm is in, as edited since, is one |
OperationError
|
The arm is in no |
Mount
dataclass
Mount(
prefix: str,
xyz_m: tuple[float, float, float],
yaw_rad: float,
roll_rad: float = 0.0,
pitch_rad: float = 0.0,
)
Where a robot stands one copy of its variant's unit: an OpenArm torso carrying both arms, or one yam arm.
Mounts are stated in the world frame, the composed URDF's world link, which every pose a robot's chains and
controllers state is in too. A preset's mounts are where the shipped stands bolt the units; move them to match your
bench. The unit is turned as a URDF origin is: rolled about the world's x, then pitched about its y, then turned
about its vertical. Hung from a ceiling is roll_rad=math.pi; bolted to a wall behind it, pitch_rad=math.pi / 2.
Gravity stays the world's -z, so a tilted unit's chains, gravity compensation and IK follow the tilt. Each mount of
a robot has its own prefix, and every coordinate must be a finite number, checked where the robot is built or
next handed over.
Attributes:
| Name | Type | Description |
|---|---|---|
prefix |
str
|
What the copy's URDF link and joint names are prefixed with. |
xyz_m |
tuple[float, float, float]
|
Where the unit's base stands in the world frame, in meters. |
yaw_rad |
float
|
How far the unit is turned about the world frame's vertical, in radians, counterclockwise seen from above. |
roll_rad |
float
|
How far the unit is rolled about the world frame's x, in radians; zero stands it upright. |
pitch_rad |
float
|
How far the unit is pitched about the world frame's y, in radians; zero stands it upright. |
prefix
instance-attribute
prefix: str
What the copy's URDF link and joint names are prefixed with.
For one arm, its role's prefix then its side's, "left_", "leader_left_" or "" for an arm with no side; for
an OpenArm torso, its role's, "" or "leader_".
xyz_m
instance-attribute
xyz_m: tuple[float, float, float]
Where the unit's base stands in the world frame, in meters.
yaw_rad
instance-attribute
yaw_rad: float
How far the unit is turned about the world frame's vertical, in radians, counterclockwise seen from above.
roll_rad
class-attribute
instance-attribute
roll_rad: float = 0.0
How far the unit is rolled about the world frame's x, in radians; zero stands it upright.
The roll is applied first, before the pitch and then the yaw.
pitch_rad
class-attribute
instance-attribute
pitch_rad: float = 0.0
How far the unit is pitched about the world frame's y, in radians; zero stands it upright.
The pitch is applied after the roll and before the yaw.
Stand
Bases: StrEnum
What a robot's units stand on, as Anvil's CAD draws it.
Its frame is the one the robot's mounts are stated in, so a mount is where the stand bolts a unit, and
anvil.sim.World stands the robot in the scene of the stand's name unless told another.
Attributes:
| Name | Type | Description |
|---|---|---|
LIFT |
The wheeled lifting platform. Its frame is the top plate's face on the column's axis, x along the reach. |
|
LIFT_BRACKET |
The lift carrying the OpenYAM middle bracket, in the lift's frame. |
LIFT
class-attribute
instance-attribute
LIFT
The wheeled lifting platform. Its frame is the top plate's face on the column's axis, x along the reach.
LIFT_BRACKET
class-attribute
instance-attribute
LIFT_BRACKET
The lift carrying the OpenYAM middle bracket, in the lift's frame.
It is the rail a yam pair stands on, and the pole between the arms with a camera on its ball head: the composed
URDF's pole_cam link, which a CameraConfig.link may name.
TimedWaypoint
dataclass
TimedWaypoint(
time_from_start_s: float,
q: list[float],
qd: list[float],
)
One point of a TimedWaypoints: where every slot is at one time, and how fast it moves through there.
Attributes:
| Name | Type | Description |
|---|---|---|
time_from_start_s |
float
|
When the run reaches it, in seconds after the run starts. |
q |
list[float]
|
Position per slot, in radians; a gripper's slot is its motor angle. |
qd |
list[float]
|
Velocity per slot as the run passes through, in radians per second; zero stops there before moving on. |
time_from_start_s
instance-attribute
time_from_start_s: float
When the run reaches it, in seconds after the run starts.
q
instance-attribute
q: list[float]
Position per slot, in radians; a gripper's slot is its motor angle.
qd
instance-attribute
qd: list[float]
Velocity per slot as the run passes through, in radians per second; zero stops there before moving on.
TimedWaypoints
dataclass
TimedWaypoints(num_slots: int, points: list[TimedWaypoint])
Timed waypoints over every slot of a robot: a run the robot plans, such as its homing.
One comes from RobotConfig.home_trajectory, dehome_trajectory or rehome_trajectory. The first waypoint is
reached from wherever the arms are when it starts, and the last at rest. Play it with
anvil.control.JointTrajectoryHandle.play, send it with anvil.control.Runtime.send_command, or build the
command from it with anvil.control.JointTrajectoryCommand.from_waypoints: the controller plays it as it is.
Attributes:
| Name | Type | Description |
|---|---|---|
num_slots |
int
|
Slots every waypoint states: the robot's |
points |
list[TimedWaypoint]
|
The waypoints, in time order. |
duration_s |
float
|
Time from the start to the last waypoint, in seconds; 0 for a run with none. |
num_slots
instance-attribute
num_slots: int
Slots every waypoint states: the robot's RobotConfig.num_slots.
duration_s
property
duration_s: float
Time from the start to the last waypoint, in seconds; 0 for a run with none.
UrdfJoint
dataclass
UrdfJoint(
name: str, slot: int | None, scale: float, offset: float
)
One moving joint of a robot's composed URDF and the slot it follows, as RobotConfig.urdf_joints lists it.
The joint's value is scale times the measured position in slot, plus offset: one for one for a motor's own
joint, while a gripper's finger follows its motor through the linkage.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The joint's name in the composed URDF. |
slot |
int | None
|
The slot whose measured position drives the joint; |
scale |
float
|
What the slot's position is multiplied by; 1 for a motor's own joint. |
offset |
float
|
What is added after scaling; 0 for a motor's own joint. |
name
instance-attribute
name: str
The joint's name in the composed URDF.
slot
instance-attribute
slot: int | None
The slot whose measured position drives the joint; None for a joint nothing drives.
scale
instance-attribute
scale: float
What the slot's position is multiplied by; 1 for a motor's own joint.
offset
instance-attribute
offset: float
What is added after scaling; 0 for a motor's own joint.
RobotConfig
dataclass
RobotConfig(
arms: list[ArmConfig],
urdf: str | None = None,
mounts: list[Mount] = [],
stand: Stand | None = None,
)
The robot one run drives: its arms in slot order, the URDF they stand by, and where each copy of it is mounted.
Get one from a workcell, WorkcellConfig.OPENYAM_V1_SINGLE.robot, or build one from its fields. Each arm owns the
slots after the arm before it, chain joints then gripper, so a bimanual openarm's left arm owns slots 0 to 7 and its
right 8 to 15, and a single openyam's arm 0 to 6. Arms are declared followers before leaders and, within a role, the
left before the right.
It is checked as it is built, and again wherever it is handed over after an edit. Whether the URDF really carries
each arm is found where a chain is cut from it, by chains, composed_urdf and the calls that use them.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
No arm, or more than |
Methods:
| Name | Description |
|---|---|
arms_where |
Returns the arms of the side and role asked for, in slot order: the objects themselves. |
arm |
Returns the arm named |
layout |
Returns the robot's slot layout as it stands now, as a snapshot. |
camera_links |
Returns every |
mount_joints |
Returns the URDF joint each of |
mesh_files |
Returns every mesh the composed URDF names, each once, by its path under the robot descriptions' root. |
urdf_joints |
Returns every moving joint of |
composed_urdf |
Returns the whole robot as URDF text: what gravity compensation, the sim and a recording read. |
chains |
Returns one |
home_rows_at |
Returns one homing row per arm, in slot order, standing each where |
home_trajectory |
Returns the run that homes the robot from where its arms are, through the homing sequence each describes. |
dehome_trajectory |
Returns the homing run backwards, from where the arms are to the row a homing starts from, ending at rest. |
rehome_trajectory |
Returns a run straight to where a homing ends, in one segment from where the arms are. |
to_json |
Returns the robot as JSON, the form |
from_json |
Builds a robot from the JSON |
Attributes:
| Name | Type | Description |
|---|---|---|
arms |
list[ArmConfig]
|
The arms, in slot order: the objects themselves, so an edit through one is what that arm then runs. |
urdf |
str | None
|
The URDF text the arms stand by, without their grippers, or |
mounts |
list[Mount]
|
Where each copy of |
stand |
Stand | None
|
What the units stand on, in whose frame the |
variant |
str
|
The variant the arms share, e.g. |
num_slots |
int
|
Slots the arms occupy: the |
slot_summary |
str
|
The arms and the slots they own, for an operator's log: |
ik_params |
list[IkParams]
|
Each arm's IK parameters, in slot order, as an |
arms
instance-attribute
arms: list[ArmConfig]
The arms, in slot order: the objects themselves, so an edit through one is what that arm then runs.
urdf
class-attribute
instance-attribute
urdf: str | None = None
The URDF text the arms stand by, without their grippers, or None for the one their variant ships.
For example Path("mine.urdf").read_text(). With mounts it is the variant's unit, placed once per mount; with
none it places the arms itself.
mounts
class-attribute
instance-attribute
mounts: list[Mount] = []
Where each copy of urdf stands; empty for a urdf that places the arms itself.
stand
class-attribute
instance-attribute
stand: Stand | None = None
What the units stand on, in whose frame the mounts are; None for a bench nothing draws.
A preset without leaders stands on the lift, a yam pair on the bracket it carries; one with leaders on none.
variant
property
variant: str
The variant the arms share, e.g. openyam/v1.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot, as edited since it was built, is refused. |
num_slots
property
num_slots: int
Slots the arms occupy: the num_joints of an anvil.control.JointState or anvil.control.RobotCommand.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot, as edited since it was built, is refused. |
slot_summary
property
slot_summary: str
The arms and the slots they own, for an operator's log: left owns slots 0..8, right owns slots 8..16.
Each range is half-open: 0..8 is slots 0 to 7.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot, as edited since it was built, is refused. |
ik_params
property
ik_params: list[IkParams]
Each arm's IK parameters, in slot order, as an anvil.control.EePoseController over the robot starts out.
The rest posture is the one each arm's description states, as that arm sees it; the rest are the solver's defaults. Each read builds them afresh, so an edit to one changes nothing until it is handed to a solve or a controller.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot, as edited since it was built, is refused. |
arms_where
Returns the arms of the side and role asked for, in slot order: the objects themselves.
A filter left None matches every arm, so arms_where() is arms. An arm with no side matches no side: on a
single-arm cell, arms_where(side=Side.LEFT) is [] and the arm is arms[0].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side
|
Side | None
|
The side to match, or |
None
|
role
|
Role | None
|
The role to match, or |
None
|
arm
arm(name: str) -> ArmConfig | None
Returns the arm named name, the object itself, or None when the robot has no arm of that name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The arm's name, as its |
required |
layout
layout() -> RobotLayout
Returns the robot's slot layout as it stands now, as a snapshot.
Each slot property of the robot and of its arms works the layout out again; take it once where a loop reads it repeatedly.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot, as edited since it was built, is refused. |
camera_links
camera_links() -> list[str]
Returns every *_cam link of the composed URDF: the links a CameraConfig.link may name.
The sim renders each of these as the camera riding on it.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
As |
mount_joints
mount_joints() -> list[str]
Returns the URDF joint each of mounts stands its copy of the unit by, in the mounts' order.
That joint is what moves the whole unit, as a viewer dragging it would. Empty for a robot with no mounts.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot is refused, or its |
mesh_files
mesh_files() -> list[str]
Returns every mesh the composed URDF names, each once, by its path under the robot descriptions' root.
These are what has to travel beside the composed URDF for it to load elsewhere, e.g.
arms/openyam/v1/meshes/base_link_collision_c00.stl.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
As |
urdf_joints
urdf_joints() -> list[UrdfJoint]
Returns every moving joint of composed_urdf with the slot it follows, in the composed URDF's order.
This is how to pose a drawing of the robot from the loop's state.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
As |
composed_urdf
composed_urdf() -> str
Returns the whole robot as URDF text: what gravity compensation, the sim and a recording read.
urdf placed once per mount, each arm's gripper URDF and finger set grafted onto the hand link it ends at,
and each gripper's mass added to the link its fingers hang from, or an external gripper's to hand; the camera
a stand carries is a link fixed to world. Every mesh is named by its path under the robot descriptions'
root.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The robot is refused, or a URDF does not parse, lacks the link a gripper mounts
on, or already carries a joint a gripper or the stand adds; the message names the link or joint; a
stand's camera on a URDF with no |
chains
chains() -> list[Chain]
Returns one anvil.kinematics.Chain per arm, in slot order, cut from the composed URDF to its tool frame.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
As |
home_rows_at
home_rows_at(q: Sequence[float]) -> list[dict[str, Any]]
Returns one homing row per arm, in slot order, standing each where q has it: what a row is taught from.
Move the arms there by hand, then put each row in its arm's ArmDescription.home: the first row is the park
pose, the last the home pose, the rows between waypoints. Each row is as the left or only arm sees it, as
home states its rows, every joint held inside its travel and the gripper inside its opening, so a reading a
hair past a stop still plays; its leg is paced at the run's own speed.
Example
rows = robot.home_rows_at(q=runtime.latest().q)
for arm, row in zip(robot.arms, rows, strict=True):
arm.description.home["rows"][0] = row # the park pose
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Sequence[float]
|
Position per slot, in radians: a |
required |
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
One row per arm, in slot order, each a dict as |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
The robot is refused, or |
home_trajectory
home_trajectory(from_q: Sequence[float]) -> TimedWaypoints
Returns the run that homes the robot from where its arms are, through the homing sequence each describes.
Each segment lasts as long as the arm whose tip travels farthest needs at the speed the description states for
it, or the joint that turns farthest needs at 60 degrees a second, whichever is longer, and never less than half
a second; the waypoints are passed through without overshoot and the last is reached at rest. Play it on a
anvil.control.JointTrajectoryController over the same robot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
from_q
|
Sequence[float]
|
Position per slot where the arms are now, in radians: a |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
The robot is refused; an arm's description states no homing sequence, or the
arms' sequences have different numbers of rows; |
dehome_trajectory
dehome_trajectory(
from_q: Sequence[float],
) -> TimedWaypoints
Returns the homing run backwards, from where the arms are to the row a homing starts from, ending at rest.
It passes through the home rows last to first, each leg at the pace it is played forward, timed as
home_trajectory times it. What a teleop session plays before its drives are disabled.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
from_q
|
Sequence[float]
|
Position per slot where the arms are now, in radians: a |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
As |
rehome_trajectory
rehome_trajectory(
from_q: Sequence[float],
) -> TimedWaypoints
Returns a run straight to where a homing ends, in one segment from where the arms are.
What a teleop session plays when the operator asks for the arms back at home mid-session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
from_q
|
Sequence[float]
|
Position per slot where the arms are now, in radians: a |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
As |
to_json
to_json() -> str
Returns the robot as JSON, the form from_json reads back.
from_json
classmethod
from_json(wire: str) -> Self
Builds a robot from the JSON to_json wrote, checked as one built from its fields is.
JSON an older release wrote reads as it was written: a field added since takes its default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wire
|
str
|
The JSON text. |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
|
NearestPair
dataclass
NearestPair(
link_a: str,
link_b: str,
distance_m: float,
point_a_m: tuple[float, float, float],
point_b_m: tuple[float, float, float],
)
Two links of a robot checked against each other and their gap, from Clearance.nearest or within.
Attributes:
| Name | Type | Description |
|---|---|---|
link_a |
str
|
One piece's link, as the composed URDF names it. |
link_b |
str
|
The other piece's link. |
distance_m |
float
|
The gap between them, in meters; zero where they touch or overlap. |
point_a_m |
tuple[float, float, float]
|
The point of |
point_b_m |
tuple[float, float, float]
|
The point of |
link_a
instance-attribute
link_a: str
One piece's link, as the composed URDF names it.
link_b
instance-attribute
link_b: str
The other piece's link.
distance_m
instance-attribute
distance_m: float
The gap between them, in meters; zero where they touch or overlap.
point_a_m
instance-attribute
point_a_m: tuple[float, float, float]
The point of link_a's piece at one end of the gap, in the world frame, in meters.
point_b_m
instance-attribute
point_b_m: tuple[float, float, float]
The point of link_b's piece at the gap's other end, in the world frame, in meters.
NearestLink
dataclass
NearestLink(
link: str,
distance_m: float,
point_m: tuple[float, float, float],
box_point_m: tuple[float, float, float],
)
A link of the robot and its gap to a keep-out box, from Clearance.nearest_to or within_of.
Attributes:
| Name | Type | Description |
|---|---|---|
link |
str
|
The piece's link, as the composed URDF names it. |
distance_m |
float
|
The gap between it and the box, in meters. Where they touch or overlap, zero from |
point_m |
tuple[float, float, float]
|
The point of the piece at one end of the gap, in the world frame, in meters. |
box_point_m |
tuple[float, float, float]
|
The point of the box at the gap's other end, in the world frame, in meters. |
link
instance-attribute
link: str
The piece's link, as the composed URDF names it.
distance_m
instance-attribute
distance_m: float
The gap between it and the box, in meters. Where they touch or overlap, zero from nearest_to, and from
within_of minus how far the link must move to leave the box.
point_m
instance-attribute
point_m: tuple[float, float, float]
The point of the piece at one end of the gap, in the world frame, in meters.
box_point_m
instance-attribute
box_point_m: tuple[float, float, float]
The point of the box at the gap's other end, in the world frame, in meters.
KeepOutBox
dataclass
KeepOutBox(
name: str,
center_m: tuple[float, float, float],
size_m: tuple[float, float, float],
)
A box in the workcell the robot is kept out of: a table, a wall, a fixture.
It stands square to the world frame, the one Mount places the units in. Its name must be unique in the workcell
and every side a positive length, checked where the workcell is built or next handed over.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Its name, unique in the workcell, e.g. |
center_m |
tuple[float, float, float]
|
Its center in the world frame, in meters. |
size_m |
tuple[float, float, float]
|
Its length along each of the world frame's axes, in meters. |
name
instance-attribute
name: str
Its name, unique in the workcell, e.g. table.
center_m
instance-attribute
center_m: tuple[float, float, float]
Its center in the world frame, in meters.
size_m
instance-attribute
size_m: tuple[float, float, float]
Its length along each of the world frame's axes, in meters.
Clearance
Clearance(robot: RobotConfig)
How near a robot's links come to one another and to keep-out boxes, posed from its motors' positions.
Built once for a robot and asked as often as needed; it keeps no reference to the robot, so a later edit to the
robot does not reach it. Every collision piece of the composed URDF is checked, except the pairs each arm's
ArmDescription.excluded_pairs names. Each piece stands for a few dozen points on its convex hull, so a gap
reads a few millimeters wide of the meshes' on a rounded piece. Freed when the object is garbage-collected.
Builds the clearance of robot as it is now.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
robot
|
RobotConfig
|
The robot whose links are checked. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
The robot is refused, its URDF cannot be composed, or it names a collision mesh the SDK has no hull for, as a description read from a directory of your own can. |
Methods:
| Name | Description |
|---|---|
arm_of |
Returns the index into the robot's |
nearest |
Returns the nearest two pieces that are checked against each other, with the motors at |
nearest_to |
Returns the robot's piece nearest |
within |
Returns every pair of links checked against each other that stand no more than |
within_of |
Returns every link of the robot that stands no more than |
arm_of
arm_of(link: str) -> int | None
Returns the index into the robot's RobotConfig.arms of the arm that carries link.
An arm carries every link whose name starts with its prefix in the composed URDF, the longest prefix where several match; a robot of one follower carries every link.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
link
|
str
|
The link, as the composed URDF names it, e.g. |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
The arm's index; |
nearest
nearest(q: Sequence[float]) -> NearestPair | None
Returns the nearest two pieces that are checked against each other, with the motors at q.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Sequence[float]
|
Each slot's motor position, in radians, in slot order, as an |
required |
Returns:
| Type | Description |
|---|---|
NearestPair | None
|
The pair and the gap between them; |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
|
nearest_to
nearest_to(
q: Sequence[float], keep_out: KeepOutBox
) -> NearestLink | None
Returns the robot's piece nearest keep_out, with the motors at q, checking every piece.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Sequence[float]
|
Each slot's motor position, in slot order, as for |
required |
keep_out
|
KeepOutBox
|
The box to measure to. |
required |
Returns:
| Type | Description |
|---|---|
NearestLink | None
|
The piece and the gap; |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
|
within
within(
q: Sequence[float], within_m: float
) -> list[NearestPair]
Returns every pair of links checked against each other that stand no more than within_m apart at q.
Each pair is judged on its own, so a pair that stands close however the arms move does not hide another one
coming near, as it would behind nearest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Sequence[float]
|
Each slot's motor position, in slot order, as for |
required |
within_m
|
float
|
How far apart a pair may stand and still be returned, in meters; a negative or NaN one returns none. |
required |
Returns:
| Type | Description |
|---|---|
list[NearestPair]
|
Each pair at the gap between its nearest two pieces, nearest first; empty where none is that near. |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
|
within_of
within_of(
q: Sequence[float],
keep_out: KeepOutBox,
within_m: float,
) -> list[NearestLink]
Returns every link of the robot that stands no more than within_m from keep_out at q.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Sequence[float]
|
Each slot's motor position, in slot order, as for |
required |
keep_out
|
KeepOutBox
|
The box to measure to. |
required |
within_m
|
float
|
How far from the box a link may stand and still be returned, in meters; a negative one returns only links at least that deep inside it, and NaN none. |
required |
Returns:
| Type | Description |
|---|---|
list[NearestLink]
|
Each link at the gap from its nearest piece, nearest first; a link overlapping the box at minus how far it must move along one of the box's axes to leave it, so one sinking deeper reads nearer. Empty where none is that near. |
Raises:
| Type | Description |
|---|---|
TypeError
|
|
InvalidArgumentError
|
|
CameraRole
Bases: StrEnum
What a camera looks at.
An operator's screen shows the scene cameras big and the wrist cameras small.
Attributes:
| Name | Type | Description |
|---|---|---|
SCENE |
The workspace, from off the arms: a head, chest or overhead camera. |
|
WRIST |
One arm's gripper, from a camera riding on that arm. |
SCENE
class-attribute
instance-attribute
SCENE
The workspace, from off the arms: a head, chest or overhead camera.
WRIST
class-attribute
instance-attribute
WRIST
One arm's gripper, from a camera riding on that arm.
Lens
Bases: StrEnum
The lens fitted to a camera, which cannot be read off the camera, so a workcell says which.
Attributes:
| Name | Type | Description |
|---|---|---|
STANDARD |
Rectilinear, 92 degrees diagonal. |
|
PSEUDO_FISHEYE |
151 degrees diagonal. |
|
FISHEYE |
186 degrees diagonal. |
|
fov_h_deg |
float
|
Horizontal field of view, in degrees, from the lens's datasheet. |
fov_v_deg |
float
|
Vertical field of view, in degrees, from the lens's datasheet. |
STANDARD
class-attribute
instance-attribute
STANDARD
Rectilinear, 92 degrees diagonal.
PSEUDO_FISHEYE
class-attribute
instance-attribute
PSEUDO_FISHEYE
151 degrees diagonal.
FISHEYE
class-attribute
instance-attribute
FISHEYE
186 degrees diagonal.
fov_h_deg
property
fov_h_deg: float
Horizontal field of view, in degrees, from the lens's datasheet.
fov_v_deg
property
fov_v_deg: float
Vertical field of view, in degrees, from the lens's datasheet.
CameraConfig
dataclass
CameraConfig(
name: str,
device: str,
mode: Mode,
role: CameraRole = CameraRole.SCENE,
link: str | None = None,
lens: Lens = Lens.STANDARD,
controls: dict[str, int] = {},
)
One camera of a workcell: its name, the device it opens, the mode it streams, and where it is.
Checked where the workcell is built: a name that is empty or used twice, or a device used twice, is refused. An
empty device opens nothing, so any number of sim cameras share it.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Its name, unique in the workcell, e.g. |
device |
str
|
The device node it opens, as given. |
mode |
Mode
|
The |
role |
CameraRole
|
What it looks at. |
link |
str | None
|
The robot link it rides on, one of |
lens |
Lens
|
The lens fitted to it. |
controls |
dict[str, int]
|
The camera's own settings to write when it opens, each by the key |
name
instance-attribute
name: str
Its name, unique in the workcell, e.g. "head" or "wrist_l": what a recording and a viewer call it.
device
instance-attribute
device: str
The device node it opens, as given.
"/dev/video0", or a path that stays put across boots, such as its USB port's under /dev/v4l/by-path/.
mode
instance-attribute
mode: Mode
The anvil.camera.Mode it streams, one of those anvil.camera.modes lists for the device.
role
class-attribute
instance-attribute
role: CameraRole = CameraRole.SCENE
What it looks at.
A workcell saved before cameras had a role reads as CameraRole.SCENE.
link
class-attribute
instance-attribute
link: str | None = None
The robot link it rides on, one of RobotConfig.camera_links(), which the sim renders as this camera.
None for a camera on nothing of the robot's, which the sim has no view of.
lens
class-attribute
instance-attribute
lens: Lens = Lens.STANDARD
The lens fitted to it.
A workcell saved before cameras had a lens reads as Lens.STANDARD.
controls
class-attribute
instance-attribute
controls: dict[str, int] = {}
The camera's own settings to write when it opens, each by the key anvil.camera.controls gives it.
For example {"exposure_time_absolute": 156}. A setting not named keeps what the camera holds.
Preset
dataclass
Preset(
name: str, variant: str, arms: ArmCount, leaders: bool
)
A shipped workcell's name and shape, from WorkcellConfig.preset_shapes, building nothing until asked.
Methods:
| Name | Description |
|---|---|
build |
Returns the workcell, built fresh: |
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The name of its |
variant |
str
|
The arms' variant, e.g. |
arms |
ArmCount
|
How many followers it stands. |
leaders |
bool
|
Whether each follower has a leader. |
name
instance-attribute
name: str
The name of its WorkcellConfig class attribute, e.g. OPENYAM_V1_SINGLE.
variant
instance-attribute
variant: str
The arms' variant, e.g. openyam/v1.
leaders
instance-attribute
leaders: bool
Whether each follower has a leader.
build
build() -> WorkcellConfig
Returns the workcell, built fresh: WorkcellConfig.shipped of this shape.
WorkcellConfig
dataclass
WorkcellConfig(
robot: RobotConfig,
cameras: list[CameraConfig] = [],
keep_out: list[KeepOutBox] = [],
)
A workcell: its robot, the cameras it streams, and the boxes its robot is kept out of.
The shipped workcells are class attributes, WorkcellConfig.OPENARM_V2_BIMANUAL, each built fresh on every access
with no cameras and no keep-out boxes, since which a bench has is the bench's. Edit the arms, append a
CameraConfig per camera and a KeepOutBox per obstacle, and save it; then hand robot to the hw interface
and controllers you compose, and the workcell to anvil.camera.Cameras.
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
A camera with no name, two cameras of one name or of one non-empty device, a
keep-out box with no name, two boxes of one name, or a box side that is not a positive length; or a robot
refused as |
Methods:
| Name | Description |
|---|---|
to_json |
Returns the workcell as JSON, the form |
from_json |
Builds a workcell from the JSON |
load |
Reads the workcell |
save |
Writes the workcell to |
presets |
Returns every shipped workcell by its class attribute's name, each built fresh, e.g. for a |
preset_shapes |
Returns every shipped workcell's name and shape, building none: what to choose among by variant and shape. |
shipped |
Builds a workcell of a shipped variant's arms, standing where the shipped stands bolt them. |
Attributes:
| Name | Type | Description |
|---|---|---|
robot |
RobotConfig
|
The robot the run drives. |
cameras |
list[CameraConfig]
|
The cameras, in the order stated. |
keep_out |
list[KeepOutBox]
|
The boxes the robot is kept out of. |
OPENARM_V1_BIMANUAL |
Two OpenArm v1 arms, one torso, on the lift. |
|
OPENARM_V2_BIMANUAL |
Two OpenArm v2 arms, one torso, on the lift. |
|
OPENYAM_V1_BIMANUAL |
Two OpenYAM v1 arms on the lift's bracket, where its ports place them, 0.61 m apart. |
|
OPENYAM_V1_SINGLE |
One OpenYAM v1 arm, |
|
OPENARM_V1_LEADER_FOLLOWER |
Two OpenArm v1 torsos on no stand: the followers at the origin, and a leader torso 1 m to their left. |
|
OPENARM_V2_LEADER_FOLLOWER |
Two OpenArm v2 torsos on no stand: the followers at the origin, and a leader torso 1 m to their left. |
|
OPENYAM_V1_LEADER_FOLLOWER |
Four OpenYAM v1 arms on no stand: the followers spaced as on the bracket, each leader 0.6 m behind its own. |
|
OPENYAM_V1_SINGLE_LEADER_FOLLOWER |
One OpenYAM v1 follower on no stand and its leader 0.6 m behind it, neither with a side. |
|
OPENYAM_V2_BIMANUAL |
Two OpenYAM v2 arms on the lift's bracket, where its ports place them, 0.61 m apart. |
|
OPENYAM_V2_SINGLE |
One OpenYAM v2 arm, |
|
OPENYAM_V2_LEADER_FOLLOWER |
Four OpenYAM v2 arms on no stand: the followers spaced as on the bracket, each leader 0.6 m behind its own. |
|
OPENYAM_V2_SINGLE_LEADER_FOLLOWER |
One OpenYAM v2 follower on no stand and its leader 0.6 m behind it, neither with a side. |
cameras
class-attribute
instance-attribute
cameras: list[CameraConfig] = []
The cameras, in the order stated.
keep_out
class-attribute
instance-attribute
keep_out: list[KeepOutBox] = []
The boxes the robot is kept out of.
OPENARM_V1_BIMANUAL
class-attribute
instance-attribute
OPENARM_V1_BIMANUAL
Two OpenArm v1 arms, one torso, on the lift.
OPENARM_V2_BIMANUAL
class-attribute
instance-attribute
OPENARM_V2_BIMANUAL
Two OpenArm v2 arms, one torso, on the lift.
OPENYAM_V1_BIMANUAL
class-attribute
instance-attribute
OPENYAM_V1_BIMANUAL
Two OpenYAM v1 arms on the lift's bracket, where its ports place them, 0.61 m apart.
OPENYAM_V1_SINGLE
class-attribute
instance-attribute
OPENYAM_V1_SINGLE
One OpenYAM v1 arm, follower, with no side, on the lift.
OPENARM_V1_LEADER_FOLLOWER
class-attribute
instance-attribute
OPENARM_V1_LEADER_FOLLOWER
Two OpenArm v1 torsos on no stand: the followers at the origin, and a leader torso 1 m to their left.
OPENARM_V2_LEADER_FOLLOWER
class-attribute
instance-attribute
OPENARM_V2_LEADER_FOLLOWER
Two OpenArm v2 torsos on no stand: the followers at the origin, and a leader torso 1 m to their left.
OPENYAM_V1_LEADER_FOLLOWER
class-attribute
instance-attribute
OPENYAM_V1_LEADER_FOLLOWER
Four OpenYAM v1 arms on no stand: the followers spaced as on the bracket, each leader 0.6 m behind its own.
OPENYAM_V1_SINGLE_LEADER_FOLLOWER
class-attribute
instance-attribute
OPENYAM_V1_SINGLE_LEADER_FOLLOWER
One OpenYAM v1 follower on no stand and its leader 0.6 m behind it, neither with a side.
OPENYAM_V2_BIMANUAL
class-attribute
instance-attribute
OPENYAM_V2_BIMANUAL
Two OpenYAM v2 arms on the lift's bracket, where its ports place them, 0.61 m apart.
OPENYAM_V2_SINGLE
class-attribute
instance-attribute
OPENYAM_V2_SINGLE
One OpenYAM v2 arm, follower, with no side, on the lift.
OPENYAM_V2_LEADER_FOLLOWER
class-attribute
instance-attribute
OPENYAM_V2_LEADER_FOLLOWER
Four OpenYAM v2 arms on no stand: the followers spaced as on the bracket, each leader 0.6 m behind its own.
OPENYAM_V2_SINGLE_LEADER_FOLLOWER
class-attribute
instance-attribute
OPENYAM_V2_SINGLE_LEADER_FOLLOWER
One OpenYAM v2 follower on no stand and its leader 0.6 m behind it, neither with a side.
to_json
to_json() -> str
Returns the workcell as JSON, the form from_json reads back.
from_json
classmethod
from_json(wire: str) -> Self
Builds a workcell from the JSON to_json wrote, checked as one built from its fields is.
JSON an older release wrote reads as it was written: a field added since takes its default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wire
|
str
|
The JSON text. |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
|
load
classmethod
load(path: Path) -> Self
Reads the workcell save wrote to path, checked as one built from its fields is.
A file an older release saved reads as it was saved: a field added since takes its default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
The file to read. |
required |
Raises:
| Type | Description |
|---|---|
NotFoundError
|
There is no file at |
InvalidArgumentError
|
The file is not a workcell, a newer release saved it, or the workcell is refused; the message names the path. |
OperationError
|
The file could not be read for another reason, such as being a directory. |
save
save(path: Path) -> None
Writes the workcell to path as indented JSON a person can edit, for load to read back.
The file is to_json's JSON with the format's version beside it. The directory is made if it is missing, and
the file is replaced whole, so a crash mid-save leaves the old file or the new one, never a torn one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
The file to write. |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
The workcell is refused; nothing is written. |
OperationError
|
The directory could not be made or the file could not be written; a subclass
where the failure names the reason, as for |
presets
staticmethod
presets() -> dict[str, WorkcellConfig]
Returns every shipped workcell by its class attribute's name, each built fresh, e.g. for a --workcell flag.
Builds all of them; preset_shapes lists them without building any.
preset_shapes
staticmethod
preset_shapes() -> list[Preset]
Returns every shipped workcell's name and shape, building none: what to choose among by variant and shape.
shipped
classmethod
shipped(
variant: str, arms: ArmCount, leaders: bool
) -> Self
Builds a workcell of a shipped variant's arms, standing where the shipped stands bolt them.
Every preset is one of these shapes, and a shape no preset names is built the same way, e.g. a single
yam/v1. A pair's arms are left and right, their leaders leader_left and leader_right; a single arm is
follower and its leader leader, neither with a side. Each leader carries the leader handle in place of a
gripper. Without leaders it stands on Stand.LIFT, a yam pair on Stand.LIFT_BRACKET; with leaders on no
stand, a yam pair spaced as the bracket spaces it. The workcell has no cameras and no keep-out boxes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variant
|
str
|
The variant, |
required |
arms
|
ArmCount
|
One follower or a pair. |
required |
leaders
|
bool
|
Whether each follower gets a leader. |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
Anvil ships no description or URDF for |
shipped_urdf
shipped_urdf(variant: str) -> str
Returns the URDF text a shipped variant carries: the unit a robot's mounts stand copies of.
For a yam that is one arm on its base plate; for an OpenArm, the torso carrying both arms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variant
|
str
|
The variant, |
required |
Raises:
| Type | Description |
|---|---|
InvalidArgumentError
|
Anvil ships no URDF for |
realhand_gripper
realhand_gripper(
family: str, version: int, side: Side
) -> ExternalGripper
Returns the external gripper an arm states for the RealHand L6 bolted to it, as the hand's description gives it.
It holds the CAN ID the side hand answers on, which the arm's motors must not use, and the hand's mass in the
arm's hand frame, which gravity compensation carries. Set it as that arm's ArmDescription.gripper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
family
|
str
|
The arm's family, |
required |
version
|
int
|
The arm's version, |
required |
side
|
Side
|
Which hand: the two answer on different CAN IDs, and their masses mirror each other. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
|
InvalidArgumentError
|
The hand's description has no mass on that arm. |
shipped_finger_sets
shipped_finger_sets(gripper: str) -> list[FingerSet]
Returns every finger set Anvil ships for gripper, in name order: what its Gripper.fingers may be set to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gripper
|
str
|
The gripper, |
required |
Returns:
| Type | Description |
|---|---|
list[FingerSet]
|
The finger sets; empty for a gripper whose fingers are its own, and for a name Anvil ships no gripper by. |