Skip to content

Repository files navigation

🦇 REBOUND — Biomimetic Sonar Navigation

One link, one place: a logo hub linking to the pitch, the full story, and the interactive Qwen Memory Agent demo.

REBOUND logo

Built for someone who can't see the wall in front of them, but deserves to know it's there.

Biomimetic sonar for indoor navigation, designed for visually impaired users. Inspired by bat CF-FM echolocation. Built for the Global AI Hackathon Series with Qwen CloudTrack: MemoryAgent, persistent adaptive memory across multi-turn, cross-session interactions.


Why this exists

There are millions of people who navigate the world without sight. A white cane tells you what's at arm's length. A guide dog tells you what's ahead — if you're lucky enough to have one, afford one, and live somewhere that trains them. Almost nobody has real-time knowledge of open space, walls, doorways, corners, and corridors before they get there.

Bats solved this problem 50 million years ago. They emit a chirp, listen to the echo, and build a picture of the world from sound alone — in real time, while flying, in total darkness. REBOUND borrows that idea and puts it in a phone: emit a chirp, capture the echo, run it through signal processing and a neural classifier, and tell the person what's around them — out loud, in their language, before they touch it with a cane.

This is not a finished product. It's a hackathon build, made in days, not years. But the idea underneath it — that echolocation plus an adaptive memory agent could give a blind person a few extra seconds of certainty in an unfamiliar space — is real, and worth building further.


See it live

rebound-olga.vercel.app — the deployed story page, end to end: from the human problem, to bat-inspired echolocation, to the Qwen Memory Agent that remembers each user.

Interactive demo → /demo — the ML part, live: run a session and watch the Memory Agent learn. The Bayesian priors adapt, episodic memory fills and decays, and semantic patterns ("hesitates in doorways", "confident in open space") consolidate on screen — the real deterministic memory, in the browser, no backend needed.

▶ Watch the walkthrough video — the Memory Agent learning, end to end.

Memory Agent after a session: adaptive Bayesian priors, episodic and semantic counts, and consolidated behavioural patterns

The Memory Agent after a live session: Bayesian priors adapted per space class, 26 episodes stored, and 6 behavioural patterns consolidated — open space and corridors learned as confident, doorways and corners as hesitant. Real deterministic memory, computed in the browser.

Hero — Hear what lies ahead The human problem
Sonar classification, not a guess Qwen Memory Agent live profile
The five-block narrative Inspiration — bats navigate with sound
Qwen + Alibaba Cloud Finale — This is REBOUND

What it actually does

  1. Emits a CF-FM chirp (8 kHz constant tone + downward sweep) through the phone's speaker.
  2. Captures the returning echo through the microphone, in a latency-aware window that survives Android's variable output delay.
  3. Deconvolves the echo into a Room Impulse Response (adaptive Wiener filter).
  4. Extracts acoustic features — mel spectrogram (64×32), MFCCs (13×32), RT60, spectral centroid.
  5. Classifies the space with a lightweight PyTorch CNN: open space, nearby wall, doorway, corner, corridor, or stairs.
  6. Runs an independent two-pass staircase detector as DSP reinforcement — stairs are a different kind of danger than a wall, and don't get to rely on the CNN alone.
  7. A Qwen-powered Memory Agent takes that classification, remembers what it has learned about this user across sessions, and generates a spoken navigation instruction personalized to how this person hesitates, advances, and reacts.
  8. Adaptive Bayesian priors mean the system gets quieter about things the user has already proven they handle well, and more careful about the things that have tripped them up before.
  9. Feedback reaches the user through four independent channels — earcons (rhythm and melodic contour, not just pitch), synthesized speech, vibration, and ARIA live regions for VoiceOver/TalkBack — because a navigation aid that only works when the screen is visible has already failed its user.

Architecture

REBOUND system architecture

REBOUND system architecture (dark)

  Mobile (PWA)                        Alibaba Cloud ECS
 ┌──────────────┐                   ┌──────────────────────────────────┐
 │ Web Audio API │── audio buffer ──▶│ POST /predict                    │
 │ getUserMedia  │  (f32) + sr       │   ├─ Wiener deconvolution (RIR) │
 │ speaker emit  │                   │   ├─ Feature extraction          │
 │               │                   │   ├─ CNN classifier (6 classes)  │
 │ DeviceOrienta │── gyro pitch ────▶│   ├─ Stair detector (DSP)       │
 │ tionEvent     │                   │   └─ predict() result            │
 │               │◀── JSON ─────────│                                  │
 │ earcons ·     │   instruction     │ POST /process                    │
 │ speech ·      │   distance_m      │   ├─ Qwen-Plus Memory Agent     │
 │ haptics ·     │   class_name      │   ├─ Episodic/Semantic memory   │
 │ ARIA live     │   stair_message   │   └─ User profile update        │
 └──────────────┘                   └──────────────────────────────────┘
                                              │
                                     DashScope API (Qwen-Plus)

