Files
ros-raspbot-v2/robot/README.md
T
m5p3nc3r ef78f19e72 Add image and streaming from USB camera
Plus a little freshen up of the readme's
2026-05-07 16:38:36 +00:00

9.6 KiB
Raw Blame History

Robot Controller

ROS 2 nodes for the Yahboom Raspbot V2 — differential-drive motor control, pan/tilt camera orientation, and ultrasonic range sensing.

All three nodes share the same I²C bus. The Linux kernel serialises individual transactions, so they run as separate processes without additional locking.


Motor controller

                      ┌───────────────────────────────────┐
                      │      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

Sending velocity commands

# Drive forward at 0.2 m/s
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
  "{linear: {x: 0.02}, 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}}"

Camera orientation controller

                         ┌──────────────────────────────────────┐
                         │      CameraOrientationNode           │
                         │                                      │
 /joint_command  ────────>│  JointState (names: pan, tilt)      │
 (sensor_msgs/           │  position in radians                 │
  JointState)            │                                      │
                         │  pan  → servo 1  (0°–180°)          │
                         │  tilt → servo 2  (0°–110°)          │
                         │                                      │
                         │         ▼                            │
                         │   raspbot_v2_interface               │
                         │   I²C bus 1, addr 0x2B               │
                         │         ▼                            │
                         │   /dev/i2c-1 ──────> Pan/tilt servos │
                         │                                      │
 /joint_states   <────────│  current angles @ 10 Hz             │
 (sensor_msgs/           │  position in radians                 │
  JointState)            │                                      │
                         └──────────────────────────────────────┘

Topics

Topic Direction Type Description
/joint_command Subscribed sensor_msgs/JointState Commanded pan/tilt angles. Joint names "pan" and "tilt", positions in radians. Unknown joint names are ignored.
/joint_states Published sensor_msgs/JointState Current angles reflected from the last command, published at 10 Hz

Parameters

Parameter Default Description
pan_servo_id 1 Raspbot servo channel for pan
tilt_servo_id 2 Raspbot servo channel for tilt
pan_min_deg 0.0 Pan lower limit (degrees)
pan_max_deg 180.0 Pan upper limit (degrees)
tilt_min_deg 0.0 Tilt lower limit (degrees)
tilt_max_deg 110.0 Tilt upper limit (degrees) — hardware cap
pan_center_deg 90.0 Startup and shutdown park position for pan
tilt_center_deg 60.0 Startup and shutdown park position for tilt
state_rate_hz 10.0 ~/joint_states publish rate

Hardware interface

The node drives the pan and tilt servos over I²C bus 1 (device address 0x2B). The same /dev/i2c-1 device used by the motor controller is sufficient — no additional device node is required.

Commanding the camera

Pan to centre (90°) and tilt to 30°:

ros2 topic pub --once /joint_command sensor_msgs/msg/JointState \
  "{name: ['pan', 'tilt'], position: [1.5708, 0.5236]}"

A single axis can be commanded by omitting the other joint name:

# Pan only
ros2 topic pub --once /joint_command sensor_msgs/msg/JointState \
  "{name: ['pan'], position: [0.0]}"

Ultrasonic range sensor

                        ┌──────────────────────────────────────┐
                        │          UltrasonicNode              │
                        │                                      │
                        │  Sensor off when no subscribers      │
                        │  Sensor on  when subscribers > 0     │
                        │  1 s warm-up after power-on          │
                        │                                      │
                        │         ▼                            │
                        │   raspbot_v2_interface               │
                        │   I²C bus 1, addr 0x2B               │
                        │         ▼                            │
                        │   /dev/i2c-1 ──────> HC-SR04 sensor  │
                        │                                      │
 /ultrasonic/range <────│  Range @ configurable rate           │
 (sensor_msgs/Range)    │  radiation_type = ULTRASOUND         │
                        │  range in metres (REP-117)           │
                        └──────────────────────────────────────┘

Topics

Topic Direction Type Description
/ultrasonic/range Published sensor_msgs/Range Distance in metres. +inf when beyond max range, -inf when closer than min range (REP-117). Only published while subscribers are connected.

Parameters

Parameter Default Description
publish_rate_hz 10.0 Sensor poll and publish rate
frame_id 'ultrasonic' header.frame_id on published messages
min_range_m 0.02 Minimum valid range in metres
max_range_m 4.0 Maximum valid range in metres
field_of_view 0.2618 Sensor cone width in radians (~15°)
warmup_s 1.0 Seconds to wait after powering the sensor on before publishing

Verifying range readings

ros2 topic echo /ultrasonic/range

The sensor activates automatically when a subscriber connects and deactivates when it disconnects.


Launch arguments

Launch arguments can be appended when running the container manually:

docker run --rm \
  --network=host \
  --device /dev/i2c-1 \
  --env ROS_DOMAIN_ID=0 \
  raspbot_v2:latest \
  ros2 launch raspbot_v2 robot.launch.py \
    wheel_base:=0.25 max_speed:=0.8 tilt_center_deg:=45.0
Argument Default Description
wheel_base 0.3 Distance between left and right wheels (m)
max_speed 1.0 Maximum motor speed in library units
pan_center_deg 90.0 Pan angle at startup and shutdown (degrees)
tilt_center_deg 60.0 Tilt angle at startup and shutdown (degrees)
ultrasonic_rate_hz 10.0 Ultrasonic sensor publish rate (Hz)

Project layout

robot/
├── Dockerfile                    # Two-stage build: colcon compile → clean runtime image
├── src/
│   └── raspbot_v2/
│       ├── package.xml
│       ├── setup.py
│       ├── launch/
│       │   └── robot.launch.py   # Starts all three nodes together
│       └── raspbot_v2/
│           ├── motor_controller_node.py
│           ├── camera_orientation_node.py
│           └── ultrasonic_node.py
└── raspbot_v2_interface/         # Vendored Yahboom hardware library
    └── Raspbot_Lib/
        └── Raspbot_Lib.py        # I²C driver (smbus, bus 1, addr 0x2B)