Individual transform lookupΒΆ

Use olo.spatial.Spatial through a namespace-scoped RobotFrames handle to resolve frames, look up transforms, publish static calibration frames, and stream transform updates.

from olo import Client
from olo.spatial import Transform, Vector

with Client() as client:
    robot = client.robot()
    arm = robot.kinematics

    # Namespace-scoped TF handle.
    robot_frames = robot.frames
    base_frame = robot_frames.base_frame()
    if base_frame is None:
        raise RuntimeError("No base frame detected for this robot")

    print(f"{base_frame = }")

    # Look up the base frame in the world frame.
    world_to_base = robot_frames.lookup("world", base_frame)
    print(f"Robot position in world frame: {world_to_base.translation}")

    # Read the end-effector pose in the robot planning frame.
    base_to_ee = arm.pose()
    print(f"EE position in robot planning frame: {base_to_ee.position}")

    # Re-express the end-effector pose in world frame.
    world_to_ee = world_to_base * base_to_ee
    print(f"EE position in world frame: {world_to_ee.position}")

    # Publish a static calibration frame on /tf_static.
    robot_frames.publish_static(
        Transform(
            translation=Vector(x=0.0, y=0.0, z=0.12),
            frame_id=base_frame,
            child_frame_id="tool0",
        )
    )

    # Stream a few transform updates, useful for a moving base.
    with robot_frames.subscribe(target_frame="world", source_frame=base_frame) as stream:
        for _, latest in zip(range(5), stream):
            print(f"Latest world -> {base_frame} transform: {latest.translation}")
import { connect } from "olo/web";
import { Transform, Vector } from "olo/spatial";

const client = connect();
const robot = await client.robot();
const arm = robot.kinematics;

// Namespace-scoped TF handle.
const robotFrames = robot.frames;
const baseFrame = await robotFrames.baseFrame();
if (baseFrame === undefined) {
  throw new Error("No base frame detected for this robot");
}

console.log(`baseFrame = ${baseFrame}`);

// Look up the base frame in the world frame.
const worldToBase = await robotFrames.lookup("world", baseFrame);
console.log(`Robot position in world frame: ${worldToBase.translation}`);

// Read the end-effector pose in the robot planning frame.
const baseToEe = await arm.pose();
console.log(`EE position in robot planning frame: ${baseToEe.position}`);

// Re-express the end-effector pose in world frame.
const worldToEe = worldToBase.multiply(baseToEe);
console.log(`EE position in world frame: ${worldToEe.position}`);

// Publish a static calibration frame on /tf_static.
await robotFrames.publishStatic(
  new Transform({
    translation: new Vector(0.0, 0.0, 0.12),
    frameId: baseFrame,
    childFrameId: "tool0",
  }),
);

// Stream a few transform updates, useful for a moving base.
const stream = robotFrames.subscribe("world", baseFrame);
let count = 0;
for await (const latest of stream) {
  console.log(`Latest world -> ${baseFrame} transform: ${latest.translation}`);
  if (++count === 5) stream.close();
}