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.
Files changed (55) hide show
  1. simulo/__init__.py +433 -0
  2. simulo/_client/__init__.py +6 -0
  3. simulo/_client/_entrypoint.py +313 -0
  4. simulo/_client/_mounts.py +25 -0
  5. simulo/_client/_runner.py +186 -0
  6. simulo/_client/_secure_downloads.py +1181 -0
  7. simulo/_client/app.py +1308 -0
  8. simulo/_client/asset.py +331 -0
  9. simulo/_client/asset_api.py +517 -0
  10. simulo/_client/asset_package.py +1103 -0
  11. simulo/_client/asset_pins.py +187 -0
  12. simulo/_client/builtin_aliases.py +107 -0
  13. simulo/_client/bundle.py +254 -0
  14. simulo/_client/cancel_api.py +104 -0
  15. simulo/_client/cli.py +9063 -0
  16. simulo/_client/config.py +186 -0
  17. simulo/_client/credentials.py +210 -0
  18. simulo/_client/discovery.py +214 -0
  19. simulo/_client/export_api.py +212 -0
  20. simulo/_client/export_bundle.py +296 -0
  21. simulo/_client/facades.py +581 -0
  22. simulo/_client/http.py +414 -0
  23. simulo/_client/identity_api.py +117 -0
  24. simulo/_client/install_samples.py +267 -0
  25. simulo/_client/jobs_api.py +224 -0
  26. simulo/_client/learning.py +393 -0
  27. simulo/_client/login.py +319 -0
  28. simulo/_client/mode.py +29 -0
  29. simulo/_client/outputs.py +116 -0
  30. simulo/_client/packaging.py +445 -0
  31. simulo/_client/preflight_api.py +186 -0
  32. simulo/_client/preflight_render.py +200 -0
  33. simulo/_client/registry.py +98 -0
  34. simulo/_client/runtime.py +185 -0
  35. simulo/_client/runtime_display.py +90 -0
  36. simulo/_client/seed_ref.py +76 -0
  37. simulo/_client/stub.py +41 -0
  38. simulo/_client/submit_api.py +1057 -0
  39. simulo/_client/templates/__init__.py +21 -0
  40. simulo/_client/templates/inference/app.py.tmpl +316 -0
  41. simulo/_client/templates/inference/simuloignore.tmpl +30 -0
  42. simulo/_client/templates/scenario/app.py.tmpl +93 -0
  43. simulo/_client/templates/scenario/simuloignore.tmpl +27 -0
  44. simulo/_client/templates/training/app.py.tmpl +235 -0
  45. simulo/_client/templates/training/simuloignore.tmpl +29 -0
  46. simulo/_client/view_fragment.py +21 -0
  47. simulo/_client/view_session_api.py +122 -0
  48. simulo/_client/volume.py +71 -0
  49. simulo/callbacks.py +274 -0
  50. simulo/py.typed +0 -0
  51. simulo-0.26.0.dist-info/METADATA +130 -0
  52. simulo-0.26.0.dist-info/RECORD +55 -0
  53. simulo-0.26.0.dist-info/WHEEL +5 -0
  54. simulo-0.26.0.dist-info/entry_points.txt +2 -0
  55. 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")