simulo 0.26.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.
- simulo/__init__.py +433 -0
- simulo/_client/__init__.py +6 -0
- simulo/_client/_entrypoint.py +313 -0
- simulo/_client/_mounts.py +25 -0
- simulo/_client/_runner.py +186 -0
- simulo/_client/_secure_downloads.py +1181 -0
- simulo/_client/app.py +1308 -0
- simulo/_client/asset.py +331 -0
- simulo/_client/asset_api.py +517 -0
- simulo/_client/asset_package.py +1103 -0
- simulo/_client/asset_pins.py +187 -0
- simulo/_client/builtin_aliases.py +107 -0
- simulo/_client/bundle.py +254 -0
- simulo/_client/cancel_api.py +104 -0
- simulo/_client/cli.py +9063 -0
- simulo/_client/config.py +186 -0
- simulo/_client/credentials.py +210 -0
- simulo/_client/discovery.py +214 -0
- simulo/_client/export_api.py +212 -0
- simulo/_client/export_bundle.py +296 -0
- simulo/_client/facades.py +581 -0
- simulo/_client/http.py +414 -0
- simulo/_client/identity_api.py +117 -0
- simulo/_client/install_samples.py +267 -0
- simulo/_client/jobs_api.py +224 -0
- simulo/_client/learning.py +393 -0
- simulo/_client/login.py +319 -0
- simulo/_client/mode.py +29 -0
- simulo/_client/outputs.py +116 -0
- simulo/_client/packaging.py +445 -0
- simulo/_client/preflight_api.py +186 -0
- simulo/_client/preflight_render.py +200 -0
- simulo/_client/registry.py +98 -0
- simulo/_client/runtime.py +185 -0
- simulo/_client/runtime_display.py +90 -0
- simulo/_client/seed_ref.py +76 -0
- simulo/_client/stub.py +41 -0
- simulo/_client/submit_api.py +1057 -0
- simulo/_client/templates/__init__.py +21 -0
- simulo/_client/templates/inference/app.py.tmpl +316 -0
- simulo/_client/templates/inference/simuloignore.tmpl +30 -0
- simulo/_client/templates/scenario/app.py.tmpl +93 -0
- simulo/_client/templates/scenario/simuloignore.tmpl +27 -0
- simulo/_client/templates/training/app.py.tmpl +235 -0
- simulo/_client/templates/training/simuloignore.tmpl +29 -0
- simulo/_client/view_fragment.py +21 -0
- simulo/_client/view_session_api.py +122 -0
- simulo/_client/volume.py +71 -0
- simulo/callbacks.py +274 -0
- simulo/py.typed +0 -0
- simulo-0.26.0.dist-info/METADATA +130 -0
- simulo-0.26.0.dist-info/RECORD +55 -0
- simulo-0.26.0.dist-info/WHEEL +5 -0
- simulo-0.26.0.dist-info/entry_points.txt +2 -0
- simulo-0.26.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"""Mode-aware lazy resolution of the learning / authoring surface.
|
|
2
|
+
|
|
3
|
+
The thin client exposes the training & simulation authoring names — ``Task``,
|
|
4
|
+
``Scene``, ``Robot``, ``LearningEnv``, ``RLTrainer``, components, … — as clean
|
|
5
|
+
top-level ``simulo.*`` attributes via a PEP 562 ``__getattr__`` in
|
|
6
|
+
``simulo/__init__.py`` that delegates here. The point is to let a user author a
|
|
7
|
+
normal training program with clean names that **submits locally without the heavy
|
|
8
|
+
runtime installed** and is **executed unchanged** by the backend runner.
|
|
9
|
+
|
|
10
|
+
What a name resolves to depends on the thin client's current submit/execution mode:
|
|
11
|
+
|
|
12
|
+
* **discovery** (*submit*, the default) — return a lean, torch-free **stand-in** so
|
|
13
|
+
the user app imports without ``torch`` / ``simulo.core``:
|
|
14
|
+
|
|
15
|
+
- *Subclassable* names (``Task``, ``Scenario``, ``Policy``, ``Player``,
|
|
16
|
+
``Trainer`` and the
|
|
17
|
+
three component bases) resolve to a concrete class derived from the matching
|
|
18
|
+
``simulo.interfaces.runtime`` ``@runtime_checkable`` Protocol, so
|
|
19
|
+
``class CartpoleTask(simulo.Task)`` is definable at module level AND
|
|
20
|
+
``isinstance(CartpoleTask(), TaskProtocol)`` holds — the task is nominally
|
|
21
|
+
contract-typed without importing any heavy runtime.
|
|
22
|
+
- *Value / config + in-body-only* names (``Scene``, ``Robot``, ``LearningEnv``,
|
|
23
|
+
``RLTrainer``, …) resolve to an inert :class:`Stub`, so
|
|
24
|
+
``simulo.Scene(...)`` / ``simulo.LearningEnv(...)`` are harmless if touched
|
|
25
|
+
while a class or job body is *read* (never executed) at submit. The engine
|
|
26
|
+
authoring vocabulary — ``Camera`` and its sibling sensors, ``Simulation``,
|
|
27
|
+
the controllers, the actuators, and the ``*Set`` component containers —
|
|
28
|
+
rides the exact same Stub mechanism: their real definitions live in
|
|
29
|
+
``simulo.core`` (torch-adjacent modules), so they cannot be eager imports
|
|
30
|
+
the way the RELOCATED authoring value types below are.
|
|
31
|
+
- *Relocated authoring value types* (``Pose``, ``Material``, ``Physics``,
|
|
32
|
+
``Light`` since Plan C Wave C1; ``Terrain``, ``Entity``, ``Visual`` since
|
|
33
|
+
Wave C2; ``RecordConfig`` and ``World`` since Wave C4 — dependency-free,
|
|
34
|
+
single-definition classes living in
|
|
35
|
+
``simulo.interfaces.authoring``) resolve to the **real
|
|
36
|
+
class in BOTH modes**: they need no heavy runtime, so submit-time authoring
|
|
37
|
+
gets real construction and precise static typing instead of an inert stub
|
|
38
|
+
(``RecordConfig`` even validates its fields at construction, so a bad
|
|
39
|
+
profile now fails at submit instead of on the worker), and
|
|
40
|
+
``isinstance`` agrees everywhere because only one definition exists.
|
|
41
|
+
``World`` names the authoring concept of a prebuilt place you *bring*
|
|
42
|
+
(``World.usd(...)``); ``Terrain`` keeps the ground you *generate*
|
|
43
|
+
(``plane``/``rough``). ``World`` is unrelated to the backend's sim
|
|
44
|
+
clock, ``core.simulation.Simulation`` — a different class entirely.
|
|
45
|
+
|
|
46
|
+
* **execution** (*run*, set only by the ``simulo-backend`` runner on a worker that
|
|
47
|
+
has the heavy runtime) — lazily import the real defining module and return the
|
|
48
|
+
real class. Most names live on the ``simulo.core`` aggregate; a few resolve from
|
|
49
|
+
a per-name source module recorded in :data:`_EXECUTION_ALIAS` (``Scenario`` from
|
|
50
|
+
``simulo.scenario``, the component bases from their ``simulo.core.<module>``,
|
|
51
|
+
the relocated value types from ``simulo.interfaces.authoring``).
|
|
52
|
+
|
|
53
|
+
Importing the heavy runtime happens **only** in execution mode, and only on first
|
|
54
|
+
access (then cached). At submit ``simulo.core`` / ``simulo.recording`` are never
|
|
55
|
+
imported.
|
|
56
|
+
|
|
57
|
+
Two non-learning names ride the same mechanism:
|
|
58
|
+
|
|
59
|
+
* ``simulo.save_output`` — the execution-time output registration helper.
|
|
60
|
+
Its execution-mode target is the torch-free implementation in the thin
|
|
61
|
+
client's internal outputs module — thin client code, but its call
|
|
62
|
+
reaches the ``simulo-backend`` registry (``simulo.outputs``), so at
|
|
63
|
+
discovery it resolves to an inert :class:`Stub` exactly like the
|
|
64
|
+
value/config names.
|
|
65
|
+
* ``simulo.run`` — the scenario execution loop (``simulo.scenario.run`` on
|
|
66
|
+
the worker). Called from a job body exactly like ``save_output``
|
|
67
|
+
(in-body-only, so a discovery-mode touch is harmless and never executes),
|
|
68
|
+
it resolves at discovery to an inert :class:`Stub` and at execution to the
|
|
69
|
+
real function via :data:`_EXECUTION_ALIAS`. Before this name existed, the
|
|
70
|
+
scaffold and shipped examples spelled it ``from simulo.scenario import
|
|
71
|
+
run`` — a second import into a module the torch-free client cannot even
|
|
72
|
+
see, breaking the one-import rule.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
from __future__ import annotations
|
|
76
|
+
|
|
77
|
+
import importlib
|
|
78
|
+
|
|
79
|
+
from simulo._client.mode import EXECUTION, current_mode
|
|
80
|
+
from simulo._client.stub import Stub
|
|
81
|
+
from simulo.interfaces.authoring import Entity, Light, Material, Physics, Pose, RecordConfig, Terrain, Visual, World
|
|
82
|
+
from simulo.interfaces.runtime import (
|
|
83
|
+
ObservationComponentProtocol,
|
|
84
|
+
PlayerProtocol,
|
|
85
|
+
PolicyProtocol,
|
|
86
|
+
RewardComponentProtocol,
|
|
87
|
+
ScenarioProtocol,
|
|
88
|
+
TaskProtocol,
|
|
89
|
+
TerminationConditionProtocol,
|
|
90
|
+
TrainerProtocol,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
#: Every name exposed lazily and mode-aware on ``simulo`` (the PEP 562
|
|
94
|
+
#: surface). Mostly the learning/authoring names; ``save_output`` and
|
|
95
|
+
#: ``run`` are the two non-learning members — execution-time platform helpers
|
|
96
|
+
#: that need exactly the same resolution (discovery → inert Stub, execution →
|
|
97
|
+
#: the real implementation), so they ride the same mechanism rather than a
|
|
98
|
+
#: parallel one.
|
|
99
|
+
LEARNING_NAMES: frozenset[str] = frozenset(
|
|
100
|
+
{
|
|
101
|
+
# subclassable bases
|
|
102
|
+
"Task",
|
|
103
|
+
"Scenario",
|
|
104
|
+
"Policy",
|
|
105
|
+
"Player",
|
|
106
|
+
"Trainer",
|
|
107
|
+
"ObservationComponent",
|
|
108
|
+
"RewardComponent",
|
|
109
|
+
"TerminationCondition",
|
|
110
|
+
# value / config + in-body-only
|
|
111
|
+
"Scene",
|
|
112
|
+
"Robot",
|
|
113
|
+
"LearningEnv",
|
|
114
|
+
"RLTrainer",
|
|
115
|
+
"RLPlayer",
|
|
116
|
+
"RecordConfig",
|
|
117
|
+
"Pose",
|
|
118
|
+
"Terrain",
|
|
119
|
+
"World",
|
|
120
|
+
"Light",
|
|
121
|
+
"Entity",
|
|
122
|
+
"Material",
|
|
123
|
+
"Physics",
|
|
124
|
+
"Visual",
|
|
125
|
+
# engine authoring vocabulary (one-import rule, second half) — value/config classes
|
|
126
|
+
# and one runtime-context class whose real definition lives in
|
|
127
|
+
# ``simulo.core`` (torch-adjacent), so they are Stubs in discovery,
|
|
128
|
+
# never RELOCATED real classes like the authoring types above.
|
|
129
|
+
"Camera",
|
|
130
|
+
"CameraSpawnConfig",
|
|
131
|
+
"SensorOffset",
|
|
132
|
+
"ContactSensor",
|
|
133
|
+
"RayCaster",
|
|
134
|
+
"RayPattern",
|
|
135
|
+
"IMU",
|
|
136
|
+
"ForceTorqueSensor",
|
|
137
|
+
"FrameTransformer",
|
|
138
|
+
"FrameTransformerTarget",
|
|
139
|
+
"Simulation",
|
|
140
|
+
"ObservationSet",
|
|
141
|
+
"RewardSet",
|
|
142
|
+
"TerminationSet",
|
|
143
|
+
"DifferentialIKController",
|
|
144
|
+
"OperationalSpaceController",
|
|
145
|
+
"SurfaceGripperActuator",
|
|
146
|
+
"ParallelGripperActuator",
|
|
147
|
+
"GripperState",
|
|
148
|
+
"GripperCommand",
|
|
149
|
+
"ActuatorGainsConfig",
|
|
150
|
+
"Prop",
|
|
151
|
+
# execution-time output registration (Plan B PR-B8) — in-body-only
|
|
152
|
+
"save_output",
|
|
153
|
+
# scenario execution loop — in-body-only, real definition in
|
|
154
|
+
# simulo.scenario (simulo-backend distribution)
|
|
155
|
+
"run",
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# --- Discovery-mode subclassable bases --------------------------------------
|
|
160
|
+
#
|
|
161
|
+
# A concrete (non-protocol) subclass of a ``@runtime_checkable`` Protocol is both
|
|
162
|
+
# instantiable AND structurally an instance of that Protocol on Python 3.11 and
|
|
163
|
+
# 3.12. Deriving the user-facing base from the Protocol gives ``class
|
|
164
|
+
# X(simulo.Task)`` nominal contract typing while keeping submit torch-free — the
|
|
165
|
+
# stand-in is the Protocol, never ``simulo.core.Task``.
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class _Task(TaskProtocol):
|
|
169
|
+
"""Discovery stand-in for :class:`simulo.core.task.Task`."""
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class _Scenario(ScenarioProtocol):
|
|
173
|
+
"""Discovery stand-in for :class:`simulo.scenario.Scenario`."""
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class _Policy(PolicyProtocol):
|
|
177
|
+
"""Discovery stand-in for :class:`simulo.core.policy.Policy`."""
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class _Player(PlayerProtocol):
|
|
181
|
+
"""Discovery stand-in for :class:`simulo.core.player.Player`."""
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class _Trainer(TrainerProtocol):
|
|
185
|
+
"""Discovery stand-in for :class:`simulo.core.trainer.Trainer`.
|
|
186
|
+
|
|
187
|
+
Joined the subclassable table in Plan C Wave C4: ``Trainer`` is the
|
|
188
|
+
user-extensible training-orchestration base (``RLTrainer`` is the
|
|
189
|
+
instantiated concrete name), so ``class MyTrainer(simulo.Trainer)`` must
|
|
190
|
+
be definable at module level at submit — a bare :class:`Stub` (its
|
|
191
|
+
pre-C4 stand-in) is not subclassable at all.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class _ObservationComponent(ObservationComponentProtocol):
|
|
196
|
+
"""Discovery stand-in for ``simulo.core.observations.ObservationComponent``."""
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class _RewardComponent(RewardComponentProtocol):
|
|
200
|
+
"""Discovery stand-in for ``simulo.core.rewards.RewardComponent``."""
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class _TerminationCondition(TerminationConditionProtocol):
|
|
204
|
+
"""Discovery stand-in for ``simulo.core.terminations.TerminationCondition``."""
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class _RobotDiscoveryStandIn:
|
|
208
|
+
"""Discovery-mode ``simulo.Robot`` stand-in that ALSO enforces kind
|
|
209
|
+
safety — the submit-reachable half of the two-layer split: a module-level/entrypoint ``Robot(asset=<world
|
|
210
|
+
handle>)`` fails HERE, at construction, because that code path runs during
|
|
211
|
+
discovery; a task-BODY construction is structurally unreachable at
|
|
212
|
+
discovery (job bodies never execute at submit) and is instead caught by
|
|
213
|
+
the execution-mode guard in ``core/robot.py``. Otherwise inert — returns a
|
|
214
|
+
plain :class:`Stub`, exactly like the bare ``Stub("simulo.Robot")`` this
|
|
215
|
+
replaces.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
def __call__(self, *args: object, **kwargs: object) -> Stub:
|
|
219
|
+
asset = kwargs.get("asset", args[0] if args else None)
|
|
220
|
+
require_kind = getattr(asset, "require_kind", None)
|
|
221
|
+
if callable(require_kind):
|
|
222
|
+
require_kind("robot")
|
|
223
|
+
return Stub("simulo.Robot()")
|
|
224
|
+
|
|
225
|
+
def __getattr__(self, item: str) -> Stub:
|
|
226
|
+
if item.startswith("__") and item.endswith("__"):
|
|
227
|
+
raise AttributeError(item)
|
|
228
|
+
return Stub(f"simulo.Robot.{item}")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# Discovery-mode resolution table. Subclassable names map to their Protocol-derived
|
|
232
|
+
# base (a stable singleton class — stable identity for ``isinstance`` / ``issubclass``);
|
|
233
|
+
# value/config names map to an inert :class:`Stub` (``Robot`` maps to the
|
|
234
|
+
# kind-checking stand-in above instead of a bare Stub — see its docstring).
|
|
235
|
+
# RELOCATED authoring value types (``Pose``/``Material``/``Physics``/``Light``
|
|
236
|
+
# from Wave C1; ``Terrain``/``Entity``/``Visual`` from Wave C2;
|
|
237
|
+
# ``RecordConfig``/``World`` from Wave C4)
|
|
238
|
+
# map to their REAL, dependency-free class — the same object execution mode
|
|
239
|
+
# resolves, so submit-time authoring constructs real values (see the module
|
|
240
|
+
# docstring).
|
|
241
|
+
_DISCOVERY_STANDINS: dict[str, object] = {
|
|
242
|
+
"Task": _Task,
|
|
243
|
+
"Scenario": _Scenario,
|
|
244
|
+
"Policy": _Policy,
|
|
245
|
+
"Player": _Player,
|
|
246
|
+
"Trainer": _Trainer,
|
|
247
|
+
"ObservationComponent": _ObservationComponent,
|
|
248
|
+
"RewardComponent": _RewardComponent,
|
|
249
|
+
"TerminationCondition": _TerminationCondition,
|
|
250
|
+
"Scene": Stub("simulo.Scene"),
|
|
251
|
+
"Robot": _RobotDiscoveryStandIn(),
|
|
252
|
+
"LearningEnv": Stub("simulo.LearningEnv"),
|
|
253
|
+
"RLTrainer": Stub("simulo.RLTrainer"),
|
|
254
|
+
"RLPlayer": Stub("simulo.RLPlayer"),
|
|
255
|
+
"RecordConfig": RecordConfig,
|
|
256
|
+
"Pose": Pose,
|
|
257
|
+
"Terrain": Terrain,
|
|
258
|
+
"World": World,
|
|
259
|
+
"Light": Light,
|
|
260
|
+
"Entity": Entity,
|
|
261
|
+
"Material": Material,
|
|
262
|
+
"Physics": Physics,
|
|
263
|
+
"Visual": Visual,
|
|
264
|
+
# Engine authoring vocabulary (one-import rule, second half): plain inert Stubs, same
|
|
265
|
+
# posture as Scene/LearningEnv/RLTrainer/RLPlayer above — none of these
|
|
266
|
+
# are subclassed, all are constructed and then only touched (attached to
|
|
267
|
+
# a scene/robot, read for config), which a Stub tolerates harmlessly.
|
|
268
|
+
"Camera": Stub("simulo.Camera"),
|
|
269
|
+
"CameraSpawnConfig": Stub("simulo.CameraSpawnConfig"),
|
|
270
|
+
"SensorOffset": Stub("simulo.SensorOffset"),
|
|
271
|
+
"ContactSensor": Stub("simulo.ContactSensor"),
|
|
272
|
+
"RayCaster": Stub("simulo.RayCaster"),
|
|
273
|
+
"RayPattern": Stub("simulo.RayPattern"),
|
|
274
|
+
"IMU": Stub("simulo.IMU"),
|
|
275
|
+
"ForceTorqueSensor": Stub("simulo.ForceTorqueSensor"),
|
|
276
|
+
"FrameTransformer": Stub("simulo.FrameTransformer"),
|
|
277
|
+
"FrameTransformerTarget": Stub("simulo.FrameTransformerTarget"),
|
|
278
|
+
"Simulation": Stub("simulo.Simulation"),
|
|
279
|
+
"ObservationSet": Stub("simulo.ObservationSet"),
|
|
280
|
+
"RewardSet": Stub("simulo.RewardSet"),
|
|
281
|
+
"TerminationSet": Stub("simulo.TerminationSet"),
|
|
282
|
+
"DifferentialIKController": Stub("simulo.DifferentialIKController"),
|
|
283
|
+
"OperationalSpaceController": Stub("simulo.OperationalSpaceController"),
|
|
284
|
+
"SurfaceGripperActuator": Stub("simulo.SurfaceGripperActuator"),
|
|
285
|
+
"ParallelGripperActuator": Stub("simulo.ParallelGripperActuator"),
|
|
286
|
+
"GripperState": Stub("simulo.GripperState"),
|
|
287
|
+
"GripperCommand": Stub("simulo.GripperCommand"),
|
|
288
|
+
"ActuatorGainsConfig": Stub("simulo.ActuatorGainsConfig"),
|
|
289
|
+
"Prop": Stub("simulo.Prop"),
|
|
290
|
+
# ``simulo.save_output`` is in-body-only: job bodies never execute at
|
|
291
|
+
# submit, so a discovery-mode call (necessarily module-level) is inert and
|
|
292
|
+
# registers nothing — the same posture as touching ``simulo.Scene(...)``.
|
|
293
|
+
"save_output": Stub("simulo.save_output"),
|
|
294
|
+
# ``simulo.run`` (the scenario execution loop) is in-body-only too: a
|
|
295
|
+
# scenario job's ``@app.job`` body calls ``simulo.run(MyScenario, ...)``
|
|
296
|
+
# and job bodies never execute at submit, so the discovery-mode call is
|
|
297
|
+
# inert — same posture as ``save_output`` above.
|
|
298
|
+
"run": Stub("simulo.run"),
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
# Execution-mode resolution targets: thin-client name -> (source module, attribute).
|
|
302
|
+
# Most learning names are re-exported from the ``simulo.core`` package aggregate,
|
|
303
|
+
# so they default to ``("simulo.core", name)``. Names whose defining module is NOT
|
|
304
|
+
# the ``simulo.core`` aggregate carry an explicit per-name source module here: the
|
|
305
|
+
# component bases and ``Scenario`` live in their own modules, and ``RecordConfig``
|
|
306
|
+
# belongs to the recording subpackage (``simulo.recording``) — it is deliberately
|
|
307
|
+
# not re-exported from ``simulo.core``.
|
|
308
|
+
_EXECUTION_ALIAS: dict[str, tuple[str, str]] = {
|
|
309
|
+
"Scenario": ("simulo.scenario", "Scenario"),
|
|
310
|
+
# ``run`` is the scenario execution loop that takes a ``Scenario``
|
|
311
|
+
# subclass and drives its lifecycle — it lives alongside ``Scenario``
|
|
312
|
+
# itself in ``simulo.scenario`` (the simulo-backend distribution), not on
|
|
313
|
+
# the ``simulo.core`` aggregate.
|
|
314
|
+
"run": ("simulo.scenario", "run"),
|
|
315
|
+
"ObservationComponent": ("simulo.core.observations", "ObservationComponent"),
|
|
316
|
+
"RewardComponent": ("simulo.core.rewards", "RewardComponent"),
|
|
317
|
+
"TerminationCondition": ("simulo.core.terminations", "TerminationCondition"),
|
|
318
|
+
# RELOCATED authoring value types (Plan C — Waves C1, C2, then C4's
|
|
319
|
+
# ``RecordConfig`` — formerly resolved from the recording subpackage —
|
|
320
|
+
# and C4's ``World``, the spatial-vocabulary split): the
|
|
321
|
+
# single definition lives in ``simulo.interfaces.authoring`` —
|
|
322
|
+
# ``simulo.core`` deliberately does NOT re-export it ("nuke as you go", no
|
|
323
|
+
# shims), so the default ``getattr(simulo.core, name)`` resolution would
|
|
324
|
+
# fail on the worker.
|
|
325
|
+
"RecordConfig": ("simulo.interfaces.authoring", "RecordConfig"),
|
|
326
|
+
"Pose": ("simulo.interfaces.authoring", "Pose"),
|
|
327
|
+
"Material": ("simulo.interfaces.authoring", "Material"),
|
|
328
|
+
"Physics": ("simulo.interfaces.authoring", "Physics"),
|
|
329
|
+
"Light": ("simulo.interfaces.authoring", "Light"),
|
|
330
|
+
"Terrain": ("simulo.interfaces.authoring", "Terrain"),
|
|
331
|
+
"World": ("simulo.interfaces.authoring", "World"),
|
|
332
|
+
"Entity": ("simulo.interfaces.authoring", "Entity"),
|
|
333
|
+
"Visual": ("simulo.interfaces.authoring", "Visual"),
|
|
334
|
+
# Engine authoring vocabulary (one-import rule, second half): unlike the RELOCATED
|
|
335
|
+
# authoring types above, these stay defined in ``simulo.core`` — but
|
|
336
|
+
# ``simulo.core.__init__`` only re-exports a curated subset onto the
|
|
337
|
+
# aggregate (measured: ``Simulation``, ``SurfaceGripperActuator``,
|
|
338
|
+
# ``ParallelGripperActuator``, ``GripperState``, ``GripperCommand``,
|
|
339
|
+
# ``Prop`` and ``DifferentialIKController`` ARE on the aggregate, so they
|
|
340
|
+
# fall through to the default ``("simulo.core", name)`` resolution
|
|
341
|
+
# below and need no entry here). Everything else here is bound only on
|
|
342
|
+
# its OWN submodule, never on the aggregate, so the default resolution
|
|
343
|
+
# would raise ``AttributeError`` on the worker without an explicit alias.
|
|
344
|
+
"Camera": ("simulo.core.sensor", "Camera"),
|
|
345
|
+
"CameraSpawnConfig": ("simulo.core.sensor", "CameraSpawnConfig"),
|
|
346
|
+
"SensorOffset": ("simulo.core.sensor", "SensorOffset"),
|
|
347
|
+
"ContactSensor": ("simulo.core.sensor", "ContactSensor"),
|
|
348
|
+
"RayCaster": ("simulo.core.sensor", "RayCaster"),
|
|
349
|
+
"RayPattern": ("simulo.core.sensor", "RayPattern"),
|
|
350
|
+
"IMU": ("simulo.core.sensor", "IMU"),
|
|
351
|
+
"ForceTorqueSensor": ("simulo.core.sensor", "ForceTorqueSensor"),
|
|
352
|
+
"FrameTransformer": ("simulo.core.sensor", "FrameTransformer"),
|
|
353
|
+
"FrameTransformerTarget": ("simulo.core.sensor", "FrameTransformerTarget"),
|
|
354
|
+
"ObservationSet": ("simulo.core.observations", "ObservationSet"),
|
|
355
|
+
"RewardSet": ("simulo.core.rewards", "RewardSet"),
|
|
356
|
+
"TerminationSet": ("simulo.core.terminations", "TerminationSet"),
|
|
357
|
+
"OperationalSpaceController": ("simulo.core.controller", "OperationalSpaceController"),
|
|
358
|
+
"ActuatorGainsConfig": ("simulo.core.robot", "ActuatorGainsConfig"),
|
|
359
|
+
# The real ``save_output`` lives in the thin client itself (it is
|
|
360
|
+
# torch-free); only its CALL reaches the ``simulo.outputs`` registry that
|
|
361
|
+
# ships with ``simulo-backend`` — see ``_client/outputs.py``.
|
|
362
|
+
"save_output": ("simulo._client.outputs", "save_output"),
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
# Cache resolved execution-mode classes for stable identity across repeated access.
|
|
366
|
+
_EXECUTION_CACHE: dict[str, object] = {}
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _resolve_execution(name: str) -> object:
|
|
370
|
+
"""Lazily import the name's real defining module and return the real class."""
|
|
371
|
+
module_name, attribute = _EXECUTION_ALIAS.get(name, ("simulo.core", name))
|
|
372
|
+
module = importlib.import_module(module_name)
|
|
373
|
+
return getattr(module, attribute)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def resolve(name: str) -> object:
|
|
377
|
+
"""Resolve a learning name under the current mode.
|
|
378
|
+
|
|
379
|
+
Execution → the real class from its defining module (``simulo.core`` by
|
|
380
|
+
default, or the per-name source in :data:`_EXECUTION_ALIAS`; imported lazily,
|
|
381
|
+
then cached). Discovery → the lean torch-free stand-in (a stable singleton) —
|
|
382
|
+
which for the RELOCATED authoring value types is the real class itself.
|
|
383
|
+
Raises ``AttributeError`` for any name outside :data:`LEARNING_NAMES`.
|
|
384
|
+
"""
|
|
385
|
+
if name not in LEARNING_NAMES:
|
|
386
|
+
raise AttributeError(name)
|
|
387
|
+
if current_mode() == EXECUTION:
|
|
388
|
+
cached = _EXECUTION_CACHE.get(name)
|
|
389
|
+
if cached is None:
|
|
390
|
+
cached = _resolve_execution(name)
|
|
391
|
+
_EXECUTION_CACHE[name] = cached
|
|
392
|
+
return cached
|
|
393
|
+
return _DISCOVERY_STANDINS[name]
|