antioch-py 2.2.3__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.3.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.3.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 -98
  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.3.dist-info/RECORD +0 -85
  81. antioch_py-2.2.3.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 -430
  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.3.dist-info → antioch_py-3.0.0.dist-info}/top_level.txt +0 -0
  94. /common/message/{base.py → message.py} +0 -0
@@ -1,22 +1,32 @@
1
1
  from common.message.annotation import CircleAnnotation, ImageAnnotations, PointsAnnotation, PointsAnnotationType, TextAnnotation
2
2
  from common.message.array import Array
3
- from common.message.base import DeserializationError, Message, MessageError, MismatchError, SerializationError
4
3
  from common.message.camera import CameraInfo
5
4
  from common.message.color import Color
5
+ from common.message.detection import DetectionDistances
6
+ from common.message.foxglove import FoxgloveConvertible
6
7
  from common.message.frame import FrameTransform, FrameTransforms
7
8
  from common.message.image import Image, ImageEncoding
8
9
  from common.message.imu import ImuSample
9
10
  from common.message.joint import JointState, JointStates, JointTarget, JointTargets
10
11
  from common.message.log import Log, LogLevel
12
+ from common.message.message import (
13
+ DeserializationError,
14
+ FileAccessError,
15
+ Message,
16
+ MessageError,
17
+ MismatchError,
18
+ SerializationError,
19
+ )
11
20
  from common.message.pir import PirStatus
21
+ from common.message.plot import PlotData
12
22
  from common.message.point import Point2, Point3
13
23
  from common.message.point_cloud import PointCloud
14
24
  from common.message.pose import Pose
15
25
  from common.message.quaternion import Quaternion
16
- from common.message.radar import RadarDetection, RadarScan
26
+ from common.message.radar import RadarScan, RangeMap
27
+ from common.message.twist import Twist
17
28
  from common.message.types import Bool, Float, Int, String
18
29
  from common.message.vector import Vector2, Vector3
19
- from common.message.velocity import Twist
20
30
 
