# raspbot_v2 ROS 2 robot platform based on the Yahboom Raspbot V2. Multiple services run as Docker containers, coordinated by Docker Compose. --- ## Sub-projects | Directory | Description | |---|---| | [robot/](robot/README.md) | Differential-drive motor control, pan/tilt camera, and ultrasonic range sensor | | [lidar/](lidar/README.md) | RPLIDAR A1 laser scanner | | [oled/](oled/README.md) | OLED display dashboard | | [wifi/](wifi/README.md) | Wi-Fi hotspot fallback manager | | [camera_publisher/](camera_publisher/README.md) | V4L2 camera → ROS 2 topic publisher | | [webrtc_streamer/](webrtc_streamer/README.md) | WebRTC browser stream server | | [webui/](webui/README.md) | Browser-based robot controller | | [ansible/](ansible/README.md) | Provisioning playbook for the Raspberry Pi | | [teleop/](teleop/README.md) | Keyboard and joystick teleoperation container | --- ## Setting up the robot ### 1. Flash Raspberry Pi OS Use the [Raspberry Pi Imager](https://www.raspberrypi.com/software/) to write Raspberry Pi OS (64-bit, Lite recommended) to a microSD card. Before writing, open **Advanced options** (⚙) and configure: | Setting | Value | |---|---| | Hostname | `raspbot-v2.local` | | SSH | Enabled | | Username / Password | Your preferred credentials | | Wi-Fi | Your network SSID and password (if not using Ethernet) | Write the image, insert the card, and power on the Pi. Once it is reachable on the network (test with `ping raspbot-v2.local`), proceed to the next step. ### 2. Provision with Ansible The [ansible/](ansible/) directory contains a playbook that handles the remaining setup (enabling SPI, installing Docker). See [ansible/README.md](ansible/README.md) for full instructions. --- ## Building ### Prerequisites - Docker with BuildKit enabled - For cross-compilation from an amd64 host, register QEMU user-space emulation once: ```bash docker run --rm --privileged tonistiigi/binfmt --install arm64 ``` ### Build all images ```bash docker compose build ``` Or build a single service: ```bash docker compose build robot docker compose build lidar ``` --- ## Deploying Pipe images directly to the target over SSH — no intermediate file or registry needed: ```bash # Upload all images docker save $(docker compose config --images) | ssh @raspbot-v2.local docker load # Upload a single image docker save raspbot_v2_oled:latest | ssh @raspbot-v2.local docker load ``` `docker compose config --images` resolves all image names from the compose file, including any environment variable substitutions. Then copy the compose file and any `.env` to the target: ```bash scp docker-compose.yml @raspbot-v2.local:~/ ``` Replace `` with the username configured in [ansible/inventory.ini](ansible/inventory.ini). --- ## Launching ### Start everything ```bash docker compose up ``` To run in the background: ```bash docker compose up -d docker compose logs -f # follow logs docker compose down # stop and remove containers ``` ### Dev container An interactive ROS desktop environment (`osrf/ros:kilted-desktop-full`) is provided for development, visualisation, and ad-hoc `ros2` commands. It shares the host network so it participates in the same DDS domain as the robot. Allow X11 forwarding from Docker (required once per session): ```bash xhost +local:docker ``` Then launch the container: ```bash docker compose -f docker-compose.dev.yml run --rm dev ``` The container drops you into a bash shell with the ROS underlay sourced. Set `FASTDDS_INTERFACE` in your `.env` (or inline) to bind DDS traffic to the correct network interface when connecting over Wi-Fi: ```bash FASTDDS_INTERFACE=wlp195s0 docker compose -f docker-compose.dev.yml run --rm dev ``` See [teleop/README.md](teleop/README.md#working-out-the-network-interface-to-bind-to) for instructions on identifying the correct interface name. --- ### Environment variables Create a `.env` file alongside `docker-compose.yml` to override defaults: ```bash ROS_DOMAIN_ID=0 LIDAR_PORT=/dev/ttyUSB0 LIDAR_FRAME_ID=laser WIFI_SSID=MyNetwork ``` | Variable | Default | Description | |---|---|---| | `ROS_DOMAIN_ID` | `0` | ROS 2 domain — must match on all nodes | | `LIDAR_PORT` | `/dev/ttyUSB0` | Host device node for the RPLIDAR | | `LIDAR_FRAME_ID` | `laser` | `frame_id` in published `LaserScan` messages | | `WIFI_SSID` | _(empty)_ | Target SSID; if unset the Wi-Fi container creates a hotspot immediately | | `HOTSPOT_SSID` | `raspbot-hotspot` | Fallback hotspot SSID | | `HOTSPOT_PASSWORD` | `raspbot1234` | Fallback hotspot passphrase | --- ## Project layout ``` . ├── docker-compose.yml ├── docker-compose.dev.yml # Interactive dev/visualisation container ├── docker-entrypoint.sh ├── raspbot_v2/ # ROS 2 packages (control, description, hardware interface) ├── lidar/ # RPLIDAR A1 ├── oled/ # OLED display dashboard ├── wifi/ # Wi-Fi hotspot fallback ├── camera_publisher/ # V4L2 camera → ROS 2 topic ├── webrtc_streamer/ # WebRTC browser stream ├── webui/ # Browser-based controller UI ├── teleop/ # Keyboard and joystick teleoperation └── ansible/ # Raspberry Pi provisioning ```