aether-robotics 3.0.0__py3-none-any.whl
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.
- aether/__init__.py +2 -0
- aether/__main__.py +10 -0
- aether/actions/__init__.py +0 -0
- aether/actions/abstract_actions.py +136 -0
- aether/adapters/__init__.py +0 -0
- aether/adapters/base_adapter.py +32 -0
- aether/adapters/drone_adapter.py +67 -0
- aether/adapters/rover_adapter.py +87 -0
- aether/adapters/universal_adapter.py +594 -0
- aether/agents/__init__.py +0 -0
- aether/agents/adaptation_agent.py +234 -0
- aether/agents/camera_agent.py +114 -0
- aether/agents/correction_agent.py +387 -0
- aether/agents/execution_agent.py +89 -0
- aether/agents/fault_agent.py +508 -0
- aether/agents/memory_agent.py +200 -0
- aether/agents/movement_agent.py +147 -0
- aether/agents/navigation_agent.py +163 -0
- aether/agents/perception_agent.py +112 -0
- aether/agents/planner_agent.py +40 -0
- aether/agents/power_agent.py +103 -0
- aether/agents/task_manager.py +246 -0
- aether/agents/thermal_agent.py +120 -0
- aether/capabilities/__init__.py +0 -0
- aether/capabilities/capability_loader.py +116 -0
- aether/core/__init__.py +0 -0
- aether/core/auto_installer.py +164 -0
- aether/core/auto_updater.py +173 -0
- aether/core/banner.py +50 -0
- aether/core/calibration.py +1006 -0
- aether/core/executor.py +71 -0
- aether/core/feedback.py +97 -0
- aether/core/goal_parser.py +110 -0
- aether/core/llm_planner.py +219 -0
- aether/core/memory.py +123 -0
- aether/core/message_bus.py +107 -0
- aether/core/metrics.py +184 -0
- aether/core/navigation_engine.py +1741 -0
- aether/core/planner.py +386 -0
- aether/core/tool_builder.py +1158 -0
- aether/core/tool_discovery.py +1215 -0
- aether/core/tool_registry.py +957 -0
- aether/core/visualizer.py +194 -0
- aether/faults/__init__.py +0 -0
- aether/faults/fault_detector.py +309 -0
- aether/faults/fault_injector.py +317 -0
- aether/simulation/__init__.py +0 -0
- aether/simulation/environment.py +385 -0
- aether/simulation/real_perception.py +276 -0
- aether/simulation/scenarios.py +169 -0
- aether_robotics-3.0.0.dist-info/METADATA +269 -0
- aether_robotics-3.0.0.dist-info/RECORD +56 -0
- aether_robotics-3.0.0.dist-info/WHEEL +5 -0
- aether_robotics-3.0.0.dist-info/entry_points.txt +2 -0
- aether_robotics-3.0.0.dist-info/licenses/LICENSE +21 -0
- aether_robotics-3.0.0.dist-info/top_level.txt +1 -0
aether/__init__.py
ADDED
aether/__main__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Action Abstraction Layer: hardware-independent action definitions.
|
|
3
|
+
Each AbstractAction defines what the action means, not how it's implemented.
|
|
4
|
+
"""
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import Dict, Optional
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class ActionResult:
|
|
12
|
+
action: str
|
|
13
|
+
success: bool
|
|
14
|
+
reason: str = ""
|
|
15
|
+
state: Dict = field(default_factory=dict)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AbstractAction(ABC):
|
|
19
|
+
name: str = ""
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def preconditions(self, state: Dict) -> bool:
|
|
23
|
+
"""Returns True if action can be executed given current state."""
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def expected_effect(self, state: Dict) -> Dict:
|
|
28
|
+
"""Returns expected state changes after action."""
|
|
29
|
+
...
|
|
30
|
+
|
|
31
|
+
def description(self) -> str:
|
|
32
|
+
return f"Abstract action: {self.name}"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class MoveForward(AbstractAction):
|
|
36
|
+
name = "move_forward"
|
|
37
|
+
|
|
38
|
+
def preconditions(self, state: Dict) -> bool:
|
|
39
|
+
return not state.get("obstacles_nearby") or len(state["obstacles_nearby"]) == 0
|
|
40
|
+
|
|
41
|
+
def expected_effect(self, state: Dict) -> Dict:
|
|
42
|
+
return {"agent_moved": True, "direction": "forward"}
|
|
43
|
+
|
|
44
|
+
def description(self) -> str:
|
|
45
|
+
return "Move the agent forward in its current heading direction"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class FollowTarget(AbstractAction):
|
|
49
|
+
name = "follow_target"
|
|
50
|
+
|
|
51
|
+
def preconditions(self, state: Dict) -> bool:
|
|
52
|
+
return (
|
|
53
|
+
state.get("target_detected", False)
|
|
54
|
+
and state.get("target_info") is not None
|
|
55
|
+
and "camera" not in state.get("failed_sensors", [])
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def expected_effect(self, state: Dict) -> Dict:
|
|
59
|
+
return {"closer_to_target": True, "following": True}
|
|
60
|
+
|
|
61
|
+
def description(self) -> str:
|
|
62
|
+
return "Move toward the nearest detected target"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class AvoidObstacle(AbstractAction):
|
|
66
|
+
name = "avoid_obstacle"
|
|
67
|
+
|
|
68
|
+
def preconditions(self, state: Dict) -> bool:
|
|
69
|
+
return len(state.get("obstacles_nearby", [])) > 0
|
|
70
|
+
|
|
71
|
+
def expected_effect(self, state: Dict) -> Dict:
|
|
72
|
+
return {"obstacle_avoided": True, "heading_changed": True}
|
|
73
|
+
|
|
74
|
+
def description(self) -> str:
|
|
75
|
+
return "Steer away from detected obstacles"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class Stop(AbstractAction):
|
|
79
|
+
name = "stop"
|
|
80
|
+
|
|
81
|
+
def preconditions(self, state: Dict) -> bool:
|
|
82
|
+
return True # can always stop
|
|
83
|
+
|
|
84
|
+
def expected_effect(self, state: Dict) -> Dict:
|
|
85
|
+
return {"velocity": 0, "stopped": True}
|
|
86
|
+
|
|
87
|
+
def description(self) -> str:
|
|
88
|
+
return "Halt all movement immediately"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class ScanEnvironment(AbstractAction):
|
|
92
|
+
name = "scan_environment"
|
|
93
|
+
|
|
94
|
+
def preconditions(self, state: Dict) -> bool:
|
|
95
|
+
sensors = state.get("failed_sensors", [])
|
|
96
|
+
return "camera" not in sensors or "ultrasonic" not in sensors
|
|
97
|
+
|
|
98
|
+
def expected_effect(self, state: Dict) -> Dict:
|
|
99
|
+
return {"environment_mapped": True, "obstacles_known": True}
|
|
100
|
+
|
|
101
|
+
def description(self) -> str:
|
|
102
|
+
return "Use available sensors to observe and map surroundings"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class Turn(AbstractAction):
|
|
106
|
+
name = "turn"
|
|
107
|
+
|
|
108
|
+
def preconditions(self, state: Dict) -> bool:
|
|
109
|
+
return "wheels" not in state.get("failed_actuators", [])
|
|
110
|
+
|
|
111
|
+
def expected_effect(self, state: Dict) -> Dict:
|
|
112
|
+
return {"heading_changed": True}
|
|
113
|
+
|
|
114
|
+
def description(self) -> str:
|
|
115
|
+
return "Rotate the agent in place"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
ACTION_REGISTRY: Dict[str, AbstractAction] = {
|
|
119
|
+
"move_forward": MoveForward(),
|
|
120
|
+
"follow_target": FollowTarget(),
|
|
121
|
+
"avoid_obstacle": AvoidObstacle(),
|
|
122
|
+
"stop": Stop(),
|
|
123
|
+
"scan_environment": ScanEnvironment(),
|
|
124
|
+
"turn": Turn(),
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def get_action(name: str) -> Optional[AbstractAction]:
|
|
129
|
+
return ACTION_REGISTRY.get(name)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def check_preconditions(action_name: str, state: Dict) -> bool:
|
|
133
|
+
action = get_action(action_name)
|
|
134
|
+
if action is None:
|
|
135
|
+
return False
|
|
136
|
+
return action.preconditions(state)
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base hardware adapter ABC: uniform interface all robot adapters must implement.
|
|
3
|
+
"""
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from typing import Dict, Tuple
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HardwareAdapter(ABC):
|
|
9
|
+
"""Abstract base class for all robot hardware adapters."""
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def execute(self, action: str, state: Dict) -> Tuple[Dict, bool]:
|
|
13
|
+
"""Execute action. Returns (result_dict, success)."""
|
|
14
|
+
...
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def is_action_available(self, action: str) -> bool:
|
|
18
|
+
"""Check if an action is currently executable."""
|
|
19
|
+
...
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def get_degradation_state(self) -> Dict:
|
|
23
|
+
"""Return current degradation levels per subsystem (0=healthy, 1=failed)."""
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
def get_actuator_state(self) -> Dict:
|
|
27
|
+
"""Return current actuator states."""
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
def simulate_degradation(self, degradation_level: float) -> None:
|
|
31
|
+
"""Inject simulated degradation for testing (0=none, 1=full failure)."""
|
|
32
|
+
pass
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DroneAdapter v3: stub adapter for drone hardware, same interface as RoverAdapter.
|
|
3
|
+
Raises NotImplementedError for unimplemented flight-specific actions.
|
|
4
|
+
"""
|
|
5
|
+
from typing import Dict, Tuple
|
|
6
|
+
from .base_adapter import HardwareAdapter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DroneAdapter(HardwareAdapter):
|
|
10
|
+
"""Drone adapter stub — implements interface, flight controller integration pending."""
|
|
11
|
+
|
|
12
|
+
ROBOT_TYPE = "drone"
|
|
13
|
+
DEFAULT_ALTITUDE = 5.0
|
|
14
|
+
|
|
15
|
+
def __init__(self, environment, max_speed: float = 2.0):
|
|
16
|
+
self.env = environment
|
|
17
|
+
self.max_speed = max_speed
|
|
18
|
+
self.altitude = self.DEFAULT_ALTITUDE
|
|
19
|
+
self._thruster_degradation: float = 0.0
|
|
20
|
+
|
|
21
|
+
def execute(self, action: str, state: Dict) -> Tuple[Dict, bool]:
|
|
22
|
+
params = self._translate(action, state)
|
|
23
|
+
mapped = self._map_to_env_action(action)
|
|
24
|
+
obs, reward, done, info = self.env.step(mapped, params)
|
|
25
|
+
result = {
|
|
26
|
+
"observation": obs,
|
|
27
|
+
"reward": reward,
|
|
28
|
+
"done": done,
|
|
29
|
+
"info": info,
|
|
30
|
+
"action_taken": mapped,
|
|
31
|
+
"state_dict": self.env.get_state_dict(),
|
|
32
|
+
}
|
|
33
|
+
return result, not info.get("collision", False)
|
|
34
|
+
|
|
35
|
+
def is_action_available(self, action: str) -> bool:
|
|
36
|
+
if "thrusters" in self.env.failed_actuators and action not in ("stop", "emergency_stop"):
|
|
37
|
+
return False
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
def get_degradation_state(self) -> Dict:
|
|
41
|
+
return {"thrusters": self._thruster_degradation}
|
|
42
|
+
|
|
43
|
+
def simulate_degradation(self, level: float) -> None:
|
|
44
|
+
self._thruster_degradation = min(1.0, level)
|
|
45
|
+
|
|
46
|
+
def _translate(self, action: str, state: Dict) -> Dict:
|
|
47
|
+
eff_speed = self.max_speed * (1.0 - self._thruster_degradation * 0.9)
|
|
48
|
+
if action == "move_forward":
|
|
49
|
+
return {"speed": eff_speed, "altitude": self.altitude}
|
|
50
|
+
elif action == "hover":
|
|
51
|
+
return {"speed": 0, "altitude": self.altitude}
|
|
52
|
+
elif action == "avoid_obstacle":
|
|
53
|
+
return {"altitude": self.altitude + 3.0, "speed": eff_speed * 0.5}
|
|
54
|
+
elif action in ("turn_left", "turn_right"):
|
|
55
|
+
return {"altitude": self.altitude}
|
|
56
|
+
return {"speed": 0, "altitude": self.altitude}
|
|
57
|
+
|
|
58
|
+
def _map_to_env_action(self, action: str) -> str:
|
|
59
|
+
mapping = {
|
|
60
|
+
"hover": "stop",
|
|
61
|
+
"emergency_stop": "stop",
|
|
62
|
+
"safe_mode": "stop",
|
|
63
|
+
"turn_left": "turn_left",
|
|
64
|
+
"turn_right": "turn_right",
|
|
65
|
+
"follow_target": "follow_target",
|
|
66
|
+
}
|
|
67
|
+
return mapping.get(action, action)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RoverAdapter v3: translates abstract actions into rover hardware commands.
|
|
3
|
+
Implements HardwareAdapter interface with degradation simulation.
|
|
4
|
+
"""
|
|
5
|
+
from typing import Dict, Optional, Tuple
|
|
6
|
+
from .base_adapter import HardwareAdapter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RoverAdapter(HardwareAdapter):
|
|
10
|
+
"""Full rover adapter with degradation simulation and actuator state tracking."""
|
|
11
|
+
|
|
12
|
+
ROBOT_TYPE = "rover"
|
|
13
|
+
|
|
14
|
+
def __init__(self, environment, max_speed: float = 1.0):
|
|
15
|
+
self.env = environment
|
|
16
|
+
self.max_speed = max_speed
|
|
17
|
+
self._wheel_degradation: float = 0.0
|
|
18
|
+
self._arm_degradation: float = 0.0
|
|
19
|
+
self._actuator_state: Dict = {"wheels": "nominal", "arm": "nominal"}
|
|
20
|
+
|
|
21
|
+
def execute(self, action: str, state: Dict) -> Tuple[Dict, bool]:
|
|
22
|
+
"""Execute abstract action → rover hardware command → env step."""
|
|
23
|
+
params = self._translate(action, state)
|
|
24
|
+
effective_action = self._map_to_env_action(action)
|
|
25
|
+
obs, reward, done, info = self.env.step(effective_action, params)
|
|
26
|
+
success = info.get("success", False) or not info.get("collision", False)
|
|
27
|
+
result = {
|
|
28
|
+
"observation": obs,
|
|
29
|
+
"reward": reward,
|
|
30
|
+
"done": done,
|
|
31
|
+
"info": info,
|
|
32
|
+
"action_taken": effective_action,
|
|
33
|
+
"state_dict": self.env.get_state_dict(),
|
|
34
|
+
}
|
|
35
|
+
return result, success
|
|
36
|
+
|
|
37
|
+
def is_action_available(self, action: str) -> bool:
|
|
38
|
+
if "wheels" in self.env.failed_actuators and action in (
|
|
39
|
+
"move_forward", "move_backward", "turn_left", "turn_right", "follow_target"):
|
|
40
|
+
return False
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
def get_degradation_state(self) -> Dict:
|
|
44
|
+
return {
|
|
45
|
+
"wheels": self._wheel_degradation,
|
|
46
|
+
"arm": self._arm_degradation,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
def get_actuator_state(self) -> Dict:
|
|
50
|
+
return dict(self._actuator_state)
|
|
51
|
+
|
|
52
|
+
def simulate_degradation(self, degradation_level: float) -> None:
|
|
53
|
+
self._wheel_degradation = min(1.0, degradation_level)
|
|
54
|
+
if self._wheel_degradation > 0.8:
|
|
55
|
+
self._actuator_state["wheels"] = "critical"
|
|
56
|
+
elif self._wheel_degradation > 0.4:
|
|
57
|
+
self._actuator_state["wheels"] = "degraded"
|
|
58
|
+
|
|
59
|
+
def _translate(self, action: str, state: Dict) -> Dict:
|
|
60
|
+
eff_speed = self.max_speed * (1.0 - self._wheel_degradation * 0.8)
|
|
61
|
+
if action == "move_forward":
|
|
62
|
+
return {"speed": eff_speed}
|
|
63
|
+
elif action == "move_backward":
|
|
64
|
+
return {"speed": eff_speed * 0.5}
|
|
65
|
+
elif action in ("turn_left", "turn_right"):
|
|
66
|
+
return {}
|
|
67
|
+
elif action == "follow_target":
|
|
68
|
+
return {"speed": eff_speed, "target": state.get("target_info")}
|
|
69
|
+
elif action in ("stop", "emergency_stop"):
|
|
70
|
+
return {"speed": 0}
|
|
71
|
+
elif action == "scan":
|
|
72
|
+
return {}
|
|
73
|
+
elif action == "safe_mode":
|
|
74
|
+
return {"speed": 0}
|
|
75
|
+
return {}
|
|
76
|
+
|
|
77
|
+
def _map_to_env_action(self, action: str) -> str:
|
|
78
|
+
mapping = {
|
|
79
|
+
"turn_left": "turn_left",
|
|
80
|
+
"turn_right": "turn_right",
|
|
81
|
+
"follow_target": "follow_target",
|
|
82
|
+
"emergency_stop": "stop",
|
|
83
|
+
"safe_mode": "stop",
|
|
84
|
+
"scan": "scan_environment",
|
|
85
|
+
"report_state": "scan_environment",
|
|
86
|
+
}
|
|
87
|
+
return mapping.get(action, action)
|