A lightweight, universal tele-robotics kit that turns almost any powered wheelchair into a remotely driven robot using commodity parts, an Android phone and/or a Raspberry Pi, and a camera—all accessed through a secure web interface.
About 1 in 100 people are using a wheelchair. If you include scooters, it’s about 1 in 50. There’s a saying in accessibility, you’re either disabled or not yet disabled. Half of us will spend time in a wheelchair. Everyone in a wheelchair wishes they had an electric wheelchair, but only about 1 in 50 wheelchairs are electric.
Imagine not being able to move and use your arms at the same time. Imagine falling down and not being able to get up if you go off a slight ledge. Wheelchairs need to be smart. 800 million people would live better lives.
My dad‘s been disabled for almost 15 years. I want his wheelchair to go to him when he falls. I want him to be able to travel without thinking. I want everyone with a disability to not have a compromised quality of life.
Extended Docs:
Wheelchair-Bot is designed as a modular, service-based system that requires minimal hardware and avoids heavy frameworks like ROS. It provides a complete solution for remote wheelchair control with real-time video streaming, responsive controls, and comprehensive safety features.
- Universal Compatibility: Works with most powered wheelchairs using commodity hardware
- Lightweight Stack: No ROS dependency - uses FastAPI, WebSockets, and WebRTC
- Multiple Platform Support: Run on Raspberry Pi, Android devices, or standard computers
- Real-Time Video/Audio: WebRTC-based streaming with low latency
- Secure Web Access: Control from any modern web browser
- Safety-First Design: Built-in E-stop, deadman switch, and speed limiting
- Network Resilient: Supports both LTE and Wi-Fi connectivity
- Modular Architecture: Easy to customize and extend
The system consists of five core services that work together. For a detailed architecture overview, see docs/architecture.md.
-
teleopd - Teleoperations daemon (Python FastAPI)
- WebSocket server for real-time control commands
- REST API for configuration and status
- Handles motor control interface
- Service endpoint:
http://localhost:8000
-
webrtc - Video and audio streaming
- WebRTC peer connection management
- Real-time video from camera to web client
- Bidirectional audio support
- Low-latency streaming
-
streamer - Camera capture service
- Uses libcamera (Raspberry Pi) or GStreamer (general)
- Configurable resolution and framerate
- H.264 encoding for efficient streaming
- Supports USB and CSI cameras
-
safety-agent - Safety monitoring service
- Emergency stop (E-stop) monitoring
- Deadman switch enforcement
- Speed and acceleration limiting
- Watchdog for all critical services
-
net-agent - Network management service
- LTE and Wi-Fi connectivity management
- Dynamic DNS for remote access
- VPN/secure tunnel setup
- Connection quality monitoring
- Web Client - Browser-based control interface
- Virtual joystick for precise control
- Real-time video display
- Status monitoring
- Works on desktop and mobile
- No app installation required
-
Computing Platform (choose one or more):
- Raspberry Pi 4 (2GB+ RAM recommended)
- Raspberry Pi 3B+
- Android phone/tablet (for camera and compute)
- Any Linux-capable computer
-
Camera:
- Raspberry Pi Camera Module v2/v3 (CSI interface)
- USB webcam (UVC compatible)
- Android device camera
-
Wheelchair Interface:
- Motor driver board (L298N, L293D, or similar)
- OR direct interface to wheelchair's control system
- Power supply appropriate for your motors
-
Network (choose one):
- Wi-Fi dongle or built-in Wi-Fi
- 4G/LTE USB modem or built-in cellular
- Ethernet connection
- GPS module for location tracking
- IMU for motion sensing
- Motor encoders for odometry
- Battery monitoring system
- External speakers for audio feedback
For detailed wheelchair model compatibility and controller interface information, see docs/wheelchair-support.md.
For the fastest setup, see QUICKSTART.md. For a comprehensive getting started guide, see docs/getting-started.md.
The easiest way to get started with development is using Docker:
# Clone the repository
git clone https://github.com/mrhegemon/Wheelchair-Bot.git
cd Wheelchair-Bot
# Build and run tests
make docker-build
make docker-test
# Start interactive development container
make docker-dev
make docker-shell
# Inside the container, run the application in mock mode
python main.py --mock --verboseSee docs/docker.md for complete Docker documentation.
git clone https://github.com/mrhegemon/Wheelchair-Bot.git
cd Wheelchair-BotOn Raspberry Pi:
# Install system packages
sudo apt-get update
sudo apt-get install -y python3-pip libcamera-apps gstreamer1.0-tools
# Install Python dependencies
pip3 install -r requirements.txtOn other Linux systems:
# Install GStreamer
sudo apt-get install -y gstreamer1.0-tools gstreamer1.0-plugins-good
# Install Python dependencies
pip3 install -r requirements.txtFor development:
# Install with development tools
pip3 install -e ".[dev]"Edit configuration files in the config/ directory:
teleopd.json- Teleoperations service settingssafety.json- Safety parameters and limitsnetwork.json- Network and security settingscamera.json- Camera and streaming configuration
Default GPIO pin assignments (BCM mode):
| Function | GPIO Pin |
|---|---|
| Left Motor Forward | 17 |
| Left Motor Backward | 18 |
| Left Motor Enable (PWM) | 12 |
| Right Motor Forward | 22 |
| Right Motor Backward | 23 |
| Right Motor Enable (PWM) | 13 |
| E-Stop Input | 27 |
Customize pin assignments in config/default_config.json.
For detailed usage instructions and control methods, see docs/usage.md.
# Start all services using the main launcher
python3 main.pyThis starts:
- teleopd (control server)
- webrtc (video/audio streaming)
- streamer (camera capture)
- safety-agent (safety monitoring)
- net-agent (network management)
# Terminal 1: Start teleopd
python3 -m wheelchair_bot.services.teleopd
# Terminal 2: Start video streamer
python3 -m wheelchair_bot.services.streamer
# Terminal 3: Start safety agent
python3 -m wheelchair_bot.services.safety_agent
# Terminal 4: Start network agent (if needed)
python3 -m wheelchair_bot.services.net_agent# Run with mock GPIO and camera
python3 main.py --mockOnce the services are running:
- Open a web browser on any device
- Navigate to:
http://<raspberry-pi-ip>:8080orhttp://localhost:8080(local) - The control interface will load automatically
- Click "Connect" to establish WebRTC connection
- Use the virtual joystick or keyboard to control the wheelchair
When using the web interface:
- W or ↑ - Move Forward
- S or ↓ - Move Backward
- A or ← - Turn Left
- D or → - Turn Right
- Space or Esc - Stop (E-Stop)
- +/- - Adjust Speed
python3 main.py [OPTIONS]
Options:
--mock Use mock GPIO and camera (for testing)
--config FILE Configuration file (default: config/default_config.json)
--max-speed SPEED Maximum speed percentage (0-100, default: 80)
--port PORT Web server port (default: 8080)
--camera DEVICE Camera device (default: auto-detect)
--no-video Disable video streaming
--verbose, -v Enable verbose logging
--help, -h Show help messageWheelchair-Bot/
├── wheelchair_bot/ # Main package
│ ├── services/ # Service implementations
│ │ ├── teleopd.py # Teleoperations daemon
│ │ ├── streamer.py # Camera streaming service
│ │ ├── safety_agent.py # Safety monitoring
│ │ └── net_agent.py # Network management
│ ├── controllers/ # Input controllers
│ │ ├── joystick.py # Virtual joystick
│ │ └── gamepad.py # Physical gamepad
│ ├── motors/ # Motor control
│ │ ├── differential.py # Differential drive
│ │ └── base.py # Motor interface
│ ├── safety/ # Safety features
│ │ ├── deadman.py # Deadman switch
│ │ └── limiter.py # Speed/acceleration limits
│ └── wheelchairs/ # Wheelchair models
│ └── models.py # Wheelchair configurations
├── packages/
│ ├── backend/ # FastAPI backend (teleopd) - see packages/backend/README.md
│ ├── frontend/ # React web UI (optional) - see packages/frontend/README.md
│ └── shared/ # Shared utilities - see packages/shared/README.md
├── config/ # Configuration files
│ ├── default_config.json # Main configuration
│ ├── teleopd.json # Teleopd settings
│ ├── safety.json # Safety parameters
│ └── network.json # Network settings
├── web/ # Web client (HTML/JS/CSS)
│ ├── index.html # Main UI
│ ├── webrtc.js # WebRTC handling
│ ├── controller.js # Control logic
│ └── styles.css # Styling
├── docs/ # Documentation
│ ├── api.md # API reference
│ ├── architecture.md # System architecture
│ ├── docker.md # Docker setup guide
│ ├── emulator.md # Testing framework
│ ├── getting-started.md # Setup guide
│ ├── usage.md # Usage instructions
│ └── wheelchair-support.md # Hardware compatibility
├── tests/ # Test suite - see tests/README.md
├── main.py # Main entry point
├── requirements.txt # Python dependencies
├── QUICKSTART.md # Quick start guide
├── CONTRIBUTING.md # Contribution guidelines
└── README.md # This file
For more details on specific packages:
- Backend package: packages/backend/README.md
- Frontend package: packages/frontend/README.md
- Shared utilities: packages/shared/README.md
- Test suite: tests/README.md
Each service can be configured via JSON files in the config/ directory:
{
"host": "0.0.0.0",
"port": 8000,
"websocket_port": 8080,
"max_clients": 5,
"command_timeout": 1.0
}{
"max_speed": 0.8,
"max_angular_speed": 0.8,
"deadman_timeout": 0.5,
"estop_enabled": true,
"speed_limit_enabled": true
}{
"device": "/dev/video0",
"width": 1280,
"height": 720,
"framerate": 30,
"codec": "h264",
"backend": "libcamera"
}{
"interfaces": ["wlan0", "eth0", "usb0"],
"ddns_enabled": true,
"ddns_hostname": "mychair.local",
"vpn_enabled": false
}Edit config/default_config.json to customize:
- GPIO pin assignments
- Motor parameters
- Safety thresholds
- PWM frequencies
The system includes multiple layers of safety:
- E-Stop Button: Physical emergency stop (GPIO input)
- Deadman Switch: Requires continuous operator input
- Watchdog Timer: Automatic shutdown if service fails
- Speed Limiting: Configurable maximum speeds
- Acceleration Limiting: Prevents sudden movements
- Command Timeout: Stops if no commands received
- Input Validation: All commands validated before execution
- Secure WebSocket: WSS encryption for commands
- Authentication: Optional password/token protection
- Rate Limiting: Prevents command flooding
- Connection Monitoring: Detects and handles disconnections
# Activate emergency stop from command line
python3 -m wheelchair_bot.safety.estop --trigger
# Reset after E-stop
python3 -m wheelchair_bot.safety.estop --resetRun the complete test suite:
# All tests
python3 -m pytest tests/ -v
# Unit tests only
python3 -m unittest discover -s tests -v
# Integration tests
python3 -m pytest tests/test_integration.py -v
# With coverage
python3 -m pytest --cov=wheelchair_bot tests/Test without hardware:
# Mock GPIO, camera, and network
python3 main.py --mock --verbose
# Mock specific components
python3 main.py --mock-gpio --mock-camera
# Run individual service in mock mode
python3 -m wheelchair_bot.services.teleopd --mockFor the complete emulator testing framework, see docs/emulator.md.
The project includes a Three.js based 3D simulator for visualizing the wheelchair emulator in real-time:
# Start the emulator with 3D visualization
PYTHONPATH=src python3 examples/simulator_demo.pyThis opens a browser with a 3D view showing the wheelchair's position, orientation, and movement. See docs/simulator.md for complete details.
# Format code
black wheelchair_bot/ tests/
# Lint code
ruff check wheelchair_bot/ tests/
# Type checking
mypy wheelchair_bot/# Generate API documentation
python3 -m pdoc wheelchair_bot --output-dir docs/api
# Build documentation site (if using mkdocs)
mkdocs buildThe modular design makes it easy to extend:
- New Control Interface: Add to
wheelchair_bot/controllers/ - New Motor Type: Implement in
wheelchair_bot/motors/ - New Safety Feature: Add to
wheelchair_bot/safety/ - New Service: Create in
wheelchair_bot/services/
See CONTRIBUTING.md for detailed guidelines.
Create a systemd service for automatic startup:
# Create service file
sudo nano /etc/systemd/system/wheelchair-bot.serviceService file content:
[Unit]
Description=Wheelchair Bot Tele-Robotics System
After=network.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/Wheelchair-Bot
ExecStart=/usr/bin/python3 /home/pi/Wheelchair-Bot/main.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl enable wheelchair-bot
sudo systemctl start wheelchair-bot
sudo systemctl status wheelchair-botAccess via local IP: http://192.168.1.X:8080
Configure in config/network.json for external access:
{
"ddns_enabled": true,
"ddns_provider": "duckdns",
"ddns_hostname": "mychair.duckdns.org",
"ddns_token": "your-token-here"
}For secure remote access without port forwarding:
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# Access via Tailscale networkUse Termux on Android as the computing platform:
# Install Termux from F-Droid
# Inside Termux:
pkg install python clang libusb
pip install -r requirements.txt
python main.py --platform androidFor the Android remote control application, see:
- android-controller/README.md - Full documentation
- android-controller/QUICKSTART.md - Quick start guide
- android-controller/IMPLEMENTATION.md - Implementation details
- Change default passwords in configuration files
- Enable HTTPS for production use
- Use strong authentication tokens
- Enable firewall rules:
sudo ufw allow 8080/tcp # Web interface sudo ufw allow 8000/tcp # API sudo ufw enable
- Regular updates: Keep system and dependencies updated
- Monitor logs: Check
/var/log/wheelchair-bot/regularly
Cannot connect to web interface
- Verify services are running:
systemctl status wheelchair-bot - Check firewall settings:
sudo ufw status - Confirm correct IP address and port
- Test local access first:
http://localhost:8080
WebRTC not connecting
- Check STUN/TURN server configuration
- Verify network allows UDP traffic
- Test with browser console open (F12) for errors
- Ensure camera permissions are granted
GPIO Permission Errors
# Add user to gpio group
sudo usermod -a -G gpio $USER
# Or run with sudo
sudo python3 main.pyMotors not responding
- Check GPIO connections and wiring
- Verify power supply to motors (separate from Pi)
- Test with multimeter for voltage
- Run diagnostic:
python3 -m wheelchair_bot.diagnostics.motors - Check verbose logs:
python3 main.py --verbose
Camera not detected
# List camera devices
v4l2-ctl --list-devices
# Test camera
libcamera-hello # Raspberry Pi
gst-launch-1.0 v4l2src ! autovideosink # USB camera
# Check permissions
sudo usermod -a -G video $USERService won't start
# Check logs
journalctl -u wheelchair-bot -n 50
# Run manually to see errors
python3 main.py --verbose
# Verify dependencies
pip3 install -r requirements.txt --upgradeHigh latency / lag
- Reduce video resolution in
config/camera.json - Use wired Ethernet instead of Wi-Fi
- Close bandwidth-heavy applications
- Check CPU usage:
htop
- Check the documentation
- Review existing issues
- Run diagnostics:
python3 -m wheelchair_bot.diagnostics - Enable debug logging:
--verboseflag - Open a new issue with:
- System information (
uname -a,python3 --version) - Error logs
- Configuration (redact sensitive info)
- Steps to reproduce
- System information (
// config/camera.json - Low latency preset
{
"width": 640,
"height": 480,
"framerate": 24,
"codec": "h264",
"bitrate": 500000
}# Use hardware encoding (Raspberry Pi)
echo "h264_v4l2m2m" | sudo tee -a /etc/modules
# Limit background processes
sudo systemctl disable bluetooth
sudo systemctl disable cups# Increase network buffer sizes
sudo sysctl -w net.core.rmem_max=26214400
sudo sysctl -w net.core.wmem_max=26214400Connect to ws://hostname:8080/ws
Send movement command:
{
"type": "movement",
"direction": "forward",
"speed": 50,
"timestamp": 1699999999999
}Direction values: forward, backward, left, right, stop
Send configuration:
{
"type": "config",
"max_speed": 0.8,
"acceleration_limit": 1.0
}Get system status:
GET http://hostname:8000/api/statusResponse:
{
"battery_level": 85,
"is_moving": false,
"speed": 0,
"direction": null,
"services": {
"teleopd": "running",
"streamer": "running",
"safety_agent": "running"
}
}Get configuration:
GET http://hostname:8000/api/configUpdate configuration:
POST http://hostname:8000/api/config
Content-Type: application/json
{
"max_speed": 0.8,
"turn_speed": 0.6
}Emergency stop:
POST http://hostname:8000/api/emergency-stopSee docs/api.md for complete API documentation.
We welcome contributions! See CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make changes and test thoroughly
- Run tests:
python3 -m pytest tests/ -v - Format code:
black wheelchair_bot/ - Commit changes:
git commit -am "Add feature" - Push to branch:
git push origin feature/my-feature - Create Pull Request
- Follow PEP 8 style guide
- Add docstrings to all functions/classes
- Include type hints
- Write tests for new features
- Update documentation
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with FastAPI, WebRTC, and modern web technologies
- Inspired by the need for accessible, affordable robotic assistance
- Community contributions and feedback
- Documentation: docs/
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Multi-wheelchair support (fleet management)
- Advanced autonomous features (obstacle avoidance)
- Voice control integration
- Mobile app (iOS/Android native)
- ROS2 bridge (optional)
- Multi-camera support
- Sensor fusion (LIDAR, ultrasonic)
- Cloud telemetry and analytics
Safety Notice: This system is designed for assistive robotics and should be used responsibly. Always ensure proper safety measures, including physical E-stop, are in place. Never rely solely on software safety features. Test thoroughly in safe environments before real-world use.
