microfly

A fly-connectome model steers a simulated MicroDuck through the official walking policy. A second path that maps neural activity directly to fourteen servo-position targets remains in the code, with its controls temporarily hidden. All computation runs locally in the visitor's browser; no server, GPU account or physical robot is needed.

Run and build

Node.js 22.12 or newer:

npm ci
npm run dev

Open the address printed by Vite. Production build: npm run build; preview: npm run preview. Serve dist/ with an HTTP server. Opening index.html as a local file will not work. The source archive includes all necessary model and connectome assets. Production files have no external CDN dependencies.

Use it

Head cutaway and food

The small inset in the upper right of the arena shows the real MicroDuck head mesh as a translucent cutaway, containing an illustrative enlarged fly with six legs, two veined wings, red eyes and four brain electrodes. Four leads run from its brain to sockets on the inside ceiling. The cutaway rotates slowly by default, and the fly makes small wing and leg movements. Drag to rotate it manually; the arrow enlarges it. Pause freezes this automatic movement, and reduced-motion preferences disable it. The fly movement is illustrative animation, independent of motor commands. The green electrode signal reflects modeled descending-neuron activity and goes quiet when disconnected. It is a conceptual illustration, not a real implant or an anatomical reconstruction of a complete fly.

The arena's scent source is a mottled 3D overripe banana. The left/right buttons and floor clicks move it; removing it also removes odor input. Fermenting fruit is an appropriate cue for this species: research on Drosophila attraction identifies yeast fermentation odors as an attractant. When an upright duck comes within 18 cm of the banana’s center, the fruit and its scent disappear. After 0.4 seconds of simulation time, a new banana appears at a different location inside the arena, at least 65 cm from the duck. This continues as fruit is collected. Manually removing the banana cancels any pending respawn. The existing artificial odor encoder is unchanged, and fruit collection does not train or reward the neural model. The banana has no physical collision body.

The interface opens directly with a single-line title and the two scenes. A prominent arena hint explains how to place a banana; supporting details are available under How it works in the footer. Duplicate technical captions and the mode selector are hidden. The page, robot shell and arena use neutral white/gray surfaces, with green retained for active controls and the brain anatomy view. The fly and banana are built from local geometry and reuse the loaded head mesh, so they add no asset downloads.

What the model does

The graph is the pinned connectome.bin.gz from snedea/flybrain, which reports FlyWire FAFB v783 as its source. Its binary contains 139,255 neurons and 2,698,236 directed weighted edges. All those neurons and edges are retained here. This is the supplied, aggregated graph; it is not a claim to reproduce every synapse in the original FlyWire release, nor the MaleCNS dataset used by DOOMFLY.

Sensory/descending indices are selected from the upstream classification table by exact root-ID joins to its neurons table, preserving the binary's original neuron order. No empty synthetic DN_WALK or leg-motor groups are used. There are 647 left and 650 right descending neurons.

Every neural tick:

  1. Membrane values decay by 0.94, with a discrete refractory counter.
  2. Previous spikes propagate over a sparse adjacency table; incoming absolute connection weights are normalized to a total gain of 3 per postsynaptic neuron.
  3. Only annotated visual, olfactory and mechanosensory neurons receive probabilistic external input (seeded RNG, amplitude 1.1, probability 0.6 × stimulus).
  4. Values at or above 1 fire and reset, with refractory counter 3. All neurons are evaluated on every tick.

Ten neural ticks are run per worker update, targeting ten updates per wall-clock second. These are toy discrete dynamics, not calibrated biological time. Group traces show the last tick's actual spike counts; the total spike counter and descending rates average the ten-tick update.

Version 2 reduces recurrent gain from 4 to 3: previously, background activity saturated forward speed, and averaging the entire descending populations erased odor laterality. Steering now reads the annotated left/right antennal-lobe projection neurons (ALPN, 341/344 neurons), downstream of the stimulated sensory cells. Descending firing supplies forward drive. Both use an exponential moving average with update coefficient 0.3.

Let L,R be filtered descending firing fractions, A,B the filtered ALPN firing fractions. The walking decoder is:

odor = A + B
contrast = (A − B) / max(0.02, odor)
drive = min(1, (L + R) / 0.0006) × min(1, (odor − 0.008) / 0.04)
forward = 0.24 × drive × (1 − min(0.15, |contrast| × 0.5))  [m/s]
turn = 0.7 × tanh(5 × contrast)                           [rad/s]

If odor < 0.008 or descending firing is zero, both commands are zero. Clearing scent therefore stops neural drive even with ambient light. The gains are engineered and untrained. No target position enters this decoder.

