antioch-py 2.2.4__py3-none-any.whl → 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of antioch-py might be problematic. Click here for more details.

Files changed (94) hide show
  1. antioch/__init__.py +101 -0
  2. antioch/{module/execution.py → execution.py} +1 -1
  3. antioch/{module/input.py → input.py} +2 -4
  4. antioch/{module/module.py → module.py} +17 -34
  5. antioch/{module/node.py → node.py} +17 -16
  6. {antioch_py-2.2.4.dist-info → antioch_py-3.0.0.dist-info}/METADATA +8 -11
  7. antioch_py-3.0.0.dist-info/RECORD +61 -0
  8. {antioch_py-2.2.4.dist-info → antioch_py-3.0.0.dist-info}/WHEEL +1 -1
  9. antioch_py-3.0.0.dist-info/licenses/LICENSE +21 -0
  10. common/ark/__init__.py +6 -16
  11. common/ark/ark.py +23 -62
  12. common/ark/hardware.py +1 -1
  13. common/ark/kinematics.py +1 -1
  14. common/ark/module.py +22 -0
  15. common/ark/node.py +46 -3
  16. common/ark/scheduler.py +2 -29
  17. common/ark/sim.py +1 -1
  18. {antioch/module → common/ark}/token.py +17 -0
  19. common/assets/rigging.usd +0 -0
  20. common/constants.py +63 -5
  21. common/core/__init__.py +37 -24
  22. common/core/auth.py +87 -112
  23. common/core/container.py +261 -0
  24. common/core/registry.py +131 -152
  25. common/core/rome.py +251 -0
  26. common/core/telemetry.py +176 -0
  27. common/core/types.py +219 -0
  28. common/message/__init__.py +19 -5
  29. common/message/annotation.py +174 -23
  30. common/message/array.py +25 -1
  31. common/message/camera.py +23 -1
  32. common/message/color.py +32 -6
  33. common/message/detection.py +40 -0
  34. common/message/foxglove.py +20 -0
  35. common/message/frame.py +71 -7
  36. common/message/image.py +58 -9
  37. common/message/imu.py +24 -4
  38. common/message/joint.py +69 -10
  39. common/message/log.py +52 -7
  40. common/message/pir.py +23 -8
  41. common/message/plot.py +57 -0
  42. common/message/point.py +55 -6
  43. common/message/point_cloud.py +55 -19
  44. common/message/pose.py +59 -19
  45. common/message/quaternion.py +105 -92
  46. common/message/radar.py +195 -29
  47. common/message/twist.py +34 -0
  48. common/message/types.py +40 -5
  49. common/message/vector.py +180 -245
  50. common/sim/__init__.py +49 -0
  51. common/{session/config.py → sim/objects.py} +97 -27
  52. common/sim/state.py +11 -0
  53. common/utils/comms.py +30 -12
  54. common/utils/logger.py +26 -7
  55. antioch/message.py +0 -87
  56. antioch/module/__init__.py +0 -53
  57. antioch/session/__init__.py +0 -152
  58. antioch/session/ark.py +0 -500
  59. antioch/session/asset.py +0 -65
  60. antioch/session/error.py +0 -80
  61. antioch/session/objects/__init__.py +0 -40
  62. antioch/session/objects/animation.py +0 -162
  63. antioch/session/objects/articulation.py +0 -180
  64. antioch/session/objects/basis_curve.py +0 -180
  65. antioch/session/objects/camera.py +0 -65
  66. antioch/session/objects/collision.py +0 -46
  67. antioch/session/objects/geometry.py +0 -58
  68. antioch/session/objects/ground_plane.py +0 -48
  69. antioch/session/objects/imu.py +0 -53
  70. antioch/session/objects/joint.py +0 -49
  71. antioch/session/objects/light.py +0 -123
  72. antioch/session/objects/pir_sensor.py +0 -102
  73. antioch/session/objects/radar.py +0 -62
  74. antioch/session/objects/rigid_body.py +0 -197
  75. antioch/session/objects/xform.py +0 -119
  76. antioch/session/record.py +0 -158
  77. antioch/session/scene.py +0 -1544
  78. antioch/session/session.py +0 -211
  79. antioch/session/task.py +0 -309
  80. antioch_py-2.2.4.dist-info/RECORD +0 -85
  81. antioch_py-2.2.4.dist-info/entry_points.txt +0 -2
  82. common/core/agent.py +0 -324
  83. common/core/task.py +0 -36
  84. common/message/velocity.py +0 -11
  85. common/rome/__init__.py +0 -9
  86. common/rome/client.py +0 -435
  87. common/rome/error.py +0 -16
  88. common/session/__init__.py +0 -31
  89. common/session/environment.py +0 -31
  90. common/session/sim.py +0 -129
  91. common/utils/usd.py +0 -12
  92. /antioch/{module/clock.py → clock.py} +0 -0
  93. {antioch_py-2.2.4.dist-info → antioch_py-3.0.0.dist-info}/top_level.txt +0 -0
  94. /common/message/{base.py → message.py} +0 -0
