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();
}