Documentation
Docs API & SDK Reference
api & sdk reference

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 kindReliabilityHistoryNotes
High-rate sensor topics (joint_states, imu/data)Best effortKeep last 1Match this QoS on your subscriber or you won't connect
Low-rate status topics (battery_state, diagnostics)ReliableKeep last 1
Commands (cmd_vel, trajectory topics)ReliableKeep last 1
Services and actionsReliable (RMW default)—Standard ROS 2 defaults, nothing custom

Topics

TopicTypeDirectionRateDescription
/buildo/joint_statessensor_msgs/JointStatePub200 HzPosition, velocity, effort for every arm, hand, and wheel joint
/buildo/cmd_velgeometry_msgs/TwistSub50 HzBase velocity command
/buildo/odomnav_msgs/OdometryPub50 HzBase odometry from wheel encoders
/buildo/imu/datasensor_msgs/ImuPub200 HzTorso IMU
/buildo/battery_statesensor_msgs/BatteryStatePub1 HzHot-swap battery charge, voltage, health
/buildo/camera/color/image_rawsensor_msgs/ImagePub30 fpsHead camera, color stream
/buildo/camera/depth/image_rawsensor_msgs/ImagePub30 fpsHead camera, depth stream (RealSense D435i)
/buildo/left_hand/state, /buildo/right_hand/statebuildo_msgs/msg/HandStatePub200 HzPer-finger position, velocity, and fingertip force
/buildo/system_modebuildo_msgs/msg/SystemModePubOn changeWhich control tier currently owns motion
/buildo/diagnosticsdiagnostic_msgs/DiagnosticArrayPub1 HzRolled-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

ServiceTypeDescription
/buildo/set_control_modebuildo_msgs/srv/SetControlModeSwitch between STANDBY, TELEOP, AUTONOMOUS
/buildo/calibrate_armbuildo_msgs/srv/CalibrateArmRe-home a single arm's joint encoders
/buildo/set_grasp_presetbuildo_msgs/srv/SetGraspPresetLoad a named grip profile (force/aperture curve) onto a hand

Actions

ActionTypeDescription
/buildo/left_arm/follow_joint_trajectory, /buildo/right_arm/follow_joint_trajectorycontrol_msgs/action/FollowJointTrajectoryStandard ros2_control action — what MoveIt calls under the hood
/buildo/navigate_to_posenav2_msgs/action/NavigateToPoseStandard Nav2 action for the base
/buildo/left_hand/grasp, /buildo/right_hand/graspbuildo_msgs/action/GraspClosed-loop grasp: approach, close to target force, hold
/buildo/execute_skillbuildo_msgs/action/ExecuteSkillHigh-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:

ParameterTypeDefaultDescription
can_interfacestringcan0Linux SocketCAN interface name
can_bitrateint1000000Bus bitrate in bps
joint_torque_limitdouble[]15.0 per jointFirmware-enforced torque clamp, N·m
control_loop_rate_hzint1000Hardware 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.