21
31
  __all__ = [
22
32
  "Array",
@@ -25,7 +35,10 @@ __all__ = [
25
35
  "CircleAnnotation",
26
36
  "Color",
27
37
  "DeserializationError",
38
+ "DetectionDistances",
39
+ "FileAccessError",
28
40
  "Float",
41
+ "FoxgloveConvertible",
29
42
  "FrameTransform",
30
43
  "FrameTransforms",
31
44
  "Image",
@@ -43,6 +56,7 @@ __all__ = [
43
56
  "MessageError",
44
57
  "MismatchError",
45
58
  "PirStatus",
59
+ "PlotData",
46
60
  "Point2",
47
61
  "Point3",
48
62
  "PointCloud",
@@ -50,12 +64,12 @@ __all__ = [
50
64
  "PointsAnnotationType",
51
65
  "Pose",
52
66
  "Quaternion",
53
- "RadarDetection",
54
67
  "RadarScan",
68
+ "RangeMap",
55
69
  "SerializationError",
56
70
  "String",
57
71
  "TextAnnotation",
72
+ "Twist",
58
73
  "Vector2",
59
74
  "Vector3",
60
- "Twist",
61
75
  ]
@@ -2,14 +2,33 @@ from __future__ import annotations
2
2
 
3
3
  from enum import IntEnum
4
4
 
5
- from common.message.base import Message
5
+ from foxglove.schemas import (
6
+ CircleAnnotation as FoxgloveCircleAnnotation,
7
+ Color as FoxgloveColor,
8
+ ImageAnnotations as FoxgloveImageAnnotations,
9
+ Point2 as FoxglovePoint2,
10
+ PointsAnnotation as FoxglovePointsAnnotation,
11
+ PointsAnnotationType as FoxglovePointsAnnotationType,
12
+ TextAnnotation as FoxgloveTextAnnotation,
13
+ )
14
+ from pydantic import Field
15
+
6
16
  from common.message.color import Color
17
+ from common.message.message import Message
7
18
  from common.message.point import Point2
8
19
 
9
20
 
10
21
  class PointsAnnotationType(IntEnum):
11
22
  """
12
23
  Type of points annotation.
24
+
25
+ Example:
26
+ ```python
27
+ from common.message import PointsAnnotationType
28
+
29
+ # Use as enum value
30
+ annotation_type = PointsAnnotationType.LINE_STRIP
31
+ ```
13
32
  """
14
33
 
15
34
  UNKNOWN = 0
@@ -24,14 +43,29 @@ class CircleAnnotation(Message):
24
43
  A circle annotation on a 2D image.
25
44
 
26
45
  Coordinates use the top-left corner of the top-left pixel as the origin.
46
+
47
+ Example:
48
+ ```python
49
+ from common.message import CircleAnnotation, Point2, Color
50
+
51
+ # Create a circle annotation
52
+ circle = CircleAnnotation(
53
+ timestamp_us=1000000,
54
+ position=Point2(x=100.0, y=100.0),
55
+ diameter=50.0,
56
+ thickness=2.0,
57
+ fill_color=Color.transparent(),
58
+ outline_color=Color.red(),
59
+ )
60
+ ```
27
61
  """
28
62
 
29
- timestamp_us: int
30
- position: Point2
31
- diameter: float
32
- thickness: float
33
- fill_color: Color
34
- outline_color: Color
63
+ timestamp_us: int = Field(description="Timestamp in microseconds")
64
+ position: Point2 = Field(description="Center position of the circle")
65
+ diameter: float = Field(description="Diameter of the circle in pixels")
66
+ thickness: float = Field(description="Line thickness in pixels")
67
+ fill_color: Color = Field(description="Fill color of the circle")
68
+ outline_color: Color = Field(description="Outline color of the circle")
35
69
 
36
70
 
37
71
  class PointsAnnotation(Message):
@@ -39,15 +73,33 @@ class PointsAnnotation(Message):
39
73
  An array of points on a 2D image.
40
74
 
41
75
  Coordinates use the top-left corner of the top-left pixel as the origin.
76
+
77
+ Example:
78
+ ```python
79
+ from common.message import PointsAnnotation, PointsAnnotationType, Point2, Color
80
+
81
+ # Create a line strip annotation
82
+ annotation = PointsAnnotation(
83
+ timestamp_us=1000000,
84
+ type=PointsAnnotationType.LINE_STRIP,
85
+ points=[
86
+ Point2(x=10.0, y=10.0),
87
+ Point2(x=100.0, y=50.0),
88
+ Point2(x=150.0, y=100.0),
89
+ ],
90
+ outline_color=Color.green(),
91
+ thickness=2.0,
92
+ )
93
+ ```
42
94
  """
43
95
 
44
- timestamp_us: int
45
- type: PointsAnnotationType
46
- points: list[Point2]
47
- outline_color: Color
48
- outline_colors: list[Color] | None = None
49
- fill_color: Color | None = None
50
- thickness: float
96
+ timestamp_us: int = Field(description="Timestamp in microseconds")
97
+ type: PointsAnnotationType = Field(description="Type of points annotation (points, line_strip, etc.)")
98
+ points: list[Point2] = Field(description="List of 2D points")
99
+ outline_color: Color = Field(description="Primary outline color")
100
+ outline_colors: list[Color] | None = Field(default=None, description="Per-point outline colors")
101
+ fill_color: Color | None = Field(default=None, description="Fill color for closed shapes")
102
+ thickness: float = Field(description="Line thickness in pixels")
51
103
 
52
104
 
53
105
  class TextAnnotation(Message):
@@ -56,14 +108,29 @@ class TextAnnotation(Message):
56
108
 
57
109
  Position uses the bottom-left origin of the text label.
58
110
  Coordinates use the top-left corner of the top-left pixel as the origin.
111
+
112
+ Example:
113
+ ```python
114
+ from common.message import TextAnnotation, Point2, Color
115
+
116
+ # Create a text annotation
117
+ text = TextAnnotation(
118
+ timestamp_us=1000000,
119
+ position=Point2(x=50.0, y=30.0),
120
+ text="Detection: Person",
121
+ font_size=14.0,
122
+ text_color=Color.white(),
123
+ background_color=Color.rgba(0.0, 0.0, 0.0, 0.5),
124
+ )
125
+ ```
59
126
  """
60
127
 
61
- timestamp_us: int
62
- position: Point2
63
- text: str
64
- font_size: float
65
- text_color: Color
66
- background_color: Color
128
+ timestamp_us: int = Field(description="Timestamp in microseconds")
129
+ position: Point2 = Field(description="Bottom-left position of the text label")
130
+ text: str = Field(description="Text content to display")
131
+ font_size: float = Field(description="Font size in pixels")
132
+ text_color: Color = Field(description="Color of the text")
133
+ background_color: Color = Field(description="Background color behind the text")
67
134
 
68
135
 
69
136
  class ImageAnnotations(Message):
@@ -71,12 +138,36 @@ class ImageAnnotations(Message):
71
138
  Array of annotations for a 2D image.
72
139
 
73
140
  Used in the Foxglove Image panel for visualization.
141
+
142
+ Example:
143
+ ```python
144
+ from common.message import ImageAnnotations, CircleAnnotation, Point2, Color
145
+
146
+ # Create an empty annotations container
147
+ annotations = ImageAnnotations.empty()
148
+
149
+ # Or create with annotations
150
+ annotations = ImageAnnotations(
151
+ circles=[
152
+ CircleAnnotation(
153
+ timestamp_us=1000000,
154
+ position=Point2(x=100.0, y=100.0),
155
+ diameter=20.0,
156
+ thickness=2.0,
157
+ fill_color=Color.transparent(),
158
+ outline_color=Color.red(),
159
+ ),
160
+ ],
161
+ points=[],
162
+ texts=[],
163
+ )
164
+ ```
74
165
  """
75
166
 
76
167
  _type = "antioch/image_annotations"
77
- circles: list[CircleAnnotation]
78
- points: list[PointsAnnotation]
79
- texts: list[TextAnnotation]
168
+ circles: list[CircleAnnotation] = Field(description="Circle annotations")
169
+ points: list[PointsAnnotation] = Field(description="Points/line annotations")
170
+ texts: list[TextAnnotation] = Field(description="Text annotations")
80
171
 
81
172
  @classmethod
82
173
  def empty(cls) -> ImageAnnotations:
@@ -87,3 +178,63 @@ class ImageAnnotations(Message):
87
178
  """
88
179
 
89
180
  return cls(circles=[], points=[], texts=[])
181
+
182
+ def to_foxglove(self) -> FoxgloveImageAnnotations:
183
+ """
184
+ Convert to Foxglove ImageAnnotations for telemetry.
185
+
186
+ :return: Foxglove ImageAnnotations schema.
187
+ """
188
+
189
+ # Convert PointsAnnotationType to Foxglove type
190
+ type_map = {
191
+ PointsAnnotationType.UNKNOWN: FoxglovePointsAnnotationType.Unknown,
192
+ PointsAnnotationType.POINTS: FoxglovePointsAnnotationType.Points,
193
+ PointsAnnotationType.LINE_LOOP: FoxglovePointsAnnotationType.LineLoop,
194
+ PointsAnnotationType.LINE_STRIP: FoxglovePointsAnnotationType.LineStrip,
195
+ PointsAnnotationType.LINE_LIST: FoxglovePointsAnnotationType.LineList,
196
+ }
197
+
198
+ # Convert circles
199
+ circles = [
200
+ FoxgloveCircleAnnotation(
201
+ timestamp=None,
202
+ position=FoxglovePoint2(x=c.position.x, y=c.position.y),
203
+ diameter=c.diameter,
204
+ thickness=c.thickness,
205
+ fill_color=FoxgloveColor(r=c.fill_color.r, g=c.fill_color.g, b=c.fill_color.b, a=c.fill_color.a),
206
+ outline_color=FoxgloveColor(r=c.outline_color.r, g=c.outline_color.g, b=c.outline_color.b, a=c.outline_color.a),
207
+ )
208
+ for c in self.circles
209
+ ]
210
+
211
+ # Convert points annotations
212
+ points = [
213
+ FoxglovePointsAnnotation(
214
+ timestamp=None,
215
+ type=type_map[p.type],
216
+ points=[FoxglovePoint2(x=pt.x, y=pt.y) for pt in p.points],
217
+ outline_color=FoxgloveColor(r=p.outline_color.r, g=p.outline_color.g, b=p.outline_color.b, a=p.outline_color.a),
218
+ outline_colors=[FoxgloveColor(r=c.r, g=c.g, b=c.b, a=c.a) for c in p.outline_colors] if p.outline_colors else [],
219
+ fill_color=FoxgloveColor(r=p.fill_color.r, g=p.fill_color.g, b=p.fill_color.b, a=p.fill_color.a) if p.fill_color else None,
220
+ thickness=p.thickness,
221
+ )
222
+ for p in self.points
223
+ ]
224
+
225
+ # Convert text annotations
226
+ texts = [
227
+ FoxgloveTextAnnotation(
228
+ timestamp=None,
229
+ position=FoxglovePoint2(x=t.position.x, y=t.position.y),
230
+ text=t.text,
231
+ font_size=t.font_size,
232
+ text_color=FoxgloveColor(r=t.text_color.r, g=t.text_color.g, b=t.text_color.b, a=t.text_color.a),
233
+ background_color=FoxgloveColor(
234
+ r=t.background_color.r, g=t.background_color.g, b=t.background_color.b, a=t.background_color.a
235
+ ),
236
+ )
237
+ for t in self.texts
238
+ ]
239
+
240
+ return FoxgloveImageAnnotations(circles=circles, points=points, texts=texts)
common/message/array.py CHANGED
@@ -5,7 +5,7 @@ from typing import Any
5
5
  import numpy as np
6
6
  from pydantic import Field, PrivateAttr, model_validator
7
7
 
8
- from common.message.base import Message
8
+ from common.message.message import Message
9
9
 
10
10
 
11
11
  class Array(Message):
@@ -27,6 +27,30 @@ class Array(Message):
27
27
  cmd = RobotCommand(joint_positions=[0.1, 0.2, 0.3]) # List auto-converts!
28
28
 
29
29
  This makes it seamless to use in APIs without explicit conversion calls.
30
+
31
+ Example:
32
+ ```python
33
+ from common.message import Array
34
+ import numpy as np
35
+
36
+ # Create from list
37
+ arr = Array.from_list([1.0, 2.0, 3.0])
38
+
39
+ # Create from numpy
40
+ np_arr = np.array([0.1, 0.2, 0.3], dtype=np.float32)
41
+ arr = Array.from_numpy(np_arr)
42
+
43
+ # Arithmetic operations
44
+ arr2 = arr * 2.0
45
+ arr3 = arr + arr2
46
+
47
+ # Statistics
48
+ mean = arr.mean()
49
+ magnitude = arr.magnitude()
50
+
51
+ # Convert back to numpy
52
+ result = arr.to_numpy()
53
+ ```
30
54
  """
31
55
 
32
56
  _type = "antioch/array"
common/message/camera.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import numpy as np
2
2
  from pydantic import Field
3
3
 
4
- from common.message.base import Message
4
+ from common.message.message import Message
5
5
 
6
6
 
7
7
  class CameraInfo(Message):
@@ -10,6 +10,28 @@ class CameraInfo(Message):
10
10
 
11
11
  Follows standard camera calibration conventions with support for various
12
12
  distortion models and projection operations.
13
+
14
+ Example:
15
+ ```python
16
+ from common.message import CameraInfo
17
+
18
+ # Create camera info for a 640x480 camera
19
+ camera_info = CameraInfo(
20
+ width=640,
21
+ height=480,
22
+ fx=500.0,
23
+ fy=500.0,
24
+ cx=320.0,
25
+ cy=240.0,
26
+ )
27
+
28
+ # Get the intrinsics matrix
29
+ K = camera_info.intrinsics_matrix
30
+
31
+ # Project a 3D point to pixel coordinates
32
+ point_3d = np.array([0.5, 0.3, 2.0])
33
+ u, v = camera_info.project_point(point_3d)
34
+ ```
13
35
  """
14
36
 
15
37
  _type = "antioch/camera_info"
common/message/color.py CHANGED
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from pydantic import field_validator
3
+ from foxglove.schemas import Color as FoxgloveColor
4
+ from pydantic import Field, field_validator
4
5
 
5
- from common.message.base import Message
6
+ from common.message.message import Message
6
7
 
7
8
 
8
9
  class Color(Message):
@@ -10,13 +11,29 @@ class Color(Message):
10
11
  An RGBA color with values in the range [0.0, 1.0].
11
12
 
12
13
  Used in image annotations and visualization.
14
+
15
+ Example:
16
+ ```python
17
+ from common.message import Color
18
+
19
+ # Create a custom color
20
+ color = Color(r=0.5, g=0.8, b=0.2, a=1.0)
21
+
22
+ # Use factory methods for common colors
23
+ red = Color.red()
24
+ green = Color.green()
25
+ transparent = Color.transparent()
26
+
27
+ # Create with alpha
28
+ semi_transparent = Color.rgba(1.0, 0.0, 0.0, 0.5)
29
+ ```
13
30
  """
14
31
 
15
32
  _type = "antioch/color"
16
- r: float
17
- g: float
18
- b: float
19
- a: float
33
+ r: float = Field(description="Red component [0.0, 1.0]")
34
+ g: float = Field(description="Green component [0.0, 1.0]")
35
+ b: float = Field(description="Blue component [0.0, 1.0]")
36
+ a: float = Field(description="Alpha (opacity) component [0.0, 1.0]")
20
37
 
21
38
  @field_validator("r", "g", "b", "a")
22
39
  @classmethod
@@ -137,3 +154,12 @@ class Color(Message):
137
154
  """
138
155
 
139
156
  return cls(r=0.0, g=0.0, b=0.0, a=0.0)
157
+
158
+ def to_foxglove(self) -> FoxgloveColor:
159
+ """
160
+ Convert to Foxglove Color for telemetry.
161
+
162
+ :return: Foxglove Color schema.
163
+ """
164
+
165
+ return FoxgloveColor(r=self.r, g=self.g, b=self.b, a=self.a)
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import Field
6
+
7
+ from common.message.message import Message
8
+
9
+
10
+ class DetectionDistances(Message):
11
+ """
12
+ Detection distances for Foxglove range-time plotting.
13
+
14
+ In Foxglove Plot panel, use Y = .distances[:] to see detections over time.
15
+
16
+ Example:
17
+ ```python
18
+ from common.message import DetectionDistances
19
+
20
+ # Detections at 3.5m and 4.5m
21
+ detections = DetectionDistances(distances=[3.5, 4.5])
22
+ sim.logger.telemetry("radar/detections/combined", detections)
23
+ ```
24
+ """
25
+
26
+ _type = "antioch/detection_distances"
27
+
28
+ distances: list[float] = Field(
29
+ default_factory=list,
30
+ description="Distances where detections occurred",
31
+ )
32
+
33
+ def to_foxglove(self) -> dict[str, Any]:
34
+ """
35
+ Convert to Foxglove-compatible dict.
36
+
37
+ :return: Dict with distances array.
38
+ """
39
+
40
+ return {"distances": self.distances}
@@ -0,0 +1,20 @@
1
+ from typing import Any, Protocol, runtime_checkable
2
+
3
+
4
+ @runtime_checkable
5
+ class FoxgloveConvertible(Protocol):
6
+ """
7
+ Protocol for messages that can be converted to Foxglove format.
8
+
9
+ Implement this protocol for any message type that has a corresponding Foxglove
10
+ schema. The protocol provides a conversion method that returns the Foxglove type.
11
+ """
12
+
13
+ def to_foxglove(self) -> Any | None:
14
+ """
15
+ Convert this message to its Foxglove representation.
16
+
17
+ :return: The Foxglove schema object, or None if this message should not be published.
18
+ """
19
+
20
+ ...
common/message/frame.py CHANGED
@@ -1,6 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from foxglove.schemas import (
4
+ FrameTransform as FoxgloveFrameTransform,
5
+ FrameTransforms as FoxgloveFrameTransforms,
6
+ Quaternion as FoxgloveQuaternion,
7
+ Vector3 as FoxgloveVector3,
8
+ )
1
9
  from pydantic import Field
2
10
 
3
- from common.message.base import Message
11
+ from common.message.message import Message
4
12
  from common.message.quaternion import Quaternion
5
13
  from common.message.vector import Vector3
6
14
 
@@ -9,10 +17,21 @@ class FrameTransform(Message):
9
17
  """
10
18
  A transform between two reference frames in 3D space.
11
19
 
12
- :param parent_frame_id: Name of the parent frame.
13
- :param child_frame_id: Name of the child frame.
14
- :param translation: Translation component of the transform.
15
- :param rotation: Rotation component of the transform.
20
+ Example:
21
+ ```python
22
+ from common.message import FrameTransform, Vector3, Quaternion
23
+
24
+ # Create a transform from world to robot base
25
+ transform = FrameTransform(
26
+ parent_frame_id="world",
27
+ child_frame_id="robot_base",
28
+ translation=Vector3(x=1.0, y=0.0, z=0.0),
29
+ rotation=Quaternion.identity(),
30
+ )
31
+
32
+ # Create an identity transform
33
+ identity = FrameTransform.identity("parent", "child")
34
+ ```
16
35
  """
17
36
 
18
37
  _type = "antioch/frame_transform"
@@ -22,7 +41,7 @@ class FrameTransform(Message):
22
41
  rotation: Quaternion = Field(description="Rotation component of the transform")
23
42
 
24
43
  @classmethod
25
- def identity(cls, parent_frame_id: str, child_frame_id: str) -> "FrameTransform":
44
+ def identity(cls, parent_frame_id: str, child_frame_id: str) -> FrameTransform:
26
45
  """
27
46
  Create an identity transform between two frames.
28
47
 
@@ -38,13 +57,58 @@ class FrameTransform(Message):
38
57
  rotation=Quaternion.identity(),
39
58
  )
40
59
 
60
+ def to_foxglove(self) -> FoxgloveFrameTransform:
61
+ """
62
+ Convert to Foxglove FrameTransform for telemetry.
63
+
64
+ :return: Foxglove FrameTransform schema.
65
+ """
66
+
67
+ return FoxgloveFrameTransform(
68
+ timestamp=None,
69
+ parent_frame_id=self.parent_frame_id,
70
+ child_frame_id=self.child_frame_id,
71
+ translation=FoxgloveVector3(x=self.translation.x, y=self.translation.y, z=self.translation.z),
72
+ rotation=FoxgloveQuaternion(x=self.rotation.x, y=self.rotation.y, z=self.rotation.z, w=self.rotation.w),
73
+ )
74
+
41
75
 
42
76
  class FrameTransforms(Message):
43
77
  """
44
78
  An array of FrameTransform messages.
45
79
 
46
- :param transforms: Array of transforms.
80
+ Example:
81
+ ```python
82
+ from common.message import FrameTransforms, FrameTransform, Vector3, Quaternion
83
+
84
+ # Create a collection of transforms for a robot
85
+ transforms = FrameTransforms(transforms=[
86
+ FrameTransform(
87
+ parent_frame_id="world",
88
+ child_frame_id="base_link",
89
+ translation=Vector3(x=0.0, y=0.0, z=0.1),
90
+ rotation=Quaternion.identity(),
91
+ ),
92
+ FrameTransform(
93
+ parent_frame_id="base_link",
94
+ child_frame_id="camera",
95
+ translation=Vector3(x=0.5, y=0.0, z=0.3),
96
+ rotation=Quaternion.identity(),
97
+ ),
98
+ ])
99
+ ```
47
100
  """
48
101
 
49
102
  _type = "antioch/frame_transforms"
50
103
  transforms: list[FrameTransform] = Field(default_factory=list, description="Array of transforms")
104
+
105
+ def to_foxglove(self) -> FoxgloveFrameTransforms:
106
+ """
107
+ Convert to Foxglove FrameTransforms for telemetry.
108
+
109
+ :return: Foxglove FrameTransforms schema.
110
+ """
111
+
112
+ return FoxgloveFrameTransforms(
113
+ transforms=[t.to_foxglove() for t in self.transforms],
114
+ )