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.
- antioch/__init__.py +101 -0
- antioch/{module/execution.py → execution.py} +1 -1
- antioch/{module/input.py → input.py} +2 -4
- antioch/{module/module.py → module.py} +17 -34
- antioch/{module/node.py → node.py} +17 -16
- {antioch_py-2.2.4.dist-info → antioch_py-3.0.0.dist-info}/METADATA +8 -11
- antioch_py-3.0.0.dist-info/RECORD +61 -0
- {antioch_py-2.2.4.dist-info → antioch_py-3.0.0.dist-info}/WHEEL +1 -1
- antioch_py-3.0.0.dist-info/licenses/LICENSE +21 -0
- common/ark/__init__.py +6 -16
- common/ark/ark.py +23 -62
- common/ark/hardware.py +1 -1
- common/ark/kinematics.py +1 -1
- common/ark/module.py +22 -0
- common/ark/node.py +46 -3
- common/ark/scheduler.py +2 -29
- common/ark/sim.py +1 -1
- {antioch/module → common/ark}/token.py +17 -0
- common/assets/rigging.usd +0 -0
- common/constants.py +63 -5
- common/core/__init__.py +37 -24
- common/core/auth.py +87 -112
- common/core/container.py +261 -0
- common/core/registry.py +131 -152
- common/core/rome.py +251 -0
- common/core/telemetry.py +176 -0
- common/core/types.py +219 -0
- common/message/__init__.py +19 -5
- common/message/annotation.py +174 -23
- common/message/array.py +25 -1
- common/message/camera.py +23 -1
- common/message/color.py +32 -6
- common/message/detection.py +40 -0
- common/message/foxglove.py +20 -0
- common/message/frame.py +71 -7
- common/message/image.py +58 -9
- common/message/imu.py +24 -4
- common/message/joint.py +69 -10
- common/message/log.py +52 -7
- common/message/pir.py +23 -8
- common/message/plot.py +57 -0
- common/message/point.py +55 -6
- common/message/point_cloud.py +55 -19
- common/message/pose.py +59 -19
- common/message/quaternion.py +105 -92
- common/message/radar.py +195 -29
- common/message/twist.py +34 -0
- common/message/types.py +40 -5
- common/message/vector.py +180 -245
- common/sim/__init__.py +49 -0
- common/{session/config.py → sim/objects.py} +97 -27
- common/sim/state.py +11 -0
- common/utils/comms.py +30 -12
- common/utils/logger.py +26 -7
- antioch/message.py +0 -87
- antioch/module/__init__.py +0 -53
- antioch/session/__init__.py +0 -152
- antioch/session/ark.py +0 -500
- antioch/session/asset.py +0 -65
- antioch/session/error.py +0 -80
- antioch/session/objects/__init__.py +0 -40
- antioch/session/objects/animation.py +0 -162
- antioch/session/objects/articulation.py +0 -180
- antioch/session/objects/basis_curve.py +0 -180
- antioch/session/objects/camera.py +0 -65
- antioch/session/objects/collision.py +0 -46
- antioch/session/objects/geometry.py +0 -58
- antioch/session/objects/ground_plane.py +0 -48
- antioch/session/objects/imu.py +0 -53
- antioch/session/objects/joint.py +0 -49
- antioch/session/objects/light.py +0 -123
- antioch/session/objects/pir_sensor.py +0 -102
- antioch/session/objects/radar.py +0 -62
- antioch/session/objects/rigid_body.py +0 -197
- antioch/session/objects/xform.py +0 -119
- antioch/session/record.py +0 -158
- antioch/session/scene.py +0 -1544
- antioch/session/session.py +0 -211
- antioch/session/task.py +0 -309
- antioch_py-2.2.4.dist-info/RECORD +0 -85
- antioch_py-2.2.4.dist-info/entry_points.txt +0 -2
- common/core/agent.py +0 -324
- common/core/task.py +0 -36
- common/message/velocity.py +0 -11
- common/rome/__init__.py +0 -9
- common/rome/client.py +0 -435
- common/rome/error.py +0 -16
- common/session/__init__.py +0 -31
- common/session/environment.py +0 -31
- common/session/sim.py +0 -129
- common/utils/usd.py +0 -12
- /antioch/{module/clock.py → clock.py} +0 -0
- {antioch_py-2.2.4.dist-info → antioch_py-3.0.0.dist-info}/top_level.txt +0 -0
- /common/message/{base.py → message.py} +0 -0
common/message/__init__.py
CHANGED
|
@@ -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
|
|
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
|
]
|
common/message/annotation.py
CHANGED
|
@@ -2,14 +2,33 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from enum import IntEnum
|
|
4
4
|
|
|
5
|
-
from
|
|
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.
|
|
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.
|
|
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
|
|
3
|
+
from foxglove.schemas import Color as FoxgloveColor
|
|
4
|
+
from pydantic import Field, field_validator
|
|
4
5
|
|
|
5
|
-
from common.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.
|
|
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
|
-
:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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) ->
|
|
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
|
-
:
|
|
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
|
+
)
|