Quickstart
Bring an arm up in the sim, move it home, and read back where its gripper is. Nothing here needs a robot: the sim stands in for the drives, so the same script runs against a real arm by swapping one line.
Install
The SDK is the anvil package, which PyPI holds as anvil-robotics; its sim extra brings the sim:
pip install 'anvil-robotics[sim]'
The script below then runs as it is.
The script
"""Brings an arm up in the sim, homes it, and says where its gripper ended up."""
import anvil.control
import anvil.hw
import anvil.sim
import anvil.workcell
# The single-arm yam, as Anvil ships it.
workcell = anvil.workcell.WorkcellConfig.OPENYAM_V1_SINGLE
robot = workcell.robot
# The sim stands in for the bench: a world with the arm bolted onto a lift, its drives enabled as real ones would be.
with anvil.sim.World(robot=robot, scene="lift") as world:
hw = anvil.hw.SimHw(world=world)
hw.enable()
# The control loop, holding the one controller this script needs, ticking at 500 Hz on a thread of its own.
trajectory_controller = anvil.control.JointTrajectoryController(robot=robot)
with anvil.control.Runtime(hw=hw, controllers=[trajectory_controller], rate_hz=500) as runtime:
runtime.start()
handle = runtime.controller(kind=anvil.control.JointTrajectoryController)
runtime.activate(controller=handle)
# Home the arm from wherever it stands, and wait for the move to finish.
home = robot.home_trajectory(from_q=runtime.latest().q)
handle.play(trajectory=home, timeout_s=30.0)
arm = anvil.control.control_arms(robot=robot, kind=anvil.control.JointTrajectoryController)[0]
tip = arm.tip_pose(q=runtime.latest().q)
print(f"homed: the gripper is at {[round(x, 3) for x in tip.position]} m")
# The same arm by name: a joint by the name its description gives it, and how far the jaws are open.
follower = runtime.latest().arm(name="follower")
joint_3_rad = follower.joint(name="joint_3").q_rad
print(f"joint_3 is at {joint_3_rad:.2f} rad, the jaws open {follower.gripper.opening_m * 1000:.0f} mm")
Run it with python quickstart.py. It prints where the gripper ended up, in meters, in the world frame, then one
joint's angle and how far the jaws are open:
homed: the gripper is at [0.28, 0.0, 0.299] m
joint_3 is at 0.57 rad, the jaws open 98 mm
What it did
- Picked a workcell.
anvil.workcell.WorkcellConfig.OPENYAM_V1_SINGLEis the single-arm yam as Anvil ships it: the arm, its gripper, its tuning and where it stands. - Stood it in the sim.
anvil.sim.Worldstarts a sim and stands the arm in it, on a lift, its drives off;anvil.hw.SimHwtakes the arm over and drives it the way the real drives are driven.enable()switches the drives on. - Started the control loop.
anvil.control.Runtimeruns the loop on a thread of its own at 500 Hz, ticking the active controller each time. Here it holds one, theanvil.control.JointTrajectoryController, which plays timed joint trajectories. - Moved the arm.
anvil.workcell.RobotConfig.home_trajectoryplans the homing run the arm's description states, from where the arm stands, andplayruns it, returning once the arm is home. - Read where it is.
tip_poseturns the measured joint positions into the gripper's pose. - Read it by name.
Snapshot.armgives the arm as the loop last measured it, each joint by the name its description gives it and the gripper as a jaw opening. Actuators, joints and arms says how that relates to the lists a snapshot holds.
Leaving the with blocks stops the loop and closes the sim.
On a real arm
The same script drives real drives with anvil.hw.DamiaoHw in place of the
sim, once the bench passes its readiness check. Run on real arms takes it there, and
says how to take the drives down without dropping an arm: leaving the with blocks disables them.
Next
anvil.control.Runtime: the loop, and switching controllers.anvil.control: the other controllers, which follow streamed joint targets or end-effector poses.