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.
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:
- Optic lobe (
NeckSight): retina/lamina preprocessing,T4/T5motion detectors, 3-DOF gyro derotation, and64LPLC2+32LC4looming detectors whose receptive fields are compiled fromBANC v888. - Central complex (
NeckCompass): 9-axis tilt-compensated heading, anEPG ↔ Delta7ring attractor andPFL3/PFL2homing steering onBANC v888-compiled matrices, plusCPU4-style path integration. - Mushroom body (
NeckSense): vibration front-end, antennal normalisation, and a Kenyon-cell projection using realBANC v888claws (1,024cells), with novelty and 2-compartment memory. - Descending decision layer (
ConnectomeArbitrator):11brain populations (LPLC2,LC4,LPLC1,PFL3,PFL2,MBON) →10descending neurons (DNp01,MDN,DNa02, …) →6leg motor pools, by matrix multiplication throughW_brain_dnandW_dn_leg. Turning direction is read from the motor-pool output, not hard-coded. - 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]".
MAVLink v2 & ROS 2 autopilot bridges
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.030misses the pre-registered0.01threshold (12 seeds per shuffle); the pipeline (for example theLPLC1drive,MDNinhibition andDNa02response) 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.
When to use NeckLink CNS, and when not to
Reasonable to try:
- Research on connectome-constrained control: compile real
BANC v888circuits 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 useconnectome_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:
ConnectomeArbitratorreplaces the v2 hand-coded priority table withBANC v888W_brain_dn(10×11) andW_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 v888weights (it previously ran the analytic ring while Python ranBANC v888). - Fix: WASM singletons are compiled only for WebAssembly builds (
0 B.bsson MCUs). - Fix: importing
necklink_cnsno longer requires SciPy/pandas; the extraction tools moved to the[connectome]extra. - Provenance:
NeckLinkCNS/ConnectomeArbitratorcarryPROVENANCE = "connectome"; MAVLink, ROS 2 and cervical-link classes carryPROVENANCE = "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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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
Release files / necklink_cns-3.0.0.tar.gz
| Download URL | necklink_cns-3.0.0.tar.gz |
|---|---|
| Size | 287.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e617779a90234b46b5190167da0eb25f0dbc27d47fc9ad9329f936ceb042cf58
|
|
BLAKE2b-256 checksum How to use checksums |
f807f1605417ccd6f7bafba2d26362ae45c11ddf248aac267dcddf2a9f58ef9c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / necklink_cns-3.0.0-py3-none-any.whl
| Download URL | necklink_cns-3.0.0-py3-none-any.whl |
|---|---|
| Size | 50.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d5a1fa751c9376efa04911e08fa916e013ed728a3abd505c70dc9474db6e2245
|
|
BLAKE2b-256 checksum How to use checksums |
2619618341e4317dca9e21be9187b33d6358725ab360cfbeedbd61c39ca570b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
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.