One scan end to end:

Signal pipeline


The Alibaba Cloud part — and why it mattered more than we expected

REBOUND started deployed in Singapore. It worked. It also had almost a full second of round-trip latency for every scan — noticeable, and for a navigation tool where "noticeable" can mean "walked into it before the warning arrived," that latency wasn't a footnote. It was the whole problem.

We didn't guess at the cause. We measured it: a plain curl to /health — an endpoint that does nothing but return a JSON blob, no model, no Qwen call — was already taking over a second round-trip. That ruled out the LLM as the bottleneck and pointed straight at geography. So we did the unglamorous thing: stood up a second ECS instance from scratch in US-Virginia, migrated the whole stack — Docker image, model checkpoint, Qwen credentials, Caddy reverse proxy with a real Let's Encrypt certificate via DuckDNS — and pointed the domain at it.

The latency dropped hard. Not because the code got smarter, but because we stopped assuming "cloud" means "close enough," and went and checked.

Along the way we also found and fixed a second, subtler problem: /predict — the single most CPU-expensive endpoint in the system — was running its signal-processing pipeline synchronously inside the async event loop. Two people scanning at once weren't just competing for CPU; they were fully blocking each other. We moved the pipeline to a thread pool behind a bounded semaphore, so it now degrades gracefully (429, retry) instead of serializing invisibly. That fix mattered more for concurrent judges testing the live demo than any latency the region migration alone could have solved.

We treat Alibaba Cloud as more than a place to point a Docker container. Real deployment means real hardening, and it means being honest when something is slow instead of hand-waving it as "cloud latency, nothing we can do."

Proof it ran on Alibaba Cloud

Not a claim — receipts. The stack ran on Alibaba Cloud ECS, first in Singapore and then migrated to US-Virginia, with the FastAPI backend serving live inference over HTTP.

ECS Workbench, Singapore instance, nginx active and running Alibaba Cloud ECS console showing the running instance
Uvicorn backend live on ECS serving POST /predict Continuous stream of live sonar classifications, all HTTP 200
1. ECS Workbench — the first instance in Singapore (launch-advisor-20260701): the nginx reverse proxy active (running).
2. ECS console — the running instance in US-Virginia (ecs.c9i.large, 2 vCPU / 4 GiB, public IP 47.85.198.176).
3. The REBOUND FastAPI backend live on that instance — Uvicorn on :8000, "Application startup complete", serving real POST /predict and /process requests.
4. A continuous stream of live classifications (open space, nearby wall, corner) at ~10–25 ms each — every request HTTP 200 OK.

Qwen Cloud integration

The Memory Agent (src/memory/agent.py) calls Qwen-Plus through the DashScope international endpoint (dashscope-intl.aliyuncs.com/compatible-mode/v1, OpenAI-compatible chat/completions), both synchronously (QwenMemoryAgent) and asynchronously (AsyncQwenMemoryAgent via httpx.AsyncClient, non-blocking for the FastAPI server). Every call is forced to response_format: json_object against a fixed schema and retried up to 3 times with exponential backoff.

Qwen is the reasoning brain of the memory system, not a chat add-on. Given the CNN's acoustic classification, the current sonar features, the user's episodic/semantic memory, and their behavioral signal (advance / hesitate / retreat / ignore), it decides in a single structured call:

  • The navigation instruction to speak to the user
  • Confidence adjustments to the Bayesian priors per space class
  • Memory operations — what to store, consolidate, or selectively forget across episodic/semantic/procedural memory
  • The haptic pattern to trigger

When DASHSCOPE_API_KEY is unset, MockQwenMemoryAgent/MockAsyncQwenMemoryAgent generate deterministic rule-based responses with the same shape, so the pipeline runs identically offline for testing and demos.

The backend (src/cloud/api_server.py) is deployed on Alibaba Cloud ECS (region US-Virginia) via Docker, with a Caddy reverse proxy and a real Let's Encrypt certificate, exposing endpoints for audio prediction, observation processing, user profiles, and session management. Every Qwen response is guarded against hallucination before it touches state: confidence multipliers clamped to [0.1, 10.0], memory key/value sizes capped, and space-class names checked against a whitelist before they ever reach a prompt or get applied.


Results

We built and trained the classifier ourselves. ReboundCNN (src/models/classifier.py) is a custom multi-task CNN written and trained from scratch on our own NVIDIA RTX 3090 — not a fine-tuned off-the-shelf model. A single forward pass produces both the space class and the distance estimate, and the trained checkpoint (models/checkpoints/best_model.pt) ships in this repo.

