antioch-py 2.2.4__py3-none-any.whl → 3.0.1__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.1.dist-info}/METADATA +8 -11
  7. antioch_py-3.0.1.dist-info/RECORD +61 -0
  8. {antioch_py-2.2.4.dist-info → antioch_py-3.0.1.dist-info}/WHEEL +1 -1
  9. antioch_py-3.0.1.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.1.dist-info}/top_level.txt +0 -0
  94. /common/message/{base.py → message.py} +0 -0
common/message/radar.py CHANGED
@@ -1,31 +1,106 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import numpy as np
1
6
  from pydantic import Field
2
7
 
3
- from common.message.base import Message
8
+ from common.message.array import Array
9
+ from common.message.image import Image, ImageEncoding
10
+ from common.message.message import Message
4
11
  from common.message.point_cloud import PointCloud
5
- from common.message.vector import Vector3
6
12
 
7
13
 
8
- class RadarDetection(Message):
9
- """
10
- Single radar detection point with position and properties.
14
+ class RadarScan(Message):
11
15
  """
16
+ Radar scan data containing all detections from a single scan.
12
17
 
13
- _type = "antioch/radar_detection"
14
- position: Vector3 = Field(description="3D position of detection in sensor frame")
15
- range: float = Field(description="Range to target in meters")
16
- azimuth: float = Field(description="Azimuth angle in radians")
17
- elevation: float = Field(description="Elevation angle in radians")
18
- velocity: float = Field(default=0.0, description="Radial velocity in m/s (positive = moving away)")
19
- rcs: float = Field(default=0.0, description="Radar cross section in dBsm")
18
+ Data is stored as numpy arrays (via Array) for efficient processing.
20
19
 
20
+ Example:
21
+ ```python
22
+ from common.message import RadarScan
21
23
 
22
- class RadarScan(Message):
23
- """
24
- Radar scan data containing all detections from a single scan.
24
+ # Access detection data efficiently via arrays
25
+ scan = radar.get_scan()
26
+ ranges = scan.ranges.to_numpy()
27
+ rcs = scan.rcs.to_numpy()
28
+
29
+ # Filter detections by range
30
+ close_mask = ranges < 10.0
31
+ close_rcs = rcs[close_mask]
32
+
33
+ # Convert to point cloud for visualization
34
+ point_cloud = scan.to_point_cloud(frame_id="radar_link")
35
+ ```
25
36
  """
26
37
 
27
38
  _type = "antioch/radar_scan"
28
- detections: list[RadarDetection] = Field(default_factory=list, description="List of radar detections")
39
+
40
+ # Raw spherical coordinates (stored as Arrays for serialization)
41
+ ranges: Array = Field(default_factory=lambda: Array.zeros(0), description="Range to targets in meters")
42
+ azimuths: Array = Field(default_factory=lambda: Array.zeros(0), description="Azimuth angles in radians")
43
+ elevations: Array = Field(default_factory=lambda: Array.zeros(0), description="Elevation angles in radians")
44
+ rcs: Array = Field(default_factory=lambda: Array.zeros(0), description="Radar cross section in dBsm")
45
+ velocities: Array = Field(default_factory=lambda: Array.zeros(0), description="Radial velocities in m/s")
46
+
47
+ # Cartesian positions (computed from spherical, stored for efficiency)
48
+ x: Array = Field(default_factory=lambda: Array.zeros(0), description="X positions in sensor frame")
49
+ y: Array = Field(default_factory=lambda: Array.zeros(0), description="Y positions in sensor frame")
50
+ z: Array = Field(default_factory=lambda: Array.zeros(0), description="Z positions in sensor frame")
51
+
52
+ @property
53
+ def num_detections(self) -> int:
54
+ """
55
+ Number of detections in this scan.
56
+ """
57
+
58
+ return len(self.ranges)
59
+
60
+ @classmethod
61
+ def from_arrays(
62
+ cls,
63
+ ranges: np.ndarray,
64
+ azimuths: np.ndarray,
65
+ elevations: np.ndarray,
66
+ rcs: np.ndarray,
67
+ velocities: np.ndarray,
68
+ x: np.ndarray,
69
+ y: np.ndarray,
70
+ z: np.ndarray,
71
+ ) -> RadarScan:
72
+ """
73
+ Create RadarScan directly from numpy arrays.
74
+
75
+ This is the most efficient way to create a RadarScan as it avoids
76
+ creating any intermediate Python objects.
77
+
78
+ :param ranges: Range values in meters.
79
+ :param azimuths: Azimuth angles in radians.
80
+ :param elevations: Elevation angles in radians.
81
+ :param rcs: RCS values in dBsm.
82
+ :param velocities: Radial velocities in m/s.
83
+ :param x: X positions in sensor frame.
84
+ :param y: Y positions in sensor frame.
85
+ :param z: Z positions in sensor frame.
86
+ :return: RadarScan instance.
87
+ :raises ValueError: If arrays have mismatched lengths.
88
+ """
89
+
90
+ n = len(ranges)
91
+ if not all(len(arr) == n for arr in [azimuths, elevations, rcs, velocities, x, y, z]):
92
+ raise ValueError("All arrays must have the same length")
93
+
94
+ return cls(
95
+ ranges=Array.from_numpy(ranges.astype(np.float32)),
96
+ azimuths=Array.from_numpy(azimuths.astype(np.float32)),
97
+ elevations=Array.from_numpy(elevations.astype(np.float32)),
98
+ rcs=Array.from_numpy(rcs.astype(np.float32)),
99
+ velocities=Array.from_numpy(velocities.astype(np.float32)),
100
+ x=Array.from_numpy(x.astype(np.float32)),
101
+ y=Array.from_numpy(y.astype(np.float32)),
102
+ z=Array.from_numpy(z.astype(np.float32)),
103
+ )
29
104
 
30
105
  def to_point_cloud(self, frame_id: str = "radar") -> PointCloud:
31
106
  """
