Previous
Camera Calibration
You have a robot arm and need to move it to a specific position and orientation in 3D space. The motion service computes a collision-free path from the arm’s current pose to the target, taking into account the frame system, kinematics, and any defined obstacles.
from viam.robot.client import RobotClient
from viam.services.motion import MotionClient
from viam.proto.common import PoseInFrame, Pose
machine = await RobotClient.at_address(
"<MACHINE-ADDRESS>",
RobotClient.Options.with_api_key(
api_key="<API-KEY>",
api_key_id="<API-KEY-ID>"
)
)
motion_service = MotionClient.from_robot(machine, "builtin")
import (
"go.viam.com/rdk/services/motion"
"go.viam.com/rdk/referenceframe"
"go.viam.com/rdk/spatialmath"
"github.com/golang/geo/r3"
)
motionService, err := motion.FromRobot(machine, "builtin")
if err != nil {
logger.Fatal(err)
}
A pose specifies position (x, y, z in mm) and orientation. The reference_frame
determines which coordinate system the pose is expressed in.
# Move to a position 300mm right, 200mm forward, 400mm up
# Orientation: end effector pointing straight down
destination = PoseInFrame(
reference_frame="world",
pose=Pose(x=300, y=200, z=400, o_x=0, o_y=0, o_z=-1, theta=0)
)
// Move to a position 300mm right, 200mm forward, 400mm up
// Orientation: end effector pointing straight down
destination := referenceframe.NewPoseInFrame("world",
spatialmath.NewPose(
r3.Vector{X: 300, Y: 200, Z: 400},
&spatialmath.OrientationVectorDegrees{OX: 0, OY: 0, OZ: -1, Theta: 0},
))
await motion_service.move(
component_name="my-arm",
destination=destination,
)
print("Arm moved to target pose")
_, err = motionService.Move(ctx, motion.MoveReq{
ComponentName: "my-arm",
Destination: destination,
})
if err != nil {
logger.Fatal(err)
}
fmt.Println("Arm moved to target pose")
Pass a WorldState with obstacles to plan collision-free paths.
from viam.proto.common import (
Vector3, RectangularPrism, Geometry,
GeometriesInFrame, WorldState
)
# Define a table obstacle
table = Geometry(
center=Pose(x=0, y=0, z=-20),
box=RectangularPrism(dims_mm=Vector3(x=800, y=600, z=40)),
label="table"
)
obstacles = GeometriesInFrame(
reference_frame="world",
geometries=[table]
)
world_state = WorldState(obstacles=[obstacles])
await motion_service.move(
component_name="my-arm",
destination=destination,
world_state=world_state
)
tableOrigin := spatialmath.NewPose(
r3.Vector{X: 0, Y: 0, Z: -20},
&spatialmath.OrientationVectorDegrees{OX: 0, OY: 0, OZ: 1, Theta: 0},
)
table, _ := spatialmath.NewBox(tableOrigin,
r3.Vector{X: 800, Y: 600, Z: 40}, "table")
obstaclesInFrame := referenceframe.NewGeometriesInFrame(
referenceframe.World, []spatialmath.Geometry{table})
worldState, _ := referenceframe.NewWorldState(
[]*referenceframe.GeometriesInFrame{obstaclesInFrame}, nil)
_, err = motionService.Move(ctx, motion.MoveReq{
ComponentName: "my-arm",
Destination: destination,
WorldState: worldState,
})
if err != nil {
logger.Fatal(err)
}
Read the arm’s current pose after moving to confirm it reached the target:
from viam.components.arm import Arm
arm = Arm.from_robot(machine, "my-arm")
current_pose = await arm.get_end_position()
print(f"Current position: x={current_pose.x:.1f}, "
f"y={current_pose.y:.1f}, z={current_pose.z:.1f}")
import "go.viam.com/rdk/components/arm"
myArm, err := arm.FromRobot(machine, "my-arm")
if err != nil {
logger.Fatal(err)
}
currentPose, err := myArm.EndPosition(ctx, nil)
if err != nil {
logger.Fatal(err)
}
pt := currentPose.Point()
fmt.Printf("Current position: x=%.1f, y=%.1f, z=%.1f\n",
pt.X, pt.Y, pt.Z)
You can move the arm and check poses without writing code:
# Check the arm's current pose
viam machines motion get-pose --part "my-machine-main" --component "my-arm"
# Move the arm to a new position (only specified values change)
viam machines motion set-pose --part "my-machine-main" --component "my-arm" \
--x 300 --y 200 --z 400
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!