Metric Value
Architecture Custom multi-task CNN — 3 conv blocks (1→16→32→64, Conv2d 3×3 + BatchNorm + ReLU + MaxPool) into a shared FC trunk with two heads
Inputs Mel spectrogram (1×64×32) fused with 2 acoustic scalars — RT60 and spectral centroid
Outputs Class head (6-way softmax) + distance head (regression, Softplus)
Parameters ~296K — small enough to run on CPU, no GPU at inference
Loss / optimizer CrossEntropy + MSE (multi-task), Adam @ lr 1e-3, ReduceLROnPlateau, early stopping on val loss
Training run 50 epochs, batch size 64, on an NVIDIA RTX 3090
CNN classes 6 (open_space, nearby_wall, doorway, corner, corridor, stairs)
val_accuracy (20% stratified split) 0.953
val_distance_MAE 0.302 m
Tests passing 88/88
Staircase detector SNR threshold ~27 dB

Mel spectrograms extracted from the synthetic dataset — one sample per class, showing the acoustic signature the CNN classifier learns to distinguish:

Mel spectrogram — one sample per class

All figures above are measured on simulated rooms — see Known limitations. Full empirical detail: LIMITATIONS.md.


API endpoints

Method Path Description
POST /predict Raw audio in → classification + distance + stair detection
POST /process Classification result → Memory Agent → navigation instruction
GET /profile/{user_id} User profile, episodic stats, semantic memory
POST /session Start new session for user
GET /health Health check

All endpoints except /health require an X-API-Token header when REBOUND_API_TOKEN is set (see Security).


