aether-robotics 3.4.2__tar.gz → 3.4.4__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 (94) hide show
  1. aether_robotics-3.4.4/PKG-INFO +226 -0
  2. aether_robotics-3.4.4/README.md +185 -0
  3. aether_robotics-3.4.4/VERSION +1 -0
  4. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/__init__.py +1 -1
  5. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/calibration.py +6 -2
  6. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/navigation_engine.py +10 -2
  7. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/tool_registry.py +41 -7
  8. aether_robotics-3.4.4/aether_robotics.egg-info/PKG-INFO +226 -0
  9. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/main.py +3 -0
  10. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/pyproject.toml +1 -1
  11. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_calibration.py +89 -0
  12. aether_robotics-3.4.2/PKG-INFO +0 -256
  13. aether_robotics-3.4.2/README.md +0 -215
  14. aether_robotics-3.4.2/VERSION +0 -1
  15. aether_robotics-3.4.2/aether_robotics.egg-info/PKG-INFO +0 -256
  16. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/LICENSE +0 -0
  17. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/MANIFEST.in +0 -0
  18. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/__main__.py +0 -0
  19. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/actions/__init__.py +0 -0
  20. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/actions/abstract_actions.py +0 -0
  21. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/adapters/__init__.py +0 -0
  22. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/adapters/base_adapter.py +0 -0
  23. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/adapters/drone_adapter.py +0 -0
  24. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/adapters/rover_adapter.py +0 -0
  25. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/adapters/universal_adapter.py +0 -0
  26. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/__init__.py +0 -0
  27. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/adaptation_agent.py +0 -0
  28. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/camera_agent.py +0 -0
  29. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/correction_agent.py +0 -0
  30. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/execution_agent.py +0 -0
  31. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/fault_agent.py +0 -0
  32. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/memory_agent.py +0 -0
  33. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/movement_agent.py +0 -0
  34. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/navigation_agent.py +0 -0
  35. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/perception_agent.py +0 -0
  36. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/planner_agent.py +0 -0
  37. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/power_agent.py +0 -0
  38. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/task_manager.py +0 -0
  39. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/agents/thermal_agent.py +0 -0
  40. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/app.py +0 -0
  41. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/capabilities/__init__.py +0 -0
  42. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/capabilities/capability_loader.py +0 -0
  43. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/__init__.py +0 -0
  44. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/auto_installer.py +0 -0
  45. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/auto_updater.py +0 -0
  46. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/banner.py +0 -0
  47. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/executor.py +0 -0
  48. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/feedback.py +0 -0
  49. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/goal_parser.py +0 -0
  50. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/llm_planner.py +0 -0
  51. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/mapper.py +0 -0
  52. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/memory.py +0 -0
  53. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/message_bus.py +0 -0
  54. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/metrics.py +0 -0
  55. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/planner.py +0 -0
  56. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/task_scheduler.py +0 -0
  57. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/tool_builder.py +0 -0
  58. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/tool_discovery.py +0 -0
  59. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/core/visualizer.py +0 -0
  60. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/faults/__init__.py +0 -0
  61. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/faults/fault_detector.py +0 -0
  62. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/faults/fault_injector.py +0 -0
  63. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/simulation/__init__.py +0 -0
  64. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/simulation/environment.py +0 -0
  65. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/simulation/real_perception.py +0 -0
  66. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether/simulation/scenarios.py +0 -0
  67. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether_robotics.egg-info/SOURCES.txt +0 -0
  68. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether_robotics.egg-info/dependency_links.txt +0 -0
  69. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether_robotics.egg-info/entry_points.txt +0 -0
  70. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether_robotics.egg-info/requires.txt +0 -0
  71. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/aether_robotics.egg-info/top_level.txt +0 -0
  72. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/configs/calibrated_camera_only_20260331_121709.json +0 -0
  73. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/configs/calibrated_camera_only_20260331_122446.json +0 -0
  74. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/configs/calibrated_camera_only_20260401_094544.json +0 -0
  75. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/configs/calibrated_camera_only_20260401_094554.json +0 -0
  76. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/configs/drone_v1.json +0 -0
  77. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/configs/rover_v1.json +0 -0
  78. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/context/aether_definitions.txt +0 -0
  79. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/install.sh +0 -0
  80. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/requirements.txt +0 -0
  81. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/setup.cfg +0 -0
  82. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_auto_updater.py +0 -0
  83. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_calibration_unit.py +0 -0
  84. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_chaos.py +0 -0
  85. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_entrypoint.py +0 -0
  86. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_mapper.py +0 -0
  87. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_navigation_engine.py +0 -0
  88. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_persistent_memory.py +0 -0
  89. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_security.py +0 -0
  90. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_task_scheduler.py +0 -0
  91. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_tool_builder.py +0 -0
  92. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_tool_discovery.py +0 -0
  93. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/tests/test_yolo_integration.py +0 -0
  94. {aether_robotics-3.4.2 → aether_robotics-3.4.4}/weights/fault_agent.npy +0 -0
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: aether-robotics
3
+ Version: 3.4.4
4
+ Summary: Autonomous multi-agent robotics system with DRL-First Hybrid FDIR
5
+ Author: Chahel Paatur
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ChahelPaatur/AETHER
8
+ Project-URL: Repository, https://github.com/ChahelPaatur/AETHER
9
+ Project-URL: Issues, https://github.com/ChahelPaatur/AETHER/issues
10
+ Keywords: robotics,autonomous,FDIR,fault-detection,raspberry-pi,drone,AI
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Classifier: Topic :: System :: Hardware
16
+ Classifier: Intended Audience :: Science/Research
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: numpy>=1.24.0
21
+ Requires-Dist: psutil>=5.9.0
22
+ Requires-Dist: requests>=2.32.0
23
+ Provides-Extra: full
24
+ Requires-Dist: anthropic>=0.50.0; extra == "full"
25
+ Requires-Dist: flask>=3.0.0; extra == "full"
26
+ Requires-Dist: opencv-python-headless>=4.8.0; extra == "full"
27
+ Requires-Dist: matplotlib>=3.7.0; extra == "full"
28
+ Provides-Extra: pi
29
+ Requires-Dist: picamera2; extra == "pi"
30
+ Requires-Dist: RPi.GPIO; extra == "pi"
31
+ Requires-Dist: gpiozero; extra == "pi"
32
+ Requires-Dist: smbus2; extra == "pi"
33
+ Provides-Extra: drone
34
+ Requires-Dist: pymavlink; extra == "drone"
35
+ Requires-Dist: pyserial; extra == "drone"
36
+ Provides-Extra: ml
37
+ Requires-Dist: ultralytics; extra == "ml"
38
+ Requires-Dist: scipy; extra == "ml"
39
+ Requires-Dist: scikit-learn; extra == "ml"
40
+ Dynamic: license-file
41
+
42
+ ```
43
+ ████████████████████████████████
44
+ ████████████████████████████████
45
+ █████╔═══════════════════╗█████
46
+ █████║ ▄████▄ ▄████▄ ║█████
47
+ █████║ ████████████████ ║█████
48
+ █████║ ██████████████ ║█████
49
+ █████║ █▀▀████████▀▀█ ║█████
50
+ █████║ ▀████▀ ▀████▀ ║█████
51
+ █████║▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄║█████
52
+ █████║ ━━━━━━━━━━━━━━━ ║█████
53
+ █████║ ▌ AETHER v3 ▐ ║█████
54
+ █████║ ━━━━━━━━━━━━━━━ ║█████
55
+ █████╚═══════════════════╝█████
56
+ ████████████████████████████████
57
+ ████████████████████████████████
58
+ ```
59
+
60
+ # AETHER — Autonomous Robotics Operating System
61
+
62
+ > AETHER is the autonomous operating system for robots. Plug in and talk to your robot in plain English and ask it to do anything you want.
63
+
64
+ AETHER connects to whatever hardware is present at startup, discovers every actuator through an interactive GPIO calibration walk, and writes a `physical_map` of every servo and motor by BCM pin. That map feeds into an LLM planner that translates plain-English objectives into the correct hardware action — pin pre-filled, servo type resolved, direction inferred. Motion commands dispatch to GPIO, while a PPO fault-detection network runs concurrently on the 15-dimensional sensor observation vector, detecting and recovering from failures in real time. Every layer — discovery, pin mapping, natural-language planning, execution, fault recovery — runs on a Raspberry Pi with no cloud dependency except the Anthropic API for the planner.
65
+
66
+ [Demo and docs → aether-robotics.com](https://aether-robotics.com)
67
+
68
+ ---
69
+
70
+ ## Quick Start
71
+
72
+ ```bash
73
+ pip install aether-robotics
74
+ aether --calibrate
75
+ aether --mode agent
76
+ ```
77
+
78
+ Calibration walks every safe GPIO pin (BCM 4–27, excluding I2C/SPI/UART), pulses each with a positional servo sweep, and prompts you to label what moved. The result is a `physical_map` saved in your calibration profile and loaded automatically at next startup.
79
+
80
+ Once calibrated:
81
+
82
+ ```
83
+ objective> move the wheel forward for 5 seconds
84
+ [PLAN] [LLM] servo_cont_wheel
85
+ [EXEC] servo_cont_wheel(speed=50, duration=5)
86
+ [OK] success=True (5009ms)
87
+ ```
88
+
89
+ AETHER discovered the wheel on BCM 17 during calibration, the planner mapped "wheel forward" to the calibrated action, the servo spun for 5 seconds and stopped.
90
+
91
+ ---
92
+
93
+ ## What AETHER Does That Others Don't
94
+
95
+ - **Discovers the robot.** Calibration walks every GPIO pin, you label what moved, AETHER builds a `physical_map` with BCM pin, device type, and action label for each actuator (unlike ROS/Viam where you configure drivers manually before the system knows what hardware exists).
96
+ - **Speaks natural language.** Type plain English; the LLM planner resolves intent against your robot's `physical_map` and dispatches the correct BCM pin pre-filled (unlike ROS action servers that require typed message structs and correct namespace knowledge).
97
+ - **Detects faults in real time.** DRL-First Hybrid FDIR achieves SFRI 69.99, 100% detection rate, and 100% recovery rate over 6,023 real-hardware steps (unlike threshold-rule systems that require manual parameter tuning per platform and miss novel fault signatures).
98
+ - **Improves through use.** Correction traces are logged per step; operational memory and sim-to-real action transfer are on the roadmap (unlike static planners that repeat the same failure mode without feedback).
99
+
100
+ ---
101
+
102
+ ## Commands
103
+
104
+ ### Modes
105
+
106
+ | Flag | Description |
107
+ |------|-------------|
108
+ | `--mode sim` | Simulation with fault injection against a virtual robot (default) |
109
+ | `--mode agent` | Interactive LLM-planned objectives on live hardware; prompts for input |
110
+ | `--mode realworld` | Continuous live-hardware FDIR loop — camera + system sensors, no planner |
111
+ | `--mode server` | HTTP API on `--port`; accepts `POST /objective` and `GET /health` |
112
+ | `--mode dashboard` | Flask web UI on port 5000 with live objective submission and OLED preview |
113
+
114
+ ### Useful Flags
115
+
116
+ | Flag | When to use |
117
+ |------|-------------|
118
+ | `--calibrate` | First-time setup — walks every GPIO pin, you label what moves |
119
+ | `--recalibrate` | Re-run the full pin walk (e.g. after wiring changes); skips known-empty pins |
120
+ | `--auto-calibrate` | Headless calibration with no interactive prompts |
121
+ | `--once "objective"` | Run a single objective non-interactively and exit; useful in scripts |
122
+ | `--task "objective"` | Task description for `--mode sim` |
123
+ | `--schedule "..."` | Scheduled runs: `"every 30s: scan environment"`, `"for 5min: obj"`, `"until 22:00: obj"` |
124
+ | `--continuous` | Run `--mode realworld` indefinitely until Ctrl-C |
125
+ | `--servo-pin N` | Override the servo GPIO BCM pin for this session (supersedes calibration profile) |
126
+ | `--robot {rover_v1,drone_v1}` | Robot config for `--mode sim` (default: `rover_v1`) |
127
+ | `--faults {disabled,enabled,heavy}` | Fault injection level for sim/realworld (default: `disabled`) |
128
+ | `--scenario TEXT` | Sim scenario: `simple`, `obstacles`, `imu_fault`, `battery`, `compound`, `fault_heavy` |
129
+ | `--max-steps N` | Max steps per episode (default: 300) |
130
+ | `--seed N` | Random seed for reproducible sim runs (default: 42) |
131
+ | `--render` | Print ASCII state render at each sim step |
132
+ | `--plots` | Generate matplotlib SFRI/metrics plots after a sim run |
133
+ | `--no-learning` | Freeze PPO weights — useful for controlled benchmarking |
134
+ | `--port N` | Port for `--mode server` (default: 8080) |
135
+ | `--auto-install` | Install missing Python packages without prompting |
136
+ | `--auto-update` | Pull the latest version without prompting |
137
+ | `--no-install` | Skip the package-install prompt entirely |
138
+ | `--no-update` | Skip the update check |
139
+ | `--verbose` | Enable debug logging |
140
+
141
+ ---
142
+
143
+ ## Supported Hardware
144
+
145
+ **Tested and working**
146
+
147
+ Raspberry Pi 4 Model B · USB camera or picamera2 · GPIO servos (positional or continuous-rotation) · SSD1306 OLED over SPI · Anthropic API (LLM planner and vision)
148
+
149
+ **Should work, unverified**
150
+
151
+ Pi Zero 2 W · Pi 5 (requires `rpi-lgpio` in place of `RPi.GPIO`) · PCA9685 I2C 16-channel servo driver · MAVLink flight controllers via USB serial
152
+
153
+ **In development**
154
+
155
+ Arduino/ESP32 serial bridge · ArduPilot drone support · multi-robot coordination
156
+
157
+ ---
158
+
159
+ ## Architecture
160
+
161
+ ```
162
+ User input (plain English)
163
+
164
+
165
+ ToolDiscovery ──────────────► physical_map (saved calibration profile)
166
+ │ │
167
+ ▼ ▼
168
+ LLMPlanner ◄──── physical_map injected into planner context
169
+
170
+
171
+ NavigationEngine (L1 camera / L2 GPIO / L3 MAVLink)
172
+ │ │
173
+ ▼ ▼
174
+ Hardware (servo/motor/FC) FaultAgent (PPO, 15-dim obs → fault class)
175
+
176
+ detect · recover · log
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Benchmarks
182
+
183
+ Real-hardware deployment: Raspberry Pi 4, GPIO servos, live camera, Anthropic API planner.
184
+
185
+ | Metric | Value | Conditions |
186
+ |--------|------:|------------|
187
+ | SFRI | **69.99** | 6,023 steps, real hardware |
188
+ | MTTR | **1.35 steps** | Mean time to recover from injected fault |
189
+ | Detection rate | **100%** | 0 misses, 0 false positives |
190
+
191
+ > SFRI (Stability Fault Recovery Index) = 35×DR + 25×(1 − MTTR/max\_steps) + 10×RR − 30×FPR. Range 0–70; higher is better.
192
+
193
+ ---
194
+
195
+ ## Roadmap
196
+
197
+ - ✓ **Phase 1 — Reverse Engineering** (current)
198
+ - **Phase 2 — Robot Genome** (portable robot identity card)
199
+ - **Phase 3 — Vision-Language Grounding** ("follow the orange cone")
200
+ - **Phase 4 — Operational Memory + Sim-to-Real Action Transfer**
201
+ - **Phase 5 — Multi-robot coordination**
202
+
203
+ ---
204
+
205
+ ## Early Access
206
+
207
+ AETHER is in early access. We're working with a small number of robotics teams and researchers to refine the platform. Email chahelpaatur@aether-robotics.com for access.
208
+
209
+ ---
210
+
211
+ ## Citation
212
+
213
+ ```bibtex
214
+ @software{aether2026,
215
+ title = {AETHER: Autonomous Operating System for Robots},
216
+ author = {Paatur, Chahel},
217
+ year = {2026},
218
+ version = {3.4.3},
219
+ url = {https://aether-robotics.com},
220
+ note = {DRL-First Hybrid FDIR with physical-map calibration and LLM planning},
221
+ }
222
+ ```
223
+
224
+ ---
225
+
226
+ AETHER is proprietary software in early access. All rights reserved. © 2026 Chahel Paatur.
@@ -0,0 +1,185 @@
1
+ ```
2
+ ████████████████████████████████
3
+ ████████████████████████████████
4
+ █████╔═══════════════════╗█████
5
+ █████║ ▄████▄ ▄████▄ ║█████
6
+ █████║ ████████████████ ║█████
7
+ █████║ ██████████████ ║█████
8
+ █████║ █▀▀████████▀▀█ ║█████
9
+ █████║ ▀████▀ ▀████▀ ║█████
10
+ █████║▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄║█████
11
+ █████║ ━━━━━━━━━━━━━━━ ║█████
12
+ █████║ ▌ AETHER v3 ▐ ║█████
13
+ █████║ ━━━━━━━━━━━━━━━ ║█████
14
+ █████╚═══════════════════╝█████
15
+ ████████████████████████████████
16
+ ████████████████████████████████
17
+ ```
18
+
19
+ # AETHER — Autonomous Robotics Operating System
20
+
21
+ > AETHER is the autonomous operating system for robots. Plug in and talk to your robot in plain English and ask it to do anything you want.
22
+
23
+ AETHER connects to whatever hardware is present at startup, discovers every actuator through an interactive GPIO calibration walk, and writes a `physical_map` of every servo and motor by BCM pin. That map feeds into an LLM planner that translates plain-English objectives into the correct hardware action — pin pre-filled, servo type resolved, direction inferred. Motion commands dispatch to GPIO, while a PPO fault-detection network runs concurrently on the 15-dimensional sensor observation vector, detecting and recovering from failures in real time. Every layer — discovery, pin mapping, natural-language planning, execution, fault recovery — runs on a Raspberry Pi with no cloud dependency except the Anthropic API for the planner.
24
+
25
+ [Demo and docs → aether-robotics.com](https://aether-robotics.com)
26
+
27
+ ---
28
+
29
+ ## Quick Start
30
+
31
+ ```bash
32
+ pip install aether-robotics
33
+ aether --calibrate
34
+ aether --mode agent
35
+ ```
36
+
37
+ Calibration walks every safe GPIO pin (BCM 4–27, excluding I2C/SPI/UART), pulses each with a positional servo sweep, and prompts you to label what moved. The result is a `physical_map` saved in your calibration profile and loaded automatically at next startup.
38
+
39
+ Once calibrated:
40
+
41
+ ```
42
+ objective> move the wheel forward for 5 seconds
43
+ [PLAN] [LLM] servo_cont_wheel
44
+ [EXEC] servo_cont_wheel(speed=50, duration=5)
45
+ [OK] success=True (5009ms)
46
+ ```
47
+
48
+ AETHER discovered the wheel on BCM 17 during calibration, the planner mapped "wheel forward" to the calibrated action, the servo spun for 5 seconds and stopped.
49
+
50
+ ---
51
+
52
+ ## What AETHER Does That Others Don't
53
+
54
+ - **Discovers the robot.** Calibration walks every GPIO pin, you label what moved, AETHER builds a `physical_map` with BCM pin, device type, and action label for each actuator (unlike ROS/Viam where you configure drivers manually before the system knows what hardware exists).
55
+ - **Speaks natural language.** Type plain English; the LLM planner resolves intent against your robot's `physical_map` and dispatches the correct BCM pin pre-filled (unlike ROS action servers that require typed message structs and correct namespace knowledge).
56
+ - **Detects faults in real time.** DRL-First Hybrid FDIR achieves SFRI 69.99, 100% detection rate, and 100% recovery rate over 6,023 real-hardware steps (unlike threshold-rule systems that require manual parameter tuning per platform and miss novel fault signatures).
57
+ - **Improves through use.** Correction traces are logged per step; operational memory and sim-to-real action transfer are on the roadmap (unlike static planners that repeat the same failure mode without feedback).
58
+
59
+ ---
60
+
61
+ ## Commands
62
+
63
+ ### Modes
64
+
65
+ | Flag | Description |
66
+ |------|-------------|
67
+ | `--mode sim` | Simulation with fault injection against a virtual robot (default) |
68
+ | `--mode agent` | Interactive LLM-planned objectives on live hardware; prompts for input |
69
+ | `--mode realworld` | Continuous live-hardware FDIR loop — camera + system sensors, no planner |
70
+ | `--mode server` | HTTP API on `--port`; accepts `POST /objective` and `GET /health` |
71
+ | `--mode dashboard` | Flask web UI on port 5000 with live objective submission and OLED preview |
72
+
73
+ ### Useful Flags
74
+
75
+ | Flag | When to use |
76
+ |------|-------------|
77
+ | `--calibrate` | First-time setup — walks every GPIO pin, you label what moves |
78
+ | `--recalibrate` | Re-run the full pin walk (e.g. after wiring changes); skips known-empty pins |
79
+ | `--auto-calibrate` | Headless calibration with no interactive prompts |
80
+ | `--once "objective"` | Run a single objective non-interactively and exit; useful in scripts |
81
+ | `--task "objective"` | Task description for `--mode sim` |
82
+ | `--schedule "..."` | Scheduled runs: `"every 30s: scan environment"`, `"for 5min: obj"`, `"until 22:00: obj"` |
83
+ | `--continuous` | Run `--mode realworld` indefinitely until Ctrl-C |
84
+ | `--servo-pin N` | Override the servo GPIO BCM pin for this session (supersedes calibration profile) |
85
+ | `--robot {rover_v1,drone_v1}` | Robot config for `--mode sim` (default: `rover_v1`) |
86
+ | `--faults {disabled,enabled,heavy}` | Fault injection level for sim/realworld (default: `disabled`) |
87
+ | `--scenario TEXT` | Sim scenario: `simple`, `obstacles`, `imu_fault`, `battery`, `compound`, `fault_heavy` |
88
+ | `--max-steps N` | Max steps per episode (default: 300) |
89
+ | `--seed N` | Random seed for reproducible sim runs (default: 42) |
90
+ | `--render` | Print ASCII state render at each sim step |
91
+ | `--plots` | Generate matplotlib SFRI/metrics plots after a sim run |
92
+ | `--no-learning` | Freeze PPO weights — useful for controlled benchmarking |
93
+ | `--port N` | Port for `--mode server` (default: 8080) |
94
+ | `--auto-install` | Install missing Python packages without prompting |
95
+ | `--auto-update` | Pull the latest version without prompting |
96
+ | `--no-install` | Skip the package-install prompt entirely |
97
+ | `--no-update` | Skip the update check |
98
+ | `--verbose` | Enable debug logging |
99
+
100
+ ---
101
+
102
+ ## Supported Hardware
103
+
104
+ **Tested and working**
105
+
106
+ Raspberry Pi 4 Model B · USB camera or picamera2 · GPIO servos (positional or continuous-rotation) · SSD1306 OLED over SPI · Anthropic API (LLM planner and vision)
107
+
108
+ **Should work, unverified**
109
+
110
+ Pi Zero 2 W · Pi 5 (requires `rpi-lgpio` in place of `RPi.GPIO`) · PCA9685 I2C 16-channel servo driver · MAVLink flight controllers via USB serial
111
+
112
+ **In development**
113
+
114
+ Arduino/ESP32 serial bridge · ArduPilot drone support · multi-robot coordination
115
+
116
+ ---
117
+
118
+ ## Architecture
119
+
120
+ ```
121
+ User input (plain English)
122
+
123
+
124
+ ToolDiscovery ──────────────► physical_map (saved calibration profile)
125
+ │ │
126
+ ▼ ▼
127
+ LLMPlanner ◄──── physical_map injected into planner context
128
+
129
+
130
+ NavigationEngine (L1 camera / L2 GPIO / L3 MAVLink)
131
+ │ │
132
+ ▼ ▼
133
+ Hardware (servo/motor/FC) FaultAgent (PPO, 15-dim obs → fault class)
134
+
135
+ detect · recover · log
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Benchmarks
141
+
142
+ Real-hardware deployment: Raspberry Pi 4, GPIO servos, live camera, Anthropic API planner.
143
+
144
+ | Metric | Value | Conditions |
145
+ |--------|------:|------------|
146
+ | SFRI | **69.99** | 6,023 steps, real hardware |
147
+ | MTTR | **1.35 steps** | Mean time to recover from injected fault |
148
+ | Detection rate | **100%** | 0 misses, 0 false positives |
149
+
150
+ > SFRI (Stability Fault Recovery Index) = 35×DR + 25×(1 − MTTR/max\_steps) + 10×RR − 30×FPR. Range 0–70; higher is better.
151
+
152
+ ---
153
+
154
+ ## Roadmap
155
+
156
+ - ✓ **Phase 1 — Reverse Engineering** (current)
157
+ - **Phase 2 — Robot Genome** (portable robot identity card)
158
+ - **Phase 3 — Vision-Language Grounding** ("follow the orange cone")
159
+ - **Phase 4 — Operational Memory + Sim-to-Real Action Transfer**
160
+ - **Phase 5 — Multi-robot coordination**
161
+
162
+ ---
163
+
164
+ ## Early Access
165
+
166
+ AETHER is in early access. We're working with a small number of robotics teams and researchers to refine the platform. Email chahelpaatur@aether-robotics.com for access.
167
+
168
+ ---
169
+
170
+ ## Citation
171
+
172
+ ```bibtex
173
+ @software{aether2026,
174
+ title = {AETHER: Autonomous Operating System for Robots},
175
+ author = {Paatur, Chahel},
176
+ year = {2026},
177
+ version = {3.4.3},
178
+ url = {https://aether-robotics.com},
179
+ note = {DRL-First Hybrid FDIR with physical-map calibration and LLM planning},
180
+ }
181
+ ```
182
+
183
+ ---
184
+
185
+ AETHER is proprietary software in early access. All rights reserved. © 2026 Chahel Paatur.
@@ -0,0 +1 @@
1
+ 3.4.4
@@ -1,2 +1,2 @@
1
- __version__ = "3.4.2"
1
+ __version__ = "3.4.4"
2
2
  __author__ = "Chahel Paatur"
@@ -134,8 +134,12 @@ _CATEGORY_ACTION_PREFIX: Dict[int, str] = {
134
134
  # Stopwords stripped before slugifying descriptions (Bug 4)
135
135
  _SLUG_STOPWORDS = frozenset({
136
136
  "the", "then", "and", "a", "an", "that", "moved", "move", "moves",
137
- "is", "was", "it", "of", "to", "in", "at", "by", "for", "from",
138
- "with", "or", "but", "on", "its", "when", "while", "also", "did",
137
+ "is", "was", "it", "of", "to",
138
+ # "in" and "on" intentionally excluded: they appear in directional phrases
139
+ # like "in front", "on the left", "on top" and must survive slugification.
140
+ "at", "by", "for", "from",
141
+ "with", "or", "but",
142
+ "its", "when", "while", "also", "did",
139
143
  "went", "going", "started", "which",
140
144
  })
141
145
 
@@ -858,10 +858,17 @@ class _MotorNav:
858
858
  return _ok({"action": "stop"})
859
859
 
860
860
  def servo_set(self, pin: int, angle: float,
861
- servo_type: str = "positional") -> Dict:
861
+ servo_type: str = "positional",
862
+ duty_cycle: Optional[float] = None) -> Dict:
862
863
  if self._gpio is None:
863
864
  return _err("GPIO not available")
864
865
 
866
+ # If an explicit duty_cycle is supplied, use it directly and skip the
867
+ # angle→duty formula. This lets CorrectionAgent override the output
868
+ # without having to reverse-engineer the mapping.
869
+ if duty_cycle is not None:
870
+ return self.pwm_set(pin, 50, float(duty_cycle))
871
+
865
872
  if servo_type == "continuous":
866
873
  # Continuous-rotation servo: interpret angle as speed -100..+100
867
874
  # 0 → stop (90°), positive → forward, negative → reverse
@@ -1682,7 +1689,8 @@ class NavigationEngine:
1682
1689
  "servo_set": lambda: self._motors.servo_set(
1683
1690
  params.get("pin") or self._default_servo_pin(),
1684
1691
  params.get("angle", 90),
1685
- params.get("servo_type") or self._default_servo_type()),
1692
+ params.get("servo_type") or self._default_servo_type(),
1693
+ duty_cycle=params.get("duty_cycle")),
1686
1694
  "navigate_to_color": lambda: self._motors.navigate_to_color(
1687
1695
  params.get("color", params.get("class_name", "red")),
1688
1696
  lp, rp, sp, params.get("timeout", 30)),
@@ -1023,18 +1023,52 @@ def register_built_tools(registry: "ToolRegistry",
1023
1023
  def _make_physical_fn(pin, pwm_type):
1024
1024
  def _fn(**kwargs):
1025
1025
  if pwm_type == "servo_continuous":
1026
- # Accept direction/speed/angle any key the LLM uses
1027
- hint = kwargs.get(
1028
- "direction",
1029
- kwargs.get("speed",
1030
- kwargs.get("angle", "forward")))
1026
+ # Resolve direction from whichever kwarg the LLM uses.
1027
+ # Priority: direction/speed > angle > position > default.
1028
+ if "direction" in kwargs or "speed" in kwargs:
1029
+ hint = kwargs.get("direction") or kwargs.get("speed")
1030
+ elif "angle" in kwargs:
1031
+ hint = kwargs["angle"]
1032
+ elif "position" in kwargs:
1033
+ # "position" is a positional-servo idiom with no
1034
+ # meaning on a continuous servo. position=90 is the
1035
+ # center/neutral default — treat it as forward intent
1036
+ # because stopping requires an explicit stop/halt/neutral.
1037
+ # TODO: thread objective text into the closure so that
1038
+ # "stop" + position=90 maps to neutral (0.0) while
1039
+ # "move" + position=90 maps to forward (100.0).
1040
+ pos = kwargs["position"]
1041
+ hint = "forward" if float(pos) == 90.0 else pos
1042
+ else:
1043
+ # No direction hint at all — default to forward.
1044
+ # Stopping requires explicit stop/halt/neutral intent.
1045
+ hint = "forward"
1046
+
1031
1047
  speed = _infer_continuous_speed(hint)
1032
- return registry.execute(
1048
+ result = registry.execute(
1033
1049
  "servo_set",
1034
1050
  {"pin": pin, "angle": speed,
1035
1051
  "servo_type": "continuous"})
1052
+
1053
+ # Optional timed run: spin for N seconds then neutral.
1054
+ duration = kwargs.get("duration")
1055
+ if duration is not None and result.success:
1056
+ try:
1057
+ time.sleep(float(duration))
1058
+ except (ValueError, TypeError):
1059
+ pass
1060
+ registry.execute(
1061
+ "servo_set",
1062
+ {"pin": pin, "angle": 0.0,
1063
+ "servo_type": "continuous"})
1064
+
1065
+ return result
1066
+
1036
1067
  elif pwm_type == "servo_positional":
1037
- angle = float(kwargs.get("angle", 90))
1068
+ # Accept both "angle" and "position" — LLM uses either
1069
+ angle = float(
1070
+ kwargs.get("angle",
1071
+ kwargs.get("position", 90)))
1038
1072
  return registry.execute(
1039
1073
  "servo_set",
1040
1074
  {"pin": pin, "angle": angle,