ℹ️ Scope. This page covers writing Python scripts against the RO1 ROS2 topics. Docker, network/Wi-Fi, and cyclonedds.xml configuration 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.

1. When to use the ROS2 bridge (and when not to)

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).

2. Three things to know before you write code

3. Topic reference

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.

4. The mandatory pattern: enable → work → disable

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.

4a. Connect the SDK and enable ROS2 control

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 with block and then do all your pub/sub work — exactly what write_poses.py does.