antioch-py 2.0.6__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 (99) hide show
  1. antioch/__init__.py +0 -0
  2. antioch/message.py +87 -0
  3. antioch/module/__init__.py +53 -0
  4. antioch/module/clock.py +62 -0
  5. antioch/module/execution.py +278 -0
  6. antioch/module/input.py +127 -0
  7. antioch/module/module.py +218 -0
  8. antioch/module/node.py +357 -0
  9. antioch/module/token.py +42 -0
  10. antioch/session/__init__.py +150 -0
  11. antioch/session/ark.py +504 -0
  12. antioch/session/asset.py +65 -0
  13. antioch/session/error.py +80 -0
  14. antioch/session/record.py +158 -0
  15. antioch/session/scene.py +1521 -0
  16. antioch/session/session.py +220 -0
  17. antioch/session/task.py +323 -0
  18. antioch/session/views/__init__.py +40 -0
  19. antioch/session/views/animation.py +189 -0
  20. antioch/session/views/articulation.py +245 -0
  21. antioch/session/views/basis_curve.py +186 -0
  22. antioch/session/views/camera.py +92 -0
  23. antioch/session/views/collision.py +75 -0
  24. antioch/session/views/geometry.py +74 -0
  25. antioch/session/views/ground_plane.py +63 -0
  26. antioch/session/views/imu.py +73 -0
  27. antioch/session/views/joint.py +64 -0
  28. antioch/session/views/light.py +175 -0
  29. antioch/session/views/pir_sensor.py +140 -0
  30. antioch/session/views/radar.py +73 -0
  31. antioch/session/views/rigid_body.py +282 -0
  32. antioch/session/views/xform.py +119 -0
  33. antioch_py-2.0.6.dist-info/METADATA +115 -0
  34. antioch_py-2.0.6.dist-info/RECORD +99 -0
  35. antioch_py-2.0.6.dist-info/WHEEL +5 -0
  36. antioch_py-2.0.6.dist-info/entry_points.txt +2 -0
  37. antioch_py-2.0.6.dist-info/top_level.txt +2 -0
  38. common/__init__.py +0 -0
  39. common/ark/__init__.py +60 -0
  40. common/ark/ark.py +128 -0
  41. common/ark/hardware.py +121 -0
  42. common/ark/kinematics.py +31 -0
  43. common/ark/module.py +85 -0
  44. common/ark/node.py +94 -0
  45. common/ark/scheduler.py +439 -0
  46. common/ark/sim.py +33 -0
  47. common/assets/__init__.py +3 -0
  48. common/constants.py +47 -0
  49. common/core/__init__.py +52 -0
  50. common/core/agent.py +296 -0
  51. common/core/auth.py +305 -0
  52. common/core/registry.py +331 -0
  53. common/core/task.py +36 -0
  54. common/message/__init__.py +59 -0
  55. common/message/annotation.py +89 -0
  56. common/message/array.py +500 -0
  57. common/message/base.py +517 -0
  58. common/message/camera.py +91 -0
  59. common/message/color.py +139 -0
  60. common/message/frame.py +50 -0
  61. common/message/image.py +171 -0
  62. common/message/imu.py +14 -0
  63. common/message/joint.py +47 -0
  64. common/message/log.py +31 -0
  65. common/message/pir.py +16 -0
  66. common/message/point.py +109 -0
  67. common/message/point_cloud.py +63 -0
  68. common/message/pose.py +148 -0
  69. common/message/quaternion.py +273 -0
  70. common/message/radar.py +58 -0
  71. common/message/types.py +37 -0
  72. common/message/vector.py +786 -0
  73. common/rome/__init__.py +9 -0
  74. common/rome/client.py +430 -0
  75. common/rome/error.py +16 -0
  76. common/session/__init__.py +54 -0
  77. common/session/environment.py +31 -0
  78. common/session/sim.py +240 -0
  79. common/session/views/__init__.py +263 -0
  80. common/session/views/animation.py +73 -0
  81. common/session/views/articulation.py +184 -0
  82. common/session/views/basis_curve.py +102 -0
  83. common/session/views/camera.py +147 -0
  84. common/session/views/collision.py +59 -0
  85. common/session/views/geometry.py +102 -0
  86. common/session/views/ground_plane.py +41 -0
  87. common/session/views/imu.py +66 -0
  88. common/session/views/joint.py +81 -0
  89. common/session/views/light.py +96 -0
  90. common/session/views/pir_sensor.py +115 -0
  91. common/session/views/radar.py +82 -0
  92. common/session/views/rigid_body.py +236 -0
  93. common/session/views/viewport.py +21 -0
  94. common/session/views/xform.py +39 -0
  95. common/utils/__init__.py +4 -0
  96. common/utils/comms.py +571 -0
  97. common/utils/logger.py +123 -0
  98. common/utils/time.py +42 -0
  99. common/utils/usd.py +12 -0