common/message/pose.py CHANGED
@@ -3,9 +3,10 @@ from __future__ import annotations
3
3
  from typing import Any
4
4
 
5
5
  import numpy as np
6
+ from foxglove.schemas import Pose as FoxglovePose, Quaternion as FoxgloveQuaternion, Vector3 as FoxgloveVector3
6
7
  from pydantic import Field, field_validator, model_validator
7
8
 
8
- from common.message.base import Message
9
+ from common.message.message import Message
9
10
  from common.message.vector import Vector3
10
11
 
11
12
 
@@ -19,11 +20,31 @@ class Pose(Message):
19
20
  Automatically converts from common Python types:
20
21
  - Lists/tuples: Pose(position=[1.0, 2.0, 3.0], orientation=[0.0, 0.0, 1.57])
21
22
  - Dicts: Pose(position={"x": 1.0, "y": 2.0, "z": 3.0}, orientation={"x": 0.0, "y": 0.0, "z": 1.57})
23
+
24
+ Example:
25
+ ```python
26
+ from common.message import Pose, Vector3
27
+
28
+ # Create a pose with position and orientation
29
+ pose = Pose(
30
+ position=[1.0, 2.0, 0.5],
31
+ orientation=[0.0, 0.0, 1.57], # 90 degrees yaw
32
+ )
33
+
34
+ # Create from identity
35
+ identity = Pose.identity()
36
+
37
+ # Translate a pose
38
+ translated = pose.translate(Vector3(x=1.0, y=0.0, z=0.0))
39
+
40
+ # Access position components
41
+ print(f"Position: ({pose.position.x}, {pose.position.y}, {pose.position.z})")
42
+ ```
22
43
  """
23
44
 
24
45
  _type = "antioch/pose"
25
- position: Vector3 = Field(default_factory=lambda: Vector3.zeros())
26
- orientation: Vector3 = Field(default_factory=lambda: Vector3.zeros())
46
+ position: Vector3 = Field(default_factory=lambda: Vector3.zeros(), description="Position in 3D space as (x, y, z)")
47
+ orientation: Vector3 = Field(default_factory=lambda: Vector3.zeros(), description="Orientation as (roll, pitch, yaw) in radians")
27
48
 
28
49
  def __add__(self, other: Vector3) -> Pose:
29
50
  """
@@ -71,7 +92,7 @@ class Pose(Message):
71
92
  """
72
93
 
73
94
  if isinstance(v, (list, tuple, np.ndarray)):
74
- return Vector3.convert_iterables.__func__(Vector3, v)
95
+ return Vector3._convert_input.__func__(Vector3, v)
75
96
  return v
76
97
 
77
98
  @field_validator("orientation", mode="before")
@@ -82,29 +103,34 @@ class Pose(Message):
82
103
  """
83
104
 
