neckcord 1.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.
neckcord-1.0.0/LICENSE ADDED
@@ -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,11 @@
1
+ include LICENSE
2
+ include README.md
3
+ include pyproject.toml
4
+ recursive-include neckcord *.py py.typed
5
+ recursive-include csrc *.c *.h Makefile
6
+ prune csrc/build
7
+ prune assets
8
+ prune dist
9
+ prune results
10
+ prune scripts
11
+ prune tests
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.4
2
+ Name: neckcord
3
+ Version: 1.0.0
4
+ Summary: Descending cervical 4-byte command bottleneck, self-healing hexapod VNC CPG, and presynaptic-shunting fault-tolerant thruster allocator
5
+ Author: Amandeep Singh Bains
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/indian-aman/neckcord
8
+ Project-URL: Repository, https://github.com/indian-aman/neckcord
9
+ Project-URL: Releases, https://github.com/indian-aman/neckcord/releases
10
+ Project-URL: Issues, https://github.com/indian-aman/neckcord/issues
11
+ Project-URL: Documentation, https://github.com/indian-aman/neckcord#readme
12
+ Keywords: neckcord,necklink,drosophila,connectome,descending-neurons,ventral-nerve-cord,cpg,kuramoto,control-allocation,fault-tolerant-control,usv,rov,hexapod,robotics,embedded-c99
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: C
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
25
+ Classifier: Topic :: System :: Hardware :: Hardware Drivers
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: numpy>=1.24
30
+ Provides-Extra: nltp
31
+ Requires-Dist: pynltp>=1.2.0; extra == "nltp"
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=7.0; extra == "dev"
34
+ Requires-Dist: matplotlib>=3.7; extra == "dev"
35
+ Requires-Dist: build>=1.0; extra == "dev"
36
+ Requires-Dist: twine>=5.0; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ <div align="center">
40
+
41
+ # NeckCord (`neckcord` v1.0.0)
42
+
43
+ **4-byte descending cervical command bottleneck, self-healing hexapod VNC phase CPG, and millisecond presynaptic-shunting thruster control allocation — in Python and zero-heap, zero-float ANSI C99.**
44
+
45
+ [![PyPI](https://img.shields.io/pypi/v/neckcord?style=flat-square&logo=pypi&logoColor=white&label=PyPI%20neckcord&color=0284C7)](https://pypi.org/project/neckcord/)
46
+ [![Release](https://img.shields.io/badge/release-v1.0.0-0EA5E9?style=flat-square)](https://github.com/indian-aman/neckcord/releases/tag/v1.0.0)
47
+ [![Python](https://img.shields.io/badge/python-3.9%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/neckcord/)
48
+ [![ANSI C99](https://img.shields.io/badge/C99-zero--heap%20%7C%20zero--float%20%7C%20304%20B%20RAM-00599C?style=flat-square&logo=c&logoColor=white)](csrc/)
49
+ [![Wire Bandwidth](https://img.shields.io/badge/cervical%20frame-4%20bytes%20(400%20B%2Fs%20%40%20100%20Hz)-10B981?style=flat-square)](neckcord/cervical.py)
50
+ [![Tests](https://img.shields.io/badge/tests-22%20Py%20%2B%2010%20C99%20passed-10B981?style=flat-square)](tests/test_neckcord.py)
51
+ [![License: MIT](https://img.shields.io/badge/license-MIT-F59E0B?style=flat-square)](LICENSE)
52
+
53
+ [**Quick Start**](#-30-second-quick-start) ·
54
+ [**4-Byte Cervical Codec**](#1-4-byte-descending-cervical-command-frame-neckcordcervical) ·
55
+ [**Self-Healing Hexapod CPG**](#2-segmental-vnc-hexapod-cpg-neckcordcpg) ·
56
+ [**Shunting Thruster Allocator**](#3-presynaptic-shunting-thruster-cord-neckcordallocator) ·
57
+ [**Zero-Float ANSI C99**](#-zero-heap-zero-float-ansi-c99-core-csrc) ·
58
+ [**Benchmarks**](#-empirical-benchmarks) ·
59
+ [**When to Use**](#-when-to-use-neckcord--and-when-not-to)
60
+
61
+ </div>
62
+
63
+ <p align="center">
64
+ <img src="https://raw.githubusercontent.com/indian-aman/neckcord/main/assets/neckcord_benchmarks.png" alt="NeckCord v1.0.0 USV Thruster Fault Reallocation and Hexapod Leg-Loss Benchmarks" width="100%">
65
+ </p>
66
+
67
+ ---
68
+
69
+ ## Biological Architecture: Brain → Cervical Bottleneck → Self-Healing VNC
70
+
71
+ In *Drosophila melanogaster*, roughly ~1,300 descending neurons cross a tiny cervical neck connective to coordinate thousands of thoracic motor units (`BANC` / `MANC` connectomes; Braun et al., *Nature* 2024; Lesser et al., *Nature* 2024). Rather than streaming high-rate per-muscle waveforms over the neck bottleneck, the brain sends compact behavioral intent (`DNa02` bilateral steering, `DNp09` forward drive, `MDN` reverse walk, `Giant Fiber` emergency freeze), while the **Ventral Nerve Cord (`VNC`)** handles local rhythm generation, **campaniform sensilla** load-error monitoring, and **presynaptic shunting** injury adaptation.
72
+
73
+ **NeckCord** (Product #5 in the [**NeckLink**](https://github.com/indian-aman/necklink) fruit-fly brain ecosystem) brings this exact split architecture to marine USVs, ROVs, multirotors, and legged robots:
74
+
75
+ 1. **4-Byte Cervical Command Frame (`neckcord.cervical`)**: Packs `drive_fwd`, `turn_yaw`, `strafe_lat`, `gait_mode`, `freeze_reflex`, a `2-bit` rolling sequence counter, and `4-bit` bus-fault-hardened `CRC-4` into **`32 bits` (`400 B/s` at `100 Hz`)** — `6.0x` smaller than raw `4×float32 + header` actuator streams and ready to ride directly inside [`pynltp`](https://pypi.org/project/pynltp/) frames over lossy marine radio or cellular CGNAT links.
76
+ 2. **Segmental 6-Limb VNC CPG (`neckcord.cpg.SegmentalCPGCord`)**: Phase-coupled Kuramoto oscillator network with contralateral commissural anti-phase inhibition and ipsilateral intersegmental lags. Smoothly transitions across **Metachronal Wave**, **Tetrapod**, and **Tripod** gaits from a single scalar descending drive, and automatically re-indexes into a **5-limb pentapod ring (`Δφ = 72°`, duty `0.82`) + ipsilateral foothold gap-closure reflex** (`100.0%` static CoM support-polygon stability) when any leg jams or loses load.
77
+ 3. **Presynaptic-Shunting Thruster Allocator (`neckcord.allocator.ShuntingThrusterCord`)**: Online fault-tolerant wrench allocator (`W H W^T + λI`) for `4`–`8` actuators. Detects weed-fouling, propulsor shear, or ESC brownout from campaniform effort-vs-feedback discrepancy in **`~42 ms`**, shunts drive away from the fouled thruster (`0.02 N` wasted effort), and rebalances `surge`, `sway`, and `yaw` across surviving thrusters with yaw/sway-prioritized desaturation.
78
+
79
+ ```mermaid
80
+ flowchart LR
81
+ A["Shore / Brain Planner"] -->|"4-Byte DescendingFrame (400 B/s @ 100 Hz, CRC-4)"| B["Cervical Bottleneck (UART / CAN / pynltp)"]
82
+ B --> C["SegmentalCPGCord (6-Limb Tripod / Tetrapod / Wave / 5-Leg Heal)"]
83
+ B --> D["ShuntingThrusterCord (4..8 Ch W*H*W^T + λI Reallocator)"]
84
+ E["Campaniform Load / ESC Feedback"] -->|"Effort Discrepancy (42 ms)"| C
85
+ E -->|"Presynaptic Shunting (s_i -> 0)"| D
86
+ ```
87
+
88
+ ---
89
+
90
+ ## ⚡ 30-Second Quick Start
91
+
92
+ ### Install
93
+
94
+ ```bash
95
+ pip install neckcord
96
+ # Optional NLTP encrypted radio/UDP transport integration:
97
+ pip install "neckcord[nltp]"
98
+ ```
99
+
100
+ ### Run from the Terminal
101
+
102
+ ```bash
103
+ neckcord demo
104
+ neckcord benchmark-quick
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Python API
110
+
111
+ ### 1. 4-Byte Descending Cervical Command Frame (`neckcord.cervical`)
112
+
113
+ ```python
114
+ from neckcord import DescendingFrame, GaitMode, encode_descending_4b, decode_descending_4b
115
+
116
+ tx = DescendingFrame(
117
+ drive_fwd=0.82, # DNp09 forward (+1) / MDN Moonwalker reverse (-1)
118
+ turn_yaw=-0.25, # DNa02 bilateral steering [-1, +1]
119
+ strafe_lat=0.10, # Lateral sway / crab walk [-1, +1]
120
+ gait_mode=GaitMode.AUTO,
121
+ freeze_reflex=False,
122
+ seq=2,
123
+ )
124
+
125
+ raw = encode_descending_4b(tx) # b'\x68\xe0\x0c\x20' (4 bytes = 32 bits)
126
+ rx = decode_descending_4b(raw, expected_seq=2)
127
+ wrench = rx.to_wrench(max_surge=60.0, max_sway=40.0, max_yaw=25.0)
128
+ ```
129
+
130
+ | Bits | Field | Encoding | Resolution / Role |
131
+ | :--- | :--- | :--- | :--- |
132
+ | `[31:24]` | `drive_fwd` | `8-bit` symmetric `-127..+127` | `0.0079` step, exact `0.0` & `±1.0` |
133
+ | `[23:16]` | `turn_yaw` | `8-bit` symmetric `-127..+127` | `0.0079` step, exact `0.0` & `±1.0` |
134
+ | `[15:9]` | `strafe_lat` | `7-bit` symmetric `-63..+63` | `0.0159` step, exact `0.0` & `±1.0` |
135
+ | `[8:7]` | `gait_mode` | `2-bit` unsigned `0..3` | `0=AUTO`, `1=TRIPOD`, `2=TETRAPOD`, `3=WAVE` |
136
+ | `[6]` | `freeze_reflex` | `1-bit` flag | `Giant Fiber` instant stance lock / zero wrench |
137
+ | `[5:4]` | `seq` | `2-bit` rolling counter | `0..3` packet-loss & reorder tracking |
138
+ | `[3:0]` | `crc4` | `x^4 + x + 1` (`init=0x9, xor=0x5`) | Rejects `100%` of 1-bit flips, `0x00000000` & `0xFFFFFFFF` |
139
+
140
+ ### 2. Segmental VNC Hexapod CPG (`neckcord.cpg`)
141
+
142
+ ```python
143
+ from neckcord import SegmentalCPGCord
144
+
145
+ cpg = SegmentalCPGCord(adapt_to_damage=True)
146
+
147
+ # Fast forward command -> Tripod gait; low speed -> Metachronal Wave
148
+ state = cpg.step(raw, dt=0.01)
149
+
150
+ # Simulate sudden middle-left leg (L2) jam / amputation mid-stride:
151
+ cpg.inject_limb_fault("L2")
152
+ for _ in range(100):
153
+ state = cpg.step(0.85, dt=0.01)
154
+
155
+ assert state.active_gait == "adaptive_pentapod"
156
+ assert state.is_statically_stable is True # CoM strictly inside >=3-leg polygon!
157
+ ```
158
+
159
+ ### 3. Presynaptic-Shunting Thruster Cord (`neckcord.allocator`)
160
+
161
+ ```python
162
+ import numpy as np
163
+ from neckcord import ShuntingThrusterCord
164
+
165
+ # Standard 4-thruster X-vectored marine USV / ROV (Port-Fore, Stbd-Fore, Port-Aft, Stbd-Aft)
166
+ cord = ShuntingThrusterCord.usv_vectored_4(lx=0.45, ly=0.35, cant_deg=45.0, u_max=35.0)
167
+
168
+ w_des = np.array([35.0, 0.0, 0.0]) # Pure forward surge [Fx, Fy, Tz]
169
+ alloc = cord.step(w_des, dt=0.02)
170
+
171
+ # Port-Aft thruster (index 2) gets fouled by kelp (90% loss of thrust):
172
+ true_effectiveness = np.array([1.0, 1.0, 0.10, 1.0])
173
+ for _ in range(4):
174
+ measured_thrust = true_effectiveness * alloc.commands
175
+ alloc = cord.step(w_des, feedback_thrust=measured_thrust, dt=0.02)
176
+
177
+ # T2 is shunted to 0.0 N; T0 & T1 rebalance pure forward surge with zero yaw spin!
178
+ assert alloc.isolated_mask[2] and alloc.commands[2] == 0.0
179
+ ```
180
+
181
+ ---
182
+
183
+ ## 🔧 Zero-Heap, Zero-Float ANSI C99 Core (`csrc/`)
184
+
185
+ [`csrc/neckcord.h`](csrc/neckcord.h) and [`csrc/neckcord.c`](csrc/neckcord.c) implement the complete `NeckCord` stack in pure fixed-point `Q15` / `Q14` / `16-bit BAM` integer arithmetic for bare-metal `STM32`, `ESP32`, `RP2040`, and safety MCUs without an FPU:
186
+
187
+ - **Zero dynamic allocation**: No `malloc`, `calloc`, `realloc`, or `free`.
188
+ - **Zero floating-point instructions**: Quarter-wave `65`-entry `Q15` sine lookup table (`130 B` ROM) + exact `int64_t` `3×3` Gram cofactor solver and integer cross-product CoM convex-hull verifier.
189
+ - **`304 bytes` total runtime state**: Combined `sizeof` all 5 state/result structs (`< 10%` of the `3 KB` static RAM budget).
190
+ - **100% wire-compatible with Python**: Encodes and decodes identical 4-byte frames (`0x68E00C20`).
191
+
192
+ ```bash
193
+ cd csrc && make clean all test
194
+ # Compiles cleanly under: gcc -O2 -std=c99 -Wall -Wextra -pedantic -Werror (10/10 passed)
195
+ ```
196
+
197
+ ---
198
+
199
+ ## 📊 Empirical Benchmarks
200
+
201
+ Reproduce all numbers and regenerate `assets/neckcord_benchmarks.png` and `results/benchmark_summary.json` locally:
202
+
203
+ ```bash
204
+ python scripts/benchmark_neckcord.py
205
+ ```
206
+
207
+ ### 1. 3-DOF X-Vectored 4-Thruster USV Corridor Tracking (`dt = 0.02 s`, `30 s`, `10` Irregular Wave Seeds)
208
+
209
+ Both architectures use the **exact same Fossen 3-DOF hull model, wave seeds, and outer LOS + PID controller**:
210
+
211
+ | Scenario & Metric | `Static Pseudo-Inverse + Raw Float32` | `NeckCord (4B Cervical + Shunting VNC)` | Outcome |
212
+ | :--- | :---: | :---: | :--- |
213
+ | **Command Link Bandwidth (`100 Hz`)** | `2,400 B/s` (`24 B/frame`) | **`400 B/s` (`4 B/frame`)** | **`6.0x` lower wire bandwidth** |
214
+ | **Intact Fleet (`100%` Health) — RMS XTE** | `0.108 m` (`0.233 m` max) | `0.109 m` (`0.233 m` max) | **Identical nominal tracking (`1 mm`)** |
215
+ | **Intact Fleet (`100%` Health) — Peak Yaw** | `4.84° ± 0.94°` | `4.81° ± 0.79°` | **No quantization degradation** |
216
+ | **`90%` Port-Aft Loss (`t = 8 s`) — Peak Yaw** | `24.19° ± 2.28°` | **`4.77° ± 0.65°`** | **`5.07x` less heading spin-out** |
217
+ | **`90%` Port-Aft Loss (`t = 8 s`) — RMS XTE** | `0.498 m` (`0.735 m` max) | **`0.112 m` (`0.224 m` max)** | **`4.45x` tighter corridor tracking** |
218
+ | **Fault Isolation Latency** | Never isolated | **`42.0 ms`** | **Shunted in ~2 control ticks** |
219
+ | **Mean Drive Sent to Fouled `T2` Thruster** | `22.70 N` | **`0.02 N`** | **Protects jammed ESC / windings** |
220
+
221
+ ### 2. Hexapod Single-Leg Jam (`L2` Middle-Left Lost at Fast `0.85` Drive)
222
+
223
+ | Condition | `%` Cycle in `>=3`-Leg CoM Static Support Polygon | Min CoM Stability Margin |
224
+ | :--- | :---: | :---: |
225
+ | **Intact 6-Leg Tripod** | `100.0%` | `+3.90 cm` |
226
+ | **`L2` Jammed — Unadapted Tripod CPG** | `55.0%` *(tips out of polygon every half-stride)* | `< 0 cm` *(collinear 2-leg phase)* |
227
+ | **`L2` Jammed — NeckCord Adaptive VNC** | **`100.0%`** | **`+2.24 cm`** |
228
+ | **All 6 Single-Leg Faults (`L1..R3` Mean) — NeckCord** | **`100.0%`** | **`+1.89 to +2.24 cm`** |
229
+
230
+ ---
231
+
232
+ ## 🎯 When to Use NeckCord — and When Not To
233
+
234
+ **Reach for `NeckCord` when:**
235
+ - Controlling **4-to-8 thruster vectored USVs, ROVs, or multirotors** exposed to kelp/weed fouling, propulsor damage, or ESC brownouts where losing one actuator would otherwise spin the vehicle off heading and burn the stalled motor.
236
+ - Streaming real-time operator or autonomy commands across **narrow, lossy acoustic, LoRa, marine UHF, or `4G`/`5G` links** (`400 B/s` at `100 Hz` — pairs directly with `pynltp`).
237
+ - Running **hexapod robots or bare-metal C99 motor cords** (`304 B` RAM, zero FPU/heap) that need smooth single-parameter gait transitions (`Wave ↔ Tetrapod ↔ Tripod`) and instant 5-legged self-healing on leg failure.
238
+
239
+ **Stick with standard tools when:**
240
+ - **Underactuated 2-thruster differential hulls with no bow thruster or rudder**: If 1 of 2 fixed parallel thrusters dies completely, no allocator can produce forward surge without net yaw moment (`rank(W_surviving) = 1 < 2`).
241
+ - **Clean local wired buses on healthy, un-faulted vehicles**: As shown in our intact-fleet benchmark above, a 3-line static Moore-Penrose pseudo-inverse achieves identical nominal tracking (`0.108 m` vs `0.109 m` XTE) when all actuators remain `100%` healthy.
242
+ - **Asymmetric unidirectional thrusters (`u_i >= 0` only, e.g. non-reversible quadrotor props in 6-DOF)**: `ShuntingThrusterCord` assumes bidirectional control authority (`[-u_max, +u_max]`) with yaw/sway-prioritized scaling; strictly non-negative polyhedral actuator bounds with `> 6` coupled DOFs are better served by an active-set QP solver (`OSQP` / `proxqp`).
243
+
244
+ ---
245
+
246
+ ## 🗂️ Repository Layout
247
+
248
+ | Path | Description |
249
+ | :--- | :--- |
250
+ | [`neckcord/cervical.py`](neckcord/cervical.py) | `DescendingFrame`, `encode_descending_4b`, `decode_descending_4b`, `CRC-4`, `CervicalBottleneckLink` |
251
+ | [`neckcord/cpg.py`](neckcord/cpg.py) | `SegmentalCPGCord` 6-limb Kuramoto CPG, gait transitions, pentapod + gap-closure self-healing |
252
+ | [`neckcord/allocator.py`](neckcord/allocator.py) | `ShuntingThrusterCord` online health estimation, presynaptic shunting, `W H W^T + λI` allocator |
253
+ | [`neckcord/cli.py`](neckcord/cli.py) | `neckcord` CLI (`demo`, `benchmark-quick`, `--json`) |
254
+ | [`csrc/`](csrc/) | Zero-heap, zero-float `Q15`/`Q14` ANSI C99 core (`neckcord.h`, `neckcord.c`, `10/10` `neckcord_selftest.c`) |
255
+ | [`scripts/benchmark_neckcord.py`](scripts/benchmark_neckcord.py) | 10-seed 3-DOF USV + 6-limb hexapod benchmark & 3-panel hero chart generator |
256
+ | [`results/benchmark_summary.json`](results/benchmark_summary.json) | Reproducible empirical benchmark output JSON |
257
+ | [`tests/test_neckcord.py`](tests/test_neckcord.py) | `22` `pytest` unit, edge-case, CLI, and C99 source-audit tests |
258
+
259
+ ---
260
+
261
+ ## License
262
+
263
+ Released under the [MIT License](LICENSE). Copyright (c) 2026 Amandeep Singh Bains.
@@ -0,0 +1,225 @@
1
+ <div align="center">
2
+
3
+ # NeckCord (`neckcord` v1.0.0)
4
+
5
+ **4-byte descending cervical command bottleneck, self-healing hexapod VNC phase CPG, and millisecond presynaptic-shunting thruster control allocation — in Python and zero-heap, zero-float ANSI C99.**
6
+
7
+ [![PyPI](https://img.shields.io/pypi/v/neckcord?style=flat-square&logo=pypi&logoColor=white&label=PyPI%20neckcord&color=0284C7)](https://pypi.org/project/neckcord/)
8
+ [![Release](https://img.shields.io/badge/release-v1.0.0-0EA5E9?style=flat-square)](https://github.com/indian-aman/neckcord/releases/tag/v1.0.0)
9
+ [![Python](https://img.shields.io/badge/python-3.9%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/neckcord/)
10
+ [![ANSI C99](https://img.shields.io/badge/C99-zero--heap%20%7C%20zero--float%20%7C%20304%20B%20RAM-00599C?style=flat-square&logo=c&logoColor=white)](csrc/)
11
+ [![Wire Bandwidth](https://img.shields.io/badge/cervical%20frame-4%20bytes%20(400%20B%2Fs%20%40%20100%20Hz)-10B981?style=flat-square)](neckcord/cervical.py)
12
+ [![Tests](https://img.shields.io/badge/tests-22%20Py%20%2B%2010%20C99%20passed-10B981?style=flat-square)](tests/test_neckcord.py)
13
+ [![License: MIT](https://img.shields.io/badge/license-MIT-F59E0B?style=flat-square)](LICENSE)
14
+
15
+ [**Quick Start**](#-30-second-quick-start) ·
16
+ [**4-Byte Cervical Codec**](#1-4-byte-descending-cervical-command-frame-neckcordcervical) ·
17
+ [**Self-Healing Hexapod CPG**](#2-segmental-vnc-hexapod-cpg-neckcordcpg) ·
18
+ [**Shunting Thruster Allocator**](#3-presynaptic-shunting-thruster-cord-neckcordallocator) ·
19
+ [**Zero-Float ANSI C99**](#-zero-heap-zero-float-ansi-c99-core-csrc) ·
20
+ [**Benchmarks**](#-empirical-benchmarks) ·
21
+ [**When to Use**](#-when-to-use-neckcord--and-when-not-to)
22
+
23
+ </div>
24
+
25
+ <p align="center">
26
+ <img src="https://raw.githubusercontent.com/indian-aman/neckcord/main/assets/neckcord_benchmarks.png" alt="NeckCord v1.0.0 USV Thruster Fault Reallocation and Hexapod Leg-Loss Benchmarks" width="100%">
27
+ </p>
28
+
29
+ ---
30
+
31
+ ## Biological Architecture: Brain → Cervical Bottleneck → Self-Healing VNC
32
+
33
+ In *Drosophila melanogaster*, roughly ~1,300 descending neurons cross a tiny cervical neck connective to coordinate thousands of thoracic motor units (`BANC` / `MANC` connectomes; Braun et al., *Nature* 2024; Lesser et al., *Nature* 2024). Rather than streaming high-rate per-muscle waveforms over the neck bottleneck, the brain sends compact behavioral intent (`DNa02` bilateral steering, `DNp09` forward drive, `MDN` reverse walk, `Giant Fiber` emergency freeze), while the **Ventral Nerve Cord (`VNC`)** handles local rhythm generation, **campaniform sensilla** load-error monitoring, and **presynaptic shunting** injury adaptation.
34
+
35
+ **NeckCord** (Product #5 in the [**NeckLink**](https://github.com/indian-aman/necklink) fruit-fly brain ecosystem) brings this exact split architecture to marine USVs, ROVs, multirotors, and legged robots:
36
+
37
+ 1. **4-Byte Cervical Command Frame (`neckcord.cervical`)**: Packs `drive_fwd`, `turn_yaw`, `strafe_lat`, `gait_mode`, `freeze_reflex`, a `2-bit` rolling sequence counter, and `4-bit` bus-fault-hardened `CRC-4` into **`32 bits` (`400 B/s` at `100 Hz`)** — `6.0x` smaller than raw `4×float32 + header` actuator streams and ready to ride directly inside [`pynltp`](https://pypi.org/project/pynltp/) frames over lossy marine radio or cellular CGNAT links.
38
+ 2. **Segmental 6-Limb VNC CPG (`neckcord.cpg.SegmentalCPGCord`)**: Phase-coupled Kuramoto oscillator network with contralateral commissural anti-phase inhibition and ipsilateral intersegmental lags. Smoothly transitions across **Metachronal Wave**, **Tetrapod**, and **Tripod** gaits from a single scalar descending drive, and automatically re-indexes into a **5-limb pentapod ring (`Δφ = 72°`, duty `0.82`) + ipsilateral foothold gap-closure reflex** (`100.0%` static CoM support-polygon stability) when any leg jams or loses load.
39
+ 3. **Presynaptic-Shunting Thruster Allocator (`neckcord.allocator.ShuntingThrusterCord`)**: Online fault-tolerant wrench allocator (`W H W^T + λI`) for `4`–`8` actuators. Detects weed-fouling, propulsor shear, or ESC brownout from campaniform effort-vs-feedback discrepancy in **`~42 ms`**, shunts drive away from the fouled thruster (`0.02 N` wasted effort), and rebalances `surge`, `sway`, and `yaw` across surviving thrusters with yaw/sway-prioritized desaturation.
40
+
41
+ ```mermaid
42
+ flowchart LR
43
+ A["Shore / Brain Planner"] -->|"4-Byte DescendingFrame (400 B/s @ 100 Hz, CRC-4)"| B["Cervical Bottleneck (UART / CAN / pynltp)"]
44
+ B --> C["SegmentalCPGCord (6-Limb Tripod / Tetrapod / Wave / 5-Leg Heal)"]
45
+ B --> D["ShuntingThrusterCord (4..8 Ch W*H*W^T + λI Reallocator)"]
46
+ E["Campaniform Load / ESC Feedback"] -->|"Effort Discrepancy (42 ms)"| C
47
+ E -->|"Presynaptic Shunting (s_i -> 0)"| D
48
+ ```
49
+
50
+ ---
51
+
52
+ ## ⚡ 30-Second Quick Start
53
+
54
+ ### Install
55
+
56
+ ```bash
57
+ pip install neckcord
58
+ # Optional NLTP encrypted radio/UDP transport integration:
59
+ pip install "neckcord[nltp]"
60
+ ```
61
+
62
+ ### Run from the Terminal
63
+
64
+ ```bash
65
+ neckcord demo
66
+ neckcord benchmark-quick
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Python API
72
+
73
+ ### 1. 4-Byte Descending Cervical Command Frame (`neckcord.cervical`)
74
+
75
+ ```python
76
+ from neckcord import DescendingFrame, GaitMode, encode_descending_4b, decode_descending_4b
77
+
78
+ tx = DescendingFrame(
79
+ drive_fwd=0.82, # DNp09 forward (+1) / MDN Moonwalker reverse (-1)
80
+ turn_yaw=-0.25, # DNa02 bilateral steering [-1, +1]
81
+ strafe_lat=0.10, # Lateral sway / crab walk [-1, +1]
82
+ gait_mode=GaitMode.AUTO,
83
+ freeze_reflex=False,
84
+ seq=2,
85
+ )
86
+
87
+ raw = encode_descending_4b(tx) # b'\x68\xe0\x0c\x20' (4 bytes = 32 bits)
88
+ rx = decode_descending_4b(raw, expected_seq=2)
89
+ wrench = rx.to_wrench(max_surge=60.0, max_sway=40.0, max_yaw=25.0)
90
+ ```
91
+
92
+ | Bits | Field | Encoding | Resolution / Role |
93
+ | :--- | :--- | :--- | :--- |
94
+ | `[31:24]` | `drive_fwd` | `8-bit` symmetric `-127..+127` | `0.0079` step, exact `0.0` & `±1.0` |
95
+ | `[23:16]` | `turn_yaw` | `8-bit` symmetric `-127..+127` | `0.0079` step, exact `0.0` & `±1.0` |
96
+ | `[15:9]` | `strafe_lat` | `7-bit` symmetric `-63..+63` | `0.0159` step, exact `0.0` & `±1.0` |
97
+ | `[8:7]` | `gait_mode` | `2-bit` unsigned `0..3` | `0=AUTO`, `1=TRIPOD`, `2=TETRAPOD`, `3=WAVE` |
98
+ | `[6]` | `freeze_reflex` | `1-bit` flag | `Giant Fiber` instant stance lock / zero wrench |
99
+ | `[5:4]` | `seq` | `2-bit` rolling counter | `0..3` packet-loss & reorder tracking |
100
+ | `[3:0]` | `crc4` | `x^4 + x + 1` (`init=0x9, xor=0x5`) | Rejects `100%` of 1-bit flips, `0x00000000` & `0xFFFFFFFF` |
101
+
102
+ ### 2. Segmental VNC Hexapod CPG (`neckcord.cpg`)
103
+
104
+ ```python
105
+ from neckcord import SegmentalCPGCord
106
+
107
+ cpg = SegmentalCPGCord(adapt_to_damage=True)
108
+
109
+ # Fast forward command -> Tripod gait; low speed -> Metachronal Wave
110
+ state = cpg.step(raw, dt=0.01)
111
+
112
+ # Simulate sudden middle-left leg (L2) jam / amputation mid-stride:
113
+ cpg.inject_limb_fault("L2")
114
+ for _ in range(100):
115
+ state = cpg.step(0.85, dt=0.01)
116
+
117
+ assert state.active_gait == "adaptive_pentapod"
118
+ assert state.is_statically_stable is True # CoM strictly inside >=3-leg polygon!
119
+ ```
120
+
121
+ ### 3. Presynaptic-Shunting Thruster Cord (`neckcord.allocator`)
122
+
123
+ ```python
124
+ import numpy as np
125
+ from neckcord import ShuntingThrusterCord
126
+
127
+ # Standard 4-thruster X-vectored marine USV / ROV (Port-Fore, Stbd-Fore, Port-Aft, Stbd-Aft)
128
+ cord = ShuntingThrusterCord.usv_vectored_4(lx=0.45, ly=0.35, cant_deg=45.0, u_max=35.0)
129
+
130
+ w_des = np.array([35.0, 0.0, 0.0]) # Pure forward surge [Fx, Fy, Tz]
131
+ alloc = cord.step(w_des, dt=0.02)
132
+
133
+ # Port-Aft thruster (index 2) gets fouled by kelp (90% loss of thrust):
134
+ true_effectiveness = np.array([1.0, 1.0, 0.10, 1.0])
135
+ for _ in range(4):
136
+ measured_thrust = true_effectiveness * alloc.commands
137
+ alloc = cord.step(w_des, feedback_thrust=measured_thrust, dt=0.02)
138
+
139
+ # T2 is shunted to 0.0 N; T0 & T1 rebalance pure forward surge with zero yaw spin!
140
+ assert alloc.isolated_mask[2] and alloc.commands[2] == 0.0
141
+ ```
142
+
143
+ ---
144
+
145
+ ## 🔧 Zero-Heap, Zero-Float ANSI C99 Core (`csrc/`)
146
+
147
+ [`csrc/neckcord.h`](csrc/neckcord.h) and [`csrc/neckcord.c`](csrc/neckcord.c) implement the complete `NeckCord` stack in pure fixed-point `Q15` / `Q14` / `16-bit BAM` integer arithmetic for bare-metal `STM32`, `ESP32`, `RP2040`, and safety MCUs without an FPU:
148
+
149
+ - **Zero dynamic allocation**: No `malloc`, `calloc`, `realloc`, or `free`.
150
+ - **Zero floating-point instructions**: Quarter-wave `65`-entry `Q15` sine lookup table (`130 B` ROM) + exact `int64_t` `3×3` Gram cofactor solver and integer cross-product CoM convex-hull verifier.
151
+ - **`304 bytes` total runtime state**: Combined `sizeof` all 5 state/result structs (`< 10%` of the `3 KB` static RAM budget).
152
+ - **100% wire-compatible with Python**: Encodes and decodes identical 4-byte frames (`0x68E00C20`).
153
+
154
+ ```bash
155
+ cd csrc && make clean all test
156
+ # Compiles cleanly under: gcc -O2 -std=c99 -Wall -Wextra -pedantic -Werror (10/10 passed)
157
+ ```
158
+
159
+ ---
160
+
161
+ ## 📊 Empirical Benchmarks
162
+
163
+ Reproduce all numbers and regenerate `assets/neckcord_benchmarks.png` and `results/benchmark_summary.json` locally:
164
+
165
+ ```bash
166
+ python scripts/benchmark_neckcord.py
167
+ ```
168
+
169
+ ### 1. 3-DOF X-Vectored 4-Thruster USV Corridor Tracking (`dt = 0.02 s`, `30 s`, `10` Irregular Wave Seeds)
170
+
171
+ Both architectures use the **exact same Fossen 3-DOF hull model, wave seeds, and outer LOS + PID controller**:
172
+
173
+ | Scenario & Metric | `Static Pseudo-Inverse + Raw Float32` | `NeckCord (4B Cervical + Shunting VNC)` | Outcome |
174
+ | :--- | :---: | :---: | :--- |
175
+ | **Command Link Bandwidth (`100 Hz`)** | `2,400 B/s` (`24 B/frame`) | **`400 B/s` (`4 B/frame`)** | **`6.0x` lower wire bandwidth** |
176
+ | **Intact Fleet (`100%` Health) — RMS XTE** | `0.108 m` (`0.233 m` max) | `0.109 m` (`0.233 m` max) | **Identical nominal tracking (`1 mm`)** |
177
+ | **Intact Fleet (`100%` Health) — Peak Yaw** | `4.84° ± 0.94°` | `4.81° ± 0.79°` | **No quantization degradation** |
178
+ | **`90%` Port-Aft Loss (`t = 8 s`) — Peak Yaw** | `24.19° ± 2.28°` | **`4.77° ± 0.65°`** | **`5.07x` less heading spin-out** |
179
+ | **`90%` Port-Aft Loss (`t = 8 s`) — RMS XTE** | `0.498 m` (`0.735 m` max) | **`0.112 m` (`0.224 m` max)** | **`4.45x` tighter corridor tracking** |
180
+ | **Fault Isolation Latency** | Never isolated | **`42.0 ms`** | **Shunted in ~2 control ticks** |
181
+ | **Mean Drive Sent to Fouled `T2` Thruster** | `22.70 N` | **`0.02 N`** | **Protects jammed ESC / windings** |
182
+
183
+ ### 2. Hexapod Single-Leg Jam (`L2` Middle-Left Lost at Fast `0.85` Drive)
184
+
185
+ | Condition | `%` Cycle in `>=3`-Leg CoM Static Support Polygon | Min CoM Stability Margin |
186
+ | :--- | :---: | :---: |
187
+ | **Intact 6-Leg Tripod** | `100.0%` | `+3.90 cm` |
188
+ | **`L2` Jammed — Unadapted Tripod CPG** | `55.0%` *(tips out of polygon every half-stride)* | `< 0 cm` *(collinear 2-leg phase)* |
189
+ | **`L2` Jammed — NeckCord Adaptive VNC** | **`100.0%`** | **`+2.24 cm`** |
190
+ | **All 6 Single-Leg Faults (`L1..R3` Mean) — NeckCord** | **`100.0%`** | **`+1.89 to +2.24 cm`** |
191
+
192
+ ---
193
+
194
+ ## 🎯 When to Use NeckCord — and When Not To
195
+
196
+ **Reach for `NeckCord` when:**
197
+ - Controlling **4-to-8 thruster vectored USVs, ROVs, or multirotors** exposed to kelp/weed fouling, propulsor damage, or ESC brownouts where losing one actuator would otherwise spin the vehicle off heading and burn the stalled motor.
198
+ - Streaming real-time operator or autonomy commands across **narrow, lossy acoustic, LoRa, marine UHF, or `4G`/`5G` links** (`400 B/s` at `100 Hz` — pairs directly with `pynltp`).
199
+ - Running **hexapod robots or bare-metal C99 motor cords** (`304 B` RAM, zero FPU/heap) that need smooth single-parameter gait transitions (`Wave ↔ Tetrapod ↔ Tripod`) and instant 5-legged self-healing on leg failure.
200
+
201
+ **Stick with standard tools when:**
202
+ - **Underactuated 2-thruster differential hulls with no bow thruster or rudder**: If 1 of 2 fixed parallel thrusters dies completely, no allocator can produce forward surge without net yaw moment (`rank(W_surviving) = 1 < 2`).
203
+ - **Clean local wired buses on healthy, un-faulted vehicles**: As shown in our intact-fleet benchmark above, a 3-line static Moore-Penrose pseudo-inverse achieves identical nominal tracking (`0.108 m` vs `0.109 m` XTE) when all actuators remain `100%` healthy.
204
+ - **Asymmetric unidirectional thrusters (`u_i >= 0` only, e.g. non-reversible quadrotor props in 6-DOF)**: `ShuntingThrusterCord` assumes bidirectional control authority (`[-u_max, +u_max]`) with yaw/sway-prioritized scaling; strictly non-negative polyhedral actuator bounds with `> 6` coupled DOFs are better served by an active-set QP solver (`OSQP` / `proxqp`).
205
+
206
+ ---
207
+
208
+ ## 🗂️ Repository Layout
209
+
210
+ | Path | Description |
211
+ | :--- | :--- |
212
+ | [`neckcord/cervical.py`](neckcord/cervical.py) | `DescendingFrame`, `encode_descending_4b`, `decode_descending_4b`, `CRC-4`, `CervicalBottleneckLink` |
213
+ | [`neckcord/cpg.py`](neckcord/cpg.py) | `SegmentalCPGCord` 6-limb Kuramoto CPG, gait transitions, pentapod + gap-closure self-healing |
214
+ | [`neckcord/allocator.py`](neckcord/allocator.py) | `ShuntingThrusterCord` online health estimation, presynaptic shunting, `W H W^T + λI` allocator |
215
+ | [`neckcord/cli.py`](neckcord/cli.py) | `neckcord` CLI (`demo`, `benchmark-quick`, `--json`) |
216
+ | [`csrc/`](csrc/) | Zero-heap, zero-float `Q15`/`Q14` ANSI C99 core (`neckcord.h`, `neckcord.c`, `10/10` `neckcord_selftest.c`) |
217
+ | [`scripts/benchmark_neckcord.py`](scripts/benchmark_neckcord.py) | 10-seed 3-DOF USV + 6-limb hexapod benchmark & 3-panel hero chart generator |
218
+ | [`results/benchmark_summary.json`](results/benchmark_summary.json) | Reproducible empirical benchmark output JSON |
219
+ | [`tests/test_neckcord.py`](tests/test_neckcord.py) | `22` `pytest` unit, edge-case, CLI, and C99 source-audit tests |
220
+
221
+ ---
222
+
223
+ ## License
224
+
225
+ Released under the [MIT License](LICENSE). Copyright (c) 2026 Amandeep Singh Bains.
@@ -0,0 +1,20 @@
1
+ CC ?= gcc
2
+ CFLAGS ?= -O2 -std=c99 -Wall -Wextra -pedantic -Werror
3
+ BUILD := build
4
+ TARGET := $(BUILD)/neckcord_selftest
5
+
6
+ .PHONY: all clean test
7
+
8
+ all: $(TARGET)
9
+
10
+ $(BUILD):
11
+ mkdir -p $(BUILD)
12
+
13
+ $(TARGET): neckcord.c neckcord.h tools/neckcord_selftest.c | $(BUILD)
14
+ $(CC) $(CFLAGS) -I. neckcord.c tools/neckcord_selftest.c -o $(TARGET)
15
+
16
+ test: $(TARGET)
17
+ ./$(TARGET)
18
+
19
+ clean:
20
+ rm -rf $(BUILD)