Moving a Robot on a Circular Path

A circular motion is a movement where the robot travels to a target position along a circular path in Cartesian space. Unlike point-to-point (PTP) motion, which follows the shortest path in joint space, a circular motion ensures a predictable trajectory in Cartesian coordinates. However, depending on the robot’s kinematics, this type of movement may not always be the fastest.

This chapter specifically explains circular movements. For detailed information on how to use these methods synchronously or asynchronously, see the asynchronous instructions section and the instructions chapter.

Performing a Circular Movement

A circular movement is started with move_circular() from the MoveCircular trait. It requires a target pose, a via pose, and the maximum translational speed of the tool center point along the arc, written as MetersPerSecond(0.25). The via pose is an intermediate pose that defines the circular arc between the start pose and the target pose. Both poses can be a JointPose, a CartesianPose or a CartesianTarget. Of a CartesianTarget via only the coordinate system is used.

The via pose is wrapped in the Via newtype, so that target and via cannot be confused at the call site. The speed argument takes the same forms as for linear motions and, like there, is required; see Moving on a Linear Path for the forms and the reasoning.

Perform a Circular Movement Using JointPose Parameters

To perform a circular movement to a target defined in joint space, pass JointPose values. The robot control resolves them to Cartesian poses:

let target = poses::home()
    + JointPose::new(
        Radians(FRAC_PI_2),
        Radians(0.0),
        Radians(0.0),
        Radians(0.0),
        Radians(0.0),
        Radians(0.0),
    );
// Via: home + 45 degrees on joint 1.
let via = poses::home()
    + JointPose::new(
        Radians(FRAC_PI_4),
        Radians(0.0),
        Radians(0.0),
        Radians(0.0),
        Radians(0.0),
        Radians(0.0),
    );

robot
    .move_circular(target, Via(via), common::TRAVEL_SPEED)
    .start()?
    .join()?;
info!("Circular arc (JointPose) complete.");

Target and via do not have to be of the same type; give each as a JointPose or a CartesianPose, depending on the circumstances.

Perform a Circular Movement Using CartesianPose Parameters

To perform a circular movement in Cartesian space, pass CartesianPose values. The x() and y() helpers build poses that are zero except for one component, which makes it easy to derive the target and via from a known pose:

let cartesian_target = poses::home_c() + y(Meters(0.4));
let cartesian_via = poses::home_c() + x(Meters(0.2)) + y(Meters(0.2));

robot
    .move_circular(cartesian_target, Via(cartesian_via), common::TRAVEL_SPEED)
    .start()?
    .join()?;
info!("Circular arc (CartesianPose) complete.");

Since a Cartesian pose is ambiguous for a six-axis robot, the resulting joint configuration at the target can differ depending on the starting pose of the robot.

Note

A CartesianPose is interpreted in the robot coordinate system; a CartesianTarget names another one, see Coordinate Systems.

A CartesianPose itself can be ambiguous with regard to the exact joint configuration of the robot. It is at the discretion of the underlying robot control to choose a convenient joint configuration to reach the given pose. This means that the configuration reached depends on the starting position.

Perform a Relative Circular Movement

For moving on a circular path relative to the current end effector pose, use move_circular_relative(), which accepts the same arguments as move_circular(). Both the target and the via pose are then offsets from the current pose. In this example, the robot moves in the positive x- and y-direction from its current pose:

fn relative_circular(robot: &(impl MoveCircular + MovePtp)) -> Result<()> {
    info!("--- Relative circular ---");

    robot.move_ptp(poses::home()).start()?.join()?;

    robot
        .move_circular_relative(
            y(Meters(0.4)),
            Via(x(Meters(0.2)) + y(Meters(0.2))),
            common::TRAVEL_SPEED,
        )
        .start()?
        .join()?;
    info!("Relative circular arc complete.");
    Ok(())
}

Perform a Circular Movement with Blending

Circular movements can use blending by chaining .blending() with a Factor or Percent. The higher the blending value, the more and earlier the blended path deviates from the original path that would reach the target pose. In most cases this allows the robot to maintain a higher path velocity and complete the overall path faster.

Blending only works if the instruction that follows is known to the robot control in advance, so blended motions form one block that is sent as a whole by start():

fn circular_with_blending(robot: &(impl MoveCircular + MovePtp)) -> Result<()> {
    info!("--- Circular with blending ---");

    robot.move_ptp(poses::home()).start()?.join()?;

    let cartesian_target_1 = poses::home_c() + y(Meters(0.2));
    let cartesian_target_2 = poses::home_c() + x(Meters(0.2)) + y(Meters(0.2));
    let cartesian_via = poses::home_c() + x(Meters(0.1)) + y(Meters(0.1));

    robot
        .move_circular(cartesian_target_1, Via(cartesian_via), common::TRAVEL_SPEED)
        .blending(Percent(50.0))
        .move_circular(cartesian_target_2, Via(cartesian_via), common::TRAVEL_SPEED)
        .blending(Factor(0.5))
        .move_circular(
            poses::home_c(),
            Via(cartesian_target_1),
            common::TRAVEL_SPEED,
        )
        .start()?
        .join()?;
    info!("Blending sequence complete.");
    Ok(())
}

Note how the block ends on a step without blending; a block that ends on a blended step does not compile. A blended circular step needs a linear or circular successor: the robot control cannot blend a circular motion into a PTP motion, so a PTP step after it does not compile either.

Note

The exact behavior and interpretation of the blending parameter as well as implicit limitations are highly dependent on the specific robot used. For more details on blending, please refer to the instructions chapter.

Blending parameters can also be amended after an instruction was sent with amend_blending(); see Amending Blending Parameters.

Blending Radius and Motion Profile

Like a linear step, a circular step blends by a radius in Meters and takes a .parameters() motion profile; see Blending Radius and Motion Profile.

Full Example

Trait Definition

The trait carries the entry points as default methods, which return a MotionBlock builder; its required method is what a robot type implements.