The fly’s movement comes from a repeated calculation: environment geometry produces input, the circuit updates, motor readouts produce forces, and the new pose changes the next input.

The software loop

  1. SenseCalculate size, expansion, and bearing.
  2. PropagateUpdate the signed rate network.
  3. ActTurn motor rates into body commands.
  4. IntegrateUpdate velocity and position.
The new body state returns to Sense. Rendering reads the state after calculation; it does not determine the neural response.

The body advances in 20 ms model steps. During each step, the sensory vector is held fixed while the neural network performs ten synchronous 2 ms updates. The motor adapter then reads the new activity and updates the body. Everything starts from zero activity and a resting pose.

This is a closed loop because the next input depends on what the body just did. The target has a prescribed trajectory, but there is no prescribed fly trajectory or goal-seeking controller steering it around the target.

Vision from geometry

The default target is a sphere of radius 1.25 arena units. Its x-coordinate follows 12 − 2.4t, its height is 1.1, and its lateral offset selects frontal, left, or right approach. A stationary control keeps it at x=6.

For distance d, radius R, and relative approach velocity vradial, the implementation calculates:

angular size = 2 atan2(R, d)
expansion = max(0, −2R vradial / (d² + R²))

The expansion signal is scaled, clipped, and weighted by the target’s bearing. It is zero outside the forward field. Side-specific drive enters LC4; LPLC2 drive also receives an angular-size factor. The exact clipping and scaling rules are in the equation notes.

These rules are a feature-level approximation. They skip photoreceptors, individual ommatidia, within-type spatial structure, and image processing. The visual-field canvas is an explanation of the geometry, not the input image to a retina model.

A small, explicit motor adapter

The updated network state contains activity for every included population. Three readouts connect it to the body:

ReadoutTransformationBody effect
Mean bilateral TTMnCrosses 0.008 while grounded, with more than 1 s since the previous launch.Sets upward velocity to 4.2 au/s.
Mean DLMn/DVMnp = tanh(mean activity / 0.018).Scales lift and forward thrust.
b2 right minus leftq = tanh(activity difference / 0.008).Scales yaw torque, together with power p.

The anatomy motivates separate launch and wing readouts: TTMn is associated with a jump muscle, DLM/DVM with wing power, and b2 with wing steering. hDVM denotes haltere power and is excluded from the lift readout. The particular thresholds, gains, timing, and yaw sign above are assumptions. Cheong et al., motor-circuit anatomy.

Each of the ten selected wing-power populations contributes equally to the mean. A population containing several neurons is still one contribution. No motor adapter reads the target’s position directly; environment influence passes through the sensory input and network first.

Move the body with simple dynamics

The adapter combines motor commands with gravity and drag. For power p, yaw command q, lift multiplier L, and heading ψ, the acceleration rules are:

yaw acceleration = 6 q p − 3 yaw_rate
forward thrust   = 7 p, once off the floor or launching
x acceleration   = thrust cos(ψ) − 1.7 vx
y acceleration   = thrust sin(ψ) − 1.7 vy
z acceleration   = 20 L p − 9.8 − 1.1 vz

Velocities are updated before position. A floor, side walls, and ceiling constrain the state. The visual sphere has no collision force. The model omits muscle mechanics, aerodynamic wing forces, body collisions, airflow, and leg articulation.

Distances are reported in arbitrary arena units. Although the display mesh is scaled to one nominal body length, the acceleration and time parameters are not calibrated to that physical scale. A reported model speed cannot be read as a measured fly speed.

The rules also explain a potentially surprising outcome: wing lift can raise the body without a TTMn jump. Silencing DNp01 can therefore remove an early launch while leaving later body movement. That follows from the declared network and adapter; it is not proof of a biological alternative-takeoff mechanism.

Draw the fly without confusing appearance with physics

Flybody supplies an anatomical model designed for MuJoCo and locomotion research. The app reuses its geometry, pinned to a source commit and decimated to 81 pieces with 28,700 triangles. The original XML transforms are baked into a compact display asset.

Three.js renders that asset at the computed pose. Wings have a deliberately slowed display oscillation whose amplitude follows the connected power command. This is not asynchronous muscle simulation. Flybody’s MuJoCo dynamics, aerodynamic model, and trained control policies are not executed by this site.

The same computed state drives the body view, neural graph, numeric readouts, event list, and traces. The renderer can change cameras without changing the simulation. When 3D rendering is unavailable, a labeled 2D position view can still display the numerical result.

How the implementation is organized

Source file in the downloadResponsibility
python/prepare_graph.pyDownload source tables, aggregate populations and counts, select the original subnetwork.
python/prepare_arena_graph.pyAdd actual wing motor units and their input context.
dist/sim.mjsBatch and stateful versions of the signed rate equation.
dist/sim.worker.mjsRun the circuit experiment away from its interface thread.
dist/world-sim.mjsPure sensory, neural, motor, and body integration.
dist/world.mjsArena controls, recorded states, playback, readouts, and exports. It steps the compact model on the browser’s main thread.
dist/world-render.mjs3D anatomy, cameras, trajectory, force indicators, and fallback view.
python/simulate_full.pySparse full typed-CNS propagation.

The prepared experiment runs locally in the browser after the assets load. It makes no model-server calls during a run and does not require a GPU service or an LLM. The Python scripts support data preparation and larger-scale experiments.

Reproduce the arena without its interface

Download and unzip the project. With Node.js available, run this from the package root:

node examples/run-arena.mjs
node examples/run-arena.mjs power

The example imports the same graph and pure simulation used by the site. It prints maximum height above the floor and final horizontal displacement, so the comparison can be reproduced without depending on the rendering.

To use the interactive site locally, serve its static directory with Python and open the local address printed by the server:

python -m http.server 8000 --directory dist

The README covers full-data preparation and sparse Python runs. The detailed model notes list every geometric coefficient, boundary rule, and asset provenance record.