Known limitations — said plainly, not buried

  • No spatial direction. REBOUND can tell you there's a wall a meter away. It cannot yet tell you if that wall is to your left, your right, or straight ahead. That needs a stereo microphone array to triangulate direction — a hardware constraint, not a software one. A single phone microphone can't resolve it.
  • The training dataset is synthetic, generated from acoustic simulation, not from real rooms with real people walking through them. It works well enough to demo convincingly. It is not yet trained on the messiness of real-world echoes, real hallways, real furniture.
  • It still needs a phone in your hand. For someone who already navigates with a cane and possibly a guide dog, adding "also hold a phone up and tap it" is a real usability cost we haven't solved yet.
  • Behavioral feedback loop — now demonstrated end to end in the interactive demo. The full Bayesian personalization pipeline — EpisodicMemory, SemanticMemory, UserProfile, and the Qwen Memory Agent — is real and tested, and the interactive web demo (web/, live at rebound-olga.vercel.app/demo) now runs it in the browser: across a session of real user_actions the Bayesian priors adapt, episodic memory fills and decays, and semantic patterns consolidate on screen — the same deterministic math as src/memory/*.py, client-side, with no backend and no API key (Qwen only phrases the already-computed result). This is the ML personalization finally exercised as a loop, not just unit-tested in isolation. What remains is capturing the user's real reaction on the phone: the mobile client (Live.jsx) still hardcodes user_action: "advance", so the on-device loop isn't closed in the field yet. Integration work remaining, not a capability the system lacks.

None of these are hidden from the judges because none of them are embarrassing. They're the honest next steps for a project built in days, not the finish line for a project that's done. Full empirical constraints, measured rather than assumed: LIMITATIONS.md. The adversarial security review we ran against our own system, findings and fixes both: AUDITORIA_ADVERSARIAL.md and CHANGELOG_2026-07-01.md.


What's next

The most exciting fix for all three limitations above is the same one: a dedicated IoT device. A small wearable with a stereo microphone pair (solving spatial direction), an onboard low-power inference chip (cutting round-trip latency further), and no phone required at all (solving the "hands are busy" problem cane users already live with). Once the dataset moves from synthetic to real recordings — ideally collected in partnership with actual blind or low-vision users — the CNN classifier's confidence and the Memory Agent's personalization both improve with it, because the whole system is only as honest as the data it learned from.

  • Real-world dataset — field RIR collection to close the sim-to-real gap documented above.
  • On-device personalization — Elastic Weight Consolidation fine-tuning per user (future/ewc.py, already prototyped, deferred to v2).
  • Edge inference — 296K parameters is small enough to run offline when there's no signal.

Installation

pip install -r requirements.txt

Set your DashScope API key:

export DASHSCOPE_API_KEY=your_key_here

Recommended for production — a shared demo token (see Security):

export REBOUND_API_TOKEN=$(openssl rand -hex 16)
export REBOUND_ALLOWED_ORIGINS=https://rebound-olga.duckdns.org

CUDA-capable GPU required for training. CPU is sufficient for inference and for the live demo.

The repo is self-contained. A fresh clone already ships the trained model (models/checkpoints/best_model.pt) and the processed dataset (data/processed/), so you can run inference and the API server without regenerating anything — the training step below is only for retraining from scratch. The one thing to bring is your own DASHSCOPE_API_KEY for Qwen; the /demo UI and the deterministic memory run with no key at all.


Usage

Generate dataset and train:

python3 -m src.simulation.dataset_builder
python3 -m src.models.train --data data/processed/dataset.npz --epochs 50

Run the local demo (mock agent):

python3 -m src.demo.adaptive_demo

Run the local demo (real Qwen API):

python3 -m src.demo.adaptive_demo --use-qwen

Start the API server locally:

uvicorn src.cloud.api_server:app --host 0.0.0.0 --port 8000

Deploy to Alibaba Cloud ECS:

python3 -m src.cloud.deploy --registry <your-acr-registry> --tag v0.1

Run tests:

python3 -m pytest tests/ -v

Repository structure

src/
  signal/      chirp, capture, deconvolution, staircase detector
  features/    spectral and geometric feature extraction
  simulation/  RIR generation (pyroomacoustics + synthetic stairs)
  models/      CNN classifier (6 classes), training, inference
  memory/      Qwen Memory Agent (sync + async), user profile, episodic/semantic memory
  cloud/       FastAPI API server (async) + Alibaba Cloud ECS deploy script
  feedback/    haptic pattern definitions
  demo/        adaptive real-time visualization (matplotlib)
frontend/      React PWA (Vite) — sonar engine, earcons, speech, live view
future/
  ewc.py             Elastic Weight Consolidation — deferred to v2
  augmentation.py    noise augmentation (known bug, see header) — deferred to v2
tests/                     88 unit + integration tests
LIMITATIONS.md             empirically measured system constraints
AUDITORIA_ADVERSARIAL.md   adversarial security audit (Peircean abductive method)
CHANGELOG_2026-07-01.md    bug remediation changelog

Security

REBOUND handles behavioral data about people with disabilities, so we hold it to a real security bar, not a demo-day shrug:

  • Token authentication on every data endpoint (X-API-Token, constant-time comparison) — the server logs loudly on startup if no token is configured, so "silently open" is never silent.
  • CORS scoped to the deployed frontend origin — no wildcard + credentials in production.
  • Payload size caps and bounded concurrency on /predict: oversized audio is rejected before decoding, and excess concurrent requests get a clean 429 instead of degrading every request in flight.
  • LRU eviction with a hard cap on per-user state, so no amount of invented user_ids can grow server memory without bound.
  • user_id validated against [a-zA-Z0-9_\-]{1,64} (path traversal prevention).
  • class_name validated against a fixed whitelist before reaching any prompt (prompt-injection prevention).
  • LLM-generated multipliers clamped to [0.1, 10.0] (hallucination containment); semantic memory values capped at 512 characters (unbounded growth prevention).
  • Per-user asyncio.Lock (race-condition prevention) with heavy DSP/CNN work off the event loop, so concurrent users no longer block each other.
  • .dockerignore excludes data/profiles/ and data/checkpoints/.
  • Deployed over HTTPS via Caddy with a real Let's Encrypt certificate — not self-signed, because iOS and Android both refuse microphone access otherwise.

We ran an adversarial audit against our own system before polishing the demo and published every finding: see AUDITORIA_ADVERSARIAL.md.


Built with

Python, FastAPI, PyTorch, librosa, Qwen Cloud (qwen-plus), Docker, Alibaba Cloud ECS, Caddy, DuckDNS, React (Web Audio API, PWA)


Team

Designed, architected, and developed in full by Olga Vasilieva, with infrastructure and deployment support from the VIGÍA AI Collective.

The GitHub repository is hosted under the account of Anna Tchijova (her daughter) for technical convenience. Anna Tchijova had no participation in the code, design, or technical decisions of this project.

License: Apache License 2.0 — see LICENSE


Qwen Cloud Hackathon · MemoryAgent Track

Every phone is a sonar.


Slides — Pitch

Slide 1 Slide 2 Slide 3 Slide 4 Slide 5 Slide 6 Slide 7 Slide 8 Slide 9 Slide 10


Slides — Biomimetic Sonar Navigation System

Slide 1 Slide 2 Slide 3 Slide 4 Slide 5 Slide 6 Slide 7 Slide 8 Slide 9 Slide 10 Slide 11 Slide 12 Slide 13 Slide 14 Slide 15 Slide 16

About

Echolocation on a phone for blind indoor navigation: a biomimetic chirp, a from-scratch PyTorch CNN that classifies the space, and an adaptive Qwen Memory Agent that learns each user. Qwen Cloud Hackathon, MemoryAgent track.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages