A modern robot control system for ESP32-based soccer robots with multiple interface options: a sleek Electron-based React UI, JavaFX GUI, and a lightweight 3D simulator.
This project provides a complete robot control solution with:
- Native Desktop App - Modern React UI powered by Electron + Java backend
- JavaFX GUI - Classic desktop interface (legacy)
- 3D Simulator - Lightweight robot simulator with controller support
- Headless API Mode - REST API + WebSocket server for custom frontends
- Java: JDK 17 or later
- Maven: 3.8+ for building
- Controllers: USB game controllers (Xbox, PlayStation, etc.) via JInput
- Node.js: 18+ and npm
- OS: Windows 10/11, macOS 10.14+, or Linux
- Hardware: ESP32-WROOM development boards
- Network: WiFi connection to same network as host (default: "WATCHTOWER")
- Communication: UDP ports 12345 (discovery) and 12346+ (commands)
- Firmware: Arduino IDE with ESP32 board support
1. Install Arduino IDE and ESP32 Support
# In Arduino IDE:
# - File โ Preferences โ Additional Board URLs
# - Add: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
# - Tools โ Board โ Boards Manager โ Search "ESP32" โ Install
2. Configure Robot Firmware
// In esp32_robot_firmware/minibots.ino
Minibot bot("YOUR_ROBOT_NAME_HERE"); // Change to unique name
3. Upload to ESP32
- Open
esp32_robot_firmware/minibots.ino
in Arduino IDE - Select Board: "ESP32 Dev Module"
- Select Port: Your ESP32's COM port
- Click Upload
4. Power On Robot
- Robot connects to WiFi network "WATCHTOWER" (password: "lancerrobotics")
- Sends discovery pings every 2 seconds
- Driver station automatically assigns unique port
- Robot is ready when driver station shows "connected"
Robot LED Indicators (via Serial Monitor):
- "Connecting to WiFi..." - Attempting WiFi connection
- "Connected! IP: X.X.X.X" - WiFi connected successfully
- "Sent discovery ping" - Broadcasting presence to driver station
- "Assigned port XXXX - connected!" - Port received from driver station
- "EMERGENCY STOP ACTIVATED" - All motors stopped
- "Emergency stop released" - Ready for movement commands
Important: Each robot must have a unique name in the firmware!
The modern Electron + React interface with real-time updates.
# 1. Install all dependencies
npm run install:all
# 2. Build Java backend
npm run build:backend
# 3. Build frontend
npm run build:frontend
# 4. Run the app
npm start
Development Mode (3 terminals for hot reload):
# Terminal 1: Java backend with API
npm run dev:backend
# Terminal 2: React frontend (Vite dev server)
npm run dev:frontend
# Terminal 3: Electron window
npm run dev:electron
Build Distributable:
npm run dist
# Creates installers in electron/dist/
Traditional desktop interface using Java Swing/JavaFX.
# Build and run
mvn clean compile
mvn javafx:run
Lightweight robot simulator for testing without hardware.
# Compile
mvn clean compile assembly:single
# Run simulator
java -cp target/robotics-control-system-1.0.0-jar-with-dependencies.jar \
com.soccerbots.control.simulator.SimulatorApp
Run backend with HTTP REST API + WebSocket for custom frontends.
# Build backend
mvn clean compile assembly:single
# Run headless (API on port 8080)
java -cp target/robotics-control-system-1.0.0-jar-with-dependencies.jar \
com.soccerbots.control.HeadlessLauncher
- Robot Connection Panel - Manage multiple robots, view status and signal strength
- Network Analysis - Real-time latency and bandwidth charts
- Control Panel - Emergency stop, system controls
- Terminal Monitor - Live command output and system logs
- Service Log - Event tracking with timestamps and severity levels
- REST API - Full robot/controller/network management
- WebSocket - Real-time updates and event streaming
- Auto-Discovery - Finds robots on network via UDP broadcast
- Controller Support - Automatic USB controller detection via JInput
- Live robot status updates
- Network performance monitoring
- Instant emergency stop
- Controller input visualization
- System event logging
SoccerBotsSoftwareJava/
โโโ src/main/java/com/soccerbots/control/
โ โโโ api/ # HTTP REST API & WebSocket
โ โ โโโ ApiServer.java # Javalin server with endpoints
โ โโโ controller/ # Game controller input
โ โ โโโ ControllerManager.java # USB controller handling
โ โ โโโ GameController.java # Controller abstraction
โ โ โโโ ControllerInput.java # Input normalization
โ โโโ network/ # WiFi and UDP networking
โ โ โโโ NetworkManager.java # WiFi hosting, UDP comm
โ โโโ robot/ # Robot management
โ โ โโโ RobotManager.java # Discovery, pairing, commands
โ โ โโโ Robot.java # Robot data model
โ โ โโโ RobotCommand.java # JSON command structure
โ โโโ gui/ # JavaFX GUI (legacy)
โ โ โโโ MainWindow.java # Main window
โ โ โโโ RobotPanel.java # Robot management
โ โ โโโ ControllerPanel.java # Controller pairing
โ โ โโโ NetworkPanel.java # Network status
โ โโโ simulator/ # 3D Robot Simulator
โ โ โโโ SimulatorApp.java # Main simulator window
โ โ โโโ SimulatorRenderer.java # 3D rendering
โ โ โโโ SimulatorWorld.java # Physics world
โ โ โโโ SimulatedRobot.java # Robot physics
โ โโโ HeadlessLauncher.java # API mode entry point
โ โโโ Launcher.java # JavaFX GUI launcher
โ โโโ RoboticsControlApp.java # Swing GUI launcher
โโโ frontend/ # React + TypeScript UI
โ โโโ src/
โ โ โโโ components/ # React components
โ โ โ โโโ ConnectionPanel.tsx # Robot connections
โ โ โ โโโ NetworkAnalysis.tsx # Charts
โ โ โ โโโ ControlPanel.tsx # Emergency stop
โ โ โ โโโ ServiceLog.tsx # Event log
โ โ โ โโโ TerminalMonitor.tsx # Terminal output
โ โ โโโ services/
โ โ โ โโโ api.ts # Backend API client
โ โ โโโ App.tsx # Main app component
โ โ โโโ main.tsx # Entry point
โ โโโ package.json
โ โโโ vite.config.ts
โโโ electron/ # Electron wrapper
โ โโโ main.js # Main process (launches Java)
โ โโโ preload.js # Context bridge
โ โโโ package.json
โโโ esp32_robot_firmware/ # ESP32 Arduino firmware
โโโ package.json # Root build scripts
โโโ pom.xml # Maven configuration
โโโ README.md # This file
โโโ ELECTRON_APP_README.md # Detailed Electron app guide
Method | Endpoint | Description |
---|---|---|
GET | /api/health |
Health check |
GET | /api/robots |
List all robots |
GET | /api/robots/{id} |
Get robot details |
POST | /api/robots/{id}/connect |
Connect to robot |
POST | /api/robots/{id}/disconnect |
Disconnect robot |
POST | /api/robots/{id}/enable |
Enable robot |
POST | /api/robots/{id}/disable |
Disable robot |
POST | /api/robots/refresh |
Scan for robots |
GET | /api/controllers |
List controllers |
POST | /api/emergency-stop |
Activate emergency stop |
POST | /api/emergency-stop/deactivate |
Deactivate emergency stop |
GET | /api/network/stats |
Network statistics |
Real-time events:
robot_connected
- Robot connectedrobot_disconnected
- Robot disconnectedemergency_stop
- Emergency stop state changedrobot_enabled
/robot_disabled
- Robot state changed
New Dynamic Port Assignment System:
- Robot Startup: ESP32 powers on and connects to WiFi
- Discovery Ping: Robot broadcasts
DISCOVER:<name>:<IP>
every 2 seconds - Port Assignment: Driver station responds with
PORT:<name>:<port>
(12346+) - Connected: Robot switches to assigned port for commands
- Timeout: After 5 seconds without commands, robot reverts to discovery mode
Benefits:
- No manual IP configuration required
- Automatic reconnection after power cycle
- Minimal ESP32 code (~150 lines)
- Each robot gets unique port per session
Binary Movement Commands (24 bytes):
Bytes 0-15: Robot name (null-padded)
Bytes 16-19: Axes (leftX, leftY, rightX, rightY) [0-255]
Bytes 20-21: Unused
Bytes 22: Buttons (cross, circle, square, triangle)
Bytes 23: Unused
Text Commands:
<name>:teleop
- Enable movement<name>:standby
- Disable movementESTOP
- Emergency stop (stops all motors)ESTOP_OFF
- Release emergency stop
- Sent to all robots on discovery port (always monitored)
- Persists until
ESTOP_OFF
received or robot power cycled - Blocks all movement commands while active
- Works even when robot is disconnected
- Left Stick: Forward/sideways movement
- Right Stick X: Rotation
- Values: Normalized -1.0 to 1.0 (converted to 0-255 for ESP32)
See ROBOT_PROTOCOL.md for complete protocol specification.
npm start
- No manual scanning needed! Robots automatically appear when powered on
- Driver station listens for discovery pings (passive mode)
- Each robot gets assigned a unique port automatically
- Watch the Robot Connections panel for discovered robots
- Discovered robots show in the left panel with status "discovered"
- Click Connect to start sending commands
- Status changes to "connected" with green indicator
- Robot receives commands on its assigned port
- Plug in USB game controller
- Controllers appear automatically in the interface
- Pair controller to robot in Controller panel
- Input is sent to paired robots in real-time
- Red Emergency Stop button in Control Panel
- Sends ESTOP command to all robots immediately
- All motors halt, movement blocked
- Click again to send ESTOP_OFF and resume operations
- Note: Emergency stop persists across disconnects and requires explicit release
- Network Analysis: View latency and bandwidth charts
- Terminal Monitor: See real-time system commands and discovery events
- Service Log: Track all events including discovery pings, port assignments, and emergency stops
- If robot loses connection (timeout), it reverts to discovery mode
- Driver station automatically reassigns the same port
- No manual intervention required
- Power cycling robot clears emergency stop state
# Install frontend & electron dependencies
npm run install:all
# Build Java backend
mvn clean compile assembly:single
Electron App (Hot Reload):
# Terminal 1: Backend API
npm run dev:backend
# Terminal 2: Frontend (Vite)
npm run dev:frontend
# Terminal 3: Electron
npm run dev:electron
JavaFX GUI:
mvn javafx:run
3D Simulator:
mvn exec:java -Dexec.mainClass="com.soccerbots.control.simulator.SimulatorApp"
Electron App:
npm run dist
# Output: electron/dist/ (platform-specific installers)
Standalone JAR:
mvn clean compile assembly:single
# Output: target/robotics-control-system-1.0.0-jar-with-dependencies.jar
Backend won't start:
- Ensure Java 17+ installed:
java -version
- Check port 8080 is available
- View logs in Electron DevTools console
Frontend won't load:
- Check
frontend/dist/
exists after build - In dev mode, verify Vite server on port 5173
- Open DevTools to see errors (Ctrl+Shift+I)
WebSocket connection failed:
- Backend must start before frontend
- Check backend console for "API server running"
- Verify
frontend/src/services/api.ts
API URL
- Install JInput native libraries (automatic with Maven)
- Windows: Ensure DirectInput drivers installed
- Try refreshing controller list in app
- Check USB connection and permissions
Check ESP32:
- Open Arduino Serial Monitor (115200 baud)
- Look for "Connected! IP: X.X.X.X" - confirms WiFi connection
- Look for "Sent discovery ping" - confirms broadcasting
- Verify robot name matches what you expect
Check Driver Station:
- Ensure listening on port 12345 (check logs for "Discovery service started")
- Check firewall allows UDP port 12345 (incoming)
- Verify both robot and host are on same subnet (e.g., 192.168.1.x)
- Look in Terminal Monitor for discovery ping messages
Common Issues:
- WiFi credentials incorrect in firmware (WIFI_SSID/WIFI_PASSWORD)
- Firewall blocking UDP port 12345
- Robot and driver station on different networks
- Multiple driver stations responding (port conflict)
Check Connection:
- Robot must show "connected" status (green indicator)
- Check Serial Monitor for "Assigned port XXXX - connected!"
- Verify no emergency stop active (shows in UI and Serial Monitor)
Check Game State:
- Robot only moves in "teleop" mode
- Driver station must send game state command
- Check Terminal Monitor for game state messages
Emergency Stop Active:
- Look for "EMERGENCY STOP ACTIVATED" in Serial Monitor
- Red indicator in Control Panel
- Click emergency stop button to release
- Or power cycle robot to clear
Timeout Issues:
- Robot expects commands every 5 seconds
- Check network latency and packet loss
- Verify driver station is sending keepalive messages
- Look for "Connection timeout" in Serial Monitor
WiFi Issues:
- Weak signal strength
- Network congestion
- Router interference
- Try moving robot closer to access point
- Click emergency stop button in Control Panel (shows ESTOP_OFF in logs)
- Verify command sent to robot IP (check Terminal Monitor)
- Robot Serial Monitor should show "Emergency stop released"
- If stuck: Power cycle robot (clears emergency stop state)
Maven errors:
# Clean and rebuild
mvn clean
mvn compile
npm errors:
# Clear cache and reinstall
cd frontend && rm -rf node_modules package-lock.json && npm install
cd ../electron && rm -rf node_modules package-lock.json && npm install
- ROBOT_PROTOCOL.md - Complete protocol specification with discovery, port assignment, and emergency stop
- ELECTRON_APP_README.md - Detailed Electron app guide
- INSTALLATION_GUIDE.md - Setup instructions
- USER_MANUAL.md - Complete operational guide
- PROJECT_STRUCTURE.md - File-by-file explanations
This project is licensed under the MIT License - see the LICENSE file for details.
- Figma Community - RobotControlDesktopApp design template
- React & Electron - Modern desktop framework
- JavaFX & Swing - Classic Java UI frameworks
- JInput Library - Game controller support
- Jackson & Javalin - JSON processing and web framework
- ESP32 Community - Excellent hardware documentation
Task | Command |
---|---|
Run native app | npm start |
Run JavaFX GUI | mvn javafx:run |
Run simulator | java -cp target/*-jar-with-dependencies.jar com.soccerbots.control.simulator.SimulatorApp |
Build everything | npm run build:all |
Flash ESP32 firmware | Open esp32_robot_firmware/minibots.ino in Arduino IDE โ Upload |
Check robot status | Arduino Serial Monitor @ 115200 baud |
Discovery port | UDP 12345 (firewall must allow) |
Command ports | UDP 12346+ (auto-assigned per robot) |
Emergency stop | Click E-Stop button in Control Panel or send ESTOP via UDP |
Port | Purpose | Direction |
---|---|---|
12345 | Robot discovery pings | ESP32 โ Driver Station (broadcast) |
12345 | Port assignment | Driver Station โ ESP32 (unicast) |
12345 | Emergency stop | Driver Station โ ESP32 (unicast) |
12346+ | Movement commands | Driver Station โ ESP32 (assigned per robot) |
12346+ | Game state | Driver Station โ ESP32 (assigned per robot) |
8080 | REST API | Frontend โ Backend (localhost) |
8080 | WebSocket | Frontend โ Backend (localhost) |
Choose your interface: Modern React UI, Classic JavaFX, or Lightweight Simulator โจ Protocol: Automatic discovery with dynamic port assignment - zero configuration! ๐ค