Skip to main content

NeckLink

NeckLink CNS (necklink-cns v3.0.0, research beta)

A 4-organ reflex controller whose descending decision layer runs on weight matrices compiled from the adult Drosophila BANC v888 connectome — fusing NeckSight, NeckCompass, NeckSense, and NeckCord with MAVLink v2 and ROS 2 bridges in 24,024 B of zero-heap, zero-float ANSI C99 (107.5 KB standalone WebAssembly) and Python.

PyPI Python ANSI C99 WebAssembly Status License: MIT

Live WASM Demo · Quick start · Autopilot bridges · C99, ESP32 & WASM · v3.0.0 results · When to use it


What it is

In the adult Drosophila Brain-and-Nerve-Cord connectome (BANC v888: 157,789 proofread neurons, 23,553,108 synapses), brain signals reach the body through 1,316 Descending Neurons (DNs) that drive 805 Ventral Nerve Cord motor neurons.

necklink-cns combines one library per subsystem into a single closed-loop controller:

  1. Optic lobe (NeckSight): retina/lamina preprocessing, T4/T5 motion detectors, 3-DOF gyro derotation, and 64 LPLC2 + 32 LC4 looming detectors whose receptive fields are compiled from BANC v888.
  2. Central complex (NeckCompass): 9-axis tilt-compensated heading, an EPG ↔ Delta7 ring attractor and PFL3/PFL2 homing steering on BANC v888-compiled matrices, plus CPU4-style path integration.
  3. Mushroom body (NeckSense): vibration front-end, antennal normalisation, and a Kenyon-cell projection using real BANC v888 claws (1,024 cells), with novelty and 2-compartment memory.
  4. Descending decision layer (ConnectomeArbitrator): 11 brain populations (LPLC2, LC4, LPLC1, PFL3, PFL2, MBON) → 10 descending neurons (DNp01, MDN, DNa02, …) → 6 leg motor pools, by matrix multiplication through W_brain_dn and W_dn_leg. Turning direction is read from the motor-pool output, not hard-coded.
  5. Engineering layers (PROVENANCE = "engineering"): box-constrained thruster/rotor allocator, sensorless ESC fault observer, 18-servo hexapod IK, 4-byte CRC-4 command frame, MAVLink v2 (0xFD, X.25 CRC-16 + CRC_EXTRA) codec and a ROS 2 (rclpy) adapter.

Hand-designed, not from the connectome: how sensor outputs drive the brain populations, the rate dynamics and thresholds, an expansive DNa02 response r·(0.5 + 1.5·r) (motivated by Westeinde et al., Nature 2024), and forward-walking inhibition of MDN. These apply identically to real and shuffled wiring.


Quick start

pip install --upgrade necklink-cns
necklink-cns --version
necklink-cns demo
necklink-cns priors
import numpy as np
from necklink_cns import NeckLinkCNS

cns = NeckLinkCNS(vehicle="hexacopter", grid_size=32)   # connectome_weights="banc_v888" by default
frame = np.full((32, 32), 160.0)
out = cns.step(
    dt=0.02,
    speed_m_s=1.2,
    gyro_xyz=np.array([0.02, -0.01, 0.05]),
    accel_xyz=np.array([0.3, -0.2, 9.80]),
    mag_xyz=np.array([0.45, 0.05, 0.89]),
    camera_frame=frame,
)
assert len(out.cervical_wire_4b) == 4
assert out.mavlink_manual_pkt[0] == 0xFD

# The earlier hand-tuned symmetric model (more accurate in every v3 benchmark):
analytic = NeckLinkCNS(vehicle="usv_t200", grid_size=32, connectome_weights="v2_analytic")

The extraction and shuffling tools (necklink_cns.connectome.extract_raw_subgraphs, shuffle_raw_subgraphs, …) need SciPy/pandas and the raw BANC v888 dataset: pip install "necklink-cns[connectome]".


import numpy as np
from necklink_cns import (
    MavLink2Codec,
    MavManualControl,
    NeckLinkCNS,
    NeckLinkROS2Adapter,
)

# 1. MAVLink v2 framing (ArduPilot / PX4 companion UART or UDP)
codec = MavLink2Codec(sysid=42, compid=191)
pkt = codec.encode_manual_control(MavManualControl(x=650, y=0, z=500, r=-250, buttons=0, target=1))
decoded = codec.feed(pkt)
assert len(decoded) == 1 and MavManualControl.from_payload(decoded[0].payload).r == -250

# 2. ROS 2 (rclpy-ready) sensor/cmd_vel adapter
adapter = NeckLinkROS2Adapter(NeckLinkCNS(vehicle="usv_t200", grid_size=32))
adapter.on_imu(np.array([0.01, -0.02, 0.05]), np.array([0.2, -0.1, 9.8]))
adapter.on_mag(np.array([0.45, 0.05, 0.88]))
step_out = adapter.step_camera(np.full((32, 32), 140.0), speed_m_s=1.0, dt=0.02)
assert isinstance(step_out["twist"].angular_z, float)

Zero-heap, zero-float ANSI C99, ESP32 & WASM

csrc/necklink_cns.h, csrc/necklink_cns.c, and csrc/nl_mavlink.h combine all four organs, the BANC v888 weight tables, and the MAVLink v2 codec into one static C struct (nl_cns_t) with no float/double and no malloc/free:

