Local rosbag recording¶
Record a rosbag on the appliance, inspect its topics, then play it back with
pause and resume. Use robot.archive.recordBag and robot.archive.playBag.
import time
from concurrent.futures import ThreadPoolExecutor
from olo import Client
with Client() as client:
robot = client.robot()
bag_session = None
playback = None
try:
# Record selected ROS topics for 10 seconds.
bag_session = robot.archive.record_bag(topics=["cmd_vel"])
print(f"Recording bag {bag_session.filename} for 10s")
time.sleep(10)
bag_result = bag_session.stop()
bag_session = None
print(f"Saved {bag_result.filename} ({bag_result.total_bytes} bytes)")
# Inspect the saved bag and list its topics.
info = robot.archive.inspect_bag(bag_result.filename)
summary = info.summary
print(
f"Bag: {summary.message_count} messages, "
f"{summary.duration_seconds:.1f}s, {summary.storage_format or 'unknown'} format"
)
for topic in info.topics:
print(f" {topic.name}: {topic.message_count} messages")
# Play the bag, exercise playback controls, and wait for completion.
# system_time avoids a second /clock publisher when the sim already publishes one.
with ThreadPoolExecutor(max_workers=1) as pool:
playback = robot.archive.play_bag(bag_result.filename, clock_type="system_time")
# Subscribe before control/demo sleeps so fast bags cannot finish unseen.
playback_done = pool.submit(playback.watch)
print(f"Playing back {bag_result.filename}")
time.sleep(5)
playback.pause()
print("Paused")
time.sleep(2)
playback.resume()
print("Resumed — waiting for bag to finish")
finished = playback_done.result()
print(f"Playback {finished.type} (exit {finished.exit_code})")
playback = None
finally:
if bag_session is not None:
bag_session.stop()
if playback is not None:
playback.stop()
import { connect } from "olo/node";
await using client = connect();
const robot = await client.robot();
let bagSession: Awaited<ReturnType<typeof robot.archive.recordBag>> | null = null;
let playback: Awaited<ReturnType<typeof robot.archive.playBag>> | null = null;
try {
// Record selected ROS topics for 10 seconds.
bagSession = await robot.archive.recordBag({ topics: ["cmd_vel"] });
console.log(`Recording bag ${bagSession.filename} for 10s`);
await new Promise((r) => setTimeout(r, 10_000));
const bagResult = await bagSession.stop();
bagSession = null;
console.log(`Saved ${bagResult.filename} (${bagResult.totalBytes} bytes)`);
// Inspect the saved bag and list its topics.
const info = await robot.archive.inspectBag(bagResult.filename);
const { summary } = info;
console.log(
`Bag: ${summary.messageCount} messages, ${summary.durationSeconds.toFixed(1)}s, ${summary.storageFormat || "unknown"} format`,
);
for (const topic of info.topics) {
console.log(` ${topic.name}: ${topic.messageCount} messages`);
}
// Play the bag, exercise playback controls, and wait for completion.
// system_time avoids a second /clock publisher when the sim already publishes one.
playback = await robot.archive.playBag(bagResult.filename, { clockType: "system_time" });
// Subscribe before control/demo sleeps so fast bags cannot finish unseen.
const playbackDone = playback.watch();
console.log(`Playing back ${bagResult.filename}`);
await new Promise((r) => setTimeout(r, 5_000));
await playback.pause();
console.log("Paused");
await new Promise((r) => setTimeout(r, 2_000));
await playback.resume();
console.log("Resumed — waiting for bag to finish");
const finished = await playbackDone;
console.log(`Playback ${finished.type} (exit ${finished.exitCode})`);
playback = null;
} finally {
if (bagSession) await bagSession.stop();
if (playback) await playback.stop();
}