@@ -0,0 +1,500 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import numpy as np
6
+ from pydantic import Field, PrivateAttr, model_validator
7
+
8
+ from common.message.base import Message
9
+
10
+
11
+ class Array(Message):
12
+ """
13
+ A message type for representing an unbounded array of float32 values.
14
+ Serialized as bytes, with lazy numpy array conversion for operations.
15
+
16
+ Arrays automatically convert from common Python types:
17
+ - Lists: Array(data=[1.0, 2.0, 3.0]) or Array.from_any([1.0, 2.0, 3.0])
18
+ - Tuples: Array(data=(1.0, 2.0, 3.0))
19
+ - Sets: Array(data={1.0, 2.0, 3.0})
20
+ - Numpy arrays: Array(data=np.array([1.0, 2.0, 3.0]))
21
+ - Any iterable: Array(data=range(10))
22
+
23
+ When used as a field in Messages, conversion happens automatically:
24
+ class RobotCommand(Message):
25
+ joint_positions: Array
26
+
27
+ cmd = RobotCommand(joint_positions=[0.1, 0.2, 0.3]) # List auto-converts!
28
+
29
+ This makes it seamless to use in APIs without explicit conversion calls.
30
+ """
31
+
32
+ _type = "antioch/array"
33
+ _arr: np.ndarray | None = PrivateAttr(default=None)
34
+ data: bytes = Field(description="Serialized array data as bytes")
35
+
36
+ def __len__(self) -> int:
37
+ """
38
+ Get the length of the array.
39
+
40
+ :return: The length.
41
+ """
42
+
43
+ return len(self.data) // 4 # 4 bytes per float32
44
+
45
+ def __iter__(self):
46
+ """
47
+ Iterate over array elements.
48
+
49
+ :return: Iterator over float values.
50
+ """
51
+
52
+ return iter(self.to_numpy())
53
+
54
+ def __getitem__(self, key: Any) -> Any:
55
+ """
56
+ Get an item from the array.
57
+
58
+ :param key: The index or slice.
59
+ :return: The item.
60
+ """
61
+
62
+ return self.to_numpy()[key]
63
+
64
+ def __setitem__(self, key: Any, value: Any) -> None:
65
+ """
66
+ Set an item in the array.
67
+
68
+ :param key: The index or slice.
69
+ :param value: The value to set.
70
+ """
71
+
72
+ arr = self.to_numpy().copy()
73
+ arr[key] = value
74
+ self.data = arr.tobytes()
75
+ self._arr = arr
76
+
77
+ def __eq__(self, other: object) -> bool:
78
+ """
79
+ Check equality with another Array.
80
+
81
+ :param other: Another Array.
82
+ :return: True if arrays are equal.
83
+ """
84
+
85
+ if not isinstance(other, Array):
86
+ return False
87
+ return self.data == other.data
88
+
89
+ def __repr__(self) -> str:
90
+ """
91
+ Return a readable string representation showing array values.
92
+
93
+ :return: String representation.
94
+ """
95
+
96
+ arr = self.to_numpy()
97
+ return f"Array({arr!r})"
98
+
99
+ def __str__(self) -> str:
100
+ """
101
+ Return a readable string representation showing array values.
102
+
103
+ :return: String representation.
104
+ """
105
+
106
+ arr = self.to_numpy()
107
+ return f"Array({arr!r})"
108
+
109
+ def __add__(self, other: Array | float | int) -> Array:
110
+ """
111
+ Add arrays element-wise or add a scalar to all elements.
112
+
113
+ :param other: Another Array or a scalar value.
114
+ :return: The result array.
115
+ """
116
+
117
+ if isinstance(other, Array):
118
+ result = self.to_numpy() + other.to_numpy()
119
+ elif isinstance(other, (int, float)):
120
+ result = self.to_numpy() + other
121
+ return Array.from_numpy(result)
122
+
123
+ def __radd__(self, other: float | int) -> Array:
124
+ """
125
+ Add a scalar to all elements (reversed operands).
126
+
127
+ :param other: A scalar value.
128
+ :return: The result array.
129
+ """
130
+
131
+ return self.__add__(other)
132
+
133
+ def __sub__(self, other: Array | float | int) -> Array:
134
+ """
135
+ Subtract arrays element-wise or subtract a scalar from all elements.
136
+
137
+ :param other: Another Array or a scalar value.
138
+ :return: The result array.
139
+ """
140
+
141
+ if isinstance(other, Array):
142
+ result = self.to_numpy() - other.to_numpy()
143
+ elif isinstance(other, (int, float)):
144
+ result = self.to_numpy() - other
145
+ return Array.from_numpy(result)
146
+
147
+ def __rsub__(self, other: float | int) -> Array:
148
+ """
149
+ Subtract all elements from a scalar (reversed operands).
150
+
151
+ :param other: A scalar value.
152
+ :return: The result array.
153
+ """
154
+
155
+ result = other - self.to_numpy()
156
+ return Array.from_numpy(result)
157
+
158
+ def __mul__(self, other: Array | float | int) -> Array:
159
+ """
160
+ Multiply arrays element-wise or multiply all elements by a scalar.
161
+
162
+ :param other: Another Array or a scalar value.
163
+ :return: The result array.
164
+ """
165
+
166
+ if isinstance(other, Array):
167
+ result = self.to_numpy() * other.to_numpy()
168
+ elif isinstance(other, (int, float)):
169
+ result = self.to_numpy() * other
170
+ return Array.from_numpy(result)
171
+
172
+ def __rmul__(self, other: float | int) -> Array:
173
+ """
174
+ Multiply all elements by a scalar (reversed operands).
175
+
176
+ :param other: A scalar value.
177
+ :return: The result array.
178
+ """
179
+
180
+ return self.__mul__(other)
181
+
182
+ def __truediv__(self, other: Array | float | int) -> Array:
183
+ """
184
+ Divide arrays element-wise or divide all elements by a scalar.
185
+
186
+ :param other: Another Array or a scalar value.
187
+ :return: The result array.
188
+ :raises ZeroDivisionError: If dividing by zero scalar.
189
+ """
190
+
191
+ if isinstance(other, Array):
192
+ result = self.to_numpy() / other.to_numpy()
193
+ elif isinstance(other, (int, float)):
194
+ if other == 0:
195
+ raise ZeroDivisionError("Cannot divide array by zero")
196
+ result = self.to_numpy() / other
197
+ return Array.from_numpy(result)
198
+
199
+ def __rtruediv__(self, other: float | int) -> Array:
200
+ """
201
+ Divide a scalar by all elements (reversed operands).
202
+
203
+ :param other: A scalar value.
204
+ :return: The result array.
205
+ """
206
+
207
+ result = other / self.to_numpy()
208
+ return Array.from_numpy(result)
209
+
210
+ def __neg__(self) -> Array:
211
+ """
212
+ Negate all elements in the array.
213
+
214
+ :return: The negated array.
215
+ """
216
+
217
+ return Array.from_numpy(-self.to_numpy())
218
+
219
+ def __pow__(self, other: float | int) -> Array:
220
+ """
221
+ Raise all elements to a power.
222
+
223
+ :param other: The exponent.
224
+ :return: The result array.
225
+ """
226
+
227
+ result = self.to_numpy() ** other
228
+ return Array.from_numpy(result)
229
+
230
+ @model_validator(mode="before")
231
+ @classmethod
232
+ def convert_iterables(cls, data: Any) -> Any:
233
+ """
234
+ Automatically convert common Python types to Array format.
235
+
236
+ Supports: lists, tuples, sets, numpy arrays, and any iterable.
237
+ This allows seamless usage without explicit Array.from_*() calls.
238
+ """
239
+
240
+ # Already an Array instance
241
+ if isinstance(data, cls):
242
+ return data.model_dump()
243
+
244
+ # Dict format - check if data field needs conversion
245
+ if isinstance(data, dict):
246
+ # If data field is already bytes, no conversion needed
247
+ if "data" in data and isinstance(data["data"], bytes):
248
+ return data
249
+ # If data field is an iterable, convert it
250
+ if "data" in data:
251
+ data_value = data["data"]
252
+ if isinstance(data_value, np.ndarray):
253
+ data["data"] = data_value.astype(np.float32).tobytes()
254
+ return data
255
+ if hasattr(data_value, "__iter__") and not isinstance(data_value, (str, bytes)):
256
+ try:
257
+ arr = np.array(list(data_value), dtype=np.float32)
258
+ data["data"] = arr.tobytes()
259
+ return data
260
+ except (ValueError, TypeError) as e:
261
+ raise ValueError(f"Failed to convert iterable to Array: {e}") from None
262
+ return data
263
+
264
+ # Raw bytes (used internally)
265
+ if isinstance(data, bytes):
266
+ return {"data": data}
267
+
268
+ # Numpy array - convert directly
269
+ if isinstance(data, np.ndarray):
270
+ return {"data": data.astype(np.float32).tobytes()}
271
+
272
+ # Any iterable (list, tuple, set, generator, etc.) - exclude strings and bytes
273
+ if hasattr(data, "__iter__") and not isinstance(data, (str, bytes)):
274
+ try:
275
+ arr = np.array(list(data), dtype=np.float32)
276
+ return {"data": arr.tobytes()}
277
+ except (ValueError, TypeError) as e:
278
+ raise ValueError(f"Failed to convert iterable to Array: {e}") from None
279
+
280
+ return data
281
+
282
+ @classmethod
283
+ def from_any(cls, data: Any) -> Array:
284
+ """
285
+ Create Array from any iterable type (list, tuple, set, numpy array, etc.).
286
+
287
+ :param data: Any iterable containing numeric values, or an Array instance.
288
+ :return: An Array instance.
289
+ :raises ValueError: If conversion fails.
290
+ """
291
+
292
+ # Already an Array - return as-is
293
+ if isinstance(data, cls):
294
+ return data
295
+
296
+ # Let the validator handle the conversion
297
+ try:
298
+ return cls(data=data)
299
+ except Exception as e:
300
+ raise ValueError(f"Cannot convert to Array: {e}") from None
301
+
302
+ @classmethod
303
+ def from_numpy(cls, array: np.ndarray) -> Array:
304
+ """
305
+ Create from a numpy array.
306
+
307
+ :param array: The numpy array.
308
+ :return: An Array instance.
309
+ """
310
+
311
+ return cls(data=array.astype(np.float32).tobytes())
312
+
313
+ @classmethod
314
+ def from_list(cls, values: list[float]) -> Array:
315
+ """
316
+ Create from a list of floats.
317
+
318
+ :param values: List of float values.
319
+ :return: An Array instance.
320
+ """
321
+
322
+ return cls(data=np.array(values, dtype=np.float32).tobytes())
323
+
324
+ @classmethod
325
+ def zeros(cls, size: int) -> Array:
326
+ """
327
+ Create an array of zeros.
328
+
329
+ :param size: The size of the array.
330
+ :return: An Array of zeros.
331
+ """
332
+
333
+ return cls(data=np.zeros(size, dtype=np.float32).tobytes())
334
+
335
+ @classmethod
336
+ def ones(cls, size: int) -> Array:
337
+ """
338
+ Create an array of ones.
339
+
340
+ :param size: The size of the array.
341
+ :return: An Array of ones.
342
+ """
343
+
344
+ return cls(data=np.ones(size, dtype=np.float32).tobytes())
345
+
346
+ def sum(self) -> float:
347
+ """
348
+ Compute the sum of all elements.
349
+
350
+ :return: The sum.
351
+ """
352
+
353
+ return float(np.sum(self.to_numpy()))
354
+
355
+ def mean(self) -> float:
356
+ """
357
+ Compute the mean of all elements.
358
+
359
+ :return: The mean.
360
+ """
361
+
362
+ return float(np.mean(self.to_numpy()))
363
+
364
+ def min(self) -> float:
365
+ """
366
+ Find the minimum element.
367
+
368
+ :return: The minimum value.
369
+ """
370
+
371
+ return float(np.min(self.to_numpy()))
372
+
373
+ def max(self) -> float:
374
+ """
375
+ Find the maximum element.
376
+
377
+ :return: The maximum value.
378
+ """
379
+
380
+ return float(np.max(self.to_numpy()))
381
+
382
+ def std(self) -> float:
383
+ """
384
+ Compute the standard deviation.
385
+
386
+ :return: The standard deviation.
387
+ """
388
+
389
+ return float(np.std(self.to_numpy()))
390
+
391
+ def dot(self, other: Array) -> float:
392
+ """
393
+ Compute dot product with another array.
394
+
395
+ :param other: Another Array.
396
+ :return: The dot product.
397
+ :raises ValueError: If arrays have different lengths.
398
+ """
399
+
400
+ if len(self) != len(other):
401
+ raise ValueError(f"Arrays must have same length for dot product: {len(self)} != {len(other)}")
402
+ return float(np.dot(self.to_numpy(), other.to_numpy()))
403
+
404
+ def magnitude(self) -> float:
405
+ """
406
+ Compute the magnitude (L2 norm) of the array.
407
+
408
+ :return: The magnitude.
409
+ """
410
+
411
+ return float(np.linalg.norm(self.to_numpy()))
412
+
413
+ def magnitude_squared(self) -> float:
414
+ """
415
+ Compute the squared magnitude of the array.
416
+
417
+ :return: The squared magnitude.
418
+ """
419
+
420
+ return float(np.sum(self.to_numpy() ** 2))
421
+
422
+ def normalize(self) -> Array:
423
+ """
424
+ Return a normalized version of this array (unit magnitude).
425
+
426
+ :return: The normalized array.
427
+ :raises ValueError: If the array has zero magnitude.
428
+ """
429
+
430
+ mag = self.magnitude()
431
+ if mag == 0:
432
+ raise ValueError("Cannot normalize zero-magnitude array")
433
+ return self / mag
434
+
435
+ def to_numpy(self) -> np.ndarray:
436
+ """
437
+ Convert to a numpy array (cached).
438
+
439
+ :return: The numpy array.
440
+ """
441
+
442
+ if self._arr is None:
443
+ self._arr = np.frombuffer(self.data, dtype=np.float32)
444
+ return self._arr
445
+
446
+ def to_list(self) -> list[float]:
447
+ """
448
+ Convert to a list.
449
+
450
+ :return: The list of values.
451
+ """
452
+
453
+ return self.to_numpy().tolist()
454
+
455
+ def is_empty(self) -> bool:
456
+ """
457
+ Check if the array is empty.
458
+
459
+ :return: True if empty, False otherwise.
460
+ """
461
+
462
+ return len(self.data) == 0
463
+
464
+ def as_bytes(self) -> bytes:
465
+ """
466
+ Get the raw byte data (alias for data field for Rust compatibility).
467
+
468
+ :return: The raw bytes.
469
+ """
470
+
471
+ return self.data
472
+
473
+ def get(self, index: int) -> float | None:
474
+ """
475
+ Get element at index (returns None if out of bounds).
476
+
477
+ :param index: The index.
478
+ :return: The value or None.
479
+ """
480
+
481
+ if index < 0 or index >= len(self):
482
+ return None
483
+ return float(self.to_numpy()[index])
484
+
485
+ def set(self, index: int, value: float) -> bool:
486
+ """
487
+ Set element at index.
488
+
489
+ :param index: The index.
490
+ :param value: The value to set.
491
+ :return: True if successful, False if out of bounds.
492
+ """
493
+
494
+ if index < 0 or index >= len(self):
495
+ return False
496
+ arr = self.to_numpy().copy()
497
+ arr[index] = value
498
+ self.data = arr.tobytes()
499
+ self._arr = arr
500
+ return True