@@ -35,24 +110,115 @@ class RadarScan(Message):
35
110
  :return: PointCloud with detection positions.
36
111
  """
37
112
 
38
- if not self.detections:
39
- return PointCloud(frame_id=frame_id, x=[], y=[], z=[])
40
-
41
113
  return PointCloud(
42
114
  frame_id=frame_id,
43
- x=[d.position.x for d in self.detections],
44
- y=[d.position.y for d in self.detections],
45
- z=[d.position.z for d in self.detections],
115
+ x=self.x.to_list(),
116
+ y=self.y.to_list(),
117
+ z=self.z.to_list(),
46
118
  )
47
119
 
48
- @staticmethod
49
- def combine(scans: list["RadarScan"]) -> "RadarScan":
120
+ def to_foxglove(self) -> dict[str, Any]:
121
+ """
122
+ Convert to a JSON-serializable dict for Foxglove visualization.
123
+
124
+ :return: Dictionary with all scan data as lists.
125
+ """
126
+
127
+ return {
128
+ "num_detections": self.num_detections,
129
+ "ranges": self.ranges.to_list(),
130
+ "azimuths": self.azimuths.to_list(),
131
+ "elevations": self.elevations.to_list(),
132
+ "rcs": self.rcs.to_list(),
133
+ "velocities": self.velocities.to_list(),
134
+ "x": self.x.to_list(),
135
+ "y": self.y.to_list(),
136
+ "z": self.z.to_list(),
137
+ }
138
+
139
+
140
+ class RangeMap(Message):
141
+ """
142
+ 1D range bin map for radar processing.
143
+
144
+ Represents radar signal strength across range bins, commonly used for
145
+ MTI (Moving Target Indication) processing and detection.
146
+ """
147
+
148
+ _type = "antioch/range_map"
149
+
150
+ r_bins: int = Field(description="Number of range bins")
151
+ r_min_m: float = Field(description="Minimum range in meters (inclusive)")
152
+ r_max_m: float = Field(description="Maximum range in meters (inclusive)")
153
+ dr_m: float = Field(description="Range bin size in meters")
154
+ data: Array = Field(description="Float32 array of shape (r_bins,)")
155
+
156
+ def to_numpy(self) -> np.ndarray:
157
+ """
158
+ Convert the range map to a 1D numpy array.
159
+
160
+ :return: float32 array with shape (r_bins,).
161
+ """
162
+
163
+ return self.data.to_numpy().reshape(self.r_bins)
164
+
165
+ def to_image(
166
+ self,
167
+ *,
168
+ transform: str = "log1p",
169
+ encoding: ImageEncoding = ImageEncoding.MONO8,
170
+ clip_percentile: float = 99.5,
171
+ height: int = 32,
172
+ ) -> Image:
173
+ """
174
+ Convert this range map into an Image for visualization.
175
+
176
+ The image is a horizontal bar where x-axis is range bins.
177
+
178
+ :param transform: "linear" or "log1p".
179
+ :param encoding: Image encoding to use (default MONO8).
180
+ :param clip_percentile: When encoding is MONO8, clip values to this percentile.
181
+ :param height: Height of the output image in pixels.
182
+ :return: Image representing the range map.
183
+ """
184
+
185
+ data = self.to_numpy()
186
+ if transform == "log1p":
187
+ values = np.log1p(data).astype(np.float32)
188
+ elif transform == "linear":
189
+ values = data.astype(np.float32, copy=False)
190
+ else:
191
+ raise ValueError(f"Unsupported transform '{transform}'")
192
+
193
+ if encoding == ImageEncoding.DEPTH_F32:
194
+ tiled = np.tile(values.reshape(1, -1), (height, 1))
195
+ return Image.from_numpy(tiled.astype(np.float32, copy=False), encoding=encoding)
196
+
197
+ if encoding != ImageEncoding.MONO8:
198
+ raise ValueError(f"Unsupported encoding '{encoding.value}' for range map image")
199
+
200
+ # Normalize to 8-bit
201
+ vmax = float(np.percentile(values, clip_percentile)) if values.size else 0.0
202
+ if vmax <= 0.0 or not np.isfinite(vmax):
203
+ mono = np.zeros((height, self.r_bins), dtype=np.uint8)
204
+ else:
205
+ scaled = np.clip(values / np.float32(vmax), 0.0, 1.0)
206
+ mono_row = (scaled * np.float32(255.0)).astype(np.uint8, copy=False)
207
+ mono = np.tile(mono_row.reshape(1, -1), (height, 1))
208
+
209
+ return Image.from_numpy(mono, encoding=encoding)
210
+
211
+ def to_foxglove(self) -> dict[str, Any]:
50
212
  """
