bosdyn_msgs
offers an interoperability layer between Boston Dynamics Spot SDK and ROS 2 aware code by providing ROS 2 messages equivalent to Spot SDK Protobuf messages, as well bi-directional conversion APIs in C++ and Python.
This repository contains the following packages:
Package | Description |
---|---|
bosdyn_msgs |
ROS 2 interoperability support for the Boston Dynamics Spot SDK (metapackage) |
bosdyn_api_msgs |
ROS 2 interoperability support for bosdyn.api , bosdyn.api.gps , and bosdyn.api.docking APIs |
bosdyn_spot_api_msgs |
ROS 2 interoperability support for bosdyn.api.spot APIs |
bosdyn_spot_cam_api_msgs |
ROS 2 interoperability support for bosdyn.api.spot_cam APIs |
bosdyn_mission_api_msgs |
ROS 2 interoperability support for bosdyn.api.mission APIs |
bosdyn_autowalk_api_msgs |
ROS 2 interoperability support for bosdyn.api.autowalk APIs |
bosdyn_graph_nav_api_msgs |
ROS 2 interoperability support for bosdyn.api.graph_nav APIs |
bosdyn_keepalive_api_msgs |
ROS 2 interoperability support for bosdyn.api.keepalive APIs |
bosdyn_log_status_api_msgs |
ROS 2 interoperability support for bosdyn.api.log_status APIs |
bosdyn_auto_return_api_msgs |
ROS 2 interoperability support for bosdyn.api.auto_return APIs |
bosdyn_metrics_logging_api_msgs |
ROS 2 interoperability support for bosdyn.api.metrics_logging APIs |
bosdyn_cmake_module |
CMake modules for the Boston Dynamics Spot SDK |
Just grab a binary bundle for your architecture (e.g. downloaded from available releases ) and execute it.
Packages will be installed alongside your ROS 2 distribution (e.g. under /opt/ros/<distribution>
).
#include <cassert>
#include <bosdyn/api/robot_state.pb.h>
#include <bosdyn_api_msgs/msg/motor_temperature.hpp>
#include <bosdyn_api_msgs/conversions.hpp>
int main() {
// Instantiate a Spot SDK Protobuf message.
auto proto_message = bosdyn::api::MotorTemperature{};
proto_message.set_name("wr0_joint_motor");
proto_message.set_temperature(34.0);
// Convert the Protobuf message to its ROS 2 equivalent.
auto ros_message = bosdyn_api_msgs::msg::MotorTemperature{};
bosdyn_api_msgs::conversions::convert(proto_message, &ros_message);
assert(proto_message.name() == ros_message.name);
assert(proto_message.temperature() == ros_message.temperature);
// Convert the ROS 2 message back to Protobuf message form.
auto other_proto_message = bosdyn::api::MotorTemperature{};
bosdyn_api_msgs::conversions::convert(ros_message, &other_proto_message)
assert(proto_message.name() == other_proto_message.name());
assert(proto_message.temperature() == other_proto_message.temperature());
}
Note the header naming and namespacing patterns in bosdyn_msgs
packages.
These lead to the following procedure when working with bosdyn_msgs
in C++:
-
Look up the Protobuf package on which the Protobuf message of interest is defined.
-
Look up the ROS 2 package that maps interfaces from the corresponding Protobuf package.
-
Include the header for the corresponding Protobuf package:
#include <path/to/proto/package.pb.h>
-
Include the header for the corresponding ROS 2 package and message, like:
#include <path/to/ros/package/msg/snake_cased_message_name.hpp>
-
Include the header exposing conversion APIs:
#include <path/to/ros/package/conversions.hpp>
-
Use
proto::package::MessageName
andros_package::msg::MessageName
messages, converting back and forth usingros_package::conversions::convert()
overloads.
import bosdyn.api.robot_state_pb2
import bosdyn_api_msgs.msg
from bosdyn_api_msgs.conversions import convert
proto_message = bosdyn.api.robot_state_pb2.MotorTemperature()
proto_message.name = "wr0_joint_motor"
proto_message.temperature = 34.0
ros_message = bosdyn_api_msgs.msg.MotorTemperature()
convert(proto_message, ros_message)
assert proto_message.name == ros_message.name
assert proto_message.temperature == ros_message.temperature
other_proto_message = bosdyn.api.robot_state_pb2.MotorTemperature()
convert(ros_message, other_proto_message)
assert proto_message.name == other_proto_message.name
assert proto_message.temperature == other_proto_message.temperature
Note the module naming pattern for bosdyn_msgs
packages.
This leads to the following procedure when working with bosdyn_msgs
in Python:
-
Look up the Protobuf package on which the Protobuf message of interest is defined.
-
Look up the ROS 2 package that maps interfaces from the corresponding Protobuf package.
-
Import the module for the corresponding Protobuf package:
import proto.package_pb2
-
Import the module for the corresponding ROS 2 package, like:
import ros_package.msg
-
Import conversion APIs:
from ros_package.conversions import convert
-
Use
proto.package_pb2.MessageName
andros_package.msg.MessageName
messages, converting back and forth usingconvert()
overloads.
# LocomotionStatus.msg
bosdyn_api_msgs/MotorTemperature[] temperatures
Note the message naming pattern. As elsewhere, the procedure boils down to identifying the ROS 2 package that contains the Protobuf message of interest.
Just push a tag with an appropriate release version to this repository e.g.:
git tag MAJOR.MINOR.PATCH
git push origin MAJOR.MINOR.PATCH
This will trigger a release job. Once the release is complete, bosdyn_msgs-bundle_MAJOR.MINOR.PATCH-*.run
binary bundles will be made available as release assets. As of January 2024, releases include binary
bundles compatible with ROS 2 Humble Hawksbill on Ubuntu Jammy 22.04 for AMD64 and ARM64 architectures.
Attention: it is strongly advised to keep package versions and tags in lockstep with the version of the
latest Boston Dynamics Spot SDK release to PyPI. This can be achieved by updating versions in package.xml
files and pip-constraint.txt
file to match each other and the tag.
First, ensure QEMU virtualization for multi-platform Docker containers is enabled:
sudo apt-get install qemu binfmt-support qemu-user-static
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
Now, simply invoke make -jN
at the repostory root with a suitable number of jobs N
.
This will build bosdyn_msgs_unknown-bundle-amd64.run
and bosdyn_msgs_unknown-bundle-arm64.run
binary bundles (of unknown
version, as none was specified).
You can also bundle fewer packages for specific architectures with:
make -jN <package_name>-bundle-<arch>.run
Binary bundles include the target package and its local dependencies.
Note: QEMU virtualization makes for very slow builds (from minutes to hours).
You can build these packages in colcon
workspaces, like you would for any other ROS 2 package.
First, ensure ROS 2 Humble Hawksbill is installed.
That includes development tools:
sudo apt update && sudo apt install -y python3-pip ros-dev-tools
Then clone this repository into a workspace:
mkdir -p workspace/src; cd workspace
git -C src clone --recursive https://github.com/bdaiinstitute/bosdyn_msgs.git
When installing package dependencies, make sure pip
constraints are enforced:
PIP_CONSTRAINT=src/bosdyn_msgs/pip-constraint.txt rosdep install -i -y --from-path src --skip-keys "$(cat src/bosdyn_msgs/rosdep-skip.txt)"
This will ensure apt
and pip
managed packages are compatible with each other.
Unfortunately, this is not yet enough. There are a few dependencies that are distributed separately:
ARCH=amd64 # or arm64
for url in $(cat ${ARCH}-dpkg.txt); do wget $url && sudo apt install -y ./$(basename $url); done
Finally, you can now build:
colcon build