Skip to content

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

  1. Picked a workcell. anvil.workcell.WorkcellConfig.OPENYAM_V1_SINGLE is the single-arm yam as Anvil ships it: the arm, its gripper, its tuning and where it stands.
  2. Stood it in the sim. anvil.sim.World starts a sim and stands the arm in it, on a lift, its drives off; anvil.hw.SimHw takes the arm over and drives it the way the real drives are driven. enable() switches the drives on.
  3. Started the control loop. anvil.control.Runtime runs the loop on a thread of its own at 500 Hz, ticking the active controller each time. Here it holds one, the anvil.control.JointTrajectoryController, which plays timed joint trajectories.
  4. Moved the arm. anvil.workcell.RobotConfig.home_trajectory plans the homing run the arm's description states, from where the arm stands, and play runs it, returning once the arm is home.
  5. Read where it is. tip_pose turns the measured joint positions into the gripper's pose.
  6. Read it by name. Snapshot.arm gives 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