84
105
  if isinstance(v, (list, tuple, np.ndarray)):
85
- return Vector3.convert_iterables.__func__(Vector3, v)
106
+ return Vector3._convert_input.__func__(Vector3, v)
86
107
  return v
87
108
 
88
109
  @classmethod
89
- def from_any(cls, data: Any) -> Pose:
110
+ def from_any(cls, value: Pose | dict | tuple | list | None) -> Pose:
90
111
  """
91
- Create Pose from a dict or Pose instance.
112
+ Create Pose from any compatible type.
113
+
114
+ Accepts:
115
+ - Pose instance (returned as-is)
116
+ - Dict with 'position' and/or 'orientation' keys
117
+ - Tuple/list of 3 floats (treated as position only)
118
+ - None (returns identity pose)
92
119
 
93
- :param data: Dict with position/orientation fields, or a Pose instance.
120
+ :param value: Any compatible input type.
94
121
  :return: A Pose instance.
95
- :raises ValueError: If conversion fails.
96
122
  """
97
123
 
98
- # Already a Pose - return as-is
99
- if isinstance(data, cls):
100
- return data
101
-
102
- try:
103
- if isinstance(data, dict):
104
- return cls(**data)
105
- raise ValueError("Pose requires a dict with position and orientation fields")
106
- except Exception as e:
107
- raise ValueError(f"Cannot convert to Pose: {e}") from None
124
+ if value is None:
125
+ return cls.identity()
126
+ if isinstance(value, cls):
127
+ return value
128
+ if isinstance(value, dict):
129
+ return cls.model_validate(value)
130
+ if isinstance(value, (tuple, list)):
131
+ # Treat as position only
132
+ return cls(position=Vector3.from_any(value))
133
+ raise ValueError(f"Cannot convert {type(value).__name__} to Pose")
108
134
 
109
135
  @classmethod
110
136
  def identity(cls) -> Pose:
@@ -146,3 +172,17 @@ class Pose(Message):
146
172
  """
147
173
 
148
174
  return Pose(position=self.position, orientation=self.orientation + rotation)
175
+
176
+ def to_foxglove(self) -> FoxglovePose:
177
+ """
178
+ Convert to Foxglove Pose for telemetry.
179
+
180
+ :return: Foxglove Pose schema.
181
+ """
182
+
183
+ # Convert RPY orientation to quaternion for Foxglove
184
+ quat = self.orientation.to_quat()
185
+ return FoxglovePose(
186
+ position=FoxgloveVector3(x=self.position.x, y=self.position.y, z=self.position.z),
187
+ orientation=FoxgloveQuaternion(x=quat.x, y=quat.y, z=quat.z, w=quat.w),
188
+ )
@@ -1,9 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from typing import Any
4
+
3
5
  import numpy as np
6
+ from foxglove.schemas import Quaternion as FoxgloveQuaternion
7
+ from pydantic import Field, model_validator
4
8
  from scipy.spatial.transform import Rotation
5
9
 
6
- from common.message.base import Message
10
+ from common.message.message import Message
7
11
 
8
12
  try:
9
13
  from pxr import Gf # type: ignore
@@ -15,57 +19,41 @@ except ImportError:
15
19
 
16
20
  class Quaternion(Message):
17
21
  """
