foxglove-sdk 0.6.2__cp312-cp312-win32.whl → 0.16.6__cp312-cp312-win32.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.
Binary file
@@ -1,161 +1,160 @@
1
- import json
2
- import math
3
- import os
4
- import struct
5
- import time
6
- from pathlib import Path
7
- from typing import Generator, List
8
-
9
- import foxglove
10
- import pytest
11
- from foxglove.channel import Channel
12
- from foxglove.channels import PointCloudChannel, SceneUpdateChannel
13
- from foxglove.schemas import (
14
- Color,
15
- CubePrimitive,
16
- Duration,
17
- PackedElementField,
18
- PackedElementFieldNumericType,
19
- PointCloud,
20
- Pose,
21
- Quaternion,
22
- SceneEntity,
23
- SceneUpdate,
24
- Vector3,
25
- )
26
- from pytest_benchmark.fixture import BenchmarkFixture # type: ignore
27
-
28
-
29
- @pytest.fixture
30
- def tmp_mcap(tmpdir: os.PathLike[str]) -> Generator[Path, None, None]:
31
- dir = Path(tmpdir)
32
- mcap = dir / "test.mcap"
33
- yield mcap
34
- mcap.unlink()
35
- dir.rmdir()
36
-
37
-
38
- def build_entities(entity_count: int) -> List[SceneEntity]:
39
- assert entity_count > 0
40
- return [
41
- SceneEntity(
42
- id=f"box_{i}",
43
- frame_id="box",
44
- lifetime=Duration(10, nsec=int(100 * 1e6)),
45
- cubes=[
46
- CubePrimitive(
47
- pose=Pose(
48
- position=Vector3(x=0.0, y=0.0, z=3.0),
49
- orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0),
50
- ),
51
- size=Vector3(x=1.0, y=1.0, z=1.0),
52
- color=Color(r=1.0, g=0.0, b=0.0, a=1.0),
53
- )
54
- ],
55
- )
56
- for i in range(entity_count)
57
- ]
58
-
59
-
60
- def write_scene_entity_mcap(
61
- tmp_mcap: Path, channel: SceneUpdateChannel, entities: List[SceneEntity]
62
- ) -> None:
63
- with foxglove.open_mcap(tmp_mcap, allow_overwrite=True):
64
- for _ in range(100):
65
- channel.log(SceneUpdate(entities=entities))
66
-
67
-
68
- def make_point_cloud(point_count: int) -> PointCloud:
69
- """
70
- https://foxglove.dev/blog/visualizing-point-clouds-with-custom-colors
71
- """
72
- point_struct = struct.Struct("<fffBBBB")
73
- f32 = PackedElementFieldNumericType.Float32
74
- u32 = PackedElementFieldNumericType.Uint32
75
-
76
- t = time.time()
77
- count = math.ceil(math.sqrt(point_count))
78
- points = [
79
- (x + math.cos(t + y / 5), y, 0) for x in range(count) for y in range(count)
80
- ]
81
-
82
- buffer = bytearray(point_struct.size * len(points))
83
- for i, point in enumerate(points):
84
- x, y, z = point
85
- r = g = b = a = 128
86
- point_struct.pack_into(buffer, i * point_struct.size, x, y, z, b, g, r, a)
87
-
88
- return PointCloud(
89
- frame_id="points",
90
- pose=Pose(
91
- position=Vector3(x=0, y=0, z=0),
92
- orientation=Quaternion(x=0, y=0, z=0, w=1),
93
- ),
94
- point_stride=16, # 4 fields * 4 bytes
95
- fields=[
96
- PackedElementField(name="x", offset=0, type=f32),
97
- PackedElementField(name="y", offset=4, type=f32),
98
- PackedElementField(name="z", offset=8, type=f32),
99
- PackedElementField(name="rgba", offset=12, type=u32),
100
- ],
101
- data=bytes(buffer),
102
- )
103
-
104
-
105
- def write_point_cloud_mcap(
106
- tmp_mcap: Path, channel: PointCloudChannel, point_cloud: PointCloud
107
- ) -> None:
108
- with foxglove.open_mcap(tmp_mcap, allow_overwrite=True):
109
- for _ in range(10):
110
- channel.log(point_cloud)
111
-
112
-
113
- def write_untyped_channel_mcap(
114
- tmp_mcap: Path, channel: Channel, messages: List[bytes]
115
- ) -> None:
116
- with foxglove.open_mcap(tmp_mcap, allow_overwrite=True):
117
- for message in messages:
118
- channel.log(message)
119
-
120
-
121
- @pytest.mark.benchmark
122
- @pytest.mark.parametrize("entity_count", [1, 2, 4, 8])
123
- def test_write_scene_update_mcap(
124
- benchmark: BenchmarkFixture,
125
- entity_count: int,
126
- tmp_mcap: Path,
127
- ) -> None:
128
- channel = SceneUpdateChannel(f"/scene_{entity_count}")
129
- entities = build_entities(entity_count)
130
- benchmark(write_scene_entity_mcap, tmp_mcap, channel, entities)
131
-
132
-
133
- @pytest.mark.benchmark
134
- @pytest.mark.parametrize("point_count", [100, 1000, 10000])
135
- def test_write_point_cloud_mcap(
136
- benchmark: BenchmarkFixture,
137
- point_count: int,
138
- tmp_mcap: Path,
139
- ) -> None:
140
- print("test_write_point_cloud_mcap")
141
- channel = PointCloudChannel(f"/point_cloud_{point_count}")
142
- point_cloud = make_point_cloud(point_count)
143
- benchmark(write_point_cloud_mcap, tmp_mcap, channel, point_cloud)
144
-
145
-
146
- @pytest.mark.benchmark
147
- @pytest.mark.parametrize("message_count", [10, 100, 1000])
148
- def test_write_untyped_channel_mcap(
149
- benchmark: BenchmarkFixture,
150
- message_count: int,
151
- tmp_mcap: Path,
152
- ) -> None:
153
- channel = Channel(
154
- f"/untyped_{message_count}",
155
- schema={"type": "object", "additionalProperties": True},
156
- )
157
- messages = [
158
- json.dumps({"message": f"hello_{i}"}).encode("utf-8")
159
- for i in range(message_count)
160
- ]
161
- benchmark(write_untyped_channel_mcap, tmp_mcap, channel, messages)
1
+ import json
2
+ import math
3
+ import os
4
+ import struct
5
+ import time
6
+ from pathlib import Path
7
+ from typing import Generator, List
8
+
9
+ import pytest
10
+ from foxglove import Channel, open_mcap
11
+ from foxglove.channels import PointCloudChannel, SceneUpdateChannel
12
+ from foxglove.schemas import (
13
+ Color,
14
+ CubePrimitive,
15
+ Duration,
16
+ PackedElementField,
17
+ PackedElementFieldNumericType,
18
+ PointCloud,
19
+ Pose,
20
+ Quaternion,
21
+ SceneEntity,
22
+ SceneUpdate,
23
+ Vector3,
24
+ )
25
+ from pytest_benchmark.fixture import BenchmarkFixture # type: ignore
26
+
27
+
28
+ @pytest.fixture
29
+ def tmp_mcap(tmpdir: os.PathLike[str]) -> Generator[Path, None, None]:
30
+ dir = Path(tmpdir)
31
+ mcap = dir / "test.mcap"
32
+ yield mcap
33
+ mcap.unlink()
34
+ dir.rmdir()
35
+
36
+
37
+ def build_entities(entity_count: int) -> List[SceneEntity]:
38
+ assert entity_count > 0
39
+ return [
40
+ SceneEntity(
41
+ id=f"box_{i}",
42
+ frame_id="box",
43
+ lifetime=Duration(10, nsec=int(100 * 1e6)),
44
+ cubes=[
45
+ CubePrimitive(
46
+ pose=Pose(
47
+ position=Vector3(x=0.0, y=0.0, z=3.0),
48
+ orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0),
49
+ ),
50
+ size=Vector3(x=1.0, y=1.0, z=1.0),
51
+ color=Color(r=1.0, g=0.0, b=0.0, a=1.0),
52
+ )
53
+ ],
54
+ )
55
+ for i in range(entity_count)
56
+ ]
57
+
58
+
59
+ def write_scene_entity_mcap(
60
+ tmp_mcap: Path, channel: SceneUpdateChannel, entities: List[SceneEntity]
61
+ ) -> None:
62
+ with open_mcap(tmp_mcap, allow_overwrite=True):
63
+ for _ in range(100):
64
+ channel.log(SceneUpdate(entities=entities))
65
+
66
+
67
+ def make_point_cloud(point_count: int) -> PointCloud:
68
+ """
69
+ https://foxglove.dev/blog/visualizing-point-clouds-with-custom-colors
70
+ """
71
+ point_struct = struct.Struct("<fffBBBB")
72
+ f32 = PackedElementFieldNumericType.Float32
73
+ u32 = PackedElementFieldNumericType.Uint32
74
+
75
+ t = time.time()
76
+ count = math.ceil(math.sqrt(point_count))
77
+ points = [
78
+ (x + math.cos(t + y / 5), y, 0) for x in range(count) for y in range(count)
79
+ ]
80
+
81
+ buffer = bytearray(point_struct.size * len(points))
82
+ for i, point in enumerate(points):
83
+ x, y, z = point
84
+ r = g = b = a = 128
85
+ point_struct.pack_into(buffer, i * point_struct.size, x, y, z, b, g, r, a)
86
+
87
+ return PointCloud(
88
+ frame_id="points",
89
+ pose=Pose(
90
+ position=Vector3(x=0, y=0, z=0),
91
+ orientation=Quaternion(x=0, y=0, z=0, w=1),
92
+ ),
93
+ point_stride=16, # 4 fields * 4 bytes
94
+ fields=[
95
+ PackedElementField(name="x", offset=0, type=f32),
96
+ PackedElementField(name="y", offset=4, type=f32),
97
+ PackedElementField(name="z", offset=8, type=f32),
98
+ PackedElementField(name="rgba", offset=12, type=u32),
99
+ ],
100
+ data=bytes(buffer),
101
+ )
102
+
103
+
104
+ def write_point_cloud_mcap(
105
+ tmp_mcap: Path, channel: PointCloudChannel, point_cloud: PointCloud
106
+ ) -> None:
107
+ with open_mcap(tmp_mcap, allow_overwrite=True):
108
+ for _ in range(10):
109
+ channel.log(point_cloud)
110
+
111
+
112
+ def write_untyped_channel_mcap(
113
+ tmp_mcap: Path, channel: Channel, messages: List[bytes]
114
+ ) -> None:
115
+ with open_mcap(tmp_mcap, allow_overwrite=True):
116
+ for message in messages:
117
+ channel.log(message)
118
+
119
+
120
+ @pytest.mark.benchmark
121
+ @pytest.mark.parametrize("entity_count", [1, 2, 4, 8])
122
+ def test_write_scene_update_mcap(
123
+ benchmark: BenchmarkFixture,
124
+ entity_count: int,
125
+ tmp_mcap: Path,
126
+ ) -> None:
127
+ channel = SceneUpdateChannel(f"/scene_{entity_count}")
128
+ entities = build_entities(entity_count)
129
+ benchmark(write_scene_entity_mcap, tmp_mcap, channel, entities)
130
+
131
+
132
+ @pytest.mark.benchmark
133
+ @pytest.mark.parametrize("point_count", [100, 1000, 10000])
134
+ def test_write_point_cloud_mcap(
135
+ benchmark: BenchmarkFixture,
136
+ point_count: int,
137
+ tmp_mcap: Path,
138
+ ) -> None:
139
+ print("test_write_point_cloud_mcap")
140
+ channel = PointCloudChannel(f"/point_cloud_{point_count}")
141
+ point_cloud = make_point_cloud(point_count)
142
+ benchmark(write_point_cloud_mcap, tmp_mcap, channel, point_cloud)
143
+
144
+
145
+ @pytest.mark.benchmark
146
+ @pytest.mark.parametrize("message_count", [10, 100, 1000])
147
+ def test_write_untyped_channel_mcap(
148
+ benchmark: BenchmarkFixture,
149
+ message_count: int,
150
+ tmp_mcap: Path,
151
+ ) -> None:
152
+ channel = Channel(
153
+ f"/untyped_{message_count}",
154
+ schema={"type": "object", "additionalProperties": True},
155
+ )
156
+ messages = [
157
+ json.dumps({"message": f"hello_{i}"}).encode("utf-8")
158
+ for i in range(message_count)
159
+ ]
160
+ benchmark(write_untyped_channel_mcap, tmp_mcap, channel, messages)