API & SDK Reference
The complete topic, service, action, and message surface Buildo exposes over ROS 2 — everything you can subscribe to, call, or command.
Conventions
Every interface lives under the /buildo namespace. Per-arm interfaces are further
scoped: /buildo/left_arm/..., /buildo/right_arm/.... All custom
types live in the buildo_msgs package (buildo_msgs/msg, /srv, /action) — inspectable on-robot with ros2 interface show.
| Interface kind | Reliability | History | Notes |
|---|---|---|---|
High-rate sensor topics (joint_states, imu/data) | Best effort | Keep last 1 | Match this QoS on your subscriber or you won't connect |
Low-rate status topics (battery_state, diagnostics) | Reliable | Keep last 1 | |
Commands (cmd_vel, trajectory topics) | Reliable | Keep last 1 | |
| Services and actions | Reliable (RMW default) | — | Standard ROS 2 defaults, nothing custom |
Topics
| Topic | Type | Direction | Rate | Description |
|---|---|---|---|---|
/buildo/joint_states | sensor_msgs/JointState | Pub | 200 Hz | Position, velocity, effort for every arm, hand, and wheel joint |
/buildo/cmd_vel | geometry_msgs/Twist | Sub | 50 Hz | Base velocity command |
/buildo/odom | nav_msgs/Odometry | Pub | 50 Hz | Base odometry from wheel encoders |
/buildo/imu/data | sensor_msgs/Imu | Pub | 200 Hz | Torso IMU |
/buildo/battery_state | sensor_msgs/BatteryState | Pub | 1 Hz | Hot-swap battery charge, voltage, health |
/buildo/camera/color/image_raw | sensor_msgs/Image | Pub | 30 fps | Head camera, color stream |
/buildo/camera/depth/image_raw | sensor_msgs/Image | Pub | 30 fps | Head camera, depth stream (RealSense D435i) |
/buildo/left_hand/state, /buildo/right_hand/state | buildo_msgs/msg/HandState | Pub | 200 Hz | Per-finger position, velocity, and fingertip force |
/buildo/system_mode | buildo_msgs/msg/SystemMode | Pub | On change | Which control tier currently owns motion |
/buildo/diagnostics | diagnostic_msgs/DiagnosticArray | Pub | 1 Hz | Rolled-up per-actuator and per-subsystem health |
Topics are listed exactly as published — the /buildo prefix is the robot's
namespace, not a remap. On a multi-robot network, separate units by ROS_DOMAIN_ID rather
than renaming topics.
Services & actions
Services
| Service | Type | Description |
|---|---|---|
/buildo/set_control_mode | buildo_msgs/srv/SetControlMode | Switch between STANDBY, TELEOP, AUTONOMOUS |
/buildo/calibrate_arm | buildo_msgs/srv/CalibrateArm | Re-home a single arm's joint encoders |
/buildo/set_grasp_preset | buildo_msgs/srv/SetGraspPreset | Load a named grip profile (force/aperture curve) onto a hand |
Actions
| Action | Type | Description |
|---|---|---|
/buildo/left_arm/follow_joint_trajectory, /buildo/right_arm/follow_joint_trajectory | control_msgs/action/FollowJointTrajectory | Standard ros2_control action — what MoveIt calls under the hood |
/buildo/navigate_to_pose | nav2_msgs/action/NavigateToPose | Standard Nav2 action for the base |
/buildo/left_hand/grasp, /buildo/right_hand/grasp | buildo_msgs/action/Grasp | Closed-loop grasp: approach, close to target force, hold |
/buildo/execute_skill | buildo_msgs/action/ExecuteSkill | High-level task handoff (e.g. "pick up the red cup") — the entry point for commanding Buildo by instruction rather than by trajectory |
follow_joint_trajectory and navigate_to_pose are deliberately stock
ROS 2 types with no Buildo-specific fields — any MoveIt or Nav2 client code you already
have targets them unmodified. Grasp and ExecuteSkill are the two places
the API extends past the ROS 2 standard, because no standard type covers force-closed-loop grasping
or language-conditioned task execution.
Message definitions
buildo_msgs/msg/HandState.msg
float64[5] finger_position # radians, per finger
float64[5] finger_velocity # rad/s
float64[5] fingertip_force # newtons
std_msgs/Header header buildo_msgs/msg/SystemMode.msg
uint8 STANDBY = 0
uint8 TELEOP = 1
uint8 AUTONOMOUS = 2
uint8 mode
string active_tier # "system2" | "system1" | "system0" buildo_msgs/action/Grasp.action
# Goal
string preset_name
float64 target_force # newtons
---
# Result
bool success
float64 final_force
---
# Feedback
float64 current_force SDK quickstart
There's one official SDK, and it's Python. C++ clients talk to the same topics, services, and
actions directly through rclcpp — there's no separate C++ convenience layer to
install.
Python
The Buildo SDK is a thin Python convenience layer over rclpy — every call
below maps directly to the topics and actions above, so dropping to raw rclpy at any
point works the same way it would for any ROS 2 node.
from buildo_sdk import BuildoClient
client = BuildoClient()
client.set_control_mode("AUTONOMOUS")
# Read joint state
state = client.get_joint_states()
print(state.left_shoulder_pitch.position)
# Command a grasp
result = client.right_hand.grasp(preset="pinch", target_force=4.0)
print(result.success, result.final_force)
# Drive the base
client.drive(linear_x=0.3, angular_z=0.0, duration_s=2.0)
# Hand off a high-level task
client.execute_skill("pick up the red cup") C++ (rclcpp)
The same two calls directly against the generated buildo_msgs bindings — this
is the pattern every other call in this reference follows from C++:
#include <rclcpp/rclcpp.hpp>
#include <rclcpp_action/rclcpp_action.hpp>
#include "buildo_msgs/srv/set_control_mode.hpp"
#include "buildo_msgs/action/grasp.hpp"
using Grasp = buildo_msgs::action::Grasp;
auto node = rclcpp::Node::make_shared("buildo_client_example");
// Set control mode
auto mode_client = node->create_client<buildo_msgs::srv::SetControlMode>(
"/buildo/set_control_mode");
auto mode_req = std::make_shared<buildo_msgs::srv::SetControlMode::Request>();
mode_req->mode = "AUTONOMOUS";
mode_client->async_send_request(mode_req);
// Command a grasp
auto grasp_client = rclcpp_action::create_client<Grasp>(node, "/buildo/right_hand/grasp");
Grasp::Goal goal;
goal.preset_name = "pinch";
goal.target_force = 4.0;
grasp_client->async_send_goal(goal);
rclcpp::spin(node); Parameters & versioning
buildo_hardware_interface node parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
can_interface | string | can0 | Linux SocketCAN interface name |
can_bitrate | int | 1000000 | Bus bitrate in bps |
joint_torque_limit | double[] | 15.0 per joint | Firmware-enforced torque clamp, N·m |
control_loop_rate_hz | int | 1000 | Hardware interface update rate |
buildo_msgs follows semantic versioning and is pinned per firmware release
— check ros2 pkg xml buildo_msgs against your robot's firmware version before
upgrading a client in the field. Breaking changes to any interface on this page land in a major
version bump and a note in the release changelog, never silently.