Time Override

The global time override of a robot arm is a scaling factor used to adjust the overall speed of the robot’s movements. It ranges from a factor of 0.0 to 1.0 (or from 0 % to 100 %). A factor of 1.0 means the robot operates at its maximum speed, whereas lower values slow down all movements proportionally. The time override should be used to scale the velocity of a whole application, for example to minimize hazards during testing.

Warning

A time override of 0.0 halts all motion. A motion under 0.0 does not progress, and its join() waits until the time override rises again. Do not use 0.0 to pause an application. Use pause_motion() from the PauseContinue trait instead.

Note

If possible, refrain from using the time override for scaling the velocity during operation. Instead, use the speed() modifier of the motion instructions. The effective speed of a motion is the time override times its speed.

Reading the Current Time Override

The current time override is read with time_override() from the GetTimeOverride trait. It returns a Factor; Percent::from() converts it. The robot control reports factors from 0.0 to 1.0; time_override() returns an error for anything else:

let current = robot.time_override()?;
info!(
    "Current time override: {current} ({})",
    Percent::from(current)
);

Setting the Time Override

The time override is set with set_time_override(). The desired value can be given as a Factor or as a Percent. The method returns once the robot control reports the desired value, at most after the robot’s command timeout. If the time override could not be set for any reason, set_time_override() returns an error.

send_time_override() takes the same value but returns a CommandHandle as soon as the value is sent, so the program can do other work while the robot control applies it. confirm() on the handle waits until the value is applied, at most the command timeout. confirm_timeout() takes its own timeout.

The time override is one global value that other clients of the robot control and other threads can write as well. If another writer changes the value while the confirmation is pending, set_time_override() or confirm() returns RobotArmError::NotConfirmed although the robot control accepted the value. In that case read the current value with time_override() to learn which value is in effect.

A typical use is to slow the whole application down in a test mode:

fn decrease_speed_if_in_test_mode(robot: &impl SetTimeOverride) -> Result<()> {
    let in_test_mode = env::var("TEST_MODE")
        .unwrap_or_default()
        .eq_ignore_ascii_case("true");

    if in_test_mode {
        robot.set_time_override(Factor(0.25))?;
    } else {
        robot.set_time_override(Percent(100.0))?;
    }
    Ok(())
}

Time Override for a Section

A time override that only applies to a section of the program is expressed with with_time_override(). It sets the value and waits for the confirmation, runs the closure, and restores the previous value afterwards, also when the closure returns an error or setting the value fails. The closure’s result is returned; if the previous value could not be restored after a successful closure, that error is returned instead, so the robot never silently keeps the section’s speed. The closure may return the application’s own error type, as long as RobotArmError converts into it, so non-robot work in the section can propagate its errors with ?:

robot.with_time_override(Factor(0.25), |robot| -> Result<()> {
    robot
        .move_ptp(poses::home())
        .move_ptp(poses::vertical())
        .start()?
        .join()?;
    info!("Moved at 25 %.");
    Ok(())
})?;
info!("Restored to {}.", robot.time_override()?);

Setting the Time Override with a Transition Time

The time override can also be changed gradually over a transition time with set_time_override_with_transition() from the TimeOverrideTransition trait. It takes the desired value as Factor or Percent and the transition as a Duration, which must be at least 250 ms.

If this method is called during a robot standstill, the time override is set immediately. If it is called during a robot motion, the time override transitions smoothly and reaches its value after the transition time. If the robot motion stops before the transition has ended, the transition continues until the target value is reached. A short transition time can lead to high accelerations and torques.

The transition can be observed while a motion is running:

fn run_transition_example(robot: &(impl TimeOverrideTransition + MovePtp)) -> Result<()> {
    info!("--- Time Override with Transition ---");

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

    // Slow down to 10%; the original time override is restored afterwards.
    robot.with_time_override(Factor(0.1), |robot| {
        // Start a slow motion.
        let motion = robot.move_ptp(poses::vertical()).start()?;

        // Wait for robot to start moving.
        sleep(Duration::from_millis(500));

        // Smoothly transition to 25% over 5 seconds. Returns once the
        // transition is sent.
        let transition =
            robot.send_time_override_with_transition(Factor(0.25), Duration::from_secs(5))?;

        // Monitor the changing time override while the motion completes.
        while !motion.is_done() {
            info!("Current time override: {:.2}", robot.time_override()?);
            sleep(Duration::from_secs(1));
        }

        // Wait until the time override reaches the target, at most the
        // transition time plus the command timeout.
        transition.confirm()?;
        motion.join()
    })
}

The log then shows the value rising (timestamps and log levels left out):

Current time override: 0.10
Current time override: 0.11
Current time override: 0.14
Current time override: 0.20
Current time override: 0.23
Current time override: 0.25

set_time_override_with_transition() returns once the time override reaches the desired value, at most after the transition time plus the command timeout. The example uses send_time_override_with_transition() instead, which returns a CommandHandle once the transition is sent; confirm() on the handle does the same wait. Another call while a transition is active overrides the previous one, so the previous one is not confirmed and returns RobotArmError::NotConfirmed. As the confirmation only observes the global value, a concurrent write by another client or thread can confirm the call or make it return RobotArmError::NotConfirmed; read the current value with time_override() to learn which value is in effect.

Full Example

Trait Definitions