make -C csrc clean all test sanitize   # 7 C99 self-tests under -Werror + ASan/UBSan
Target Measured Notes
ANSI C99 nl_cns_t 24,024 B (x86-64) / 23,968 B (32-bit) state, 0 B .data/.bss Weight tables are const (flash)
x86-64 -O2 ~166 µs per full tick Desktop self-test timing; not measured on a microcontroller
ESP32 (esp32dev, PlatformIO, Xtensa toolchain) 47,604 B RAM (14.5%), 515,496 B flash (39.3%) for the example sketch Compile-verified only — not yet run on a board
Standalone WebAssembly 110,129 B, 0 imports Runs in the live browser demo

arduino/NeckLinkCNS/ contains the Arduino library and an ESP32_MAVLink_Survival_Copilot.ino example sketch. Use nl_cns_set_dn_weights(&cns, NULL) to switch the C core to the analytic model.


v3.0.0 results

Closed-loop whole-controller test (simulation)

A 3-DOF boat simulation (dt = 0.05 s, 45 s): drive out 9 s, then return home on the controller alone, past 2 buoys and 2 thin pilings with real collision checks, through a localised +125° magnetic anomaly, with one thruster losing 78% of its thrust at t = 11 s, under wave roll/pitch. Camera frames are rendered from the live boat pose. N = 30 seeds. "Safe arrival" = within 2.5 m of home with zero collisions.

Controller Safe arrival Collisions per mission Closest approach to home
necklink-cns, banc_v888 (default) 66.7% (20/30) 0.70 2.83 m
necklink-cns, v2_analytic 80.0% (24/30) 0.30 2.16 m
Classical: χ²-gated EKF + dead reckoning + gyro-derotated Farneback avoidance + health-weighted pseudo-inverse 0.0% 1.53 8.16 m

Shuffled-wiring test: the whole controller with all four organs' raw matrices rewired by degree-preserving (Maslov–Sneppen) swaps, K = 100 shuffles, 12 seeds each: safe arrival 58.3% (real, same 12 seeds) vs 4.6% (shuffled mean), 2/100 shuffles at least as good, p = 0.030, z = +4.24.

What this shows:

  • The real wiring matters for this controller: scrambling it while keeping every neuron's degree and synapse weights collapses performance.
  • It is not the best controller: the hand-tuned symmetric model does better.
  • The classical baseline is not state of the art. Its allocator has no active-set redistribution and no reverse-escape manoeuvre, which partly explains 0%.
  • Caveats: simulation only; p = 0.030 misses the pre-registered 0.01 threshold (12 seeds per shuffle); the pipeline (for example the LPLC1 drive, MDN inhibition and DNa02 response) was tuned while looking at real-wiring results, which favours the real wiring over the shuffles.

Per-organ results are in each package README (NeckCompass, NeckSight, NeckSense, NeckCord); the full table, code and raw JSON are in benchmarks/v3/.

Earlier correction (v2.0.1): withdrawn v2.0.0 claims

The v2.0.0 "250-episode closed-loop survival gauntlet" (100% vs 77.2% vs 1.2% vs 0%) never ran this library — each controller was hand-scripted inside the benchmark — and was withdrawn, together with most other v2.0.0 benchmark advantages (unfair baselines, train/test leakage, a mislabelled connectome "specificity" test that used random node sets rather than a degree-preserving null). See the root README for the full list. The v3.0.0 benchmarks above were written from scratch to run the library itself, with identical inputs for every method.


Reasonable to try:

  • Research on connectome-constrained control: compile real BANC v888 circuits into a running controller and test them against shuffled wiring in your own simulations.
  • Experimenting with a small (< 24 KB) reflex layer beneath ArduPilot, PX4, or ROS 2 — in simulation or on the bench first. For best behaviour use connectome_weights="v2_analytic".

Do not use it yet for:

  • Anything safety-critical. The controller has not been run on real hardware.
  • Metric 3D mapping, object recognition, or path planning. This is a reflex controller, not a VIO/SLAM or perception stack.
  • Untextured environments (blank walls): pair it with a rangefinder.

Changelog

3.0.0

  • Connectome-driven decision layer: ConnectomeArbitrator replaces the v2 hand-coded priority table with BANC v888 W_brain_dn (10×11) and W_dn_leg (6×10) matrices in Python and C99. connectome_weights="v2_analytic" (C: nl_cns_set_dn_weights(&cns, NULL)) keeps the earlier model.
  • All four organs use their v3 connectome-derived circuits by default.
  • Fix (found by the independent audit): the C99/WASM core now initialises its ring compass with the BANC v888 weights (it previously ran the analytic ring while Python ran BANC v888).
  • Fix: WASM singletons are compiled only for WebAssembly builds (0 B .bss on MCUs).
  • Fix: importing necklink_cns no longer requires SciPy/pandas; the extraction tools moved to the [connectome] extra.
  • Provenance: NeckLinkCNS/ConnectomeArbitrator carry PROVENANCE = "connectome"; MAVLink, ROS 2 and cervical-link classes carry PROVENANCE = "engineering".

License

Released under the MIT License. Copyright (c) 2026 Amandeep Singh Bains.

Metadata

Release files for necklink-cns 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for necklink-cns 3.0.0
File Size Uploaded Provenance Actions
necklink_cns-3.0.0.tar.gz 287.8 kB Without provenance Details for necklink_cns-3.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for necklink-cns 3.0.0
File Interpreter ABI Platform Actions
necklink_cns-3.0.0-py3-none-any.whl Python 3 none any Details for necklink_cns-3.0.0-py3-none-any.whl

Total release size: 338.0 kB

Security for necklink-cns 3.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

3.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page