Complete step-by-step guide to building an autonomous robot for Spatial-RAG.
- Shopping List
- Tools Required
- Assembly Steps
- Wiring Guide
- Safety Hardware Installation
- Software Setup
- Testing & Calibration
| # | Component | Quantity | Unit Price (PKR) | Total (PKR) | Where to Buy |
|---|---|---|---|---|---|
| COMPUTE | |||||
| 1 | Raspberry Pi 4 (4GB) | 1 | Rs 18,000 | Rs 18,000 | Daraz, OLX, Hall Road |
| 2 | 32GB MicroSD Card (Class 10) | 1 | Rs 800 | Rs 800 | Any electronics shop |
| 3 | Pi 4 Heatsink + Fan | 1 | Rs 500 | Rs 500 | Hall Road |
| CAMERA | |||||
| 4 | USB Webcam (720p/1080p) | 1 | Rs 2,500 | Rs 2,500 | Hall Road, Hafeez Centre |
| 5 | Camera Mount (3D printed or bracket) | 1 | Rs 300 | Rs 300 | Hall Road |
| MOTORS & DRIVE | |||||
| 6 | L298N Motor Driver Module | 1 | Rs 600 | Rs 600 | Hall Road |
| 7 | DC Geared Motors (12V, 200 RPM) | 4 | Rs 400 | Rs 1,600 | Hall Road |
| 8 | Motor Mounting Brackets | 4 | Rs 50 | Rs 200 | Hall Road |
| 9 | Wheels (65mm diameter) | 4 | Rs 150 | Rs 600 | Hall Road |
| CHASSIS | |||||
| 10 | 4WD Robot Chassis Kit | 1 | Rs 3,000 | Rs 3,000 | Hall Road, Daraz |
| 11 | M3 Standoffs/Spacers Kit | 1 | Rs 300 | Rs 300 | Hall Road |
| POWER | |||||
| 12 | LiPo Battery 3S 11.1V 2200mAh | 1 | Rs 3,500 | Rs 3,500 | Hafeez Centre |
| 13 | LiPo Balance Charger | 1 | Rs 1,500 | Rs 1,500 | Hafeez Centre |
| 14 | Step-Down Converter (12V→5V 3A) | 1 | Rs 300 | Rs 300 | Hall Road |
| 15 | XT60 Connectors (pair) | 2 | Rs 100 | Rs 200 | Hall Road |
| SAFETY HARDWARE | |||||
| 16 | 🔴 Emergency Stop Button (Big Red, NC) | 1 | Rs 150 | Rs 150 | Hall Road |
| 17 | MPU6050 IMU Module | 1 | Rs 400 | Rs 400 | Hall Road |
| 18 | HC-SR04 Ultrasonic Sensor | 3 | Rs 250 | Rs 750 | Hall Road |
| 19 | Micro Switch (Bumper) | 2 | Rs 50 | Rs 100 | Hall Road |
| 20 | Buzzer (5V Active) | 1 | Rs 50 | Rs 50 | Hall Road |
| 21 | LED (Red, Green, Blue) | 3 | Rs 10 | Rs 30 | Hall Road |
| WIRING & CONNECTORS | |||||
| 22 | Jumper Wires (M-M, M-F, F-F) 40pc each | 3 | Rs 150 | Rs 450 | Hall Road |
| 23 | 22 AWG Wire (Red, Black, 5m each) | 2 | Rs 100 | Rs 200 | Hall Road |
| 24 | Heat Shrink Tubing Kit | 1 | Rs 200 | Rs 200 | Hall Road |
| 25 | PCB Prototype Board (7x9cm) | 2 | Rs 100 | Rs 200 | Hall Road |
| 26 | Terminal Block (2-pin) | 5 | Rs 30 | Rs 150 | Hall Road |
| 27 | Zip Ties (100 pack) | 1 | Rs 150 | Rs 150 | Any hardware store |
| MISC | |||||
| 28 | Double-Sided Tape (strong) | 1 | Rs 200 | Rs 200 | Any hardware store |
| 29 | Velcro Strips | 1 | Rs 150 | Rs 150 | Any hardware store |
| 30 | Electrical Tape | 2 | Rs 50 | Rs 100 | Any hardware store |
| TOTAL | Rs 36,880 |
| Component | Price (PKR) | Benefit |
|---|---|---|
| Wheel Encoders (x4) | Rs 2,000 | Accurate odometry |
| WiFi Antenna (external) | Rs 500 | Better range |
| GPS Module (NEO-6M) | Rs 2,000 | Outdoor navigation |
| Voltage Monitor | Rs 300 | Battery level display |
| FPV Camera | Rs 2,500 | Remote viewing |
| Tool | Purpose | Approximate Price |
|---|---|---|
| Soldering Iron (30-40W) | Connections | Rs 500-1,000 |
| Solder Wire | Joining wires | Rs 100 |
| Wire Stripper | Preparing wires | Rs 200 |
| Screwdriver Set (Phillips + Flat) | Assembly | Rs 300 |
| Multimeter | Testing | Rs 500-1,000 |
| Hot Glue Gun | Mounting | Rs 300 |
| Hex Key Set (Allen) | M3 bolts | Rs 200 |
| Needle-Nose Pliers | Wire work | Rs 200 |
| Scissors | Cutting | Already have |
┌─────────────────────────────────────────────────────────────────────────┐
│ CHASSIS ASSEMBLY │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ FRONT │
│ ┌─────────────────────────────────────────────┐ │
│ │ ●────────────────────────────────────● │ │
│ │ │ │ │ │
│ │ │ [Motor 1] [Motor 2] │ │ │
│ │ │ ○ ○ │ │ │
│ │ │ │ │ │
│ │ │ ┌──────────────┐ │ │ │
│ │ │ │ CHASSIS │ │ │ │
│ │ │ │ PLATE │ │ │ │
│ │ │ └──────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ [Motor 3] [Motor 4] │ │ │
│ │ │ ○ ○ │ │ │
│ │ │ │ │ │
│ │ ●────────────────────────────────────● │ │
│ └─────────────────────────────────────────────┘ │
│ REAR │
│ │
│ Assembly Order: │
│ 1. Attach motor brackets to chassis │
│ 2. Mount motors to brackets │
│ 3. Attach wheels to motor shafts │
│ 4. Test wheel rotation (should spin freely) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Instructions:
- Lay out the chassis plate on a flat surface
- Attach motor mounting brackets using M3 bolts
- Insert motors into brackets, secure with screws
- Push wheels onto motor shafts (may need to press firmly)
- Verify all wheels spin freely
┌─────────────────────────────────────────────────────────────────────────┐
│ ELECTRONICS MOUNTING │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ TOP VIEW (Upper Deck) │
│ ┌─────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Raspberry Pi │ │ L298N │ │ │
│ │ │ 4 │ │ Driver │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Battery │ │ Power │ │ │
│ │ │ (Velcro) │ │ Converter │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ Use M3 standoffs (25-30mm) to create upper deck │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Instructions:
- Install 4x M3 standoffs (25-30mm) on chassis corners
- Attach upper platform plate
- Mount Raspberry Pi using standoffs (to allow airflow)
- Mount L298N driver near edge (for motor wire access)
- Attach battery area with velcro (for easy removal)
┌─────────────────────────────────────────────────────────────────────────┐
│ CAMERA MOUNTING │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ SIDE VIEW │
│ │
│ ┌─────┐ │
│ │ 📷 │ ← Camera (angled 15-30° down) │
│ │ │ │
│ ┌────┴─────┴────┐ │
│ │ BRACKET │ │
│ └───────┬───────┘ │
│ │ │
│ ════════╪════════ ← Upper deck │
│ │ │
│ │
│ Camera Height: 15-20cm from ground │
│ Angle: 15-30° downward tilt │
│ Field of View: Should see ~1m ahead │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Instructions:
- Mount camera bracket at front of robot
- Attach USB camera to bracket
- Angle camera 15-30° downward
- Connect USB cable to Raspberry Pi
- Secure cable with zip ties (leave slack for movement)
┌─────────────────────────────────────────────────────────────────────────┐
│ POWER WIRING │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ │
│ │ LiPo Battery │ │
│ │ 3S 11.1V │ │
│ └───────┬────────┘ │
│ │ │
│ │ XT60 Connector │
│ │ │
│ ┌───────▼────────┐ │
│ │ 🔴 E-STOP │ ← CRITICAL: Wire E-Stop in series! │
│ │ (Normally │ │
│ │ Closed) │ │
│ └───────┬────────┘ │
│ │ │
│ ┌─────┴─────┐ │
│ │ │ │
│ ┌──▼──┐ ┌───▼───┐ │
│ │L298N│ │Step │ │
│ │12V │ │Down │ │
│ │IN │ │12V→5V │ │
│ └──┬──┘ └───┬───┘ │
│ │ │ │
│ ▼ ▼ │
│ Motors Pi + Sensors │
│ │
│ Wire Colors: │
│ • RED = Positive (+) │
│ • BLACK = Ground (-) │
│ • Always double-check polarity! │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ MOTOR WIRING │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ L298N Module │
│ ┌──────────────────┐ │
│ │ +12V GND +5V │ │
│ │ │ │ │ │ │
│ │ ▲ ▲ ▲ │ ← Power inputs │
│ │ │ │
│ Motor 1 ←──────│OUT1 OUT2│──────→ Motor 2 │
│ (Front Left) │ │ (Front Right) │
│ │ ENA IN1 IN2 │ │
│ │ IN3 IN4 ENB │ │
│ │ │ │
│ Motor 3 ←──────│OUT3 OUT4│──────→ Motor 4 │
│ (Rear Left) │ │ (Rear Right) │
│ └──────────────────┘ │
│ │
│ Raspberry Pi GPIO Connections: │
│ ┌────────────────────────────────────────┐ │
│ │ L298N Pin │ GPIO Pin │ Physical │ │
│ ├────────────┼────────────┼─────────────┤ │
│ │ ENA (PWM) │ GPIO 12 │ Pin 32 │ │
│ │ IN1 │ GPIO 5 │ Pin 29 │ │
│ │ IN2 │ GPIO 6 │ Pin 31 │ │
│ │ IN3 │ GPIO 13 │ Pin 33 │ │
│ │ IN4 │ GPIO 19 │ Pin 35 │ │
│ │ ENB (PWM) │ GPIO 18 │ Pin 12 │ │
│ │ GND │ GND │ Pin 6 │ │
│ └────────────┴────────────┴─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ SENSOR WIRING │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ULTRASONIC SENSORS (HC-SR04) │
│ ───────────────────────────── │
│ │
│ Front Sensor: Left Sensor: Right Sensor: │
│ • VCC → 5V • VCC → 5V • VCC → 5V │
│ • GND → GND • GND → GND • GND → GND │
│ • TRIG → GPIO 23 • TRIG → GPIO 24 • TRIG → GPIO 25 │
│ • ECHO → GPIO 22 • ECHO → GPIO 27 • ECHO → GPIO 17 │
│ │
│ ⚠️ ECHO pins need 5V→3.3V voltage divider: │
│ │
│ ECHO ──┬── 1kΩ ──┬── GPIO │
│ │ │ │
│ └── 2kΩ ──┴── GND │
│ │
│ IMU (MPU6050) │
│ ───────────── │
│ • VCC → 3.3V │
│ • GND → GND │
│ • SDA → GPIO 2 (Pin 3) │
│ • SCL → GPIO 3 (Pin 5) │
│ │
│ BUMPER SWITCHES │
│ ─────────────── │
│ • Front Bumper: One pin → GPIO 16, other → GND │
│ • Rear Bumper: One pin → GPIO 20, other → GND │
│ • Use internal pull-up (configured in software) │
│ │
│ BUZZER & LEDs │
│ ───────────── │
│ • Buzzer: + → GPIO 21, - → GND (through 100Ω resistor) │
│ • Red LED: + → GPIO 26 (through 220Ω), - → GND │
│ • Green LED: + → GPIO 19 (through 220Ω), - → GND │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ RASPBERRY PI 4 GPIO MAP │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 3.3V (1) (2) 5V │ Function Assignment: │
│ SDA (3) (4) 5V │ ───────────────────── │
│ SCL (5) (6) GND │ │
│ GPIO4 (7) (8) TXD │ GPIO 2 - IMU SDA │
│ GND (9) (10) RXD │ GPIO 3 - IMU SCL │
│ GPIO17(11)(12) GPIO18 │ GPIO 5 - Motor IN1 │
│ GPIO27(13)(14) GND │ GPIO 6 - Motor IN2 │
│ GPIO22(15)(16) GPIO23 │ GPIO 12 - Motor ENA (PWM) │
│ 3.3V (17)(18) GPIO24 │ GPIO 13 - Motor IN3 │
│ MOSI (19)(20) GND │ GPIO 18 - Motor ENB (PWM) │
│ MISO (21)(22) GPIO25 │ GPIO 19 - Motor IN4 / Green LED │
│ SCLK (23)(24) CE0 │ GPIO 16 - Front Bumper │
│ GND (25)(26) CE1 │ GPIO 17 - Ultrasonic Right Echo │
│ ID_SD (27)(28) ID_SC │ GPIO 20 - Rear Bumper │
│ GPIO5 (29)(30) GND │ GPIO 21 - Buzzer │
│ GPIO6 (31)(32) GPIO12 │ GPIO 22 - Ultrasonic Front Echo │
│ GPIO13(33)(34) GND │ GPIO 23 - Ultrasonic Front Trig │
│ GPIO19(35)(36) GPIO16 │ GPIO 24 - Ultrasonic Left Trig │
│ GPIO26(37)(38) GPIO20 │ GPIO 25 - Ultrasonic Right Trig │
│ GND (39)(40) GPIO21 │ GPIO 26 - Red LED │
│ │ GPIO 27 - Ultrasonic Left Echo │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ EMERGENCY STOP WIRING │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ⚠️ THE E-STOP MUST BE WIRED IN SERIES WITH POWER! │
│ ⚠️ DO NOT USE SOFTWARE-CONTROLLED RELAY FOR E-STOP! │
│ │
│ BATTERY (+) ─────┐ │
│ │ │
│ ┌─────┴─────┐ │
│ │ E-STOP │ │
│ │ 🔴 │ ← Big red button, easily accessible │
│ │ (N.C.) │ Mount on top of robot │
│ └─────┬─────┘ │
│ │ │
│ ├────────────→ L298N 12V IN │
│ │ │
│ └────────────→ Step-Down IN │
│ │
│ When E-STOP is pressed: │
│ • Circuit breaks (Normally Closed opens) │
│ • ALL power is cut instantly │
│ • Motors stop immediately │
│ • Pi shuts down (battery backup recommended for clean shutdown) │
│ │
│ TESTING: │
│ 1. Power on robot │
│ 2. Verify motors respond │
│ 3. Press E-STOP │
│ 4. Verify ALL power cuts immediately │
│ 5. Release/twist E-STOP to reset │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ SENSOR PLACEMENT DIAGRAM │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ FRONT │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ │ │ │ │
│ │ [US-L] [US-F] [US-R] │ ← Ultrasonic sensors │
│ │ ↙ ↓ ↘ │ 15cm from ground │
│ │ │ │
│ ┌─────┤ [BUMP-F] 📷 ├─────┐ │
│ │ │ │ │ │ │
│ │ ○ │ │ ┌──────┐ │ ○ │ ← Wheels │
│ │ │ │ │ 🔴 │ │ │ │
│ │ │ │ │E-STOP│ │ │ │
│ │ │ │ └──────┘ │ │ │
│ │ ○ │ │ ○ │ │
│ │ │ │ │ │
│ └─────┤ [BUMP-R] ├─────┘ │
│ │ │ │ │
│ │ │ │ │
│ └─────────────┼─────────────────┘ │
│ │ │
│ REAR │
│ │
│ Sensor Angles: │
│ • US-F: 0° (straight ahead) │
│ • US-L: -45° (left diagonal) │
│ • US-R: +45° (right diagonal) │
│ │
│ Bumper Triggers: │
│ • BUMP-F: Triggers when front contacts obstacle │
│ • BUMP-R: Triggers when rear contacts obstacle │
│ │
└─────────────────────────────────────────────────────────────────────────┘
# Download Raspberry Pi Imager and flash:
# - Raspberry Pi OS (64-bit) Lite
# - Enable SSH in imager settings
# - Set username/password
# - Configure WiFi
# After first boot, update:
sudo apt update && sudo apt upgrade -y
# Install required packages
sudo apt install -y \
python3-pip \
python3-venv \
git \
i2c-tools \
pigpio \
python3-pigpio# Enable I2C and SPI
sudo raspi-config
# → Interface Options → I2C → Enable
# → Interface Options → SPI → Enable
# Verify I2C
sudo i2cdetect -y 1
# Should show MPU6050 at address 0x68# Create virtual environment
python3 -m venv ~/robot_venv
source ~/robot_venv/bin/activate
# Install packages
pip install \
RPi.GPIO \
smbus2 \
mpu6050-raspberrypi \
numpy \
requests \
opencv-python-headlesscd ~
git clone <repo-url> Spatial-RAG-Worldmodel
cd Spatial-RAG-Worldmodel
pip install -r requirements.txt# Test motors
python3 ros2_ws/src/spatial_rag_ros/spatial_rag_ros/motor_controller.py
# Test sensors
python3 -c "
import smbus2
bus = smbus2.SMBus(1)
# Read MPU6050 WHO_AM_I register
who = bus.read_byte_data(0x68, 0x75)
print(f'MPU6050 WHO_AM_I: {hex(who)} (should be 0x68)')
"┌─────────────────────────────────────────────────────────────────────────┐
│ PRE-FLIGHT CHECKLIST │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ POWER │
│ □ Battery fully charged (check voltage: should be ~12.6V for 3S) │
│ □ All connections secure │
│ □ No exposed wires │
│ │
│ SAFETY │
│ □ E-STOP tested and working │
│ □ E-STOP easily accessible │
│ □ Bumpers trigger correctly │
│ □ Clear testing area (no obstacles, no pets, no children) │
│ │
│ MOTORS │
│ □ Wheels spin freely │
│ □ Forward command = robot moves forward │
│ □ Left turn command = robot turns left │
│ □ Speed proportional to command │
│ │
│ SENSORS │
│ □ Camera image visible │
│ □ IMU readings stable │
│ □ Ultrasonic distances reasonable │
│ │
│ SOFTWARE │
│ □ API server accessible │
│ □ Latent encoding working │
│ □ ROS2 topics publishing │
│ │
└─────────────────────────────────────────────────────────────────────────┘
#!/usr/bin/env python3
"""motor_test.py - Test and calibrate motors"""
import RPi.GPIO as GPIO
import time
# GPIO pins
ENA, IN1, IN2 = 12, 5, 6 # Left motors
ENB, IN3, IN4 = 18, 13, 19 # Right motors
GPIO.setmode(GPIO.BCM)
for pin in [ENA, IN1, IN2, ENB, IN3, IN4]:
GPIO.setup(pin, GPIO.OUT)
# PWM
pwm_a = GPIO.PWM(ENA, 1000)
pwm_b = GPIO.PWM(ENB, 1000)
pwm_a.start(0)
pwm_b.start(0)
def forward(speed=50):
GPIO.output(IN1, GPIO.HIGH)
GPIO.output(IN2, GPIO.LOW)
GPIO.output(IN3, GPIO.HIGH)
GPIO.output(IN4, GPIO.LOW)
pwm_a.ChangeDutyCycle(speed)
pwm_b.ChangeDutyCycle(speed)
def stop():
pwm_a.ChangeDutyCycle(0)
pwm_b.ChangeDutyCycle(0)
try:
print("Testing forward for 2 seconds...")
forward(30) # Start slow!
time.sleep(2)
stop()
print("Done!")
finally:
GPIO.cleanup()#!/usr/bin/env python3
"""sensor_test.py - Test all sensors"""
import RPi.GPIO as GPIO
import time
# Ultrasonic pins
SENSORS = {
"front": {"trig": 23, "echo": 22},
"left": {"trig": 24, "echo": 27},
"right": {"trig": 25, "echo": 17},
}
GPIO.setmode(GPIO.BCM)
def read_distance(trig, echo):
GPIO.setup(trig, GPIO.OUT)
GPIO.setup(echo, GPIO.IN)
GPIO.output(trig, GPIO.LOW)
time.sleep(0.002)
GPIO.output(trig, GPIO.HIGH)
time.sleep(0.00001)
GPIO.output(trig, GPIO.LOW)
pulse_start = time.time()
timeout = pulse_start + 0.1
while GPIO.input(echo) == 0 and time.time() < timeout:
pulse_start = time.time()
pulse_end = time.time()
while GPIO.input(echo) == 1 and time.time() < timeout:
pulse_end = time.time()
distance = (pulse_end - pulse_start) * 17150
return round(distance, 2)
try:
while True:
for name, pins in SENSORS.items():
dist = read_distance(pins["trig"], pins["echo"])
print(f"{name}: {dist} cm", end=" ")
print()
time.sleep(0.5)
except KeyboardInterrupt:
print("\nDone!")
finally:
GPIO.cleanup()After completing the build:
-
Test webcam streaming
python scripts/webcam_bridge.py --mode api --camera 0 --display
-
Start autonomous mode (reactive)
ros2 run spatial_rag_ros policy_node --ros-args -p mode:=reactive
-
Collect training data
# Teleoperate while recording ros2 bag record /latent /latent_next /actions -o training_data -
Train policy network
python scripts/train_policy.py --mode imitation --data training_data/
-
Deploy trained policy
ros2 run spatial_rag_ros policy_node --ros-args -p mode:=learned -p model_path:=checkpoints/policy.pt
| Problem | Likely Cause | Solution |
|---|---|---|
| Motors don't spin | Wrong GPIO pins | Check wiring, verify with multimeter |
| Motors spin wrong direction | Motor wires swapped | Swap OUT1/OUT2 or OUT3/OUT4 |
| Robot pulls to one side | Motor speed mismatch | Calibrate PWM values |
| Ultrasonic reads 0 | Voltage divider missing | Add 1kΩ/2kΩ divider on ECHO |
| IMU not detected | I2C not enabled | Run raspi-config, enable I2C |
| E-Stop doesn't work | Wired as N.O. instead of N.C. | Rewire as Normally Closed |
| Pi won't boot | Insufficient power | Use quality 5V 3A supply |
Happy Building! 🤖