In direct mode, all 1,297 descending neurons are sorted by their original graph index and assigned round-robin into 28 fixed pools. For joint i, two opposing pools give motor[i] = tanh(80 × (rate[2i] − rate[2i+1])), using the same 0.3 filtering. The target is standingPose[i] + gain × motor[i], clamped to the joint's actual limits and limited to a 0.035-radian target change per control step. These arbitrary pool assignments do not claim natural fly joint semantics. There is no oscillator, scripted gait, learned balance, inverse kinematics, or ONNX call in this path. “Direct” means position targets for the model's servo actuators, not raw electrical currents or torques. All fourteen targets and resulting physical joint positions are observable in telemetry.

Disconnect, stale neural telemetry (>1 second), or pause removes active neural control. A detected fall additionally zeros walking commands; direct mode keeps applying its neural targets until paused or disconnected. Reset stands the body up. The decoder is an engineered interface and does not guarantee successful navigation.

Scent strength decays exponentially with distance and is split between left/right sensory inputs using relative bearing. Proximity to arena walls also supplies an artificial mechanosensory signal. The gait policy does not receive scent coordinates, route instructions or scripted joint trajectories.

Robot physics

Pollen Robotics' MicroDuck simulator supplies the kinematic model, mesh, collision model and BEST_alpha_walking.onnx. Its walking loop is reduced to a standalone module here:

Physics and rendering run on separate schedules. Slow devices can still run simulation time more slowly than wall time. Add ?low to the URL to disable shadows and render at half resolution and cap drawing at 2 FPS. The displayed timer measures physics time. No real hardware transport is included or exercised.

Scientific limitations and attribution

This is an interactive engineering experiment, not a validated emulation, a living brain, evidence of consciousness, or evidence of learned navigation. The neural weights never learn. MicroDuck's previously trained policy supplies balance and gait only in walking mode.

The upstream graph aggregates signed counts and treats GABA as inhibitory, with acetylcholine, glutamate and modulatory transmitter labels positive. That is a strong simplification (in particular glutamate and modulators), inherited here rather than biologically validated. Incoming normalization, neuron dynamics, sensory encoding, ALPN/descending readouts, motor pool assignments and command scaling are additional engineering choices.

FlyWire citation: Dorkenwald, S., Matsliah, A., Sterling, A.R. et al., “Neuronal wiring diagram of an adult brain,” Nature 634, 124–138 (2024), doi:10.1038/s41586-024-07558-y. See FlyWire Codex for original data and current releases.

The anatomical view plots one representative coordinate per neuron, selected as the first supplied point in the pinned FlyBrain coordinates.csv.gz and joined by root ID in graph order. These are real locations, not synthetic layout positions, but they are not full reconstructed arbors or verified soma positions. Brightness comes from this model's spike counts across the latest ten ticks, not measured activity from an animal. The slice removes points and tissue past an adjustable depth plane.

The unchanged FlyWire whole-brain tissue mesh comes from navis-org/navis-flybrains. Its provenance describes the tissue mask and coordinate transform. The repository is GPL-3.0; its license is included separately in licenses/navis-flybrains-GPL-3.0.txt, with the original mesh source in the archive. This third-party asset is not relicensed under the app's Apache license.

FlyBrain source is MIT licensed (see licenses/flybrain-MIT.txt). Pollen Robotics MicroDuck code and assets are Apache-2.0 (see licenses/microduck-Apache-2.0.txt). Original FlyDuck code is Apache-2.0. Original datasets retain their own terms. Upstream code and asset revisions, SHA-256 hashes and population counts are in provenance.json. python3 scripts/fetch-assets.py re-fetches the pinned data and reconstructs the index mappings, verifying every asset hash.

Validation

npm test
npm run build

The food tests cover pickup, delayed respawning, manual overrides, fallen ducks and placement near arena walls. The neural tests exercise the full graph with the same scent encoder used by the browser: left/right scent reverses neural steering; clearing scent removes drive; disabling synapses leaves sensory spikes but zero ALPN, descending and direct motor output; direct targets vary and respect joint limits; reset reproduces a supplied seed. These tests establish software behavior, not biological validity.

scripts/browser-check.mjs exercises both control paths (triggering the hidden direct-mode button programmatically), physically measured walking, direct target changes with zero ONNX invocations, scent reversal/clearing, pause/reset/disconnect, ablation, anatomical slicing/expansion and mobile layout. Run against a local production preview with FLYDUCK_URL=http://localhost:4173/?low node scripts/browser-check.mjs. CHROMIUM_PATH selects an installed Chromium executable. The evidence JSON and screenshots go to test-results/ (override with FLYDUCK_EVIDENCE).

scripts/food-head-check.mjs checks rear camera following through a turn, fixed-angle wheel/pinch zoom, a physical approach and pickup, the scent disappearing and returning, respawn pausing, ceiling mounts, wing/leg movement, automatic and manual rotation, and reduced-motion behavior. It uses the same preview URL and evidence settings as the browser check.

The source is available in the source branch or the deployed source archive. window.flyduck exposes simulation state, policy invocation counts, fourteen targets and measured joint positions, sensory inputs, neural readouts and anatomical render counters for inspection.