A cross-platform project for building an embedded device that tracks a user's face using servos. Face detection and tracking are performed on a desktop or mobile client, which communicates with the embedded device to control servo movement.
- Overview
- Features
- System Requirements
- Installation & Setup
- Build & Development Workflow
- Dependencies
- Build Scripts
- Make Targets & Build Variables
- Protocol Buffers
- Troubleshooting
- License
- Additional Documentation
This project enables real-time face tracking using a combination of a desktop/mobile client and an embedded ESP32 device. The client application detects and tracks faces using a camera, then sends movement commands to the embedded device, which controls two servos (pan/tilt) to follow the user's face.
- Qt6 GUI for user interface
- OpenCV for face detection and tracking
- Manual servo control via sliders
- Bluetooth/WiFi communication with embedded device (planned)
- Protocol Buffers for message serialization
- Docker support for cross-platform builds
- Android builds (via Qt for Android and CMake presets)
- ESP32 support (ESP-IDF framework)
- Dual servo control (pan/tilt)
- Bluetooth and WiFi connectivity (planned)
- Nanopb for lightweight protobuf
- Configuration persistence via NVS
- Linux (Ubuntu 20.04+, Arch, Fedora)
- macOS (Intel/Apple Silicon)
- Windows 11 (WSL2 or Docker Desktop)
- Client: Intel/AMD x86_64 or ARM64 (Apple Silicon), 4GB+ RAM, USB camera
- Embedded: ESP32 development board, USB serial cable, 2x servo motors, 5V power supply
python scripts/install_deps.pyInstall Docker:
- Ubuntu/Debian:
sudo apt-get install docker.io docker-compose - Arch:
sudo pacman -S docker docker-compose - Fedora:
sudo dnf install docker docker-compose - macOS (Homebrew):
brew install docker docker-compose
Start Docker and add your user to the docker group if needed.
Quick start:
make client-docker-build
make client-docker-run
make client-docker-testgit clone -b v5.5.1 --depth 1 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh
. export.shmake embedded-build
make embedded-flash PORT=/dev/ttyUSB0
make embedded-monitor PORT=/dev/ttyUSB0make client-install-deps
make client-configure BUILD_TYPE=Release
make client-build BUILD_TYPE=Release
make client-test BUILD_TYPE=Release- Edit code in
src/ - Rebuild:
make client-build BUILD_TYPE=Release - Run tests:
make client-test BUILD_TYPE=Release - Format:
make client-format - Lint:
make client-lint BUILD_TYPE=Release
make client-build BUILD_TYPE=Release
make client-test BUILD_TYPE=Releasemake embedded-build
make embedded-flash PORT=/dev/ttyUSB0
make embedded-monitor PORT=/dev/ttyUSB0make client-docker-build
make client-docker-run
make client-docker-test
make client-docker-shell
make client-docker-format
make client-docker-lint
make client-docker-cleanThe Qt client supports Android builds using CMake presets and a helper script.
- Android SDK (
ANDROID_SDK_ROOT) - Android NDK (
ANDROID_NDK_ROOT) - Qt for Android (
QT_ANDROID_DIR) - Qt host tools (
QT_HOST_DIR) - OpenCV Android SDK (
OPENCV_ANDROID_SDK)
make client-android-build-debug # Debug build
make client-android-build-release # Release buildOr directly:
cd client
python3 scripts/android.py --preset android-qt-relwithdebinfo-arm64adb install client/build/debug/android-arm64/android-build/build/outputs/apk/debug/android-build-debug.apk| Dependency | Min Version | Purpose |
|---|---|---|
| CMake | 3.25+ | Build system |
| C++ Compiler | C++23 | GCC 13+, Clang 16+ |
| Boost | 1.82+ | Utilities |
| OpenCV | 4.8+ | Face detection |
| Qt6 | 6.0+ | GUI framework |
| Protobuf | 3.21+ | Message serialization |
| Python 3 | 3.8+ | Build scripts |
- ESP-IDF 4.4+ (tested with 5.x)
- Python 3 (for tools)
- ESP32 development board
Python scripts in client/scripts/ automate configuration, building, testing, and dependency management.
install_deps.py– Install/check dependenciesconfigure.py– Configure CMakebuild.py– Build projectformat.py– Format codelint.py– Run linter
Each script supports --help for usage details.
All Python scripts are interactive by default. When you run them without extra arguments, they will prompt you for missing information, confirm actions, and guide you through the process step by step.
cd client
python3 scripts/install_deps.py- The script will check for missing dependencies and interactively ask if you want to install them.
- If system packages are missing, it will show the required commands and ask for confirmation before proceeding.
cd client
python3 scripts/configure.py- You will be prompted to select build type (Debug/Release), compiler, and other options if not specified via command line.
- The script will display detected options and ask for confirmation before generating build files.
cd client
python3 scripts/build.py- If you haven't configured the project yet, the script will offer to run the configuration step for you.
- You can specify build type or number of jobs interactively, or pass them as arguments.
cd client
python3 scripts/format.py
python3 scripts/lint.py- These scripts will ask for confirmation before making changes (formatting) or let you choose the build type for linting.
All scripts provide detailed help and usage instructions:
python3 scripts/install_deps.py --help
python3 scripts/configure.py --help
python3 scripts/build.py --help
python3 scripts/format.py --help
python3 scripts/lint.py --helpYou can always run a script without arguments to be guided interactively, or provide command-line flags for automation.
make help– Show all targetsmake check– Check prerequisites
make client-install-depsmake client-configuremake client-build BUILD_TYPE=Releasemake client-test BUILD_TYPE=Releasemake client-formatmake client-lint BUILD_TYPE=Releasemake client-clean
make client-docker-buildmake client-docker-runmake client-docker-testmake client-docker-shellmake client-docker-formatmake client-docker-lintmake client-docker-cleanmake client-docker-compose-upmake client-docker-compose-down
make embedded-buildmake embedded-flash PORT=/dev/ttyUSB0make embedded-monitor PORT=/dev/ttyUSB0make embedded-flash-monitor PORT=/dev/ttyUSB0make embedded-cleanmake embedded-menuconfig
BUILD_TYPE=Release|Release|RelWithDebInfoCOMPILER=gcc|clangJOBS=8(parallel build)USE_CONAN=1(use Conan for dependencies)PORT=/dev/ttyUSB0(embedded flash/monitor)
Communication uses Protocol Buffers defined in proto/messages.proto:
- Command: Client to embedded (move, home, calibrate, stop)
- Response: Embedded to client (status, errors)
- Handshake: Connection establishment
. $IDF_PATH/export.sh
idf.py --versionls /dev/tty* | grep -E "(USB|ACM|AMA)"
sudo usermod -aG dialout $USER
# Log out and back insudo systemctl start dockersudo usermod -aG docker $USER
# Log out and back inmake client-docker-rebuildMIT License – see LICENSE file for details.
Run make help for all available commands and further documentation.