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,581 @@
|
|
|
1
|
+
"""Typing facades for the instantiated (and called) learning names on ``simulo.*``.
|
|
2
|
+
|
|
3
|
+
**Never instantiate or call anything from this module at runtime.** These
|
|
4
|
+
classes — and the one plain function below — exist so a type
|
|
5
|
+
checker sees precise types for the *instantiated* learning names
|
|
6
|
+
(``simulo.LearningEnv(...)``, ``simulo.Scene(...)``, ``simulo.Robot(...)``,
|
|
7
|
+
``simulo.RLTrainer(...)``, ``simulo.RLPlayer(...)``) and the one *called*
|
|
8
|
+
name (``simulo.run(...)``, the scenario execution loop). At runtime those
|
|
9
|
+
names resolve through the thin client's internal mode-aware learning-name
|
|
10
|
+
resolver — an inert stand-in at submit, the real heavy class/function on the
|
|
11
|
+
worker — and this module is imported ONLY under ``if TYPE_CHECKING:`` in
|
|
12
|
+
``simulo/__init__.py``.
|
|
13
|
+
|
|
14
|
+
Why a facade class per name, rather than aliasing the ``simulo.interfaces``
|
|
15
|
+
Protocol (measured, mypy 2.3.0):
|
|
16
|
+
|
|
17
|
+
* aliasing the Protocol rejects instantiation ("Cannot instantiate protocol
|
|
18
|
+
class") — which is why these names aliased ``Any`` before Plan C Wave C4;
|
|
19
|
+
* a bare subclass of the Protocol is ABSTRACT to mypy (every ``...``-bodied
|
|
20
|
+
Protocol member is implicitly abstract in an explicit subclass), so each
|
|
21
|
+
facade re-declares its contract's full surface — method/property bodies
|
|
22
|
+
``raise NotImplementedError`` (they never run; an empty body would trip
|
|
23
|
+
mypy's ``[empty-body]`` check), data members as bare annotations;
|
|
24
|
+
* the facade additionally declares ``__init__`` with the concrete class's
|
|
25
|
+
real constructor signature — the one member a Protocol cannot pin.
|
|
26
|
+
|
|
27
|
+
Drift is not left to review. The backend suite's conformance engine
|
|
28
|
+
(``sdk/tests/test_scene_protocol_conformance.py``) compares every facade
|
|
29
|
+
against its contract (member-set equality + per-member signature comparison,
|
|
30
|
+
parameter NAMES included — mypy is silent on a rename in these
|
|
31
|
+
re-declarations) and every facade ``__init__``, method, property, and bare
|
|
32
|
+
data-annotation member against the CONCRETE ``simulo.core`` class — including
|
|
33
|
+
that a facade data member (``asset``, ``initial_pose``, …) actually EXISTS on
|
|
34
|
+
the concrete class — so a member being renamed, added, or dropped on any of
|
|
35
|
+
the three sides (contract, concrete class, facade) fails a named test by
|
|
36
|
+
member name.
|
|
37
|
+
|
|
38
|
+
**What is NOT pinned (a known, deliberate gap — Wave C4 fix round):** the
|
|
39
|
+
engine compares parameter/attribute *shape* (name, kind, presence of a
|
|
40
|
+
default) and, for data members, *existence* — never the declared TYPE
|
|
41
|
+
annotation. A facade parameter or data member can carry a narrower or wider
|
|
42
|
+
type than its concrete counterpart (e.g. ``Optional[Any]`` vs
|
|
43
|
+
``Optional[ArticulationConfig]``) with every test above green; only
|
|
44
|
+
``mypy --strict`` on user code that actually touches the divergent member
|
|
45
|
+
would catch it, and only if that code exists. Five such divergences ship
|
|
46
|
+
today, all deliberate widenings where the precise type isn't importable
|
|
47
|
+
thin-side: ``Robot.articulation`` (``Any``), ``Robot.joint_config`` (element
|
|
48
|
+
type ``Any``), ``Robot.asset`` (widened), ``Robot.actuator_gains`` (value
|
|
49
|
+
type ``Any``), ``LearningEnv.viewstream`` (``Any`` vs ``ViewStreamOption``).
|
|
50
|
+
|
|
51
|
+
The facades deliberately present the surface a user of the bare
|
|
52
|
+
``simulo.<Name>`` may rely on: the contract members, plus the concrete
|
|
53
|
+
class's documented extensions (``RLTrainer.close`` / ``export_policy``;
|
|
54
|
+
``RLPlayer``'s ``record=`` playback, accessors, and exporters). Members the
|
|
55
|
+
contracts deliberately omit (gymnasium plumbing on the env; engine seams)
|
|
56
|
+
are omitted here too — see the interfaces module docstrings for the record.
|
|
57
|
+
|
|
58
|
+
**``run`` is a plain function, not a class — a different shape for a
|
|
59
|
+
different reason.** There is no ``RunProtocol`` to alias (``run`` is not a
|
|
60
|
+
method any contract declares), so the "why not alias the Protocol" bullets
|
|
61
|
+
above do not apply to it. Its problem is narrower: with no static override at
|
|
62
|
+
all, ``simulo.run`` types as ``object`` (``__getattr__``'s declared return
|
|
63
|
+
type) — which is not merely imprecise, it is **not callable**, so
|
|
64
|
+
``simulo.run(MyScenario, ...)`` in a freshly scaffolded app is a hard mypy
|
|
65
|
+
error a user cannot suppress with ``--ignore-missing-imports`` (that flag
|
|
66
|
+
only silences a *missing import*; ``object`` not being callable is a real
|
|
67
|
+
type error). A bare function with the real ``simulo.scenario.run`` signature
|
|
68
|
+
and a ``NotImplementedError`` body — never called — fixes that the same way
|
|
69
|
+
the classes above fix instantiation. Like ``Camera``, ``run`` is NOT
|
|
70
|
+
registered in the backend suite's four-layer conformance engine (that engine
|
|
71
|
+
pins classes: constructor + method/property members against a Protocol and a
|
|
72
|
+
concrete class; ``run`` is a bare function with no Protocol to check member
|
|
73
|
+
parity against). Its drift guard is a live, unmocked signature comparison
|
|
74
|
+
against the REAL ``simulo.scenario.run`` in ``simulo-backend``'s
|
|
75
|
+
``sdk/tests/test_scenario_run_execution_alias.py`` — stronger than the
|
|
76
|
+
snapshot-only pin ``test_camera_facade.py`` uses, because ``simulo.scenario``
|
|
77
|
+
(unlike ``simulo.core``) is a single-file module with no heavy top-level
|
|
78
|
+
class graph to import.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
from __future__ import annotations
|
|
82
|
+
|
|
83
|
+
from pathlib import Path
|
|
84
|
+
from typing import Any, Dict, List, Optional, Tuple, Type, Union
|
|
85
|
+
|
|
86
|
+
from simulo._client.asset import Asset as RegistryAsset
|
|
87
|
+
from simulo.interfaces.authoring import (
|
|
88
|
+
AssetSource,
|
|
89
|
+
CameraProtocol,
|
|
90
|
+
Pose,
|
|
91
|
+
PrimitiveShape,
|
|
92
|
+
PropProtocol,
|
|
93
|
+
PropStateProtocol,
|
|
94
|
+
RecordConfig,
|
|
95
|
+
RobotProtocol,
|
|
96
|
+
RobotStateProtocol,
|
|
97
|
+
SceneProtocol,
|
|
98
|
+
)
|
|
99
|
+
from simulo.interfaces.runtime import (
|
|
100
|
+
DebugOnAnomaly,
|
|
101
|
+
LearningEnvProtocol,
|
|
102
|
+
PlayerProtocol,
|
|
103
|
+
ScenarioProtocol,
|
|
104
|
+
TaskProtocol,
|
|
105
|
+
TrainerProtocol,
|
|
106
|
+
)
|
|
107
|
+
from simulo.interfaces.runtime.tensors import TensorLike
|
|
108
|
+
|
|
109
|
+
__all__ = ["Camera", "LearningEnv", "Prop", "RLPlayer", "RLTrainer", "Robot", "run"]
|
|
110
|
+
|
|
111
|
+
# There is deliberately NO ``Scene`` facade: measured across every shipped
|
|
112
|
+
# user surface (demos, thin examples, templates), ``simulo.Scene`` appears
|
|
113
|
+
# ONLY in annotation position (``def build(self, scene: simulo.Scene)``) —
|
|
114
|
+
# never instantiated (the environment constructs the scene and hands it to
|
|
115
|
+
# ``build``). So ``simulo.Scene`` aliases ``SceneProtocol`` itself, which is
|
|
116
|
+
# also what keeps a user's ``build`` override Liskov-compatible with the
|
|
117
|
+
# contract's ``scene: SceneProtocol`` parameter — a facade subtype there
|
|
118
|
+
# would make every shipped ``build`` annotation an override error.
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class Camera(CameraProtocol):
|
|
122
|
+
"""Typing facade for the ``simulo.Camera`` authoring surface.
|
|
123
|
+
|
|
124
|
+
``CameraProtocol`` (which extends ``SensorProtocol``) declares the full
|
|
125
|
+
surface this facade needs, unlike the other sensor subclasses (see the
|
|
126
|
+
``simulo/__init__.py`` TYPE_CHECKING block for why ``ContactSensor`` /
|
|
127
|
+
``RayCaster`` / ``IMU`` / ``ForceTorqueSensor`` / ``FrameTransformer`` do
|
|
128
|
+
not get a facade — they conform only to the base ``SensorProtocol``, which
|
|
129
|
+
would be a lossy alias for their richer, type-specific readers).
|
|
130
|
+
|
|
131
|
+
**Known gap (documented, not a silent one):** unlike ``Robot`` /
|
|
132
|
+
``LearningEnv`` / ``RLTrainer`` / ``RLPlayer`` above, this facade is NOT
|
|
133
|
+
registered in the backend suite's conformance engine
|
|
134
|
+
(``sdk/tests/test_scene_protocol_conformance.py`` pins those four by name,
|
|
135
|
+
not generically over ``facades.__all__``) — extending that engine to a
|
|
136
|
+
fifth facade is backend-suite work with its own gate, deliberately
|
|
137
|
+
deferred rather than bundled in here. Drift between this facade,
|
|
138
|
+
``CameraProtocol``, and the concrete ``simulo.core.sensor.Camera`` is
|
|
139
|
+
caught only by the lighter thin-client-side structural check in
|
|
140
|
+
``tests/test_camera_facade.py``, not the four-layer mirror machinery the
|
|
141
|
+
other facades get.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
path: Optional[str]
|
|
145
|
+
update_period: float
|
|
146
|
+
enabled: bool
|
|
147
|
+
debug_vis: bool
|
|
148
|
+
width: int
|
|
149
|
+
height: int
|
|
150
|
+
data_types: List[str]
|
|
151
|
+
offset: Optional[Any]
|
|
152
|
+
spawn: Any
|
|
153
|
+
|
|
154
|
+
def __init__(
|
|
155
|
+
self,
|
|
156
|
+
path: Optional[str] = None,
|
|
157
|
+
width: int = 640,
|
|
158
|
+
height: int = 480,
|
|
159
|
+
data_types: Optional[List[str]] = None,
|
|
160
|
+
update_period: float = 0.0,
|
|
161
|
+
offset: Optional[Any] = None,
|
|
162
|
+
spawn: Optional[Any] = None,
|
|
163
|
+
enabled: bool = True,
|
|
164
|
+
debug_vis: bool = False,
|
|
165
|
+
) -> None:
|
|
166
|
+
raise NotImplementedError("typing facade — never instantiate; the runtime object comes from the simulo surface")
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def name(self) -> Optional[str]:
|
|
170
|
+
raise NotImplementedError
|
|
171
|
+
|
|
172
|
+
def update(self, dt: float) -> None:
|
|
173
|
+
raise NotImplementedError
|
|
174
|
+
|
|
175
|
+
def reset(self) -> None:
|
|
176
|
+
raise NotImplementedError
|
|
177
|
+
|
|
178
|
+
def read_rgb(self) -> TensorLike:
|
|
179
|
+
raise NotImplementedError
|
|
180
|
+
|
|
181
|
+
def read_depth(self) -> TensorLike:
|
|
182
|
+
raise NotImplementedError
|
|
183
|
+
|
|
184
|
+
def read_normals(self) -> TensorLike:
|
|
185
|
+
raise NotImplementedError
|
|
186
|
+
|
|
187
|
+
def read_semantic(self) -> TensorLike:
|
|
188
|
+
raise NotImplementedError
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class Prop(PropProtocol):
|
|
192
|
+
"""Typing facade for the ``simulo.Prop`` authoring surface.
|
|
193
|
+
|
|
194
|
+
``Prop`` is an *instantiated* mirror name (``simulo.Prop(shape)``), so it
|
|
195
|
+
follows the same rule as ``Robot`` / ``Camera``: a ``PropProtocol`` alias
|
|
196
|
+
would make mypy reject the call ("Cannot instantiate protocol class"), and
|
|
197
|
+
no alias at all would type it as ``object``. Unlike the ``Camera`` facade
|
|
198
|
+
above, this one IS registered in the backend suite's conformance engine,
|
|
199
|
+
so drift against both ``PropProtocol`` and the concrete
|
|
200
|
+
``simulo.core.prop.Prop`` is caught by the same four-layer machinery
|
|
201
|
+
``Robot`` gets.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
shape: PrimitiveShape
|
|
205
|
+
|
|
206
|
+
def __init__(self, shape: PrimitiveShape) -> None:
|
|
207
|
+
raise NotImplementedError("typing facade — never instantiate; the runtime object comes from the simulo surface")
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def name(self) -> Optional[str]:
|
|
211
|
+
raise NotImplementedError
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def path(self) -> Optional[str]:
|
|
215
|
+
raise NotImplementedError
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def state(self) -> PropStateProtocol:
|
|
219
|
+
raise NotImplementedError
|
|
220
|
+
|
|
221
|
+
@property
|
|
222
|
+
def default_pose(self) -> TensorLike:
|
|
223
|
+
raise NotImplementedError
|
|
224
|
+
|
|
225
|
+
def set_pose(self, pose: TensorLike, env_ids: Optional[TensorLike] = None) -> None:
|
|
226
|
+
raise NotImplementedError
|
|
227
|
+
|
|
228
|
+
def set_velocity(self, velocity: TensorLike, env_ids: Optional[TensorLike] = None) -> None:
|
|
229
|
+
raise NotImplementedError
|
|
230
|
+
|
|
231
|
+
def reset(self, env_ids: Optional[TensorLike] = None) -> None:
|
|
232
|
+
raise NotImplementedError
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class Robot(RobotProtocol):
|
|
236
|
+
"""Typing facade for the ``simulo.Robot`` authoring surface."""
|
|
237
|
+
|
|
238
|
+
asset: AssetSource
|
|
239
|
+
initial_pose: Pose
|
|
240
|
+
collision_enabled: bool
|
|
241
|
+
visual_only: bool
|
|
242
|
+
mass_scale: float
|
|
243
|
+
scale: Tuple[float, float, float]
|
|
244
|
+
articulation: Any
|
|
245
|
+
joint_config: Optional[List[Any]]
|
|
246
|
+
disable_gravity: bool
|
|
247
|
+
actuator_gains: Optional[Dict[str, Any]]
|
|
248
|
+
|
|
249
|
+
def __init__(
|
|
250
|
+
self,
|
|
251
|
+
# The authoring model-source spec (``AssetSource.usd(...)`` /
|
|
252
|
+
# ``.urdf(...)``) or the platform registry handle
|
|
253
|
+
# (``simulo.Asset.from_registry(...)``) — both are shipped calling
|
|
254
|
+
# conventions; the runtime resolves the registry handle to a model
|
|
255
|
+
# source on the worker.
|
|
256
|
+
asset: Union[AssetSource, RegistryAsset],
|
|
257
|
+
initial_pose: Optional[Pose] = None,
|
|
258
|
+
collision_enabled: bool = True,
|
|
259
|
+
visual_only: bool = False,
|
|
260
|
+
mass_scale: float = 1.0,
|
|
261
|
+
scale: Tuple[float, float, float] = (1.0, 1.0, 1.0),
|
|
262
|
+
articulation: Optional[Any] = None,
|
|
263
|
+
joint_config: Optional[List[Any]] = None,
|
|
264
|
+
disable_gravity: bool = False,
|
|
265
|
+
actuator_gains: Optional[Dict[str, Any]] = None,
|
|
266
|
+
) -> None:
|
|
267
|
+
raise NotImplementedError("typing facade — never instantiate; the runtime object comes from the simulo surface")
|
|
268
|
+
|
|
269
|
+
@property
|
|
270
|
+
def name(self) -> Optional[str]:
|
|
271
|
+
raise NotImplementedError
|
|
272
|
+
|
|
273
|
+
@property
|
|
274
|
+
def path(self) -> Optional[str]:
|
|
275
|
+
raise NotImplementedError
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def internals(self) -> Any:
|
|
279
|
+
raise NotImplementedError
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def state(self) -> RobotStateProtocol:
|
|
283
|
+
raise NotImplementedError
|
|
284
|
+
|
|
285
|
+
@property
|
|
286
|
+
def sensors(self) -> List[Any]:
|
|
287
|
+
raise NotImplementedError
|
|
288
|
+
|
|
289
|
+
@property
|
|
290
|
+
def actuators(self) -> List[Any]:
|
|
291
|
+
raise NotImplementedError
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
def num_joints(self) -> int:
|
|
295
|
+
raise NotImplementedError
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def is_fixed_base(self) -> bool:
|
|
299
|
+
raise NotImplementedError
|
|
300
|
+
|
|
301
|
+
def add_sensor(self, sensor: Any, attach_to: str) -> "Robot":
|
|
302
|
+
raise NotImplementedError
|
|
303
|
+
|
|
304
|
+
def add_actuator(self, actuator: Any, attach_to: str) -> "Robot":
|
|
305
|
+
raise NotImplementedError
|
|
306
|
+
|
|
307
|
+
def get_joint_names(self) -> List[str]:
|
|
308
|
+
raise NotImplementedError
|
|
309
|
+
|
|
310
|
+
def find_joints(self, name_pattern: str) -> List[int]:
|
|
311
|
+
raise NotImplementedError
|
|
312
|
+
|
|
313
|
+
def find_bodies(self, name_pattern: str) -> List[int]:
|
|
314
|
+
raise NotImplementedError
|
|
315
|
+
|
|
316
|
+
def get_jacobians(self, body_indices: Optional[List[int]] = None) -> Optional[TensorLike]:
|
|
317
|
+
raise NotImplementedError
|
|
318
|
+
|
|
319
|
+
def get_mass_matrix(self, joint_ids: Optional[List[int]] = None) -> Optional[TensorLike]:
|
|
320
|
+
raise NotImplementedError
|
|
321
|
+
|
|
322
|
+
def get_gravity_compensation(self, joint_ids: Optional[List[int]] = None) -> Optional[TensorLike]:
|
|
323
|
+
raise NotImplementedError
|
|
324
|
+
|
|
325
|
+
def get_body_velocity_in_base_frame(self, body_name: str) -> Optional[Tuple[TensorLike, TensorLike]]:
|
|
326
|
+
raise NotImplementedError
|
|
327
|
+
|
|
328
|
+
def get_body_pose_in_base_frame(self, body_name: str) -> Optional[Any]:
|
|
329
|
+
raise NotImplementedError
|
|
330
|
+
|
|
331
|
+
def set_joint_state(
|
|
332
|
+
self,
|
|
333
|
+
positions: TensorLike,
|
|
334
|
+
velocities: Optional[TensorLike] = None,
|
|
335
|
+
env_ids: Optional[TensorLike] = None,
|
|
336
|
+
) -> None:
|
|
337
|
+
raise NotImplementedError
|
|
338
|
+
|
|
339
|
+
def set_joint_position_target(
|
|
340
|
+
self,
|
|
341
|
+
positions: TensorLike,
|
|
342
|
+
joint_ids: Optional[TensorLike] = None,
|
|
343
|
+
env_ids: Optional[TensorLike] = None,
|
|
344
|
+
) -> None:
|
|
345
|
+
raise NotImplementedError
|
|
346
|
+
|
|
347
|
+
def set_joint_velocity_target(
|
|
348
|
+
self,
|
|
349
|
+
velocities: TensorLike,
|
|
350
|
+
joint_ids: Optional[TensorLike] = None,
|
|
351
|
+
env_ids: Optional[TensorLike] = None,
|
|
352
|
+
) -> None:
|
|
353
|
+
raise NotImplementedError
|
|
354
|
+
|
|
355
|
+
def set_joint_effort_target(
|
|
356
|
+
self,
|
|
357
|
+
efforts: TensorLike,
|
|
358
|
+
joint_ids: Optional[TensorLike] = None,
|
|
359
|
+
) -> None:
|
|
360
|
+
raise NotImplementedError
|
|
361
|
+
|
|
362
|
+
def set_root_pose(self, pose: TensorLike, env_ids: Optional[TensorLike] = None) -> None:
|
|
363
|
+
raise NotImplementedError
|
|
364
|
+
|
|
365
|
+
def set_root_velocity(self, velocity: TensorLike, env_ids: Optional[TensorLike] = None) -> None:
|
|
366
|
+
raise NotImplementedError
|
|
367
|
+
|
|
368
|
+
def get_body_pose(self, body_name: str) -> Optional[TensorLike]:
|
|
369
|
+
raise NotImplementedError
|
|
370
|
+
|
|
371
|
+
def get_body_velocity(self, body_name: str) -> Optional[TensorLike]:
|
|
372
|
+
raise NotImplementedError
|
|
373
|
+
|
|
374
|
+
def get_joint_state(self) -> Tuple[Optional[TensorLike], Optional[TensorLike]]:
|
|
375
|
+
raise NotImplementedError
|
|
376
|
+
|
|
377
|
+
def get_root_pose(self) -> Optional[TensorLike]:
|
|
378
|
+
raise NotImplementedError
|
|
379
|
+
|
|
380
|
+
def get_root_velocity(self) -> Optional[TensorLike]:
|
|
381
|
+
raise NotImplementedError
|
|
382
|
+
|
|
383
|
+
def reset(self, env_ids: Optional[TensorLike] = None) -> None:
|
|
384
|
+
raise NotImplementedError
|
|
385
|
+
|
|
386
|
+
def reset_to_default(self) -> None:
|
|
387
|
+
raise NotImplementedError
|
|
388
|
+
|
|
389
|
+
def update(self, dt: float) -> None:
|
|
390
|
+
raise NotImplementedError
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class LearningEnv(LearningEnvProtocol):
|
|
394
|
+
"""Typing facade for the ``simulo.LearningEnv`` runtime surface."""
|
|
395
|
+
|
|
396
|
+
num_envs: int
|
|
397
|
+
task: TaskProtocol
|
|
398
|
+
|
|
399
|
+
def __init__(
|
|
400
|
+
self,
|
|
401
|
+
task: TaskProtocol,
|
|
402
|
+
num_envs: int = 1,
|
|
403
|
+
device: str = "cuda",
|
|
404
|
+
dt: float = 1.0 / 120.0,
|
|
405
|
+
physics_steps_per_action: int = 2,
|
|
406
|
+
env_spacing: float = 4.0,
|
|
407
|
+
headless: bool = True,
|
|
408
|
+
seed: int = 0,
|
|
409
|
+
render_mode: Optional[str] = None,
|
|
410
|
+
scene_usd: Optional[str] = None,
|
|
411
|
+
viewstream: Any = None,
|
|
412
|
+
enable_cameras: bool = False,
|
|
413
|
+
) -> None:
|
|
414
|
+
raise NotImplementedError("typing facade — never instantiate; the runtime object comes from the simulo surface")
|
|
415
|
+
|
|
416
|
+
@property
|
|
417
|
+
def device(self) -> str:
|
|
418
|
+
raise NotImplementedError
|
|
419
|
+
|
|
420
|
+
@property
|
|
421
|
+
def dt(self) -> float:
|
|
422
|
+
raise NotImplementedError
|
|
423
|
+
|
|
424
|
+
@property
|
|
425
|
+
def physics_dt(self) -> float:
|
|
426
|
+
raise NotImplementedError
|
|
427
|
+
|
|
428
|
+
@property
|
|
429
|
+
def physics_steps_per_action(self) -> int:
|
|
430
|
+
raise NotImplementedError
|
|
431
|
+
|
|
432
|
+
@property
|
|
433
|
+
def max_episode_length(self) -> int:
|
|
434
|
+
raise NotImplementedError
|
|
435
|
+
|
|
436
|
+
@property
|
|
437
|
+
def scene(self) -> SceneProtocol:
|
|
438
|
+
raise NotImplementedError
|
|
439
|
+
|
|
440
|
+
def reset(
|
|
441
|
+
self, seed: Optional[int] = None, options: Optional[Dict[str, Any]] = None
|
|
442
|
+
) -> Tuple[TensorLike, Dict[str, Any]]:
|
|
443
|
+
raise NotImplementedError
|
|
444
|
+
|
|
445
|
+
def step(self, actions: TensorLike) -> Tuple[TensorLike, TensorLike, TensorLike, TensorLike, Dict[str, Any]]:
|
|
446
|
+
raise NotImplementedError
|
|
447
|
+
|
|
448
|
+
def close(self) -> None:
|
|
449
|
+
raise NotImplementedError
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
class RLTrainer(TrainerProtocol):
|
|
453
|
+
"""Typing facade for the ``simulo.RLTrainer`` runtime surface.
|
|
454
|
+
|
|
455
|
+
Declares the Trainer contract plus the concrete class's documented
|
|
456
|
+
extensions: the checkpointing keywords on ``train`` (a compatible
|
|
457
|
+
extension of the contract signature), ``close``, and the
|
|
458
|
+
``export_policy`` capability (the separate narrow exporter contract).
|
|
459
|
+
"""
|
|
460
|
+
|
|
461
|
+
def __init__(
|
|
462
|
+
self,
|
|
463
|
+
env: LearningEnv,
|
|
464
|
+
algorithm: str = "PPO",
|
|
465
|
+
device: str = "cuda",
|
|
466
|
+
seed: int = 42,
|
|
467
|
+
log_dir: Optional[str] = None,
|
|
468
|
+
ml_framework: str = "torch",
|
|
469
|
+
agent_cfg: Optional[Dict[str, Any]] = None,
|
|
470
|
+
debug_on_anomaly: Optional[DebugOnAnomaly] = None,
|
|
471
|
+
) -> None:
|
|
472
|
+
raise NotImplementedError("typing facade — never instantiate; the runtime object comes from the simulo surface")
|
|
473
|
+
|
|
474
|
+
def train(
|
|
475
|
+
self,
|
|
476
|
+
max_iterations: int = 1000,
|
|
477
|
+
*,
|
|
478
|
+
checkpoint_dir: Optional[str] = None,
|
|
479
|
+
checkpoint_every: Optional[int] = None,
|
|
480
|
+
keep_last: Optional[int] = None,
|
|
481
|
+
resume: Optional[str] = None,
|
|
482
|
+
) -> Dict[str, Any]:
|
|
483
|
+
raise NotImplementedError
|
|
484
|
+
|
|
485
|
+
def evaluate(self, checkpoint: Optional[str] = None, num_episodes: int = 10) -> Dict[str, Any]:
|
|
486
|
+
raise NotImplementedError
|
|
487
|
+
|
|
488
|
+
def save(self, path: str) -> None:
|
|
489
|
+
raise NotImplementedError
|
|
490
|
+
|
|
491
|
+
def load(self, path: str) -> None:
|
|
492
|
+
raise NotImplementedError
|
|
493
|
+
|
|
494
|
+
def export_policy(self, path: str) -> str:
|
|
495
|
+
raise NotImplementedError
|
|
496
|
+
|
|
497
|
+
def close(self) -> None:
|
|
498
|
+
raise NotImplementedError
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
class RLPlayer(PlayerProtocol):
|
|
502
|
+
"""Typing facade for the ``simulo.RLPlayer`` runtime surface.
|
|
503
|
+
|
|
504
|
+
Declares the Player contract plus the concrete class's documented
|
|
505
|
+
extensions: ``play``'s MCAP ``record=`` keyword (a compatible extension
|
|
506
|
+
of the contract signature), the ``policy`` / ``agent`` / ``recorder``
|
|
507
|
+
accessors, and the ONNX/JIT exporters.
|
|
508
|
+
"""
|
|
509
|
+
|
|
510
|
+
def __init__(
|
|
511
|
+
self,
|
|
512
|
+
env: LearningEnv,
|
|
513
|
+
checkpoint: str,
|
|
514
|
+
device: str = "cuda",
|
|
515
|
+
ml_framework: str = "torch",
|
|
516
|
+
) -> None:
|
|
517
|
+
raise NotImplementedError("typing facade — never instantiate; the runtime object comes from the simulo surface")
|
|
518
|
+
|
|
519
|
+
def play(
|
|
520
|
+
self,
|
|
521
|
+
num_episodes: Optional[int] = None,
|
|
522
|
+
num_steps: Optional[int] = None,
|
|
523
|
+
real_time: bool = False,
|
|
524
|
+
video_path: Optional[str] = None,
|
|
525
|
+
video_length: int = 200,
|
|
526
|
+
deterministic: bool = True,
|
|
527
|
+
record: Union[None, str, Path, RecordConfig] = None,
|
|
528
|
+
) -> Dict[str, Any]:
|
|
529
|
+
raise NotImplementedError
|
|
530
|
+
|
|
531
|
+
def load(self, path: str) -> None:
|
|
532
|
+
raise NotImplementedError
|
|
533
|
+
|
|
534
|
+
def close(self) -> None:
|
|
535
|
+
raise NotImplementedError
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def policy(self) -> Optional[Any]:
|
|
539
|
+
raise NotImplementedError
|
|
540
|
+
|
|
541
|
+
@property
|
|
542
|
+
def agent(self) -> Optional[Any]:
|
|
543
|
+
raise NotImplementedError
|
|
544
|
+
|
|
545
|
+
@property
|
|
546
|
+
def recorder(self) -> Optional[Any]:
|
|
547
|
+
raise NotImplementedError
|
|
548
|
+
|
|
549
|
+
def export_onnx(self, path: str) -> None:
|
|
550
|
+
raise NotImplementedError
|
|
551
|
+
|
|
552
|
+
def export_jit(self, path: str) -> None:
|
|
553
|
+
raise NotImplementedError
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
def run(
|
|
557
|
+
scenario_class: Type[ScenarioProtocol],
|
|
558
|
+
device: str = "cuda",
|
|
559
|
+
dt: float = 0.01,
|
|
560
|
+
headless: bool = False,
|
|
561
|
+
seed: int = 0,
|
|
562
|
+
max_steps: Optional[int] = None,
|
|
563
|
+
num_envs: int = 1,
|
|
564
|
+
env_spacing: float = 2.0,
|
|
565
|
+
enable_cameras: bool = True,
|
|
566
|
+
viewstream: Any = None,
|
|
567
|
+
) -> None:
|
|
568
|
+
"""Typing facade for the ``simulo.run`` scenario execution loop.
|
|
569
|
+
|
|
570
|
+
A plain FUNCTION facade, not a class one — the module docstring's
|
|
571
|
+
dedicated paragraph on ``run`` explains why this shape exists (``object``
|
|
572
|
+
is not callable) and where drift against the real
|
|
573
|
+
``simulo.scenario.run`` is caught (a live signature comparison in
|
|
574
|
+
``simulo-backend``, not this snapshot).
|
|
575
|
+
|
|
576
|
+
``viewstream: Any`` is the same deliberate widening as
|
|
577
|
+
``LearningEnv.viewstream`` above and for the identical reason: the real
|
|
578
|
+
parameter type, ``simulo.streaming.config.ViewStreamOption``, is not
|
|
579
|
+
importable thin-side (``simulo.streaming`` ships with ``simulo-backend``).
|
|
580
|
+
"""
|
|
581
|
+
raise NotImplementedError("typing facade — never call; the runtime function comes from the simulo surface")
|