An AI-powered autonomous trash-collecting robot with real-time web control, live video streaming, YOLOv10 waste detection, and a combined AI + weight-based scoring system.
- Overview
- Screenshots
- Architecture
- Features
- Hardware
- Software Stack
- AI Model โ YOLOv10 Trash Detection
- Project Structure
- Setup & Installation
- How to Run
- Control Protocol
- Scoring System
- Web Control Interface
- Contributing
GCBOT is a remotely controlled garbage-collecting robot built for competitions and real-world waste management challenges. It combines:
- ๐๏ธ A 4-wheel drive chassis controlled via a motor driver
- ๐ฆพ A servo-powered arm & gripper for picking up trash
- ๐ท A live camera stream from an onboard Raspberry Pi
- ๐ง YOLOv10 AI running real-time trash detection on the laptop
- ๐ Combined AI + Weight scoring โ points are based on both what the AI detected AND how heavy the object is
- โ๏ธ HX711 load cell measures object weight for score multiplier
- ๐ A browser-based control panel accessible from any device on the network
- ๐ Login & player system โ sign in or create an account before controlling the robot
- ๐ฒ QR onboarding page โ scan to join Wi-Fi, scan again to open the game instantly
The entire system communicates over TCP sockets โ the laptop runs the Flask web server, AI inference, and score computation; the Raspberry Pi acts as a bridge between the laptop and the Arduino; and the Arduino directly controls all motors, servos, and the load cell.
Players sign in or create an account before accessing the robot controls. The glassmorphism login card sits on the animated dark background.
Displayed on a screen at the competition venue. Players scan Step 1 to join the Wi-Fi hotspot, then scan Step 2 to instantly open the control page โ no typing required.
The interface is fully responsive. On portrait mobile it prompts rotation; on landscape it shows the full control panel.
| Portrait (Login) | Landscape |
|---|---|
![]() |
![]() |
New players fill in their Full Name, Nickname (shown on leaderboard), choose an avatar, and set a password. The profile is saved and they are logged in immediately.
Shows all players ranked by total score. Each entry displays the player's avatar, nickname, full name, and points earned in the session.
The full-screen landscape control panel with live AI Detection feed, movement D-pad, gripper & arm controls, and the real-time score badge.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GCBOT โ Gamified Cleaning Bot โ
โ โ
โ โโโโโโโโโโโโโโ WiFi/TCP โโโโโโโโโโโโโโโโ Serial/USB โ
โ โ LAPTOP โโโโโโโโโโโโโโโบโ Raspberry Pi โโโโโโโโโโโโโโโโโโโโบ โ
โ โ โ โ โ โ
โ โ Flask App โ โ pi_control โ โโโโโโโโโโโโโโโ โ
โ โ (Port 5001)โ โ (Port 5000) โ โ Arduino โ โ
โ โ โ โ โ โ โ โ
โ โ YOLOv10 โโโโ Video โโโโบโ Camera โ โ Motor Driverโ โ
โ โ Inference โ (Port 9999)โ Stream Tx โ โ Servos (x4) โ โ
โ โ โ โ โ โ Load Cell โ โ
โ โ Web UI โโโโ Cmds โโโโโบโ Serial Relay โ โ HX711 โ โ
โ โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โฒ โ
โ โ HTTP (Browser) โ
โ โโโโโโโดโโโโโโโ โ
โ โ Any Device โ (Phone / Tablet / PC on same network) โ
โ โโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
graph TD
%% Define Node Styles
classDef component fill:#ffffff,stroke:#333333,stroke-width:1px;
subgraph Tier3 ["Tier 3: Host / Fog Layer"]
Browser[("Web Browser (Mobile/PC)\nControl UI & Video")]:::component
Flask["Flask Web Server"]:::component
YOLO["YOLOv10 Inference Engine"]:::component
Browser <==>|HTTP / WebSocket| Flask
Flask <==>|Frames / Classes| YOLO
end
style Tier3 fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;
subgraph Tier2 ["Tier 2: Edge Layer"]
Pi["Raspberry Pi 4"]:::component
Cam[("USB Web Camera")]:::component
Cam -->|Raw Video| Pi
end
style Tier2 fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
subgraph Tier1 ["Tier 1: Hardware Layer"]
Arduino["Arduino Uno"]:::component
L298N["L298N Motor Driver"]:::component
Motors(("4x DC Motors")):::component
Servos(("4x Servo Motors\n(Arm & Gripper)")):::component
HX711["HX711 Amplifier"]:::component
LoadCell[("1Kg Load Cell")]:::component
Arduino -->|PWM Signals| L298N
L298N -->|Power| Motors
Arduino -->|PWM Signals| Servos
HX711 -->|Digital Weight Data| Arduino
LoadCell -->|Analog Signal| HX711
end
style Tier1 fill:#fff3e0,stroke:#e65100,stroke-width:2px;
%% Cross-layer connections
Flask ==>|TCP Control Commands| Pi
Pi ==>|MJPEG Video Stream| Flask
Pi <==>|Serial USB| Arduino
sequenceDiagram
participant Browser as ๐ Browser
participant Laptop as ๐ป Laptop (Flask)
participant Pi as ๐ Raspberry Pi
participant Arduino as โก Arduino
Browser->>Laptop: HTTP POST /cmd {"cmd": "F"}
Laptop->>Pi: TCP "F\n" (Port 5000)
Pi->>Arduino: Serial "F\n"
Arduino-->>Arduino: forward()
Browser->>Laptop: HTTP GET /video_feed
Pi-->>Laptop: TCP Video Frame (Port 9999)
Laptop-->>Laptop: YOLOv10 Inference โ tracks last_detected_class
Laptop-->>Browser: MJPEG Stream
Note over Browser,Arduino: DROP OBJECT Flow (AI + Weight Scoring)
Browser->>Laptop: POST /cmd {"cmd": "WEIGHTNOW"}
Laptop->>Laptop: weighnow_pending = True
Laptop->>Pi: TCP "WEIGHTNOW\n"
Pi->>Arduino: Serial "WEIGHTNOW\n"
Arduino-->>Arduino: HX711 read โ diff = current - lastWeight
Arduino-->>Pi: Serial "W:23.45\n"
Pi-->>Laptop: TCP "W:23.45\n" (broadcast)
Laptop-->>Laptop: compute_combined_score(23.45g)
Note over Laptop: score = round(base ร (1 + 23.45/100))
Laptop-->>Browser: JSON {score: 12, event: {cls: "Bottle", pts: 12, weight: 23.5}}
| Feature | Description |
|---|---|
| ๐ฎ WASD / D-pad Control | Move forward, backward, left, right with keyboard or touch |
| ๐ฆพ Arm Lift Control | Dual servo arm with animated angle ring indicator |
| ๐ค Gripper Control | Dual servo gripper (open/close) with visual feedback |
| ๐๏ธ Drop Object | One-tap: releases gripper โ waits 2s โ weighs โ combines AI class + weight โ scores |
| ๐ท Live Camera Feed | MJPEG stream from Pi camera at ~30 FPS |
| ๐ค AI Detection Feed | YOLOv10 trash overlay feed (host only) with toggle |
| ๐ AI + Weight Scoring | Score = base_pts ร (1 + weight_g / 100) โ heavier + rarer = more points |
| โ๏ธ Load Cell Integration | HX711 reads weight diff on command, laptop combines with AI class |
| ๐ฑ Mobile Responsive | Landscape-optimized with portrait rotation hint |
| โก Low Latency | TCP_NODELAY + no blocking delays = near-zero command lag |
| ๐ Auto-Reconnect | All TCP connections auto-reconnect on drop |
| Component | Quantity | Purpose |
|---|---|---|
| Arduino Uno | 1 | Motor & servo control, load cell reading |
| Raspberry Pi 4 | 1 | Video streaming, TCP bridge to Arduino |
| L298N Motor Driver | 1 | 4WD motor control |
| DC Gear Motors (TT Motor) | 4 | Drive wheels |
| SG90 / MG90S Servo | 4 | 2ร Arm lift + 2ร Gripper |
| HX711 Load Cell Amplifier | 1 | Weight sensing for scoring |
| Load Cell (1kg) | 1 | Detects collected trash weight |
| Pi Camera Module | 1 | Live video stream |
| 3S LiPo / 18650 Pack | 1 | Power supply |
| Robot Chassis (4WD) | 1 | Physical body |
Arduino Uno
โโโ Pin 2 โ L298N IN1 (Left Motor A)
โโโ Pin 3 โ L298N IN2 (Left Motor B)
โโโ Pin 4 โ L298N IN3 (Right Motor A)
โโโ Pin 7 โ L298N IN4 (Right Motor B)
โโโ Pin 8 โ L298N ENA (Left Motor PWM)
โโโ Pin 12 โ L298N ENB (Right Motor PWM)
โโโ Pin 5 โ Gripper Servo A (grabA)
โโโ Pin 6 โ Gripper Servo B (grabB) [mirrored]
โโโ Pin 9 โ Lift Servo A (liftA)
โโโ Pin 10 โ Lift Servo B (liftB) [mirrored]
โโโ Pin A0 โ HX711 SCK
โโโ Pin A1 โ HX711 DT
| Layer | Technology |
|---|---|
| Web Framework | Flask (Python) |
| AI Inference | Ultralytics YOLOv10 (best.pt) |
| Computer Vision | OpenCV (cv2) |
| Video Protocol | MJPEG over HTTP (multipart) |
| Control Protocol | Raw TCP sockets with TCP_NODELAY |
| Serial | PySerial (Pi โ Arduino) |
| Frontend | Vanilla HTML/CSS/JS with glassmorphism UI |
| Fonts | Google Inter |
| Microcontroller | Arduino C++ with Servo.h + HX711.h |
| Pi Script | Python threading + socket server |
The onboard AI model is a custom-trained YOLOv10 fine-tuned on a multi-class garbage detection dataset. It runs locally on the laptop CPU in a dedicated inference thread at 416ร416 resolution.
Aluminium foil ยท Bottle ยท Bottle cap ยท Broken glass ยท Can ยท Carton ยท Cigarette ยท Cup ยท Lid ยท Other litter ยท Other plastic ยท Paper ยท Plastic bag/wrapper ยท Plastic container ยท Pop tab ยท Straw ยท Styrofoam piece ยท Unlabeled litter
| Precision-Recall Curve (Train) | Confusion Matrix (Train) |
![]() |
![]() |
| F1-Confidence Curve | Precision Curve |
![]() |
![]() |
| Precision-Recall Curve (Val) | Confusion Matrix (Val) |
![]() |
![]() |
- โ Frame resized to 416ร416 before inference (3ร speedup vs full-res)
- โ Duplicate frame skipping โ hashes frame identity, skips if unchanged
- โ PyTorch thread capping โ prevents CPU over-subscription
- โ Confidence threshold 0.25 โ filters weak detections
- โ Annotated frame scaled back to original resolution after inference
GCBOT/
โ
โโโ app.py # ๐ป Laptop: Flask server, YOLOv10 inference, AI+weight scoring
โโโ pi_control.py # ๐ Raspberry Pi: TCP server + Serial relay to Arduino
โ
โโโ gcbot_arduino/
โ โโโ gcbot_arduino.ino # โก Arduino: motors, servos, load cell (weight only)
โ
โโโ Trash_detection_Yolov10_StreamLit/
โ โโโ best.pt # ๐ง Trained YOLOv10 model weights
โ โโโ train_graphs/ # ๐ Training performance graphs
โ โ โโโ PR_curve.png
โ โ โโโ F1_curve.png
โ โ โโโ P_curve.png
โ โ โโโ R_curve.png
โ โ โโโ confusion_matrix_normalized.png
โ โโโ val_graphs/ # ๐ Validation performance graphs
โ โ โโโ PR_curve_val.png
โ โ โโโ F1_curve_val.png
โ โ โโโ P_curve_val.png
โ โ โโโ R_curve_val.png
โ โ โโโ confusion_matrix_normalized_val.png
โ โโโ train_yolov10_garbage_detection.ipynb # ๐ Training notebook
โ โโโ requirements.txt
โ
โโโ .gitignore
โโโ Screenshot 2026-03-26 213021.png # ๐ผ๏ธ Desktop UI screenshot
โโโ WhatsApp Image 2026-03-17 *.jpeg # ๐ผ๏ธ Hardware & mobile UI photos
โโโ README.md
- Python 3.10+ on the Laptop
- Python 3.x on the Raspberry Pi
- Arduino IDE for flashing the
.inosketch
# Clone the repository
git clone https://github.com/your-username/gcbot.git
cd gcbot
# Create virtual environment
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Linux/Mac
# Install dependencies
pip install flask ultralytics opencv-python numpy torch# Copy pi_control.py to the Raspberry Pi
scp pi_control.py pi@kavin.local:~/
# SSH into Pi and install dependencies
ssh pi@kavin.local
pip install pyserial- Open
gcbot_arduino/gcbot_arduino.inoin Arduino IDE - Install required libraries:
- Servo (built-in)
- HX711 by bogde
- Flash to your Arduino Uno
โ ๏ธ Calibrate your load cell! Replace2280.0in the sketch with your actual calibration factor. Run a calibration sketch with a known weight to find the correct value.
In app.py, update the Pi's hostname or IP:
PI_IP = "kavin.local" # or use the Pi's IP e.g. "192.168.1.42"
CONTROL_PORT = 5000
VIDEO_PORT = 9999In pi_control.py, update the serial port if needed:
ARDUINO_PORT = "/dev/ttyUSB0" # use /dev/ttyACM0 for some Arduinos
ARDUINO_BAUD = 9600Connect the Arduino to the Raspberry Pi via USB, then flash gcbot_arduino.ino from your development machine.
# On Raspberry Pi
python3 pi_control.pyThe Pi will:
- Open the Arduino serial port
- Start listening for laptop connections on port
5000 - Start a video stream sender on port
9999(handled by the Pi camera script โ ensure your Pi camera streaming script is also running)
# On the Laptop (must be on same WiFi as the Pi)
python app.pyNavigate to:
http://localhost:5001 # on the laptop (AI Detection feed)
http://<laptop-ip>:5001 # on any phone/tablet on the same WiFi
Commands are sent as newline-terminated ASCII strings over TCP:
| Command | Description |
|---|---|
F |
Move forward |
B |
Move backward |
L |
Turn left |
R |
Turn right |
S |
Stop all motors |
U<angle> |
Set arm lift angle (0โ180ยฐ), e.g. U90 |
G<angle> |
Set gripper angle (0โ180ยฐ), e.g. G120 |
WEIGHTNOW |
Trigger a weight check on the load cell |
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Serve the control UI |
/cmd |
POST | Send a command to the robot |
/video_feed |
GET | Raw MJPEG camera stream |
/video_feed_detected |
GET | YOLOv10 annotated MJPEG stream |
/score |
GET | Current score + last scoring event breakdown |
/scorechart |
GET | Full score classification chart as JSON |
Example cURL:
# Send a movement command
curl -X POST http://localhost:5001/cmd \
-H "Content-Type: application/json" \
-d '{"cmd": "F"}'
# Get the score chart
curl http://localhost:5001/scorechartScoring uses a combined AI detection + weight measurement system. The laptop computes the final score using both what the AI sees and how heavy the object is.
final_score = round(base_score ร (1 + weight_g / 100))
base_scoreโ determined by the detected trash class (see chart below)weight_gโ weight difference measured by the HX711 load cell (in grams)- No detection fallback โ if no trash was detected by AI:
base = max(1, weight_g รท 10)
| Object Class | Base Points | @ 50g | @ 100g | @ 200g | Reason |
|---|---|---|---|---|---|
| Broken glass | 15 | 22 | 30 | 45 | Dangerous โ bonus reward |
| Bottle | 10 | 15 | 20 | 30 | Recyclable |
| Can | 10 | 15 | 20 | 30 | Recyclable |
| Plastic bag / wrapper | 10 | 15 | 20 | 30 | High environmental impact |
| Carton | 8 | 12 | 16 | 24 | Recyclable |
| Cup | 8 | 12 | 16 | 24 | Disposable |
| Plastic container | 8 | 12 | 16 | 24 | Recyclable |
| Styrofoam piece | 8 | 12 | 16 | 24 | Hard to recycle |
| Other plastic | 7 | 10 | 14 | 21 | โ |
| Aluminium foil | 5 | 7 | 10 | 15 | Recyclable |
| Paper | 5 | 7 | 10 | 15 | Recyclable |
| Straw | 5 | 7 | 10 | 15 | Environmental hazard |
| Other litter | 5 | 7 | 10 | 15 | โ |
| Cigarette | 3 | 4 | 6 | 9 | Small but toxic |
| Lid | 3 | 4 | 6 | 9 | Small |
| Bottle cap | 3 | 4 | 6 | 9 | Small |
| Pop tab | 3 | 4 | 6 | 9 | Small |
| Unlabeled litter | 2 | 3 | 4 | 6 | Unknown fallback |
| (No detection) | weightรท10 | 5 | 10 | 20 | Weight-only fallback |
1. User presses ๐๏ธ DROP OBJECT button in the browser
2. Gripper opens to 50ยฐ (releases trash)
3. After 2s delay, WEIGHTNOW command sent
4. Arduino reads HX711 load cell (avg 3 readings)
5. Arduino sends weight diff: "W:23.45\n"
6. Pi broadcasts W:23.45 to all connected laptops
7. Laptop's app.py combines:
โข last_detected_class (from YOLO inference) โ base = 10 (Bottle)
โข weight_g = 23.45g โ multiplier = 1.23
โข final_score = round(10 ร 1.23) = 12 pts
8. Browser shows: "+12 Bottle (23.5g)" and updates the score badge
๐ก Tip: The weight multiplier means heavier objects of the same class score higher. A full 200g bottle scores 30 pts vs. a small 50g bottle at 15 pts.
โ๏ธ No detection fallback: If the AI didn't detect the object before drop, scoring falls back to weight-only: 1 point per 10 grams.
The control UI is a single-page, glassmorphism-styled dashboard embedded in Flask (app.py). No external CSS framework is used.
- ๐ฎ D-pad for movement (touch + WASD keyboard)
- ๐ต SVG ring indicator for real-time arm/gripper angle display
- ๐ข Score badge (top-right, always visible) with scale-bounce animation on score update
- ๐ก Feed toggle โ switch between
RawandAI Detectionvideo feed - ๐ข Status dot with pulse animation indicating live connection
- โป Portrait warning โ prompts rotation on mobile portrait mode
- โ Crosshair overlay on the video feed for targeting
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is open source and available under the MIT License.
MIT License
Copyright (c) 2026 Kavin and Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Built with โค๏ธ for making the world cleaner, one piece of trash at a time ๐โป๏ธ
GCBOT โ Gamified Cleaning Bot