18
- A quaternion for 3D rotations.
22
+ A quaternion for 3D rotations (w, x, y, z) where w is the scalar component.
23
+
24
+ Supports multiple construction styles:
25
+ - Quaternion(w=1.0, x=0.0, y=0.0, z=0.0) - keyword args
26
+ - Quaternion.from_rpy(roll, pitch, yaw) - from euler angles
27
+ - Quaternion.from_any([1.0, 0.0, 0.0, 0.0]) - from list/tuple
28
+
29
+ Example:
30
+ ```python
31
+ from common.message import Quaternion
32
+ import math
33
+
34
+ # Create identity quaternion (no rotation)
35
+ identity = Quaternion.identity()
36
+
37
+ # Create from roll-pitch-yaw angles
38
+ quat = Quaternion.from_rpy(
39
+ roll=0.0,
40
+ pitch=0.0,
41
+ yaw=math.pi / 2, # 90 degrees
42
+ )
19
43
 
20
- Serializes as a tuple [w, x, y, z] for space efficiency where w is the scalar component.
44
+ # Convert back to RPY
45
+ roll, pitch, yaw = quat.to_rpy()
21
46
 
22
- Examples:
23
- Quaternion.new(1.0, 0.0, 0.0, 0.0) # Create identity quaternion
24
- Quaternion.from_rpy(0.0, 0.0, 1.57) # Create from RPY angles
47
+ # Create from list (w, x, y, z order)
48
+ q = Quaternion.from_any([1.0, 0.0, 0.0, 0.0])
49
+ ```
25
50
  """
26
51
 
27
52
  _type = "antioch/quaternion"
28
- data: tuple[float, float, float, float]
29
-
30
- @property
31
- def w(self) -> float:
32
- """
33
- Get the w (scalar) component.
34
-
35
- :return: The w (scalar) component.
36
- """
37
-
38
- return self.data[0]
39
-
40
- @property
41
- def x(self) -> float:
42
- """
43
- Get the x component.
44
-
45
- :return: The x component.
46
- """
47
-
48
- return self.data[1]
49
-
50
- @property
51
- def y(self) -> float:
52
- """
53
- Get the y component.
54
-
55
- :return: The y component.
56
- """
57
-
58
- return self.data[2]
59
-
60
- @property
61
- def z(self) -> float:
62
- """
63
- Get the z component.
64
-
65
- :return: The z component.
66
- """
67
-
68
- return self.data[3]
53
+ w: float = Field(default=1.0, description="Scalar (real) component of the quaternion")
54
+ x: float = Field(default=0.0, description="X component of the quaternion vector part")
55
+ y: float = Field(default=0.0, description="Y component of the quaternion vector part")
56
+ z: float = Field(default=0.0, description="Z component of the quaternion vector part")
69
57
 
70
58
  def __len__(self) -> int:
71
59
  """
@@ -83,7 +71,7 @@ class Quaternion(Message):
83
71
  :return: Iterator over [w, x, y, z].
84
72
  """
85
73
 
86
- return iter(self.data)
74
+ return iter((self.w, self.x, self.y, self.z))
87
75
 
88
76
  def __getitem__(self, index: int) -> float:
89
77
  """
@@ -93,7 +81,7 @@ class Quaternion(Message):
93
81
  :return: The component value.
94
82
  """
95
83
 
96
- return self.data[index]
84
+ return (self.w, self.x, self.y, self.z)[index]
97
85
 
98
86
  def __eq__(self, other: object) -> bool:
99
87
  """
@@ -105,7 +93,7 @@ class Quaternion(Message):
105
93
 
106
94
  if not isinstance(other, Quaternion):
107
95
  return False
108
- return self.data == other.data
96
+ return self.w == other.w and self.x == other.x and self.y == other.y and self.z == other.z
109
97
 
110
98
  def __repr__(self) -> str:
111
99
  """
@@ -114,7 +102,7 @@ class Quaternion(Message):
114
102
  :return: String representation.
115
103
  """
116
104
 
117
- return f"Quaternion(w={self.w}, x={self.x}, y={self.y}, z={self.z})"
105
+ return f"Quaternion({self.w}, {self.x}, {self.y}, {self.z})"
118
106
 
119
107
  def __str__(self) -> str:
120
108
  """
@@ -123,45 +111,53 @@ class Quaternion(Message):
123
111
  :return: String representation.
124
112
  """
125
113
 
126
- return f"Quaternion(w={self.w}, x={self.x}, y={self.y}, z={self.z})"
114
+ return f"Quaternion({self.w}, {self.x}, {self.y}, {self.z})"
127
115
 
128
116
  @classmethod
