simulo-interfaces 0.7.0__tar.gz → 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {simulo_interfaces-0.7.0/src/simulo_interfaces.egg-info → simulo_interfaces-0.10.0}/PKG-INFO +1 -1
  2. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/pyproject.toml +1 -1
  3. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/__init__.py +1 -1
  4. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/__init__.py +189 -0
  5. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/actuator.py +53 -0
  6. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/asset.py +92 -0
  7. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/entity.py +180 -0
  8. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/light.py +87 -0
  9. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/materials.py +80 -0
  10. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/physics.py +154 -0
  11. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/pose.py +100 -0
  12. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/primitives.py +132 -0
  13. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/record.py +400 -0
  14. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/robot.py +378 -0
  15. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/scene.py +154 -0
  16. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/sensor.py +133 -0
  17. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/terrain.py +306 -0
  18. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/visual.py +302 -0
  19. simulo_interfaces-0.10.0/src/simulo/interfaces/authoring/world.py +111 -0
  20. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/exceptions.py +1 -1
  21. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/ids.py +1 -0
  22. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/__init__.py +61 -1
  23. simulo_interfaces-0.10.0/src/simulo/interfaces/platform/artifacts.py +721 -0
  24. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/asset.py +2 -1
  25. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/asset_catalog.py +77 -81
  26. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/debug.py +4 -4
  27. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/domain.py +5 -5
  28. simulo_interfaces-0.10.0/src/simulo/interfaces/platform/enums.py +177 -0
  29. simulo_interfaces-0.10.0/src/simulo/interfaces/platform/manifest.py +290 -0
  30. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/runs.py +26 -2
  31. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/submit.py +28 -10
  32. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/anomaly.py +74 -8
  33. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/components.py +26 -6
  34. simulo_interfaces-0.10.0/src/simulo/interfaces/runtime/env.py +101 -0
  35. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/player.py +16 -1
  36. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/scenario.py +9 -2
  37. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/task.py +8 -1
  38. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/trainer.py +10 -0
  39. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0/src/simulo_interfaces.egg-info}/PKG-INFO +1 -1
  40. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo_interfaces.egg-info/SOURCES.txt +18 -0
  41. simulo_interfaces-0.7.0/src/simulo/interfaces/platform/enums.py +0 -106
  42. simulo_interfaces-0.7.0/src/simulo/interfaces/runtime/env.py +0 -56
  43. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/MANIFEST.in +0 -0
  44. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/PYPI.md +0 -0
  45. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/setup.cfg +0 -0
  46. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/app.py +0 -0
  47. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/callbacks.py +0 -0
  48. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/runtime.py +0 -0
  49. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/platform/volume.py +0 -0
  50. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/py.typed +0 -0
  51. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/__init__.py +0 -0
  52. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/policy.py +0 -0
  53. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo/interfaces/runtime/tensors.py +0 -0
  54. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo_interfaces.egg-info/dependency_links.txt +0 -0
  55. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo_interfaces.egg-info/requires.txt +0 -0
  56. {simulo_interfaces-0.7.0 → simulo_interfaces-0.10.0}/src/simulo_interfaces.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simulo-interfaces
3
- Version: 0.7.0
3
+ Version: 0.10.0
4
4
  Summary: Type contracts for the Simulo SDK. Installed automatically as a dependency of the simulo package.
5
5
  Author-email: Simulo Team <team@simulo.ai>
6
6
  License: BSD-3-Clause
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simulo-interfaces"
7
- version = "0.7.0"
7
+ version = "0.10.0"
8
8
  description = "Type contracts for the Simulo SDK. Installed automatically as a dependency of the simulo package."
9
9
  readme = "PYPI.md"
