A simpler, more intuitive interface to Boston Dynamics' Spot robots with ROS 2.
- Overview
- Requirements
- Architecture
- Installation
- Running the Spot driver
- A first example
- Documentation
- Testing
- Limitations
- Versioning and releases
- Maintenance
- Contributing
- Help
- License
spot_basic.SpotBasic is to the Spot ROS 2 driver what the Spot Python SDK is to Spot gRPC servers:
a simpler interface to Spot capabilities. Under the hood, SpotBasic takes all ROS 2 topics,
services, and actions that the spot_ros2 driver exposes and repackages them as a set of
consistent, intuitive APIs, suitable for both synchronous and asynchronous programming.
Important
Integration with process-wide synchros2 is tight and it is usually easier (though not
strictly required) to use it when working with spot_basic.
spot_basic is developed and tested against the following environment. Other combinations may work
but are not exercised in CI.
| Component | Supported version |
|---|---|
| Operating system | Ubuntu 22.04 (Jammy) |
| ROS 2 distribution | Humble Hawksbill |
| Python | 3.10 |
| CPU architecture | AMD64 (x86_64) and ARM64 (aarch64) |
Spot SDK (bosdyn-client, bosdyn-api, bosdyn-core) |
5.0.1 |
| NumPy | < 2 (see constraints.txt) |
spatialmath-python |
>= 1.1, < 2 |
| Open3D | >= 0.17, < 0.19 (capped by the NumPy constraint) |
You will also need:
- A Boston Dynamics Spot robot, reachable over the network, with firmware compatible with Spot SDK 5.0.1. Arm-specific APIs additionally require a Spot equipped with an arm.
- The
spot_ros2driver andbosdyn_msgs, both built from source alongsidespot_basic(see Installation).
Note
The numpy < 2 constraint is for ROS 2 Humble compatibility. See
constraints.txt for details.
It might be overwhelming and confusing when you first start to work with Spots in ROS 2. Here is a
quick rundown of all packages that functionally contribute to a Spot ROS 2 driver (spot_driver)
run:
| Repository | Package | Purpose |
|---|---|---|
spot_ros2 |
spot_driver |
The driver nodes for Spot in ROS 2 (though conceptually it is closer to a bridge). |
spot_ros2 |
spot_msgs |
ROS 2 interfaces specific to Spot (mainly service and action definitions). |
spot_wrapper |
spot_wrapper |
A thin, convenience layer atop the Spot Python SDK. |
bosdyn_msgs |
bosdyn_api_msgs, bosdyn_msgs |
ROS 2 equivalents of Spot SDK Protobuf messages (bosdyn_api_msgs) plus bidirectional conversion APIs (bosdyn_msgs). |
Once brought up, the Spot ROS 2 driver node(s) act as a ROS 2 bridge to the Spot SDK. When a service
request or action goal is sent -- using SpotBasic or ROS 2 APIs directly -- the driver forwards it
to Spot wrapper, which forwards it to the Spot SDK APIs, which in turn hit the Spot robot over gRPC.
Responses follow the same path in reverse. State and sensor streams are handled separately,
requesting data via Spot SDK APIs at fixed rates and publishing Spot-specific messages on topics
while broadcasting /tf transforms.
spot_basic is a ROS 2 (ament_cmake) package, built from source inside a colcon workspace. It
depends on several open-source packages that are also built from source; these are listed in
spot_basic.repos and fetched with vcstool. Note that spot_ros2 vendors
synchros2 and spot_wrapper as git submodules, so the import is run with --recursive to pull
them in.
For most users, the install_spot_basic.sh script handles the whole setup;
fetching dependencies, installing the Spot SDK and bosdyn_msgs, resolving rosdep keys, and
building the workspace:
# Create a workspace and clone spot_basic into src/
mkdir -p ~/spot_ws/src && cd ~/spot_ws
git clone https://github.com/rai-opensource/spot_basic.git src/spot_basic
# Install everything and build (use --arm64 on ARM hosts; --help for options)
./src/spot_basic/install_spot_basic.sh
# Source the workspace
source install/setup.bashIf you prefer to run the steps yourself:
# Create a workspace and clone spot_basic into src/
mkdir -p ~/spot_ws/src && cd ~/spot_ws
git clone https://github.com/rai-opensource/spot_basic.git src/spot_basic
# Fetch source dependencies (spot_ros2 with its synchros2/spot_wrapper submodules, bosdyn_msgs)
vcs import --recursive src < src/spot_basic/spot_basic.repos
# Install system / ROS dependencies declared in package.xml
rosdep install --from-paths src --ignore-src -r -y
# Install PyPI dependencies that have no rosdep key (Spot SDK, spatialmath, etc)
pip install -r src/spot_basic/requirements.txt
# Build and source
colcon build
source install/setup.bashNote that you will also need to follow the spot_ros2 installation instructions as well if you
choose manual installation (the build will most likely fail before you do this).
spot_basic talks to a robot through the spot_ros2 driver, so a spot_driver instance must be
running first. Bring it up with:
ros2 launch spot_driver spot_driver.launch.py config_file:=<path/to/spot_ros.yaml> spot_name:=<spot-name>The config_file holds your robot's connection details (hostname, username, password). See
the spot_driver documentation for the full list of launch arguments and configuration
options.
Tip
For joint-level (mixed-level) control, launch the driver with controllable:=True. See:
Using the Mixed-Level API.
With the driver running, this script makes Spot stand up, walk forward, and sit down while streaming its front-right camera:
import argparse
import cv2
import cv_bridge
import sys
from contextlib import closing
from spatialmath import SE2
from spot_basic import SpotBasic
import synchros2.process as ros_process
def cli() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser()
parser.add_argument("robot_name")
return parser
@ros_process.main(cli(), uses_tf=True)
def main(args: argparse.Namespace) -> int:
bridge = cv_bridge.CvBridge()
spot = SpotBasic(args.robot_name)
# leash() takes the lease, powers the robot on, stands it up, and
# sits it back down and powers it off on exit.
with spot.leash(timeout_sec=10.0):
world_t_robot = spot.lookup_a_tform_b(spot.vision_frame_name, spot.body_frame_name).yaw_SE2()
world_t_goal = world_t_robot * SE2(1.0, 0.0, 0.0)
action = spot.walk.asynchronously(frame_t_goal=world_t_goal)
with closing(spot.cameras.front_right.rgb.image.stream()) as imagestream:
for image in map(bridge.imgmsg_to_cv2, imagestream):
if action.finalized:
break
cv2.imshow("Spot View", image)
cv2.waitKey(10)
cv2.destroyAllWindows()
return 0 if action.succeeded else 1
if __name__ == "__main__":
sys.exit(main())More runnable scripts live in examples/.
| Guide | Contents |
|---|---|
Using SpotBasic |
Executing commands, querying state, and capturing video. |
Extending SpotBasic |
Adding commands, actions, state streams, and joint-level control. |
| Adding an action | Step-by-step tutorial for wiring up a brand-new action. |
You can also explore the spot_basic package, the examples/, and the
tests directly.
Unit tests run with colcon test. A complete, interactive hardware-in-the-loop (HIL) testing suite
is also available:
pytest --manual -v -s path/to/spot_basic/test/systemTip
Wire your workstation to a Spot robot to avoid network issues.
Please read these before adopting spot_basic.
- A running driver is required.
spot_basicis a client of thespot_ros2driver, not a standalone Spot SDK application. Every API call ultimately travels through a runningspot_driverinstance; there is no direct-to-robot mode. - Depends on
synchros2.spot_basicis intended to be used withsynchros2. The API is designed around process-widesynchros2APIs. - Arm APIs require an arm. Arm, gripper, manipulation, and surface-contact APIs raise a
RuntimeErroron robots without an arm. - Joint-level control requires driver opt-in. Mixed-level (joint) control only works when the
driver is launched with
controllable:=True. - Partial Spot CAM coverage. Only Spot CAM audio is wrapped; other Spot CAM subsystems (for example PTZ, lighting, and media streaming) are not exposed.
- Single platform. Only Ubuntu 22.04 with ROS 2 Humble is currently supported.
- Limited hardware testing. Real robot behavior is only tested by the interactive hardware-in-the-loop suite, which must be run manually (see Testing).
spot_basic is versioned through the <version> field of its package.xml,
following the usual ROS 2 package convention of MAJOR.MINOR.PATCH.
- Releases are published as GitHub Releases, each backed by a matching git tag.
- Every release states the Spot SDK version and ROS 2 distribution it was tested against, since compatibility with the Spot SDK is the dominant compatibility concern for this package.
- Because the project is under light maintenance, breaking API changes may be introduced in a minor version bump, not just a major one. Pin to an exact version if you need stability.
Important
spot_basic is under light maintenance. No feature development is guaranteed. If you file a
bug report, or open a pull request that fixes a bug, expect an RAI maintainer to respond within a
few weeks. Requests for new features may be closed without implementation, and breaking changes
may be introduced between releases (see Versioning and releases).
Bug reports and bug-fix pull requests are welcome!
See CONTRIBUTING.md for the full guide, and SECURITY.md for
reporting security vulnerabilities privately.
Reporting an issue. Open an issue on the issue tracker. The most useful reports include your Ubuntu, ROS 2, and Spot SDK versions, whether your robot has an arm, the driver launch arguments you used, a minimal script that reproduces the problem, and the full error output.
Submitting a change. Fork the repository, follow the Installation steps, and install the pre-commit hooks before making changes:
# Install the pre-commit tool
pip install pre-commit
# Install the pre-commit hooks and run
cd ~/spot_ws/src/spot_basic
pre-commit install
pre-commit run --all-filesThen open a pull request describing what changed, why it changed, and how you tested it. All changes require review and approval from a project maintainer before merging, and CI (lint, build, and unit tests) must pass. Note that CI runs for first-time contributors require explicit maintainer approval, so there may be a delay before checks start on your pull request.
If something is not working, first check Requirements and Limitations.
A common problem is a version mismatch with the Spot SDK. A quick way to confirm your Spot SDK
installation is correct (all versions should read 5.0.1):
pip freeze | grep bosdynIf that looks right and the problem persists, open an issue.
spot_basic is released under the MIT License. See LICENSE for the full text.