129
- def new(cls, w: float, x: float, y: float, z: float) -> Quaternion:
117
+ def identity(cls) -> Quaternion:
130
118
  """
131
- Create a new quaternion.
119
+ Create an identity quaternion (no rotation).
132
120
 
133
- :param w: The w component.
134
- :param x: The x component.
135
- :param y: The y component.
136
- :param z: The z component.
137
- :return: A quaternion.
121
+ :return: An identity quaternion [1, 0, 0, 0].
138
122
  """
139
123
 
140
- return cls(data=(w, x, y, z))
124
+ return cls(w=1.0, x=0.0, y=0.0, z=0.0)
141
125
 
142
126
  @classmethod
143
- def identity(cls) -> Quaternion:
127
+ def from_any(cls, value: Quaternion | tuple | list | dict | np.ndarray | None) -> Quaternion:
144
128
  """
145
- Create an identity quaternion (no rotation).
129
+ Create Quaternion from any compatible type.
146
130
 
147
- :return: An identity quaternion [1, 0, 0, 0].
131
+ Accepts:
132
+ - Quaternion instance (returned as-is)
133
+ - Tuple/list of 4 floats: (w, x, y, z)
134
+ - Dict with 'w', 'x', 'y', and 'z' keys
135
+ - Numpy array of shape (4,)
136
+ - None (returns identity quaternion)
137
+
138
+ :param value: Any compatible input type.
139
+ :return: A Quaternion instance.
148
140
  """
149
141
 
150
- return cls(data=(1.0, 0.0, 0.0, 0.0))
142
+ if value is None:
143
+ return cls.identity()
144
+ if isinstance(value, cls):
145
+ return value
146
+ return cls.model_validate(value)
151
147
 
152
148
  @classmethod
153
149
  def from_numpy(cls, array: np.ndarray) -> Quaternion:
154
150
  """
155
151
  Create a quaternion from a numpy array [w, x, y, z].
156
152
 
157
- :param array: The numpy array to create the quaternion from (must have 4 elements).
153
+ :param array: The numpy array (must have 4 elements).
158
154
  :return: A quaternion.
159
155
  :raises ValueError: If the array does not have exactly 4 elements.
160
156
  """
161
157
 
162
158
  if array.shape != (4,):
163
159
  raise ValueError(f"Quaternion array must have shape (4,), got {array.shape}")
164
- return cls(data=(float(array[0]), float(array[1]), float(array[2]), float(array[3])))
160
+ return cls(w=float(array[0]), x=float(array[1]), y=float(array[2]), z=float(array[3]))
165
161
 
166
162
  @classmethod
167
163
  def from_rpy(cls, roll: float, pitch: float, yaw: float) -> Quaternion:
@@ -174,16 +170,9 @@ class Quaternion(Message):
174
170
  :return: A quaternion.
175
171
  """
176
172
 
177
- rotation = Rotation.from_euler("xyz", [roll, pitch, yaw])
173
+ rotation = Rotation.from_euler("XYZ", [roll, pitch, yaw])
178
174
  quat_xyzw = rotation.as_quat()
179
- return cls(
180
- data=(
181
- float(quat_xyzw[3]),
182
- float(quat_xyzw[0]),
183
- float(quat_xyzw[1]),
184
- float(quat_xyzw[2]),
185
- )
186
- )
175
+ return cls(w=float(quat_xyzw[3]), x=float(quat_xyzw[0]), y=float(quat_xyzw[1]), z=float(quat_xyzw[2]))
187
176
 
188
177
  def to_numpy(self) -> np.ndarray:
189
178
  """
@@ -192,7 +181,7 @@ class Quaternion(Message):
192
181
  :return: The numpy array [w, x, y, z].
193
182
  """
194
183
 
195
- return np.array(self.data, dtype=np.float32)
184
+ return np.array([self.w, self.x, self.y, self.z], dtype=np.float32)
196
185
 
197
186
  def to_list(self) -> list[float]:
198
187
  """
