Files
ros-raspbot-v2/README.md
T

6.3 KiB
Raw Blame History

my_robot — Motor Controller Node

ROS 2 package for differential-drive motor control on the Yahboom Raspbot V2 platform.


Architecture

                      ┌──────────────────────────────────┐
                      │      MotorControllerNode          │
                      │                                   │
 /cmd_vel  ──────────>│  Twist → differential kinematics  │
 (geometry_msgs/Twist)│  left  = linear  (angular × wb/2)│
                      │  right = linear + (angular × wb/2)│
                      │                                   │
 /wheel_speeds ──────>│  Direct per-wheel override        │
 (Float32MultiArray   │  [FL, FR, RL, RR]                 │
  4 × float32)        │                                   │
                      │         ▼                         │
                      │   raspbot_v2_interface             │
                      │   I²C bus 1, addr 0x2B            │
                      │         ▼                         │
                      │   /dev/i2c-1 ─────────> Motors    │
                      │                                   │
 /current_wheel_speeds│<─ telemetry @ 10 Hz               │
 (Float32MultiArray)  │   [FL, FR, RL, RR]                │
                      └──────────────────────────────────┘

Topics

Topic Direction Type Description
/cmd_vel Subscribed geometry_msgs/Twist Velocity command — linear.x (m/s) and angular.z (rad/s)
/wheel_speeds Subscribed std_msgs/Float32MultiArray Direct per-wheel speed override [FL, FR, RL, RR] in library units (0255)
/current_wheel_speeds Published std_msgs/Float32MultiArray Current wheel speeds read from hardware, published at 10 Hz

Parameters

Parameter Default Description
wheel_base 0.3 Distance between left and right wheels in metres
max_speed 1.0 Maximum motor speed in library units

Hardware interface

The node drives the Yahboom Raspbot V2 motor controller over I²C bus 1 (device address 0x2B) using the bundled raspbot_v2_interface library. The only host device required is /dev/i2c-1.


Setting up the robot

1. Flash Raspberry Pi OS

Use the Raspberry Pi Imager to write Raspberry Pi OS (64-bit, Lite recommended) to a microSD card.

Before writing, open the imager's 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 has booted and is reachable on the network (test with ping raspbot-v2.local), proceed to the next step.

2. Provision with Ansible

The ansible/ directory contains a playbook that handles the remaining setup (enabling SPI, installing Docker). See ansible/README.md for full instructions.


Deploying

Once the image is built, pipe it directly to the target over SSH — no intermediate file or registry needed:

docker save my_robot:latest | ssh matt@raspbot-v2.local docker load

Replace matt with the username configured in ansible/inventory.ini.


Building

Prerequisites

  • Docker (with BuildKit enabled)

  • For cross-compilation from an amd64 host, QEMU user-space emulation must be registered with the kernel. If you haven't done this before, run once:

    docker run --rm --privileged tonistiigi/binfmt --install arm64
    

Build the image

The Raspberry Pi is arm64, so the image must be built for that platform. On an amd64 host use docker buildx:

docker build --platform linux/arm64 -t my_robot:latest .

--load exports the built image into the local Docker image store so it can be deployed with docker save.

The build is split into two stages:

  1. builder — installs the Raspbot hardware library, then compiles the ROS package with colcon
  2. runtime — copies only the colcon install overlay and hardware library into a clean ros:kilted base; no build tools are included in the final image

Launching

The container needs access to the I²C bus that the motor controller is wired to. Pass only that device rather than running the container in privileged mode:

docker run --rm \
  --device /dev/i2c-1 \
  my_robot:latest

If your board exposes the motor controller on a different bus (check with ls /dev/i2c-* on the host), substitute the correct device node (e.g. --device /dev/i2c-0).

Overriding parameters at launch

ROS 2 parameters can be passed through --ros-args:

docker run --rm \
  --device /dev/i2c-1 \
  my_robot:latest \
  ros2 run my_robot motor_controller \
    --ros-args -p wheel_base:=0.25 -p max_speed:=0.8

Sending velocity commands from the host

With the container running, publish a cmd_vel message from another terminal (requires ROS 2 installed on the host or a second container on the same network):

# Drive forward at 0.2 m/s
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
  "{linear: {x: 0.2}, angular: {z: 0.0}}"

# Turn on the spot
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
  "{linear: {x: 0.0}, angular: {z: 0.5}}"

# Stop
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
  "{linear: {x: 0.0}, angular: {z: 0.0}}"

Verifying telemetry

ros2 topic echo /current_wheel_speeds

Project layout

.
├── Dockerfile                  # Two-stage production image
├── docker-entrypoint.sh        # Sources ROS overlays before exec
├── package.xml                 # ROS package manifest
├── setup.py                    # ament_python build definition
├── my_robot/
│   ├── __init__.py
│   └── motor_controller_node.py
└── raspbot_v2_interface/       # Vendored Yahboom hardware library
    └── Raspbot_Lib/
        └── Raspbot_Lib.py      # I²C driver (smbus, bus 1, addr 0x2B)