51
- Combine multiple radar scans into a single scan.
213
+ Convert to a JSON-serializable dict for Foxglove visualization.
52
214
 
53
- :param scans: List of radar scans to combine.
54
- :return: Combined radar scan with all detections.
215
+ :return: Dictionary with range map metadata and data as list.
55
216
  """
56
217
 
57
- detections = sum((scan.detections for scan in scans), [])
58
- return RadarScan(detections=detections)
218
+ return {
219
+ "r_bins": self.r_bins,
220
+ "r_min_m": self.r_min_m,
221
+ "r_max_m": self.r_max_m,
222
+ "dr_m": self.dr_m,
223
+ "data": self.data.to_list(),
224
+ }
@@ -0,0 +1,34 @@
1
+ from pydantic import Field
2
+
3
+ from common.message.message import Message
4
+ from common.message.vector import Vector3
5
+
6
+
7
+ class Twist(Message):
8
+ """
9
+ Linear and angular velocity (twist).
10
+
11
+ Represents the velocity of a rigid body in 3D space, combining both
12
+ linear velocity (translation) and angular velocity (rotation).
13
+
14
+ Example:
15
+ ```python
16
+ from common.message import Twist, Vector3
17
+
18
+ # Create a twist for forward motion with rotation
19
+ twist = Twist(
20
+ linear=Vector3(x=1.0, y=0.0, z=0.0), # 1 m/s forward
21
+ angular=Vector3(x=0.0, y=0.0, z=0.1), # 0.1 rad/s yaw
22
+ )
23
+
24
+ # Zero velocity
25
+ stationary = Twist(
26
+ linear=Vector3.zeros(),
27
+ angular=Vector3.zeros(),
28
+ )
29
+ ```
30
+ """
31
+
32
+ _type = "antioch/twist"
33
+ linear: Vector3 = Field(description="Linear velocity in m/s (x, y, z)")
34
+ angular: Vector3 = Field(description="Angular velocity in rad/s (x, y, z)")
common/message/types.py CHANGED
@@ -1,37 +1,72 @@
1
- from common.message.base import Message
1
+ from pydantic import Field
2
+
3
+ from common.message.message import Message
2
4
 
3
5
 
4
6
  class Bool(Message):
5
7
  """
6
8
  Boolean value message.
9
+
10
+ Example:
11
+ ```python
12
+ from common.message import Bool
13
+
14
+ msg = Bool(value=True)
15
+ if msg.value:
16
+ print("Value is true")
17
+ ```
7
18
  """
8
19
 
9
20
  _type = "antioch/bool"
10
- value: bool
21
+ value: bool = Field(description="Boolean value")
11
22
 
12
23
 
13
24
  class Int(Message):
14
25
  """
15
26
  Integer value message.
27
+
28
+ Example:
29
+ ```python
30
+ from common.message import Int
31
+
32
+ msg = Int(value=42)
33
+ print(f"The answer is {msg.value}")
34
+ ```
16
35
  """
17
36
 
18
37
  _type = "antioch/int"
19
- value: int
38
+ value: int = Field(description="Integer value")
20
39
 
21
40
 
22
41
  class Float(Message):
23
42
  """
24
43
  Float value message.
44
+
45
+ Example:
46
+ ```python
47
+ from common.message import Float
48
+
49
+ msg = Float(value=3.14159)
50
+ print(f"Pi is approximately {msg.value:.2f}")
51
+ ```
25
52
  """
26
53
 
27
54
  _type = "antioch/float"
28
- value: float
55
+ value: float = Field(description="Floating-point value")
29
56
 
30
57
 
31
58
  class String(Message):
32
59
  """
33
60
  String value message.
61
+
62
+ Example:
63
+ ```python
64
+ from common.message import String
65
+
66
+ msg = String(value="Hello, World!")
67
+ print(msg.value)
68
+ ```
34
69
  """
35
70
 
36
71
  _type = "antioch/string"
37
- value: str
72
+ value: str = Field(description="String value")