Limits

Limits are used to configure motion and monitoring constraints of the robot such as axis velocities, axis accelerations, TCP velocity, and many more. The robot control provides default limit sets like MACHINE and SAFETY. Users can define additional limit sets on the robot control to constrain the robot behavior for specific applications.

Note

It is expected that limit sets are preconfigured on the robot control. Creating or modifying limit sets is currently not supported by this library.

Reading the Currently Active Limits

The currently active limits are read with active_limits() from the GetLimits trait. It returns a Limits value with all currently active limit values, reflecting the combined effect of all active limit sets:

let active = robot.active_limits()?;
info!("Active limits: {active:?}");

Every field of Limits is an Option: None means the limit is not configured. The axis limits are vectors with one value per axis in the axis’s SI unit, which depends on the axis type: for example rad/s for rotational and m/s for prismatic axes in axes_velocity, N·m in the torque limits (see the field docs of Limits). The scalar limits carry their unit, for example tcp_velocity_translational as MetersPerSecond.

Reading the Limits of a Limit Set

The limits of a specific limit set are read with limits(). It returns a Limits value with only the limits that set configures; the others are None:

let limits = robot.limits(limit_set)?;
info!("Axes acceleration limits: {:?}", limits.axes_acceleration);

Selecting Limit Sets

Listing the limit sets is part of the GetLimitSets trait, which a read-only view implements as well. Activating and deactivating them is part of the SelectLimitSets trait, which extends it.

Listing Limit Sets

default_limit_sets() returns the names of the default limit sets. They are always active and cannot be deactivated. optional_limit_sets() returns the user-configurable limit sets; the default sets are not included. active_limit_sets() returns all currently active sets, the default ones as well as any activated optional ones:

info!("Default limit sets:  {:?}", robot.default_limit_sets()?);
info!("Optional limit sets: {:?}", robot.optional_limit_sets()?);
info!("Active limit sets:   {:?}", robot.active_limit_sets()?);

Activating and Deactivating a Limit Set

An optional limit set is activated with activate_limit_set() and deactivated with deactivate_limit_set(). The set must exist on the robot control, default limit sets cannot be switched, and no set can be switched while the robot is in gravity compensation or in its collision reaction. These three failures are reported as LimitSetFailed, with LimitSetError::Unknown, LimitSetError::DefaultSet or LimitSetError::RobotMoving. The robot control switches a set only while the robot stands still, so both calls first wait until the robot has come to rest, bounded by the robot’s command timeout, and return RobotArmError::DidNotStop if it does not; join pending motions first. A switch the robot control refuses returns the robot control’s error as RobotArmError::RobotInErrorState, and RobotArmError::NotConfirmed means that the robot control did not confirm the switch within the command timeout:

robot.activate_limit_set(limit_set)?;
info!(
    "Active after activation:   {:?}",
    robot.active_limit_sets()?
);

robot.deactivate_limit_set(limit_set)?;

Limit Sets for a Section

A limit set that should constrain one section of the program is expressed with with_limit_set(). It activates the set, runs the closure, and deactivates the set afterwards, also when the closure returns an error. The closure’s result is returned; if the set could not be deactivated after a successful closure, that error is returned instead. Deactivating needs the robot to be idle, so join every motion the closure starts before it returns: if the closure fails while one of its motions is still executing, the deactivation is refused, the refusal is only logged, the closure’s error is returned, and the set stays active:

fn scoped_limit_set_example(
    robot: &(impl SelectLimitSets + MovePtp),
    limit_set: &str,
) -> Result<()> {
    info!("--- Scoped limit set ---");

    robot.with_limit_set(limit_set, |robot| {
        robot
            .move_ptp(poses::home())
            .move_ptp(poses::vertical())
            .start()?
            .join()?;
        info!("Moved under {limit_set}.");
        Ok(())
    })?;
    info!("Active after the section: {:?}", robot.active_limit_sets()?);
    Ok(())
}

The section restores the state it found rather than switching the set off unconditionally: if the set was already active when the section started, for example because an enclosing section activated it, the section does not switch it at all and it stays active afterwards.

Full Example

The example picks the first optional limit set the control offers and skips the limit set sections if there is none.

Trait Definitions