One Brain, any Bot.
The BotBrain Workspace is a modular, open-source ROS2 framework for autonomous robot control, navigation, and localization. Designed with a robot-agnostic architecture, it enables rapid development and deployment of advanced robotics applications across multiple robot platforms.
Key Features:
- 🤖 Multi-Robot Support: Single codebase for Go2, Tita, G1 and custom robots
- 🗺️ Visual SLAM: RTABMap-based localization with dual camera support
- 🎮 Multiple Control Modes: Joystick, web interface, and autonomous navigation
- 👁️ AI Vision: YOLOv8/v11 object detection
- 🐳 Docker Ready: Containerized deployment with GPU acceleration
- 🔄 Lifecycle Management: Robust node orchestration and failure recovery
- Hardware Requirements
- Quick Start
- Repository Structure
- Creating a Custom Robot Package
- Package Overview
- Docker Services
- Configuration
- Unitree Go2
- Unitree G1
- Tita
- Custom Robots - Follow the Custom Robot Package Guide
- Robot Platform: One of the supported robots above
- Onboard Computer:
- Nvidia Jetson Orin Series or newer
- Sensors:
- Intel RealSense cameras (for visual SLAM)
- LiDAR (for LiDAR-based SLAM)
- Network:
- Ethernet connection to robot
- Wi-Fi adapter (for remote control)
- Game Controller: For teleoperation
For containerized deployment:
# Start all services
docker compose up -d
# Start specific services
docker compose up -d state_machine bringup localization navigation
# View logs
docker compose logs -f bringup
# Stop services
docker compose down# Check active nodes
ros2 node list
# Check topics
ros2 topic listI you want to use the same docker image for development, without creating a new service, it is possible to run an iterative dev container:
# Init the dev container
cd botbrain_ws
docker compose up dev -d
# Init an iterative terminal
docker compose exec dev bashOnce the iterative terminal opens, you can use it to create, build and run new features that are not yet integrated with the docker services.
botbrain_ws/
├── README.md # This file
├── LICENSE # MIT License
│
├── robot_config.yaml # Main configuration file
├── install.sh # Automated installation script
├── robot_select.sh # Robot selection helper
│
├── docker-compose.yaml # Docker services definition
├── botbrain.service # Systemd autostart service
├── cyclonedds_config.xml # DDS middleware configuration
│
└── src/ # ROS 2 packages
│
├── Core System Packages
│ ├── bot_bringup/ # Main launch & twist mux coordination
│ ├── bot_custom_interfaces/ # Custom messages, services, actions
│ └── bot_state_machine/ # Lifecycle & state management
│
├── Robot Model & Visualization
│ └── bot_description/ # URDF/XACRO models & robot_state_publisher
│
├── Navigation & Localization
│ ├── bot_localization/ # RTABMap SLAM (visual & LiDAR)
│ └── bot_navigation/ # Nav2 navigation stack
│
├── Perception & Control
│ ├── bot_yolo/ # YOLOv8/v11 object detection
│ └── joystick-bot/ # Game controller interface
│
├── AI & Monitoring
│ ├── bot_jetson_stats/ # Jetson hardware monitoring
│ └── bot_rosa/ # ROSA AI natural language control
│
└── Robot-Specific Packages
├── g1_pkg/ # Unitree G1 hardware interface
├── go2_pkg/ # Unitree Go2 hardware interface
├── tita_pkg/ # Tita hardware interface
└── your_robot_pkg/ # Your custom robot (see guide below)
To add support for a new robot platform, follow this guide using go2_pkg as a reference template.
Note: The go2_pkg package communicates with the Unitree Go2 robot via ROS 2 topics (subscribing to Unitree's native ROS 2 topics and republishing in BotBrain format). Your custom robot package may use similar topic-based communication, direct hardware APIs, or SDK interfaces depending on your robot's architecture. The idea is to create a standard package interface between botbrain_ws packages and the the robot.
Your custom robot package must follow this naming convention to work seamlessly with all the packages: {robot_model}_pkg
{robot_model}_pkg/
├── package.xml # ROS 2 package manifest
├── CMakeLists.txt # Build configuration
├── README.md # Package documentation
├── launch/
│ └── robot_interface.launch.py # REQUIRED: Main hardware interface launcher
├── config/
│ └── nav2_params.yaml # REQUIRED: Navigation parameters
├── scripts/
│ ├── {robot_model}_read.py # REQUIRED: Reads sensor data from robot
│ └── {robot_model}_write.py # REQUIRED: Sends commands to robot
├── {robot_model}_pkg/ # Python package directory
│ └── tools/ # OPTIONAL: ROSA AI assistant tools
│ ├── __init__.py # Empty package initialization
│ └── {robot_model}.py # LangChain tools for ROSA integration
├── xacro/
│ └── robot.xacro # REQUIRED: Robot URDF model
└── meshes/
└── *.dae, *.stl # Visual & collision meshes
Create the package structure using ROS 2 tools (if you do not have ros2 installed in your host system, this can be done from a dev container):
cd src/
ros2 pkg create {robot_model}_pkg --build-type ament_cmake --dependencies rclcpp rclpy
cd {robot_model}_pkgCreate required directories:
mkdir -p launch config scripts xacro meshes mapsEdit package.xml and add required dependencies:
- Add
bot_custom_interfacesas a dependency - Update package name, version, description, and maintainer information
- Ensure all sensor message dependencies are included
Update the build configuration to install all package resources:
- Install launch files directory
- Install config files directory
- Install scripts as executables
- Install xacro, urdf, and meshes directories
- Use
ament_python_install_package()for Python modules
CRITICAL: Create launch/robot_interface.launch.py (exact name required)
This launch file must:
- Read
robot_config.yamlfrom workspace root - Extract
robot_namefor namespace configuration - Launch lifecycle nodes for hardware read and write
- Use
LifecycleNodefromlaunch_ros.actions - Apply correct namespace to all nodes
Reference: See go2_pkg/launch/robot_interface.launch.py for complete example.
Create scripts/{robot_model}_read.py - Reads sensor data and publishes to ROS 2:
This lifecycle node must:
- Initialize as a
LifecycleNodewith namerobot_read_node - Implement lifecycle callbacks:
on_configure,on_activate,on_deactivate,on_cleanup - In
on_configure: Create publishers for odometry, IMU, joint states, and battery - In
on_activate: Start data reading loop (typically 50Hz) from robot hardware/topics - Process robot sensor data and publish to ROS 2 topics
- In
on_deactivate: Stop data publishing but maintain connections - In
on_cleanup: Close hardware connections and release resources
Reference: See go2_pkg/scripts/go2_read.py for complete implementation.
Create scripts/{robot_model}_write.py - Receives commands and sends to robot:
This lifecycle node must:
- Initialize as a
LifecycleNodewith namerobot_write_node - In
on_configure: Create subscriber forcmd_vel_outtopic and establish robot communication - Implement callback to receive velocity commands and forward to robot hardware
- In
on_deactivate: Send stop command (zero velocity) to robot - In
on_cleanup: Close hardware connections and release resources - Optionally: Implement robot-specific services (mode switching, gait control, etc.)
Reference: See go2_pkg/scripts/go2_write.py for complete implementation.
Create config/nav2_params.yaml with your robot's specifications. See Nav2 Documentation as reference.
You will need to add a wildcard to the node configuration sections. See go2_pkg/config/nav2_params.yaml for complete configuration example.
Create xacro/robot.xacro with your robot's URDF model:
Your XACRO file should define:
base_linkas the main robot body linkinterface_linkas the interface part between robot and BotBrain- All robot joints and links (legs, arms, etc.)
- Sensor links (cameras, LiDAR, IMU)
- Visual meshes for RViz visualization
- Collision meshes for navigation
- Joint limits and dynamics
- Inertial properties
Reference: See go2_pkg/xacro/robot.xacro for complete robot description.
Update the workspace robot_config.yaml (it can be done from install.sh):
robot_configuration:
robot_name: "my_robot" # Namespace for all topics
robot_model: "your_robot" # Must match your package name without "_pkg"
description_file_type: "xacro" # "xacro" or "urdf"
network_interface: "eth0" # Network interface for robot communicationIMPORTANT: The robot_model field must match your package name without the _pkg suffix:
- Package name:
your_robot_pkg - robot_model:
your_robot
# Build your package
cd ~/botbrain_workspace/BotBrain/botbrain_ws
colcon build --packages-select your_robot_pkg
# Source the workspace
source install/setup.bash
# Test your hardware interface
ros2 launch your_robot_pkg robot_interface.launch.py
# Launch with full system
ros2 launch bot_bringup bringup.launch.pyYou can build and test the new package using a dev container.
ROSA (Robot Operating System Assistant) is an AI assistant that enables natural language control of your robot. By creating tools for ROSA, users can interact with your robot using conversational commands.
Create the tools directory structure:
mkdir -p {robot_model}_pkg/tools
touch {robot_model}_pkg/tools/__init__.py
touch {robot_model}_pkg/tools/{robot_model}.pyThe BotBrain system will automatically find and use your package based on these conventions:
- Package Naming:
{robot_model}_pkgformat - Launch File:
launch/robot_interface.launch.py(exact name required) - Navigation Config:
config/nav2_params.yaml(used by bot_navigation) - Description Files:
xacro/robot.xacroorurdf/robot.urdf(used by bot_description)
For full system integration, your hardware interface should publish:
| Topic | Message Type | Description | Frequency |
|---|---|---|---|
/{namespace}/odom |
nav_msgs/Odometry | Robot odometry | 50Hz |
/{namespace}/imu |
sensor_msgs/Imu | IMU data | 100Hz |
/{namespace}/joint_states |
sensor_msgs/JointState | Joint positions/velocities | 50Hz |
And subscribe to:
| Topic | Message Type | Description |
|---|---|---|
/{namespace}/cmd_vel_out |
geometry_msgs/Twist | Velocity commands from twist_mux |
| Package | Description | Documentation |
|---|---|---|
| bot_bringup | Main launch coordination, twist multiplexer, and system orchestration | README |
| bot_state_machine | Lifecycle management, node coordination, and system state control | README |
| bot_custom_interfaces | Custom ROS 2 messages, services, and actions | README |
| bot_description | Robot URDF/XACRO models and robot_state_publisher | README |
| Package | Description | Documentation |
|---|---|---|
| bot_localization | RTABMap SLAM with support for visual and LiDAR-based mapping | README |
| bot_navigation | Nav2 navigation stack with robot-agnostic configuration | README |
| Package | Description | Documentation |
|---|---|---|
| bot_yolo | YOLOv8/v11 object detection with TensorRT acceleration | README |
| joystick-bot | Game controller interface with dead-man switch safety | README |
| Package | Description | Documentation |
|---|---|---|
| go2_pkg | Unitree Go2 quadruped hardware interface and description | README |
| tita_pkg | Tita quadruped hardware interface and description | README |
The workspace includes multiple Docker services for containerized deployment:
| Service | Description | Auto-start | Dependencies |
|---|---|---|---|
dev |
Development container (interactive) | No | - |
builder_base |
Builds all workspace packages | No | - |
state_machine |
Lifecycle management service | Yes | - |
bringup |
Main robot bringup | Yes | state_machine |
localization |
RTABMap localization | Yes | bringup |
navigation |
Nav2 navigation servers | Yes | localization |
rosa |
AI tool calling services | Yes | bringup |
yolo |
Object detection service | Yes | bringup |
# Start all services
docker compose up -d
# Start specific service with dependencies
docker compose up -d navigation # Automatically starts bringup, localization
# View logs
docker compose logs -f bringup
# Stop all services
docker compose down
# Rebuild after code changes
docker compose build
docker compose up -dThe robot_config.yaml file is the central configuration point:
robot_configuration:
# Robot identifier - used as namespace for all topics
robot_name: "" # Example: "go2_robot1", "tita_lab"
# Robot type - determines which hardware package to launch
robot_model: "go2" # Options: "go2", "tita", "your_robot"
# Description file format
description_file_type: "xacro" # Options: "xacro", "urdf"
# Network interface for ROS2 communication
network_interface: "eno1" # Example: "eth0", "wlan0", "eno1"
# Tita-specific: namespace for Tita robot communication
tita_namespace: "tita3036731" # Only used when robot_model: "tita"
# OpenAI API Key for AI features (optional)
openai_api_key: "" # Required for ROSA AI assistant
# Wi-Fi configuration (optional)
wifi_interface: "" # Wi-Fi interface name (e.g., "wlan0")
wifi_ssid: "" # Wi-Fi network SSID
wifi_password: "" # Wi-Fi network passwordThe workspace uses CycloneDDS for ROS 2 communication. Configuration in cyclonedds_config.xml:
Set the network interface in robot_config.yaml to match your hardware connection.
The botbrain.service file enables automatic startup on boot:
# Install service (done by install.sh)
sudo cp botbrain.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable botbrain.service
# Manual control
sudo systemctl start botbrain.service # Start now
sudo systemctl stop botbrain.service # Stop
sudo systemctl status botbrain.service # Check status
# View logs
journalctl -u botbrain.service -fSee the Creating a Custom Robot Package guide above. We especially welcome contributions that add support for new robot platforms!
Made with ❤️ in Brazil