Xora WiFi Motion Tracking
A camera-free human motion tracking system that uses WiFi Channel State Information (CSI) to detect and locate movement within a room - visualized through a live 2D heatmap and 3D room reconstruction.
Live walkthrough of the dashboard tracking movement across my room.
What it is
Every WiFi packet that travels through a room arrives slightly altered by what it passed through - human bodies, being mostly water, disrupt the signal far more than walls or furniture. Xora exploits this: one ESP32 transmits constantly while three others, placed in the room's corners, measure how the incoming signal's amplitude shifts. Those shifts get triangulated into an estimated position and pushed live to a dashboard.
Four ESP32 boards form a sensing layer, while Python and TensorFlow handle signal processing and position regression - no cameras, no privacy tradeoffs.
Signal → position
One ESP32 (TX) blasts WiFi packets continuously, flooding the room with a steady signal carrier.
Three ESP32 receivers in the room corners read CSI amplitude per packet using esp_wifi_set_csi_rx_cb.
Raw CSI data is pushed over UDP to a Flask backend running on the same local WiFi network.
A 30-second empty-room calibration is subtracted live - walls and furniture become invisible to the system.
A CNN+LSTM model regresses x,y position from the remaining signal variance across subcarriers.
Live 2D heatmap + interactive 3D room reconstruction, pushed to the dashboard over WebSocket.
Me moving around the room while the dashboard plots my position as an x, y point on a grid.
Still prototyping — more updates coming.
I'm actively building and iterating on Xora in my free time. Getting WiFi CSI sensing reliable across different rooms, calibrations, and edge cases is slow, experimental work. I'll keep updating this page as I make progress — expect experiments, dead ends, and the occasional breakthrough.
What it can do
Challenges & learnings
The data collection script originally opened its own UDP socket on the same port the main server was already listening on, causing collection to hang silently with no error.
The first trained model only classified motion as present/absent - it never learned where in the room someone was. Position tracking needed a fundamentally different approach.
Real CSI readings don't arrive with a perfectly consistent subcarrier count packet to packet, which broke numpy's array stacking with shape mismatches.
The laptop's local IP changed after a WiFi reconnect, silently breaking all UDP delivery from the boards with no obvious error - just nothing arriving.
Where it fits
Know when someone enters a room without putting cameras or microphones inside it.
Detect unusual stillness or sudden floor-level position without wearables or cameras in the bathroom.
Pick up motion through walls in spaces where camera coverage is impractical or unwanted.
Tech stack
Backend in Flask + Flask-SocketIO for real-time push updates. TensorFlow/Keras handles the CNN+LSTM training pipeline. The frontend is a single-page dashboard built with vanilla JS and Canvas - no framework - rendering both the 2D heatmap and a hand-rolled 3D projection engine for the room view.