10
10
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  """Simulo Interfaces — implementation-free contract layer for the Simulo platform.
2
2
 
3
- Torch-free, zero-runtime-dependency (Rule #11). Importable on a laptop with no
3
+ Torch-free, zero-runtime-dependency. Importable on a laptop with no
4
4
  torch / numpy / gymnasium / Isaac / AWS / HTTP / DB installed. Two parts:
5
5
 
6
6
  * **Part A — ``simulo.interfaces.runtime``**: tensor-library-agnostic structural
@@ -0,0 +1,189 @@
1
+ """Part C — the typed authoring surface.
2
+
3
+ The **relocation and mirror destination** for the Simulo authoring value types.
4
+ Each type here has exactly ONE definition — this one — shared by both
5
+ distributions: the thin client authors these values at submit (torch-free,
6
+ e.g. ``simulo.Pose(xyz=(1, 2, 3))``) and the backend executes them on the
7
+ worker. There is no other copy and no re-export shim anywhere ("nuke as you
8
+ go", per the owner's 2026-07-26 directive recorded in the plan): the former
9
+ backend ``core`` modules for these types are deleted, so ``isinstance`` keeps
10
+ working because only this definition exists.
11
+
12
+ Relocated so far — Wave C1: ``pose`` (``Pose``), ``materials`` (``Material``,
13
+ ``SurfaceMaterial``), ``physics`` (``Physics``, ``Collision``, ``RigidPhysics``,
14
+ ``DeformableMaterial``, ``DeformablePhysics``), ``asset`` (``Asset``,
15
+ ``USDAsset``, ``URDFAsset`` — the model-source specs, distinct from the thin
16
+ client's registry-handle ``simulo.Asset``), and ``light`` (``Light``,
17
+ ``LightConfig``, ``DistantLight``, ``DomeLight``). Wave C2: ``terrain``
18
+ (``Terrain``, ``TerrainConfig``, ``GroundPlane``, ``SubTerrainConfig``,
19
+ ``RoughTerrain``), ``primitives`` (``PrimitiveShape``, ``Cone``,
20
+ ``Cuboid``, ``Sphere``, ``Cylinder``, ``Transform``), ``entity`` (``Entity``,
21
+ ``AssetEntity``), and ``visual`` (``Visual``, ``VisualMarkerBase``,
22
+ ``AxesMarker``, ``SphereMarker``, ``ArrowMarker``, ``PointMarker``).
23
+ Wave C4: ``record`` (``RecordConfig`` — the MCAP recording configuration;
24
+ stdlib-only, so it classifies RELOCATE, and the backend recorder imports it
25
+ from here), and ``world`` (``World``, ``USDWorld``): ``Terrain`` is the
26
+ ground you *generate* (``plane``, ``rough``); ``World.usd(...)`` returns
27
+ ``USDWorld``, a prebuilt place you *bring*.
28
+
29
+ Mirrored so far — Wave C2: ``scene`` (``SceneProtocol``, ``SceneGroupProtocol``
30
+ — the first MIRROR; the concrete ``Scene``/``SceneGroup`` stay in the backend
31
+ package and explicitly inherit these Protocols). Wave C3: ``robot``
32
+ (``RobotProtocol``, plus ``RobotStateProtocol`` — the grouped live-state
33
+ contract behind ``robot.state``), ``sensor`` (``SensorProtocol``,
34
+ ``CameraProtocol``), and ``actuator`` (``ActuatorProtocol``) — same
35
+ mechanism; the concrete classes
36
+ stay in the backend package and explicitly inherit their Protocols, and the
37
+ other concrete sensor/actuator subclasses conform through their bases. Later
38
+ waves add the remaining RELOCATE-classified types and MIRROR Protocols.
39
+
40
+ **R-C3 is the hard constraint on everything that lands here:** no module in
41
+ this package — or anywhere else in ``simulo-interfaces`` — may import
42
+ ``simulo.core``, ``simulo.backend``, or the thin client's private internal
43
+ package, at import time or at call time (the ``Scene`` trap: zero torch
44
+ imports, but call-time imports of torch-coupled ``core`` modules deep inside a
45
+ method body). Guarded by ``tests/test_no_core_dependency.py`` in this package —
46
+ both a static import-statement guard and a runtime ``sys.modules`` check that
47
+ imports every submodule AND instantiates/calls the relocated API, because the
48
+ static guard alone cannot see ``from simulo import core``, dynamic access, or a
49
+ call-time-only import buried in a method body.
50
+
51
+ Two relocation mechanisms select which types land here and how (see the derived
52
+ plan for the full worked example and rejected alternatives):
53
+
54
+ * **RELOCATE** — the class definition MOVES here; the old ``core/<module>.py``
55
+ is deleted and every call site rewritten in the same PR (no re-export shims).
56
+ Reserved for types with zero import-time *or* call-time dependency on
57
+ anything that cannot live in a zero-dependency package.
58
+ * **MIRROR** — a ``typing.Protocol`` (named ``*Protocol``, matching the
59
+ ``runtime`` contracts) with real signatures and ``...`` bodies lands here,
60
+ describing the class's PUBLIC surface only; the backend's ``core/`` class
61
+ explicitly INHERITS it (nominal conformance, the same pattern
62
+ ``simulo-protocol`` already blesses for the ``runtime`` Protocols). Reserved
63
+ for everything else — anything with a real or call-time dependency on torch,
64
+ numpy, gymnasium, skrl, isaaclab, or another MIRROR-classified ``core``
65
+ module. Divergence is gated in three measured layers, because no single one
66
+ suffices: mypy fails signature-*shape* drift (arity, kinds,
67
+ default-presence, types) at the ``core/`` definition site but is SILENT on
68
+ parameter renames and on a property degrading to a plain attribute — those
69
+ need the backend suite's signature-conformance test (per-member bidirectional
70
+ — it compares the live contract against the live implementation — plus a
71
+ member-SET equality check over the implementation's statically-derivable
72
+ public surface: class-body names across its MRO and ``__init__``-bound
73
+ instance attributes, with a pinned documented-omissions allowlist; an extra
74
+ public member is legal subtyping no per-member loop can see, and attributes
75
+ bound outside ``__init__`` stay statically invisible even to the set check)
76
+ — and
77
+ constructor signatures need a separate ``__call__``-Protocol pin in the
78
+ backend's static conformance checks (type checkers exempt ``__init__`` from
79
+ override checks).
80
+
81
+ The checked-in authoring-surface inventory table classifies every name
82
+ currently referenced by the example trees (RELOCATE or MIRROR, source module,
83
+ and cross-references for cryptic engine-style names) — that table, not this
84
+ docstring, is the source of truth for what lands here and when.
85
+ """
86
+
87
+ from simulo.interfaces.authoring.actuator import ActuatorProtocol
88
+ from simulo.interfaces.authoring.asset import Asset, URDFAsset, USDAsset
89
+ from simulo.interfaces.authoring.entity import AssetEntity, Entity
90
+ from simulo.interfaces.authoring.light import DistantLight, DomeLight, Light, LightConfig
91
+ from simulo.interfaces.authoring.materials import Material, SurfaceMaterial
92
+ from simulo.interfaces.authoring.physics import (
93
+ Collision,
94
+ DeformableMaterial,
95
+ DeformablePhysics,
96
+ Physics,
97
+ RigidPhysics,
98
+ )
99
+ from simulo.interfaces.authoring.pose import Pose
100
+ from simulo.interfaces.authoring.primitives import (
101
+ Cone,
102
+ Cuboid,
103
+ Cylinder,
104
+ PrimitiveShape,
105
+ Sphere,
106
+ Transform,
107
+ )
108
+ from simulo.interfaces.authoring.record import RecordConfig
109
+ from simulo.interfaces.authoring.robot import RobotProtocol, RobotStateProtocol
110
+ from simulo.interfaces.authoring.scene import SceneGroupProtocol, SceneProtocol
111
+ from simulo.interfaces.authoring.sensor import CameraProtocol, SensorProtocol
112
+ from simulo.interfaces.authoring.terrain import (
113
+ GroundPlane,
114
+ RoughTerrain,
115
+ SubTerrainConfig,
116
+ Terrain,
117
+ TerrainConfig,
118
+ )
119
+ from simulo.interfaces.authoring.visual import (
120
+ ArrowMarker,
121
+ AxesMarker,
122
+ PointMarker,
123
+ SphereMarker,
124
+ Visual,
125
+ VisualMarkerBase,
126
+ )
127
+ from simulo.interfaces.authoring.world import USDWorld, World
128
+
129
+ __all__ = [
130
+ # pose
131
+ "Pose",
132
+ # materials
133
+ "Material",
134
+ "SurfaceMaterial",
135
+ # physics
136
+ "Collision",
137
+ "RigidPhysics",
138
+ "DeformableMaterial",
139
+ "DeformablePhysics",
140
+ "Physics",
141
+ # asset (model-source specs)
142
+ "Asset",
143
+ "USDAsset",
144
+ "URDFAsset",
145
+ # light
146
+ "LightConfig",
147
+ "DistantLight",
148
+ "DomeLight",
149
+ "Light",
150
+ # terrain (ground you generate)
151
+ "TerrainConfig",
152
+ "GroundPlane",
153
+ "SubTerrainConfig",
154
+ "RoughTerrain",
155
+ "Terrain",
156
+ # world (a prebuilt place you bring — split from terrain in Wave C4)
157
+ "USDWorld",
158
+ "World",
159
+ # primitives
160
+ "PrimitiveShape",
161
+ "Cone",
162
+ "Cuboid",
163
+ "Sphere",
164
+ "Cylinder",
165
+ "Transform",
166
+ # entity
167
+ "Entity",
168
+ "AssetEntity",
169
+ # record (RELOCATED Wave C4 — the MCAP recording config; its helper
170
+ # functions stay importable from ``simulo.interfaces.authoring.record``)
171
+ "RecordConfig",
172
+ # visual
173
+ "VisualMarkerBase",
174
+ "AxesMarker",
175
+ "SphereMarker",
176
+ "ArrowMarker",
177
+ "PointMarker",
178
+ "Visual",
179
+ # scene (MIRROR — the concrete classes live in the backend package)
180
+ "SceneProtocol",
181
+ "SceneGroupProtocol",
182
+ # robot / sensor / actuator (MIRROR — the concrete classes live in the
183
+ # backend package and explicitly inherit these Protocols)
184
+ "RobotProtocol",
185
+ "RobotStateProtocol",
186
+ "SensorProtocol",
187
+ "CameraProtocol",
188
+ "ActuatorProtocol",
189
+ ]
@@ -0,0 +1,53 @@
1
+ """``ActuatorProtocol`` — the declared actuator authoring contract.
2
+
3
+ A MIRROR, not a relocation (same mechanism as the Scene, Robot, and Sensor
4
+ contracts in this package): the concrete ``Actuator`` implementation stays in
5
+ the backend package — its command path writes into a live simulation engine
6
+ handle — so what lives here is the declared public surface only.
7
+
8
+ The backend's concrete ``Actuator`` base class explicitly inherits this
9
+ Protocol (nominal conformance); concrete actuator types (e.g. the surface
10
+ gripper) inherit it through the base and keep their richer surfaces as
11
+ implementation-defined extensions.
12
+
13
+ Enforcement is the standard four layers for a mirror (see the Robot contract
14
+ module's docstring). ``get_state`` faithfully mirrors today's untyped return:
15
+ a named supported subset for actuator state is a later, separate contract
16
+ decision, deliberately not designed here.
17
+ """
18
+
19
+ from typing import Any, Optional, Protocol, runtime_checkable
20
+
21
+
22
+ @runtime_checkable
23
+ class ActuatorProtocol(Protocol):
24
+ """The actuator authoring contract — an action interface for robots.
25
+
26
+ An actuator is configured at authoring time, attached to a scene path,
27
+ and driven with commands during simulation. Concrete actuator types
28
+ define their own command and state shapes.
29
+ """
30
+
31
+ path: Optional[str]
32
+ """Scene path where the actuator is attached (may be set via the scene)."""
33
+
34
+ enabled: bool
35
+ """Whether the actuator is active."""
36
+
37
+ @property
38
+ def name(self) -> Optional[str]:
39
+ """Actuator name — set by the scene when the actuator is added."""
40
+ ...
41
+
42
+ def set_command(self, command: Any) -> None:
43
+ """Set an actuator-specific command. Commands are buffered and
44
+ flushed automatically before the next physics step."""
45
+ ...
46
+
47
+ def get_state(self) -> Any:
48
+ """Current actuator-specific state."""
49
+ ...
50
+
51
+ def reset(self) -> None:
52
+ """Reset the actuator to its default state."""
53
+ ...
@@ -0,0 +1,92 @@
1
+ """Model-source asset specs — USD/URDF sources a scene loads.
2
+
3
+ Owns the canonical ``Asset`` / ``USDAsset`` / ``URDFAsset`` model-source
4
+ dataclasses. Distinct from the thin client's user-facing ``simulo.Asset``
5
+ registry handle (a catalog ref like ``robot/so-arm-100:v3``): these classes
6
+ name a USD/URDF *file source* to load into a scene, and the backend consumes
7
+ them when it builds the simulation.
8
+ """
9
+
10
+ from dataclasses import dataclass
11
+ from typing import TYPE_CHECKING
12
+
13
+
14
+ @dataclass
15
+ class Asset:
16
+ """Base asset class."""
17
+
18
+ if TYPE_CHECKING:
19
+ # ``Asset.usd`` / ``Asset.urdf`` are attached dynamically below (they
20
+ # return the ``USDAsset`` / ``URDFAsset`` subclasses, which are defined
21
+ # after this class). These declarations never execute; they exist so a
22
+ # type checker sees the convenience aliases with their precise
23
+ # signatures instead of rejecting ``Asset.usd(...)`` as an unknown
24
+ # attribute.
25
+ @classmethod
26
+ def usd(cls, path: str) -> "USDAsset": ...
27
+
28
+ @classmethod
29
+ def urdf(cls, path: str) -> "URDFAsset": ...
30
+
31
+
32
+ @dataclass
33
+ class USDAsset(Asset):
34
+ """USD file asset.
35
+
36
+ Attributes:
37
+ path: Path to USD file (supports file://, nucleus:// schemes). The
38
+ legacy simulo:// path alias is REMOVED — 'simulo/...' is a catalog
39
+ ref ([publisher/]kind/name[:vN], 'simulo' = the global-catalog
40
+ publisher), resolved through
41
+ simulo.Asset.from_registry("robot/<name>:v1"), never a runtime
42
+ path scheme. A simulo:// path raises a clear migration error at
43
+ resolution time.
44
+ """
45
+
46
+ path: str
47
+
48
+ @classmethod
49
+ def usd(cls, path: str) -> "USDAsset":
50
+ """Create a USD asset.
51
+
52
+ Args:
53
+ path: Path to USD file
54
+
55
+ Returns:
56
+ USDAsset instance
57
+ """
58
+ return cls(path=path)
59
+
60
+
61
+ @dataclass
62
+ class URDFAsset(Asset):
63
+ """URDF file asset.
64
+
65
+ Attributes:
66
+ path: Path to URDF file
67
+ """
68
+
69
+ path: str
70
+
71
+ @classmethod
72
+ def urdf(cls, path: str) -> "URDFAsset":
73
+ """Create a URDF asset.
74
+
75
+ Args:
76
+ path: Path to URDF file
77
+
78
+ Returns:
79
+ URDFAsset instance
80
+ """
81
+ return cls(path=path)
82
+
83
+
84
+ # Alias for convenience — callers reach for `Asset.usd(...)` / `Asset.urdf(...)`.
85
+ # Attached dynamically; the TYPE_CHECKING declarations on Asset above are what
86
+ # let a type checker see them.
87
+ Asset.usd = USDAsset.usd # type: ignore[method-assign]
88
+ Asset.urdf = URDFAsset.urdf # type: ignore[method-assign]
89
+
90
+ # Explicit public surface — keeps the TYPE_CHECKING import (needed for the
91
+ # static-only `usd`/`urdf` declarations above) off the star-import namespace.
92
+ __all__ = ["Asset", "USDAsset", "URDFAsset"]
@@ -0,0 +1,180 @@
1
+ """Entity abstraction for objects in the scene."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Optional, Tuple
5
+
6
+ from simulo.interfaces.authoring.asset import Asset
7
+ from simulo.interfaces.authoring.materials import Material
8
+ from simulo.interfaces.authoring.physics import DeformablePhysics, RigidPhysics
9
+ from simulo.interfaces.authoring.pose import Pose
10
+ from simulo.interfaces.authoring.primitives import Cone, Cuboid, Cylinder, Sphere
11
+
12
+
13
+ @dataclass
14
+ class Entity:
15
+ """An Entity is any object that can exist within a Scene.
16
+
17
+ Entities represent presence. They exist in space, have identity,
18
+ and may have physical state.
19
+ """
20
+
21
+ name: str
22
+ pose: Pose = field(default_factory=Pose.identity)
23
+ material: Optional[Material] = None
24
+ physics: Optional[RigidPhysics | DeformablePhysics] = None
25
+
26
+ class primitive:
27
+ """Factory for primitive entities."""
28
+
29
+ @staticmethod
30
+ def cone(
31
+ name: str,
32
+ radius: float = 0.5,
33
+ height: float = 1.0,
34
+ pose: Optional[Pose] = None,
35
+ material: Optional[Material] = None,
36
+ physics: Optional[RigidPhysics | DeformablePhysics] = None,
37
+ ) -> Cone:
38
+ """Create a cone entity.
39
+
40
+ Args:
41
+ name: Entity name
42
+ radius: Cone base radius
43
+ height: Cone height
44
+ pose: Pose in space
45
+ material: Visual material
46
+ physics: Physics properties
47
+
48
+ Returns:
49
+ Cone entity
50
+ """
51
+ return Cone(
52
+ name=name,
53
+ radius=radius,
54
+ height=height,
55
+ pose=pose or Pose.identity(),
56
+ material=material,
57
+ physics=physics,
58
+ )
59
+
60
+ @staticmethod
61
+ def cuboid(
62
+ name: str,
63
+ size: Tuple[float, float, float] = (1.0, 1.0, 1.0),
64
+ pose: Optional[Pose] = None,
65
+ material: Optional[Material] = None,
66
+ physics: Optional[RigidPhysics | DeformablePhysics] = None,
67
+ ) -> Cuboid:
68
+ """Create a cuboid entity.
69
+
70
+ Args:
71
+ name: Entity name
72
+ size: Box size as (width, depth, height)
73
+ pose: Pose in space
74
+ material: Visual material
75
+ physics: Physics properties
76
+
77
+ Returns:
78
+ Cuboid entity
79
+ """
80
+ return Cuboid(
81
+ name=name,
82
+ size=size,
83
+ pose=pose or Pose.identity(),
84
+ material=material,
85
+ physics=physics,
86
+ )
87
+
88
+ @staticmethod
89
+ def sphere(
90
+ name: str,
91
+ radius: float = 0.5,
92
+ pose: Optional[Pose] = None,
93
+ material: Optional[Material] = None,
94
+ physics: Optional[RigidPhysics | DeformablePhysics] = None,
95
+ ) -> Sphere:
96
+ """Create a sphere entity.
97
+
98
+ Args:
99
+ name: Entity name
100
+ radius: Sphere radius
101
+ pose: Pose in space
102
+ material: Visual material
103
+ physics: Physics properties
104
+
105
+ Returns:
106
+ Sphere entity
107
+ """
108
+ return Sphere(
109
+ name=name,
110
+ radius=radius,
111
+ pose=pose or Pose.identity(),
112
+ material=material,
113
+ physics=physics,
114
+ )
115
+
116
+ @staticmethod
117
+ def cylinder(
118
+ name: str,
119
+ radius: float = 0.5,
120
+ height: float = 1.0,
121
+ pose: Optional[Pose] = None,
122
+ material: Optional[Material] = None,
123
+ physics: Optional[RigidPhysics | DeformablePhysics] = None,
124
+ ) -> Cylinder:
125
+ """Create a cylinder entity.
126
+
127
+ Args:
128
+ name: Entity name
129
+ radius: Cylinder radius
130
+ height: Cylinder height
131
+ pose: Pose in space
132
+ material: Visual material
133
+ physics: Physics properties
134
+
135
+ Returns:
136
+ Cylinder entity
137
+ """
138
+ return Cylinder(
139
+ name=name,
140
+ radius=radius,
141
+ height=height,
142
+ pose=pose or Pose.identity(),
143
+ material=material,
144
+ physics=physics,
145
+ )
146
+
147
+ @staticmethod
148
+ def from_asset(
149
+ name: str,
150
+ asset: Asset,
151
+ pose: Optional[Pose] = None,
152
+ ) -> "AssetEntity":
153
+ """Create an entity from a USD or URDF asset.
154
+
155
+ Args:
156
+ name: Entity name
157
+ asset: Asset specification
158
+ pose: Pose in space
159
+
160
+ Returns:
161
+ AssetEntity instance
162
+ """
163
+ return AssetEntity(
164
+ name=name,
165
+ asset=asset,
166
+ pose=pose or Pose.identity(),
167
+ )
168
+
169
+
170
+ @dataclass
171
+ class AssetEntity(Entity):
172
+ """Entity loaded from an external asset file.
173
+
174
+ Attributes:
175
+ asset: Asset specification (USD, URDF, etc.). Required at construction;
176
+ ``None`` is not a valid default but is kept here to preserve the
177
+ existing dataclass field ordering. Callers always supply this.
178
+ """
179
+
180
+ asset: Optional[Asset] = None
@@ -0,0 +1,87 @@
1
+ """Light source definitions."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Optional, Tuple
5
+
6
+ from simulo.interfaces.authoring.pose import Pose
7
+
8
+
9
+ @dataclass
10
+ class LightConfig:
11
+ """Base light configuration."""
12
+
13
+ name: str
14
+ intensity: float = 1000.0
15
+ color: Tuple[float, float, float] = (1.0, 1.0, 1.0)
16
+ pose: Pose = field(default_factory=Pose.identity)
17
+
18
+
19
+ @dataclass
20
+ class DistantLight(LightConfig):
21
+ """Distant (directional) light source.
22
+
23
+ Similar to sunlight - parallel rays from infinity.
24
+ """
25
+
26
+ pass
27
+
28
+
29
+ @dataclass
30
+ class DomeLight(LightConfig):
31
+ """Dome light for ambient illumination."""
32
+
33
+ pass
34
+
35
+
36
+ class Light:
37
+ """Light factory."""
38
+
39
+ @staticmethod
40
+ def distant(
41
+ name: str = "distantLight",
42
+ intensity: float = 1000.0,
43
+ color: Tuple[float, float, float] = (1.0, 1.0, 1.0),
44
+ pose: Optional[Pose] = None,
45
+ ) -> DistantLight:
46
+ """Create a distant light.
47
+
48
+ Args:
49
+ name: Light name
50
+ intensity: Light intensity
51
+ color: RGB color
52
+ pose: Pose in space
53
+
54
+ Returns:
55
+ DistantLight instance
56
+ """
57
+ return DistantLight(
58
+ name=name,
59
+ intensity=intensity,
60
+ color=color,
61
+ pose=pose or Pose.identity(),
62
+ )
63
+
64
+ @staticmethod
65
+ def dome(
66
+ name: str = "domeLight",
67
+ intensity: float = 1000.0,
68
+ color: Tuple[float, float, float] = (1.0, 1.0, 1.0),
69
+ ) -> DomeLight:
70
+ """Create a dome light.
71
+
72
+ Args:
73
+ name: Light name
74
+ intensity: Light intensity
75
+ color: RGB color
76
+
77
+ Returns:
78
+ DomeLight instance
79
+ """
80
+ return DomeLight(
81
+ name=name,
82
+ intensity=intensity,
83
+ color=color,
84
+ )
85
+
86
+
87
+ __all__ = ["LightConfig", "DistantLight", "DomeLight", "Light"]