Tools
Robotic tools or end effectors are devices mounted to the flange of a robot arm. They enable various tasks such as grasping, welding, cutting, and many more.
An activated tool changes the tool center point (TCP) of the robot, such that the configured center of the tool moves to a desired Cartesian pose instead of the robot flange. Furthermore, it influences the dynamic parameters of the robot.
Some robotic systems also allow triggering special tool commands and querying the state of the tool.
Note
It is expected that one or multiple tools are preconfigured on the robot control to select from.
Tool configuration, tool commands, and tool states are not supported at the moment.
Selecting Tools
The selectable tools are queried with selectable_tools(), which returns the tool names. The name of the
currently selected tool is read with selected_tool(); it is None when no tool is selected:
let selectable_tools = robot.selectable_tools()?;
info!("Selectable tools: {selectable_tools:?}");
let selected = robot.selected_tool()?;
info!("Selected tool: {selected:?}");
A tool is selected by name with select_tool(). The method returns as soon as the selected tool is activated
by the robot control. If the tool does not exist on the robot control, a ToolHandlingFailed is returned. The
example names its tools once as constants:
/// Example tool name: Schunk EGP Co-act gripper.
const EXAMPLE_TOOL: &str = "Schunk_EGP_Co-act";
/// Example tool name: Schmalz `ECBPi` vacuum gripper.
const SCHMALZ_TOOL: &str = "Schmalz_ECBPi";
robot.select_tool(EXAMPLE_TOOL)?;
The active tool is deselected with deselect_tool(). Without a selected tool, it returns a ToolHandlingFailed as
well:
robot.deselect_tool()?;
The robot control changes the tool only while the robot stands still. Selecting and deselecting therefore first wait
until the robot has come to rest, for example after a stop or a pause, and then until the robot control confirms the
change. Each wait is bounded by the robot’s command timeout. The robot has come to
rest once every motion it has started is complete. Motions that are still queued, such as a blended motion waiting for
the next one, start only after the change and use the new tool. A robot that does not come to rest in time returns
RobotArmError::DidNotStop. A change the robot control refuses returns the robot control’s
error as RobotArmError::RobotInErrorState, and RobotArmError::NotConfirmed means that the robot control did not
apply the change without reporting an error.
After a change, Cartesian targets, the TCP pose and TCP jogging refer to the new TCP. The robot control attaches the payload to the active tool, so set the payload again after selecting another tool.
Full Example
Tools example
//! Tool selection examples.
//!
//! Demonstrates how to query available tools, select a tool, and deselect it.
mod common;
use tracing::info;
use voraus_robot_arm::prelude::*;
/// Example tool name: Schunk EGP Co-act gripper.
const EXAMPLE_TOOL: &str = "Schunk_EGP_Co-act";
/// Example tool name: Schmalz `ECBPi` vacuum gripper.
const SCHMALZ_TOOL: &str = "Schmalz_ECBPi";
/// Example application to select tools.
fn run_tool_selection_example(robot: &impl SelectTool) -> Result<()> {
info!("--- Tool Selection ---");
let selectable_tools = robot.selectable_tools()?;
info!("Selectable tools: {selectable_tools:?}");
let selected = robot.selected_tool()?;
info!("Selected tool: {selected:?}");
robot.select_tool(EXAMPLE_TOOL)?;
info!("Selected tool: {:?}", robot.selected_tool()?);
robot.select_tool(SCHMALZ_TOOL)?;
info!("Selected tool: {:?}", robot.selected_tool()?);
robot.deselect_tool()?;
info!("Selected tool: {:?}", robot.selected_tool()?);
Ok(())
}
fn main() -> voraus_robot_arm::error::Result<()> {
common::init_logging();
let robot = common::create_connected_robot()?;
run_tool_selection_example(&robot)?;
info!("Done.");
Ok(())
}
Trait Definitions
GetTool
pub trait GetTool {
/// Get the list of selectable tool names.
///
/// The list holds the tools that are configured on the robot control.
/// If no tool is configured, the list is empty. The call only reads and
/// does not wait for the robot to stand still.
///
/// # Example
///
/// ```rust
/// # use voraus_robot_arm::prelude::*;
/// # fn demo(robot: &impl GetTool) -> Result<()> {
/// for tool in robot.selectable_tools()? {
/// println!("selectable tool: {tool}");
/// }
/// # Ok(())
/// # }
/// ```
///
/// # Returns
///
/// A list of available tool names.
///
/// # Errors
///
/// Returns [`RobotArmError::Backend`](crate::error::RobotArmError::Backend) if the robot
/// is not connected or the call to the robot control fails.
fn selectable_tools(&self) -> Result<Vec<String>>;
/// Get the currently selected tool name, or `None` if no tool is selected.
///
/// The call only reads and does not wait for the robot to stand still.
///
/// # Example
///
/// ```rust
/// # use voraus_robot_arm::prelude::*;
/// # fn demo(robot: &impl GetTool) -> Result<()> {
/// match robot.selected_tool()? {
/// Some(tool) => println!("active tool: {tool}"),
/// None => println!("no tool, the TCP is the flange"),
/// }
/// # Ok(())
/// # }
/// ```
///
/// # Returns
///
/// The name of the currently selected tool, or `None`.
///
/// # Errors
///
/// Returns [`RobotArmError::Backend`](crate::error::RobotArmError::Backend) if the robot
/// is not connected or the read from the robot control fails.
fn selected_tool(&self) -> Result<Option<String>>;
}
SelectTool
pub trait SelectTool: GetTool {
/// Select a tool by name.
///
/// The call checks the name against
/// [`selectable_tools`](GetTool::selectable_tools) before it
/// writes anything. Then it waits until the robot stands still, bounded
/// by the command timeout, because the control refuses the change while
/// the robot moves. Queued motions start only after the control confirms
/// the change.
///
/// After the call, Cartesian targets, the TCP pose and TCP jogging refer
/// to the center of the selected tool. The control attaches the payload
/// to the active tool, so set the payload again with
/// [`SetPayload::set_payload`](crate::traits::SetPayload::set_payload).
///
/// # Example
///
/// ```rust
/// # use voraus_robot_arm::prelude::*;
/// # fn demo(robot: &impl SelectTool) -> Result<()> {
/// robot.select_tool("gripper")?;
/// assert_eq!(robot.selected_tool()?.as_deref(), Some("gripper"));
/// # Ok(())
/// # }
/// ```
///
/// # Arguments
///
/// * `tool_name` - One of the names from
/// [`selectable_tools`](GetTool::selectable_tools).
///
/// # Returns
///
/// `Ok(())` on success.
///
/// # Errors
///
/// Returns
/// [`RobotArmError::ToolHandlingFailed`](crate::error::RobotArmError::ToolHandlingFailed)
/// ([`ToolError::Unknown`](crate::error::ToolError::Unknown)) if the tool is
/// not found,
/// [`RobotArmError::DidNotStop`](crate::error::RobotArmError::DidNotStop)
/// if the robot does not come to rest within the command
/// timeout,
/// [`RobotArmError::RobotInErrorState`](crate::error::RobotArmError::RobotInErrorState)
/// with the control's error if the control refuses the write,
/// [`RobotArmError::NotConfirmed`](crate::error::RobotArmError::NotConfirmed)
/// if the control does not confirm the tool as active within the command
/// timeout, or [`RobotArmError::Backend`](crate::error::RobotArmError::Backend)
/// if the call to the robot control fails.
fn select_tool(&self, tool_name: &str) -> Result<()> {
self.send_select_tool(tool_name)?.confirm()
}
/// Send the tool selection.
///
/// The call returns before the control confirms the tool as active. Call
/// [`confirm`](CommandHandle::confirm) on the returned handle to wait
/// for it.
///
/// The checks and the wait for standstill of
/// [`select_tool`](Self::select_tool) happen before the
/// call returns. Queued motions start only after the handle is
/// confirmed or dropped.
///
/// # Arguments
///
/// * `tool_name` - One of the names from
/// [`selectable_tools`](GetTool::selectable_tools).
///
/// # Returns
///
/// The handle that confirms the tool as active. [`CommandHandle::confirm`]
/// returns
/// [`RobotArmError::RobotInErrorState`](crate::error::RobotArmError::RobotInErrorState)
/// with the control's error if the control refuses the write, or
/// [`RobotArmError::NotConfirmed`](crate::error::RobotArmError::NotConfirmed)
/// if the control does not confirm the tool as active within the command
/// timeout.
///
/// # Errors
///
/// Returns
/// [`RobotArmError::ToolHandlingFailed`](crate::error::RobotArmError::ToolHandlingFailed)
/// ([`ToolError::Unknown`](crate::error::ToolError::Unknown)) if the tool is
/// not found,
/// [`RobotArmError::DidNotStop`](crate::error::RobotArmError::DidNotStop)
/// if the robot does not come to rest within the command timeout, or
/// [`RobotArmError::Backend`](crate::error::RobotArmError::Backend) if
/// the call to the robot control fails.
fn send_select_tool(&self, tool_name: &str) -> Result<CommandHandle<'_>>;
/// Deselect the currently active tool.
///
/// If no tool is selected, the call fails before it writes anything.
/// Else it waits until the robot stands still, bounded by the command
/// timeout, because the control refuses the change while the robot moves.
/// After the call, the TCP is the flange again.
///
/// # Example
///
/// ```rust
/// # use voraus_robot_arm::prelude::*;
/// # fn demo(robot: &impl SelectTool) -> Result<()> {
/// if robot.selected_tool()?.is_some() {
/// robot.deselect_tool()?;
/// }
/// # Ok(())
/// # }
/// ```
///
/// # Returns
///
/// `Ok(())` on success.
///
/// # Errors
///
/// Returns
/// [`RobotArmError::ToolHandlingFailed`](crate::error::RobotArmError::ToolHandlingFailed)
/// ([`ToolError::NoneSelected`](crate::error::ToolError::NoneSelected)) if no
/// tool is currently selected,
/// [`RobotArmError::DidNotStop`](crate::error::RobotArmError::DidNotStop)
/// if the robot does not come to rest within the command
/// timeout,
/// [`RobotArmError::RobotInErrorState`](crate::error::RobotArmError::RobotInErrorState)
/// with the control's error if the control refuses the write,
/// [`RobotArmError::NotConfirmed`](crate::error::RobotArmError::NotConfirmed)
/// if the control does not confirm the deselection within the command
/// timeout, or [`RobotArmError::Backend`](crate::error::RobotArmError::Backend)
/// if the call to the robot control fails.
fn deselect_tool(&self) -> Result<()> {
self.send_deselect_tool()?.confirm()
}
/// Send the tool deselection.
///
/// The call returns before the control confirms the deselection. Call
/// [`confirm`](CommandHandle::confirm) on the returned handle to wait
/// for it.
///
/// The checks and the wait for standstill of
/// [`deselect_tool`](Self::deselect_tool) happen before
/// the call returns. Queued motions start only after the handle is
/// confirmed or dropped.
///
/// # Returns
///
/// The handle that confirms the deselection. [`CommandHandle::confirm`]
/// returns
/// [`RobotArmError::RobotInErrorState`](crate::error::RobotArmError::RobotInErrorState)
/// with the control's error if the control refuses the write, or
/// [`RobotArmError::NotConfirmed`](crate::error::RobotArmError::NotConfirmed)
/// if the control does not confirm the deselection within the command
/// timeout.
///
/// # Errors
///
/// Returns
/// [`RobotArmError::ToolHandlingFailed`](crate::error::RobotArmError::ToolHandlingFailed)
/// ([`ToolError::NoneSelected`](crate::error::ToolError::NoneSelected)) if no
/// tool is currently selected,
/// [`RobotArmError::DidNotStop`](crate::error::RobotArmError::DidNotStop)
/// if the robot does not come to rest within the command timeout, or
/// [`RobotArmError::Backend`](crate::error::RobotArmError::Backend) if
/// the call to the robot control fails.
fn send_deselect_tool(&self) -> Result<CommandHandle<'_>>;
}