Skip to content

Active TCP

SUMMARY

robot.active_tcp is the single place TCP changes are pushed to hardware. Assigning a new TCP name immediately pushes it to the controller when connected; offline, it refreshes the cached commanded pose via forward kinematics instead.

SUPPORTED ROBOTS

Available on all supported manipulators in offline mode. Live push-to-controller is currently supported only on Universal Robots.

The Skill

python
robot.active_tcp = "my_tcp"

The Code

python
"""
Switch the active TCP for the Synapse SDK.

Setting ``robot.active_tcp`` immediately pushes the new TCP to the
controller when connected. Offline, it only refreshes the cached
commanded pose via forward kinematics.

Universal Robots (UR10e) is used here for illustration; the same pattern
works for every supported brand.

Usage:
    python active_tcp.py [--ip <ROBOT_IP>]
"""

import argparse
from loguru import logger

from telekinesis.synapse.robots.manipulators import universal_robots


def main(ip: str | None = None):
    """Add a custom TCP, switch to it, then switch back to the default."""

    robot = universal_robots.UniversalRobotsUR10E()

    if ip is not None:
        robot.connect(ip=ip)

    # Register a custom TCP offset [x, y, z, rx, ry, rz] (m, deg)
    robot.add_tcp(name="my_tcp", tcp_offset=[0, 0, 0.15, 0, 0, 0])

    logger.info(f"Active TCP before: {robot.active_tcp}")

    # Assigning active_tcp pushes the change to the controller if connected
    robot.active_tcp = "my_tcp"
    logger.success(f"Active TCP after: {robot.active_tcp}")

    # Switch back to the robot's default TCP
    robot.active_tcp = "default_tcp"

    if ip is not None:
        robot.disconnect()


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Active TCP Synapse example")
    parser.add_argument("--ip", type=str, default=None, help="UR robot IP address (optional)")
    args = parser.parse_args()

    main(ip=args.ip)

The Explanation of the Code

python
robot.add_tcp(name="my_tcp", tcp_offset=[0, 0, 0.15, 0, 0, 0])

Registers a new named TCP frame at a fixed offset from the robot's flange. add_tcp, update_tcp, and delete_tcp all internally assign to active_tcp, so they share the same push-to-hardware behavior described here.

python
robot.active_tcp = "my_tcp"

Validates that "my_tcp" exists, stores the previous active TCP, and updates the internal state. If the robot is offline, only the cached commanded pose is refreshed via forward kinematics. If the robot is connected, the new TCP is pushed to the controller immediately - no extra call needed.

python
robot.active_tcp = "default_tcp"

Every robot ships with a default_tcp frame at the flange origin. Assign it back at any time to reset to the robot's un-offset TCP.

Return Value

TypeDescription
strThe active_tcp getter returns the name of the currently active TCP frame.

Assigning to active_tcp returns nothing - it is a property setter with a side effect (pushes to hardware when connected).

Where to Use the Skill

  • Tool changes - Switch TCP when a different tool (gripper, sensor, custom end-effector) becomes active on the flange.
  • Multi-frame workflows - Register several TCPs up front (e.g. "camera_tcp", "gripper_tcp") and switch between them as a task progresses.
  • Live re-calibration - Update an existing TCP offset with update_tcp and have the change take effect immediately without a separate push call.

When Not to Use the Skill

  • You just need to read the current pose - use Get Cartesian Pose, which already resolves against whichever TCP is currently active.
  • You need a one-off pose in a different frame - pass frame_name to Forward Kinematics instead of switching the active TCP.