@@ -201,7 +190,16 @@ class Quaternion(Message):
201
190
  :return: The list [w, x, y, z].
202
191
  """
203
192
 
204
- return list(self.data)
193
+ return [self.w, self.x, self.y, self.z]
194
+
195
+ def to_tuple(self) -> tuple[float, float, float, float]:
196
+ """
197
+ Convert the quaternion to a tuple.
198
+
199
+ :return: The tuple (w, x, y, z).
200
+ """
201
+
202
+ return (self.w, self.x, self.y, self.z)
205
203
 
206
204
  def to_gf_quatf(self) -> Gf.Quatf:
207
205
  """
@@ -213,8 +211,8 @@ class Quaternion(Message):
213
211
  :raises ImportError: If pxr is not installed.
214
212
  """
215
213
 
216
- if not HAS_PXR:
217
- raise ImportError("pxr is not installed")
214
+ from pxr import Gf
215
+
218
216
  return Gf.Quatf(self.w, self.x, self.y, self.z)
219
217
 
220
218
  def to_gf_quatd(self) -> Gf.Quatd:
@@ -227,8 +225,8 @@ class Quaternion(Message):
227
225
  :raises ImportError: If pxr is not installed.
228
226
  """
229
227
 
230
- if not HAS_PXR:
231
- raise ImportError("pxr is not installed")
228
+ from pxr import Gf
229
+
232
230
  return Gf.Quatd(self.w, self.x, self.y, self.z)
233
231
 
234
232
  def normalize(self) -> Quaternion:
@@ -242,13 +240,11 @@ class Quaternion(Message):
242
240
  norm = np.linalg.norm(arr)
243
241
  if norm > 0:
244
242
  normalized = arr / norm
245
- return self.__class__(
246
- data=(
247
- float(normalized[0]),
248
- float(normalized[1]),
249
- float(normalized[2]),
250
- float(normalized[3]),
251
- )
243
+ return Quaternion(
244
+ w=float(normalized[0]),
245
+ x=float(normalized[1]),
246
+ y=float(normalized[2]),
247
+ z=float(normalized[3]),
252
248
  )
253
249
  return self.identity()
254
250
 
@@ -263,11 +259,28 @@ class Quaternion(Message):
263
259
  rpy = rotation.as_euler("xyz")
264
260
  return (float(rpy[0]), float(rpy[1]), float(rpy[2]))
265
261
 
266
- def as_array(self) -> list[float]:
262
+ def to_foxglove(self) -> FoxgloveQuaternion:
267
263
  """
268
- Convert to a list (alias for to_list for Rust compatibility).
264
+ Convert to Foxglove Quaternion for telemetry.
269
265
 
270
- :return: The list [w, x, y, z].
266
+ :return: Foxglove Quaternion schema.
267
+ """
268
+
269
+ return FoxgloveQuaternion(x=self.x, y=self.y, z=self.z, w=self.w)
270
+
271
+ @model_validator(mode="before")
272
+ @classmethod
273
+ def _convert_input(cls, data: Any) -> Any:
274
+ """
275
+ Convert various input types to Quaternion format.
271
276
  """
272
277
 
273
- return self.to_list()
278
+ if isinstance(data, cls):
279
+ return {"w": data.w, "x": data.x, "y": data.y, "z": data.z}
280
+ if isinstance(data, (tuple, list)) and len(data) == 4:
281
+ return {"w": float(data[0]), "x": float(data[1]), "y": float(data[2]), "z": float(data[3])}
282
+ if isinstance(data, np.ndarray) and data.shape == (4,):
283
+ return {"w": float(data[0]), "x": float(data[1]), "y": float(data[2]), "z": float(data[3])}
284
+ if isinstance(data, dict) and all(k in data for k in ("w", "x", "y", "z")):
285
+ return {"w": float(data["w"]), "x": float(data["x"]), "y": float(data["y"]), "z": float(data["z"])}
286
+ return data