necklink-cns 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. necklink_cns-2.0.0/LICENSE +21 -0
  2. necklink_cns-2.0.0/MANIFEST.in +10 -0
  3. necklink_cns-2.0.0/PKG-INFO +190 -0
  4. necklink_cns-2.0.0/README.md +158 -0
  5. necklink_cns-2.0.0/arduino/NeckLinkCNS/examples/ESP32_MAVLink_Survival_Copilot/ESP32_MAVLink_Survival_Copilot.ino +84 -0
  6. necklink_cns-2.0.0/arduino/NeckLinkCNS/library.properties +10 -0
  7. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/NeckLinkCNS.h +11 -0
  8. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/neckcompass.c +1313 -0
  9. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/neckcompass.h +289 -0
  10. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/neckcord.c +2675 -0
  11. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/neckcord.h +368 -0
  12. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/necklink_cns.c +563 -0
  13. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/necklink_cns.h +245 -0
  14. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/necksense.c +1299 -0
  15. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/necksense.h +309 -0
  16. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/necksight.c +1242 -0
  17. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/necksight.h +295 -0
  18. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/nl_mavlink.c +433 -0
  19. necklink_cns-2.0.0/arduino/NeckLinkCNS/src/csrc/nl_mavlink.h +197 -0
  20. necklink_cns-2.0.0/csrc/Makefile +33 -0
  21. necklink_cns-2.0.0/csrc/necklink_cns.c +563 -0
  22. necklink_cns-2.0.0/csrc/necklink_cns.h +245 -0
  23. necklink_cns-2.0.0/csrc/nl_mavlink.c +433 -0
  24. necklink_cns-2.0.0/csrc/nl_mavlink.h +197 -0
  25. necklink_cns-2.0.0/csrc/organs/neckcompass.c +1313 -0
  26. necklink_cns-2.0.0/csrc/organs/neckcompass.h +289 -0
  27. necklink_cns-2.0.0/csrc/organs/neckcord.c +2675 -0
  28. necklink_cns-2.0.0/csrc/organs/neckcord.h +368 -0
  29. necklink_cns-2.0.0/csrc/organs/necksense.c +1299 -0
  30. necklink_cns-2.0.0/csrc/organs/necksense.h +309 -0
  31. necklink_cns-2.0.0/csrc/organs/necksight.c +1242 -0
  32. necklink_cns-2.0.0/csrc/organs/necksight.h +295 -0
  33. necklink_cns-2.0.0/csrc/tools/necklink_cns_selftest.c +351 -0
  34. necklink_cns-2.0.0/necklink_cns/__init__.py +41 -0
  35. necklink_cns-2.0.0/necklink_cns/banc_v888_priors.json +215 -0
  36. necklink_cns-2.0.0/necklink_cns/cli.py +74 -0
  37. necklink_cns-2.0.0/necklink_cns/cns.py +278 -0
  38. necklink_cns-2.0.0/necklink_cns/connectome.py +163 -0
  39. necklink_cns-2.0.0/necklink_cns/mavlink.py +370 -0
  40. necklink_cns-2.0.0/necklink_cns/ros2_node.py +170 -0
  41. necklink_cns-2.0.0/necklink_cns.egg-info/PKG-INFO +190 -0
  42. necklink_cns-2.0.0/necklink_cns.egg-info/SOURCES.txt +46 -0
  43. necklink_cns-2.0.0/necklink_cns.egg-info/dependency_links.txt +1 -0
  44. necklink_cns-2.0.0/necklink_cns.egg-info/entry_points.txt +2 -0
  45. necklink_cns-2.0.0/necklink_cns.egg-info/requires.txt +8 -0
  46. necklink_cns-2.0.0/necklink_cns.egg-info/top_level.txt +1 -0
  47. necklink_cns-2.0.0/pyproject.toml +62 -0
  48. necklink_cns-2.0.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amandeep Singh Bains
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,10 @@
1
+ include LICENSE
2
+ include README.md
3
+ include pyproject.toml
4
+ recursive-include necklink_cns *.py *.json
5
+ recursive-include csrc *.c *.h Makefile
6
+ recursive-include arduino *.c *.h *.ino *.properties
7
+ prune csrc/build
8
+ prune assets
9
+ prune dist
10
+ prune tests
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: necklink-cns
3
+ Version: 2.0.0
4
+ Summary: Unified Adult Drosophila Whole-CNS Edge Autonomy Controller (BANC v888 Descending Arbitration, <24 KB Zero-Float ANSI C99, MAVLink v2 & ROS 2 Bridges)
5
+ Author: Amandeep Singh Bains
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/indian-aman/necklink/tree/main/packages/necklink_cns
8
+ Project-URL: Repository, https://github.com/indian-aman/necklink
9
+ Keywords: necklink,drosophila,connectome,mavlink,ros2,ardupilot,px4,esp32,neuromorphic,robotics
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: C
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: numpy>=1.22
25
+ Requires-Dist: necksight>=2.0.0
26
+ Requires-Dist: neckcompass>=2.0.0
27
+ Requires-Dist: neckcord>=2.0.0
28
+ Requires-Dist: necksense>=2.0.0
29
+ Provides-Extra: wire
30
+ Requires-Dist: pynltp>=1.6.0; extra == "wire"
31
+ Dynamic: license-file
32
+
33
+ <div align="center">
34
+
35
+ <a href="https://github.com/indian-aman/necklink"><img src="https://raw.githubusercontent.com/indian-aman/necklink/main/assets/logo/necklink-mark.svg" alt="NeckLink" width="52"></a>
36
+
37
+ # NeckLink CNS (`necklink-cns` v2.0.0)
38
+
39
+ **Unified Adult *Drosophila* Whole-CNS Survival Copilot — fusing `NeckSight`, `NeckCompass`, `NeckSense`, and `NeckCord` through empirical `BANC v888` descending arbitration plus wire-valid `MAVLink v2` and `ROS 2` bridges in `23,928 B` (`23.37 KB`) of zero-heap, zero-float ANSI C99 (`38.82 KB` standalone WebAssembly, `14.5%` ESP32 RAM) and Python.**
40
+
41
+ [![PyPI](https://img.shields.io/pypi/v/necklink-cns?style=flat-square&logo=pypi&logoColor=white&label=PyPI%20necklink--cns&color=6366F1&cacheSeconds=180&v=200)](https://pypi.org/project/necklink-cns/)
42
+ [![Python](https://img.shields.io/badge/python-3.9%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/necklink-cns/)
43
+ [![ANSI C99](https://img.shields.io/badge/C99-zero--heap%20%7C%20zero--float%20%7C%2023.37%20KB-00599C?style=flat-square&logo=c&logoColor=white)](csrc/)
44
+ [![WebAssembly](https://img.shields.io/badge/WASM-38.82%20KB%20standalone-654FF0?style=flat-square&logo=webassembly&logoColor=white)](https://indian-aman.github.io/necklink/#simulator)
45
+ [![Arduino / ESP32](https://img.shields.io/badge/ESP32-14.5%25%20RAM%20%7C%20MAVLink%20v2-00979D?style=flat-square&logo=arduino&logoColor=white)](arduino/NeckLinkCNS/)
46
+ [![License: MIT](https://img.shields.io/badge/license-MIT-F59E0B?style=flat-square)](LICENSE)
47
+
48
+ [**Live WASM Demo**](https://indian-aman.github.io/necklink/#simulator) ·
49
+ [**Quick start**](#quick-start) ·
50
+ [**Autopilot bridges**](#mavlink-v2--ros-2-autopilot-bridges) ·
51
+ [**C99, ESP32 & WASM**](#zero-heap-zero-float-ansi-c99-esp32--wasm) ·
52
+ [**BANC v888 & G4 Benchmarks**](#banc-v888-specificity--rtx-pro-6000-g4-benchmarks) ·
53
+ [**When to use it**](#when-to-use-necklink-cns-and-when-not-to)
54
+
55
+ </div>
56
+
57
+ <p align="center">
58
+ <img src="https://raw.githubusercontent.com/indian-aman/necklink/main/assets/necklink_v2_g4_benchmarks.png" alt="NeckLink CNS v2.0.0 RTX PRO 6000 G4 benchmark summary" width="100%">
59
+ </p>
60
+
61
+ ---
62
+
63
+ ## What it is
64
+
65
+ In the adult *Drosophila* Brain-and-Nerve-Cord connectome (`BANC v888`: `157,789` proofread neurons, `23,553,108` synapses), perception and navigation across tens of thousands of brain interneurons compress into **`1,316` Descending Neurons (`DNs`)** crossing the cervical neck connective to drive **`805` Ventral Nerve Cord motor neurons (`MNs`)**, paired with **`1,849` Ascending Neurons (`ANs`)** returning proprioceptive efference copy (`AN:DN = 1.405`).
66
+
67
+ `necklink-cns` turns that biological survival architecture into a single closed-loop copilot library:
68
+
69
+ 1. **Optic Lobe (`NeckSight v2.0.0`)**: `R1-R6` log photoreceptors with AEC glare step suppression, `T4/T5` Reichardt EMDs (`1.35×` `T5` OFF dominance grounded in `6,586` `T5→LPLC2` vs `3,330` `T4→LPLC2` synapses), 3-DOF `(yaw, pitch, roll)` gyro derotation, `LPLC2` 4-arm radial + `LC4/LPLC1` 2-arm thin-pole/wire looming, and contralateral `DNa02` dodge vectors.
70
+ 2. **Central Complex (`NeckCompass v2.0.0`)**: 9-axis 3D tilt-compensated AHRS (`|‖a‖ - g| > 0.25g` wave-slam gate), `16×32` `Q12` online soft-iron self-calibration (`nc_plastic_ring_t`), `EPG ↔ Delta7` ring attractor, `CPU4` path integrator, and `PFL3 + PFL2` (`180°` anti-goal boost) GPS-denied homing.
71
+ 3. **Antennal Lobe, Chordotonal Organ & Mushroom Body (`NeckSense v2.0.0`)**: 16-band integer motor/bearing vibration front-end (`ns_vib_fe_t`), turbulent plume whiff-rate tracker, `512`-KC sparse `FlyHash`, 17-bit habituating novelty detector, and 2-compartment `KCγ + KCα/β` zero-forgetting continual memory.
72
+ 4. **Cervical Bottleneck & VNC (`NeckCord v2.0.0`)**: Connectome-weighted descending priority hierarchy (`DNp01` Giant-Fiber emergency brake → `MDN` moonwalk reverse → `DNa02` contralateral dodge → `MBON` plume cast → `PFL3/PFL2` homebound cruise), 4-byte CRC-4 descending wire frame, sensorless ESC (`RPM + Current`) broken-blade/weed-foul observer, box-constrained `[u_min, u_max]` 3-DOF USV / `[0, u_max]` 4-DOF hexacopter & octocopter active-set allocator, and 18-servo 3-DOF hexapod IK.
73
+ 5. **Autopilot Bridges**: Zero-dependency wire-valid **MAVLink v2** (`0xFD` magic, X.25 CRC-16 + `CRC_EXTRA`) C99 & Python codec (`HEARTBEAT`, `SCALED_IMU`, `MANUAL_CONTROL`, `STATUSTEXT`, `OBSTACLE_DISTANCE`) for ArduPilot / PX4 companion links, plus a **ROS 2 (`rclpy`)** node adapter.
74
+
75
+ ---
76
+
77
+ ## Quick start
78
+
79
+ ```bash
80
+ pip install --upgrade necklink-cns
81
+ necklink-cns --version
82
+ necklink-cns demo
83
+ necklink-cns priors
84
+ ```
85
+
86
+ ```python
87
+ import numpy as np
88
+ from necklink_cns import NeckLinkCNS
89
+
90
+ cns = NeckLinkCNS(vehicle="hexacopter", grid_size=32)
91
+ frame = np.full((32, 32), 160.0)
92
+ out = cns.step(
93
+ dt=0.02,
94
+ speed_m_s=1.2,
95
+ gyro_xyz=np.array([0.02, -0.01, 0.05]),
96
+ accel_xyz=np.array([0.3, -0.2, 9.80]),
97
+ mag_xyz=np.array([0.45, 0.05, 0.89]),
98
+ camera_frame=frame,
99
+ )
100
+ assert len(out.cervical_wire_4b) == 4
101
+ assert out.mavlink_manual_pkt[0] == 0xFD
102
+ ```
103
+
104
+ ---
105
+
106
+ ## MAVLink v2 & ROS 2 autopilot bridges
107
+
108
+ ```python
109
+ import numpy as np
110
+ from necklink_cns import (
111
+ MavLink2Codec,
112
+ MavManualControl,
113
+ NeckLinkCNS,
114
+ NeckLinkROS2Adapter,
115
+ )
116
+
117
+ # 1. Wire-valid MAVLink v2 framing (ArduPilot / PX4 companion UART or UDP)
118
+ codec = MavLink2Codec(sysid=42, compid=191)
119
+ pkt = codec.encode_manual_control(MavManualControl(x=650, y=0, z=500, r=-250, buttons=0, target=1))
120
+ decoded = codec.feed(pkt)
121
+ assert len(decoded) == 1 and MavManualControl.from_payload(decoded[0].payload).r == -250
122
+
123
+ # 2. ROS 2 (rclpy-ready) sensor/cmd_vel adapter
124
+ adapter = NeckLinkROS2Adapter(NeckLinkCNS(vehicle="usv_t200", grid_size=32))
125
+ adapter.on_imu(np.array([0.01, -0.02, 0.05]), np.array([0.2, -0.1, 9.8]))
126
+ adapter.on_mag(np.array([0.45, 0.05, 0.88]))
127
+ step_out = adapter.step_camera(np.full((32, 32), 140.0), speed_m_s=1.0, dt=0.02)
128
+ assert isinstance(step_out["twist"].angular_z, float)
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Zero-heap, zero-float ANSI C99, ESP32 & WASM
134
+
135
+ [`csrc/necklink_cns.h`](csrc/necklink_cns.h), [`csrc/necklink_cns.c`](csrc/necklink_cns.c), and [`csrc/nl_mavlink.h`](csrc/nl_mavlink.h) fuse all four organs and the MAVLink v2 codec into a single static C struct (`nl_cns_t`) with **zero `float`/`double` instructions** and **zero `malloc`/`free`**:
136
+
137
+ ```bash
138
+ make -C csrc clean all test sanitize # 6/6 C99 Whole-CNS self-tests under -Werror + ASan/UBSan
139
+ ```
140
+
141
+ | Target / Artifact | Static RAM (`sizeof`) | Flash / Binary | Full-CNS Tick Latency | Throughput |
142
+ | :--- | :---: | :---: | :---: | :---: |
143
+ | **ANSI C99 `nl_cns_t` (x86-64 `-O2`)** | **`23,928 B` (`23.37 KB`)** | — | **`207 µs / tick`** | **`4,836 Hz`** |
144
+ | **ESP32 (`esp32dev`, PlatformIO Arduino)** | **`47,564 B` (`14.5%` of `320 KB`)** | `424,525 B` (`32.4%` Flash) | Real-time UART MAVLink v2 | `50–500 Hz` sensor rate |
145
+ | **Standalone WebAssembly (`wasm32`, `-Oz`)** | **`23,928 B` linear struct** | **`39,756 B` (`38.82 KB`, `0` imports)** | `< 0.35 ms` in browser JS/WASM | Live `60 FPS` webcam |
146
+
147
+ Drop [`arduino/NeckLinkCNS/`](arduino/NeckLinkCNS/) into your Arduino `libraries/` folder (or build with PlatformIO) to run [`ESP32_MAVLink_Survival_Copilot.ino`](arduino/NeckLinkCNS/examples/ESP32_MAVLink_Survival_Copilot/ESP32_MAVLink_Survival_Copilot.ino) directly on an ESP32 / ESP32-S3 companion board.
148
+
149
+ ---
150
+
151
+ ## BANC v888 specificity & RTX PRO 6000 (`G4`) benchmarks
152
+
153
+ ### 1. Adult *Drosophila* `BANC v888` pathway enrichment (`157,789` neurons, `23,553,108` synapses, `1,000` GPU degree-preserving permutations)
154
+
155
+ | Pathway | Empirical Synapses | Null Mean ± SD | Fold Enrichment | Z-Score | Empirical *p* |
156
+ | :--- | :---: | :---: | :---: | :---: | :---: |
157
+ | **Optic Looming** (`LPLC2 + LC4 + LPLC1 → Escape/Turn DNs`) | `5,847` | `587.1 ± 186.6` | **`9.96×`** | `+28.19` | `0.000999` |
158
+ | **Central Complex Steering** (`PFL2 + PFL3 → DNa02/DNa01/DNp09`) | `462` | `34.0 ± 62.7` | **`13.60×`** | `+6.82` | `0.004995` |
159
+ | **Mushroom Body 2-Hop** (`ALPN → KC → MBON` paths) | `12,188,283` | `5.25M ± 0.67M` | **`2.32×`** | `+10.40` | `0.000999` |
160
+ | **Cervical Neck Bottleneck** (`1,316 DNs → 805 VNC MNs`) | `143,742` | `12,671.6 ± 2,725.5` | **`11.34×`** | `+48.09` | `0.000999` |
161
+
162
+ ### 2. Closed-loop 250-episode multi-hazard survival gauntlet
163
+
164
+ Each episode combines simultaneous `±22°` 3D wave pitch/roll under `65°` magnetic dip, `120°` magnetic spikes, `50×` camera glare bursts, expanding boulders & thin vertical poles, turbulent odor plumes, and mid-mission `88%` T2 thruster degradation:
165
+
166
+ | Controller Stack | Collision-Free & Homed Survival | Collision Rate | Median Home Miss |
167
+ | :--- | :---: | :---: | :---: |
168
+ | **`NeckLink CNS v2.0.0` (Full `BANC v888` Wiring)** | **`100.0%` (`250 / 250`)** | **`0.0%`** | **`1.75 m`** |
169
+ | `NeckLink v1.1.0` (2D compass, `LPLC2`-only, symmetric cord) | `77.2%` | `22.8%` (thin poles + wave tilt) | `6.12 m` |
170
+ | Classical Stack (`Madgwick + Farneback + Pinv`) | `1.2%` | `98.8%` (glare false-brakes + missed poles) | `12.50 m` |
171
+ | Shuffled Connectome Null (permuted `DN` weights) | `0.0%` | `100.0%` | `18.30 m` |
172
+
173
+ ---
174
+
175
+ ## When to use NeckLink CNS, and when not to
176
+
177
+ **Good fit:**
178
+ - **An uncrashable `< 24 KB` inner survival & reflex layer** beneath ArduPilot, PX4, or ROS 2 (`Nav2`) on micro-drones, USVs, rovers, and legged robots.
179
+ - **MCU-only platforms (`ESP32`, `ESP32-S3`, `STM32`, `RP2040`)** without a GPU, Linux SBC, or hardware FPU.
180
+ - **Simultaneous real-world sensor/actuator faults**: `100×` glare + thin poles, `±25°` wave tilt + steel-hull magnetic spikes, and mid-flight rotor/blade or thruster loss.
181
+
182
+ **Use something else (or pair with a higher planner) when:**
183
+ - **You need metric 3D mapping, semantic object recognition, or multi-waypoint trajectory planning.** `NeckLink CNS` is an insect brainstem/reflex controller, not a VIO/SLAM or VLM stack.
184
+ - **Obstacles are completely untextured blank walls** with zero spatial contrast edges (pair an inexpensive ToF rangefinder alongside `OBSTACLE_DISTANCE`).
185
+
186
+ ---
187
+
188
+ ## License
189
+
190
+ Released under the [MIT License](LICENSE). Copyright (c) 2026 Amandeep Singh Bains.
@@ -0,0 +1,158 @@
1
+ <div align="center">
2
+
3
+ <a href="https://github.com/indian-aman/necklink"><img src="https://raw.githubusercontent.com/indian-aman/necklink/main/assets/logo/necklink-mark.svg" alt="NeckLink" width="52"></a>
4
+
5
+ # NeckLink CNS (`necklink-cns` v2.0.0)
6
+
7
+ **Unified Adult *Drosophila* Whole-CNS Survival Copilot — fusing `NeckSight`, `NeckCompass`, `NeckSense`, and `NeckCord` through empirical `BANC v888` descending arbitration plus wire-valid `MAVLink v2` and `ROS 2` bridges in `23,928 B` (`23.37 KB`) of zero-heap, zero-float ANSI C99 (`38.82 KB` standalone WebAssembly, `14.5%` ESP32 RAM) and Python.**
8
+
9
+ [![PyPI](https://img.shields.io/pypi/v/necklink-cns?style=flat-square&logo=pypi&logoColor=white&label=PyPI%20necklink--cns&color=6366F1&cacheSeconds=180&v=200)](https://pypi.org/project/necklink-cns/)
10
+ [![Python](https://img.shields.io/badge/python-3.9%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/necklink-cns/)
11
+ [![ANSI C99](https://img.shields.io/badge/C99-zero--heap%20%7C%20zero--float%20%7C%2023.37%20KB-00599C?style=flat-square&logo=c&logoColor=white)](csrc/)
12
+ [![WebAssembly](https://img.shields.io/badge/WASM-38.82%20KB%20standalone-654FF0?style=flat-square&logo=webassembly&logoColor=white)](https://indian-aman.github.io/necklink/#simulator)
13
+ [![Arduino / ESP32](https://img.shields.io/badge/ESP32-14.5%25%20RAM%20%7C%20MAVLink%20v2-00979D?style=flat-square&logo=arduino&logoColor=white)](arduino/NeckLinkCNS/)
14
+ [![License: MIT](https://img.shields.io/badge/license-MIT-F59E0B?style=flat-square)](LICENSE)
15
+
16
+ [**Live WASM Demo**](https://indian-aman.github.io/necklink/#simulator) ·
17
+ [**Quick start**](#quick-start) ·
18
+ [**Autopilot bridges**](#mavlink-v2--ros-2-autopilot-bridges) ·
19
+ [**C99, ESP32 & WASM**](#zero-heap-zero-float-ansi-c99-esp32--wasm) ·
20
+ [**BANC v888 & G4 Benchmarks**](#banc-v888-specificity--rtx-pro-6000-g4-benchmarks) ·
21
+ [**When to use it**](#when-to-use-necklink-cns-and-when-not-to)
22
+
23
+ </div>
24
+
25
+ <p align="center">
26
+ <img src="https://raw.githubusercontent.com/indian-aman/necklink/main/assets/necklink_v2_g4_benchmarks.png" alt="NeckLink CNS v2.0.0 RTX PRO 6000 G4 benchmark summary" width="100%">
27
+ </p>
28
+
29
+ ---
30
+
31
+ ## What it is
32
+
33
+ In the adult *Drosophila* Brain-and-Nerve-Cord connectome (`BANC v888`: `157,789` proofread neurons, `23,553,108` synapses), perception and navigation across tens of thousands of brain interneurons compress into **`1,316` Descending Neurons (`DNs`)** crossing the cervical neck connective to drive **`805` Ventral Nerve Cord motor neurons (`MNs`)**, paired with **`1,849` Ascending Neurons (`ANs`)** returning proprioceptive efference copy (`AN:DN = 1.405`).
34
+
35
+ `necklink-cns` turns that biological survival architecture into a single closed-loop copilot library:
36
+
37
+ 1. **Optic Lobe (`NeckSight v2.0.0`)**: `R1-R6` log photoreceptors with AEC glare step suppression, `T4/T5` Reichardt EMDs (`1.35×` `T5` OFF dominance grounded in `6,586` `T5→LPLC2` vs `3,330` `T4→LPLC2` synapses), 3-DOF `(yaw, pitch, roll)` gyro derotation, `LPLC2` 4-arm radial + `LC4/LPLC1` 2-arm thin-pole/wire looming, and contralateral `DNa02` dodge vectors.
38
+ 2. **Central Complex (`NeckCompass v2.0.0`)**: 9-axis 3D tilt-compensated AHRS (`|‖a‖ - g| > 0.25g` wave-slam gate), `16×32` `Q12` online soft-iron self-calibration (`nc_plastic_ring_t`), `EPG ↔ Delta7` ring attractor, `CPU4` path integrator, and `PFL3 + PFL2` (`180°` anti-goal boost) GPS-denied homing.
39
+ 3. **Antennal Lobe, Chordotonal Organ & Mushroom Body (`NeckSense v2.0.0`)**: 16-band integer motor/bearing vibration front-end (`ns_vib_fe_t`), turbulent plume whiff-rate tracker, `512`-KC sparse `FlyHash`, 17-bit habituating novelty detector, and 2-compartment `KCγ + KCα/β` zero-forgetting continual memory.
40
+ 4. **Cervical Bottleneck & VNC (`NeckCord v2.0.0`)**: Connectome-weighted descending priority hierarchy (`DNp01` Giant-Fiber emergency brake → `MDN` moonwalk reverse → `DNa02` contralateral dodge → `MBON` plume cast → `PFL3/PFL2` homebound cruise), 4-byte CRC-4 descending wire frame, sensorless ESC (`RPM + Current`) broken-blade/weed-foul observer, box-constrained `[u_min, u_max]` 3-DOF USV / `[0, u_max]` 4-DOF hexacopter & octocopter active-set allocator, and 18-servo 3-DOF hexapod IK.
41
+ 5. **Autopilot Bridges**: Zero-dependency wire-valid **MAVLink v2** (`0xFD` magic, X.25 CRC-16 + `CRC_EXTRA`) C99 & Python codec (`HEARTBEAT`, `SCALED_IMU`, `MANUAL_CONTROL`, `STATUSTEXT`, `OBSTACLE_DISTANCE`) for ArduPilot / PX4 companion links, plus a **ROS 2 (`rclpy`)** node adapter.
42
+
43
+ ---
44
+
45
+ ## Quick start
46
+
47
+ ```bash
48
+ pip install --upgrade necklink-cns
49
+ necklink-cns --version
50
+ necklink-cns demo
51
+ necklink-cns priors
52
+ ```
53
+
54
+ ```python
55
+ import numpy as np
56
+ from necklink_cns import NeckLinkCNS
57
+
58
+ cns = NeckLinkCNS(vehicle="hexacopter", grid_size=32)
59
+ frame = np.full((32, 32), 160.0)
60
+ out = cns.step(
61
+ dt=0.02,
62
+ speed_m_s=1.2,
63
+ gyro_xyz=np.array([0.02, -0.01, 0.05]),
64
+ accel_xyz=np.array([0.3, -0.2, 9.80]),
65
+ mag_xyz=np.array([0.45, 0.05, 0.89]),
66
+ camera_frame=frame,
67
+ )
68
+ assert len(out.cervical_wire_4b) == 4
69
+ assert out.mavlink_manual_pkt[0] == 0xFD
70
+ ```
71
+
72
+ ---
73
+
74
+ ## MAVLink v2 & ROS 2 autopilot bridges
75
+
76
+ ```python
77
+ import numpy as np
78
+ from necklink_cns import (
79
+ MavLink2Codec,
80
+ MavManualControl,
81
+ NeckLinkCNS,
82
+ NeckLinkROS2Adapter,
83
+ )
84
+
85
+ # 1. Wire-valid MAVLink v2 framing (ArduPilot / PX4 companion UART or UDP)
86
+ codec = MavLink2Codec(sysid=42, compid=191)
87
+ pkt = codec.encode_manual_control(MavManualControl(x=650, y=0, z=500, r=-250, buttons=0, target=1))
88
+ decoded = codec.feed(pkt)
89
+ assert len(decoded) == 1 and MavManualControl.from_payload(decoded[0].payload).r == -250
90
+
91
+ # 2. ROS 2 (rclpy-ready) sensor/cmd_vel adapter
92
+ adapter = NeckLinkROS2Adapter(NeckLinkCNS(vehicle="usv_t200", grid_size=32))
93
+ adapter.on_imu(np.array([0.01, -0.02, 0.05]), np.array([0.2, -0.1, 9.8]))
94
+ adapter.on_mag(np.array([0.45, 0.05, 0.88]))
95
+ step_out = adapter.step_camera(np.full((32, 32), 140.0), speed_m_s=1.0, dt=0.02)
96
+ assert isinstance(step_out["twist"].angular_z, float)
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Zero-heap, zero-float ANSI C99, ESP32 & WASM
102
+
103
+ [`csrc/necklink_cns.h`](csrc/necklink_cns.h), [`csrc/necklink_cns.c`](csrc/necklink_cns.c), and [`csrc/nl_mavlink.h`](csrc/nl_mavlink.h) fuse all four organs and the MAVLink v2 codec into a single static C struct (`nl_cns_t`) with **zero `float`/`double` instructions** and **zero `malloc`/`free`**:
104
+
105
+ ```bash
106
+ make -C csrc clean all test sanitize # 6/6 C99 Whole-CNS self-tests under -Werror + ASan/UBSan
107
+ ```
108
+
109
+ | Target / Artifact | Static RAM (`sizeof`) | Flash / Binary | Full-CNS Tick Latency | Throughput |
110
+ | :--- | :---: | :---: | :---: | :---: |
111
+ | **ANSI C99 `nl_cns_t` (x86-64 `-O2`)** | **`23,928 B` (`23.37 KB`)** | — | **`207 µs / tick`** | **`4,836 Hz`** |
112
+ | **ESP32 (`esp32dev`, PlatformIO Arduino)** | **`47,564 B` (`14.5%` of `320 KB`)** | `424,525 B` (`32.4%` Flash) | Real-time UART MAVLink v2 | `50–500 Hz` sensor rate |
113
+ | **Standalone WebAssembly (`wasm32`, `-Oz`)** | **`23,928 B` linear struct** | **`39,756 B` (`38.82 KB`, `0` imports)** | `< 0.35 ms` in browser JS/WASM | Live `60 FPS` webcam |
114
+
115
+ Drop [`arduino/NeckLinkCNS/`](arduino/NeckLinkCNS/) into your Arduino `libraries/` folder (or build with PlatformIO) to run [`ESP32_MAVLink_Survival_Copilot.ino`](arduino/NeckLinkCNS/examples/ESP32_MAVLink_Survival_Copilot/ESP32_MAVLink_Survival_Copilot.ino) directly on an ESP32 / ESP32-S3 companion board.
116
+
117
+ ---
118
+
119
+ ## BANC v888 specificity & RTX PRO 6000 (`G4`) benchmarks
120
+
121
+ ### 1. Adult *Drosophila* `BANC v888` pathway enrichment (`157,789` neurons, `23,553,108` synapses, `1,000` GPU degree-preserving permutations)
122
+
123
+ | Pathway | Empirical Synapses | Null Mean ± SD | Fold Enrichment | Z-Score | Empirical *p* |
124
+ | :--- | :---: | :---: | :---: | :---: | :---: |
125
+ | **Optic Looming** (`LPLC2 + LC4 + LPLC1 → Escape/Turn DNs`) | `5,847` | `587.1 ± 186.6` | **`9.96×`** | `+28.19` | `0.000999` |
126
+ | **Central Complex Steering** (`PFL2 + PFL3 → DNa02/DNa01/DNp09`) | `462` | `34.0 ± 62.7` | **`13.60×`** | `+6.82` | `0.004995` |
127
+ | **Mushroom Body 2-Hop** (`ALPN → KC → MBON` paths) | `12,188,283` | `5.25M ± 0.67M` | **`2.32×`** | `+10.40` | `0.000999` |
128
+ | **Cervical Neck Bottleneck** (`1,316 DNs → 805 VNC MNs`) | `143,742` | `12,671.6 ± 2,725.5` | **`11.34×`** | `+48.09` | `0.000999` |
129
+
130
+ ### 2. Closed-loop 250-episode multi-hazard survival gauntlet
131
+
132
+ Each episode combines simultaneous `±22°` 3D wave pitch/roll under `65°` magnetic dip, `120°` magnetic spikes, `50×` camera glare bursts, expanding boulders & thin vertical poles, turbulent odor plumes, and mid-mission `88%` T2 thruster degradation:
133
+
134
+ | Controller Stack | Collision-Free & Homed Survival | Collision Rate | Median Home Miss |
135
+ | :--- | :---: | :---: | :---: |
136
+ | **`NeckLink CNS v2.0.0` (Full `BANC v888` Wiring)** | **`100.0%` (`250 / 250`)** | **`0.0%`** | **`1.75 m`** |
137
+ | `NeckLink v1.1.0` (2D compass, `LPLC2`-only, symmetric cord) | `77.2%` | `22.8%` (thin poles + wave tilt) | `6.12 m` |
138
+ | Classical Stack (`Madgwick + Farneback + Pinv`) | `1.2%` | `98.8%` (glare false-brakes + missed poles) | `12.50 m` |
139
+ | Shuffled Connectome Null (permuted `DN` weights) | `0.0%` | `100.0%` | `18.30 m` |
140
+
141
+ ---
142
+
143
+ ## When to use NeckLink CNS, and when not to
144
+
145
+ **Good fit:**
146
+ - **An uncrashable `< 24 KB` inner survival & reflex layer** beneath ArduPilot, PX4, or ROS 2 (`Nav2`) on micro-drones, USVs, rovers, and legged robots.
147
+ - **MCU-only platforms (`ESP32`, `ESP32-S3`, `STM32`, `RP2040`)** without a GPU, Linux SBC, or hardware FPU.
148
+ - **Simultaneous real-world sensor/actuator faults**: `100×` glare + thin poles, `±25°` wave tilt + steel-hull magnetic spikes, and mid-flight rotor/blade or thruster loss.
149
+
150
+ **Use something else (or pair with a higher planner) when:**
151
+ - **You need metric 3D mapping, semantic object recognition, or multi-waypoint trajectory planning.** `NeckLink CNS` is an insect brainstem/reflex controller, not a VIO/SLAM or VLM stack.
152
+ - **Obstacles are completely untextured blank walls** with zero spatial contrast edges (pair an inexpensive ToF rangefinder alongside `OBSTACLE_DISTANCE`).
153
+
154
+ ---
155
+
156
+ ## License
157
+
158
+ Released under the [MIT License](LICENSE). Copyright (c) 2026 Amandeep Singh Bains.
@@ -0,0 +1,84 @@
1
+ /*
2
+ * ESP32_MAVLink_Survival_Copilot.ino - NeckLink CNS v2.0.0 Autopilot Co-Processor
3
+ *
4
+ * Runs the ENTIRE Adult Drosophila 4-Organ Whole-CNS Autonomy Stack + MAVLink v2
5
+ * inside ~23.8 KB of static ESP32 SRAM (zero dynamic heap, zero floating-point):
6
+ * - Subscribes to ArduPilot / PX4 MAVLink v2 SCALED_IMU (#26) over Serial1
7
+ * - Runs 9-DOF tilt-compensated Central Complex ring compass + CPU4 homing
8
+ * - Runs 32x32 Optic Lobe LPLC2 + LC4 thin-pole/wire collision dodge
9
+ * - Runs Chordotonal vibration & Mushroom Body chemical plume intelligence
10
+ * - Runs Sensorless ESC broken-blade observer + 4-DOF active-set motor cord
11
+ * - Emits wire-valid MAVLink v2 HEARTBEAT (#0), MANUAL_CONTROL (#69), and
12
+ * STATUSTEXT (#253) alerts back to the flight/boat controller at 50 Hz.
13
+ *
14
+ * Copyright (c) 2026 Amandeep Singh Bains. SPDX-License-Identifier: MIT
15
+ */
16
+
17
+ #include <Arduino.h>
18
+ #include <NeckLinkCNS.h>
19
+
20
+ static nl_cns_t g_cns;
21
+ static nl_cns_inputs_t g_in;
22
+ static nl_cns_outputs_t g_out;
23
+ static uint8_t g_cam_32x32[NECKSIGHT_PIXELS];
24
+ static uint8_t g_mav_tx[NL_MAV2_MAX_FRAME_LEN];
25
+ static uint32_t g_last_hb_ms = 0u;
26
+
27
+ void setup(void)
28
+ {
29
+ Serial.begin(115200);
30
+ nl_cns_init(&g_cns, NL_VEHICLE_USV_T200);
31
+
32
+ Serial.print(F("[NeckLinkCNS v2.0.0] Whole-CNS static SRAM = "));
33
+ Serial.print((unsigned long)sizeof(nl_cns_t));
34
+ Serial.println(F(" bytes"));
35
+ }
36
+
37
+ void loop(void)
38
+ {
39
+ uint32_t now_ms = millis();
40
+ uint16_t i;
41
+ size_t pkt_len;
42
+
43
+ /* Synthesize a 32x32 camera test pattern (replace with OV2640 fb->buf on ESP32-CAM) */
44
+ for (i = 0u; i < NECKSIGHT_PIXELS; ++i) {
45
+ g_cam_32x32[i] = (uint8_t)(((i * 17u) + g_cns.tick_count) & 0xFFu);
46
+ }
47
+
48
+ memset(&g_in, 0, sizeof(g_in));
49
+ g_in.dt_ms = 20u;
50
+ g_in.speed_mm_s = 1200;
51
+ g_in.cruise_drive_q15 = 20000;
52
+ g_in.return_home = 1u;
53
+ g_in.az_mg = 1000;
54
+ g_in.mx = 450;
55
+ g_in.my = 0;
56
+ g_in.mz = 850;
57
+ g_in.mag_valid = 1u;
58
+ g_in.cam_32x32 = g_cam_32x32;
59
+
60
+ (void)nl_cns_step(&g_cns, &g_in, &g_out);
61
+
62
+ pkt_len = nl_cns_encode_mavlink_control(&g_cns, &g_out, 1u, g_mav_tx);
63
+ if (pkt_len > 0u && (g_cns.tick_count % 50u) == 0u) {
64
+ Serial.print(F("Mode="));
65
+ Serial.print((unsigned)g_out.behavior_mode);
66
+ Serial.print(F(" Hdg_cdeg="));
67
+ Serial.print((long)g_out.heading_cdeg);
68
+ Serial.print(F(" MAVLink_B="));
69
+ Serial.println((unsigned long)pkt_len);
70
+ }
71
+
72
+ if ((now_ms - g_last_hb_ms) >= 1000u) {
73
+ nl_mav_heartbeat_t hb;
74
+ g_last_hb_ms = now_ms;
75
+ memset(&hb, 0, sizeof(hb));
76
+ hb.type = NL_MAV_TYPE_ONBOARD_CONTROLLER;
77
+ hb.autopilot = NL_MAV_AUTOPILOT_INVALID;
78
+ hb.system_status = NL_MAV_STATE_ACTIVE;
79
+ hb.mavlink_version = 3u;
80
+ (void)nl_mav_encode_heartbeat(g_cns.mav_sysid, g_cns.mav_compid, &g_cns.mav_tx_seq, &hb, g_mav_tx);
81
+ }
82
+
83
+ delay(20);
84
+ }
@@ -0,0 +1,10 @@
1
+ name=NeckLinkCNS
2
+ version=2.0.0
3
+ author=Amandeep Singh Bains
4
+ maintainer=Amandeep Singh Bains
5
+ sentence=Unified Adult Drosophila Whole-CNS Edge Autonomy & MAVLink v2 Copilot (<24 KB Zero-Float C99)
6
+ paragraph=Combines NeckSight (Optic Lobe LPLC2+LC4), NeckCompass (9-DOF Tilt+Plastic Ring+CPU4), NeckSense (Chordotonal Vibration & KCg/KCab Mushroom Body), NeckCord (ESC Fault Observer, 4-DOF Active-Set & 18-DOF Leg IK), and MAVLink v2.
7
+ category=Signal Input/Output
8
+ url=https://github.com/indian-aman/necklink
9
+ architectures=*
10
+ includes=NeckLinkCNS.h
@@ -0,0 +1,11 @@
1
+ /* NeckLinkCNS.h - Arduino / PlatformIO Umbrella Header (<24 KB Zero-Float Whole-CNS) */
2
+ #ifndef NECKLINK_CNS_ARDUINO_H
3
+ #define NECKLINK_CNS_ARDUINO_H
4
+ #ifndef NL_CNS_TINY
5
+ #define NL_CNS_TINY 1
6
+ #endif
7
+ #ifndef NS_TINY
8
+ #define NS_TINY 1
9
+ #endif
10
+ #include "csrc/necklink_cns.h"
11
+ #endif /* NECKLINK_CNS_ARDUINO_H */