ℹ️ Scope. This page covers writing Python scripts against the RO1 ROS2 topics. Docker, network/Wi-Fi, and
cyclonedds.xmlconfiguration live in the separate STANDARDBOTS ROS2 API RUNBOOK — do that first. This page assumes the Developer API and ROS2 bridge are already enabled and your client environment is set up. You'll need the robot URL and API token (from Configure Developer API) for any script that moves the arm.
The robot exposes two complementary developer surfaces:
Rule of thumb: if you react to input every cycle and stream setpoints, use the bridge. If you issue discrete high-level commands, use the SDK.
⚠️ The bridge does not replace the SDK — it depends on it. You use the Python SDK to unbrake the arm and switch ROS2 control on and off. The two are always used together (see §4).
/<BOT_ID>/ro1/hardware/.... Call detect_bot_id() to discover it at runtime.All topics are namespaced by your bot ID: /<BOT_ID>/ro1/hardware/....
| Topic | Message type | Direction | Use |
|---|---|---|---|
.../joint_state |
sensor_msgs/JointState |
Robot → you | Live joint angles / velocities |
.../pose |
geometry_msgs/PoseStamped |
Robot → you | Live TCP pose |
.../pose/write |
geometry_msgs/PoseStamped |
You → robot | Command a target TCP pose |
.../joint_trajectory |
trajectory_msgs/JointTrajectory |
You → robot | Stream a joint trajectory to execute |
.../jacobian |
std_msgs/Float64MultiArray |
Robot → you | Jacobian (advanced / Cartesian control) |
.../end_effector_imu |
sensor_msgs/Imu |
Robot → you | Wrist IMU |
💡 To see what's actually live, list topics from a ROS2 shell with
ros2 topic list.
Every motion script follows the same skeleton. Two ideas do all the work: flip control state with the SDK (HTTPS), then stream over ROS2 (DDS), and on exit flip control back off so the arm doesn't stay live.
from standardbots import StandardBotsRobot, models
sdk = StandardBotsRobot(
url=ROBOT_URL, # from Configure Developer API
token=ROBOT_TOKEN,
robot_kind=StandardBotsRobot.RobotKind.Live, # use .Simulated against a sim
)
with sdk.connection():
sdk.movement.brakes.unbrake().ok() # release the brakes
sdk.ros.control.update_ros_control_state( # hand control to ROS2
models.ROSControlUpdateRequest(
action=models.ROSControlStateEnum.Enabled,
)
)
sdk.ros.status.get_ros_control_state().ok() # confirm it took
💡 The SDK connection only needs to be open to change the control state. The realtime data itself flows over ROS2 topics, so it's normal to close this
withblock and then do all your pub/sub work — exactly whatwrite_poses.pydoes.