import numpy as np
import pytest
from edgefirst.schemas.builtin_interfaces import Time
from edgefirst.schemas.foxglove_msgs import Color, CompressedVideo, Point2
class TestCompressedVideo:
def test_round_trip(self):
rng = np.random.default_rng(seed=0xC0DEC)
payload = rng.bytes(50_000)
cv = CompressedVideo(
timestamp=Time(sec=1234567890, nanosec=123456789),
frame_id="camera",
data=payload,
format="h264",
)
restored = CompressedVideo.from_cdr(cv.to_bytes())
assert restored.timestamp.sec == 1234567890
assert restored.frame_id == "camera"
assert restored.format == "h264"
assert restored.data.tobytes() == payload
@pytest.mark.parametrize("format", ["h264", "h265", "vp9", "av1"])
def test_format_round_trip(self, format):
cv = CompressedVideo(
timestamp=Time(0, 0),
frame_id="cam",
data=b"\x00\x00\x00\x01", format=format,
)
assert CompressedVideo.from_cdr(cv.to_bytes()).format == format
def test_data_view_zero_copy(self):
payload = bytes(100_000)
cv = CompressedVideo(
timestamp=Time(0, 0), frame_id="cam", data=payload, format="h264"
)
v1 = cv.data.view()
v2 = cv.data.view()
a1 = np.frombuffer(v1, dtype=np.uint8)
a2 = np.frombuffer(v2, dtype=np.uint8)
assert a1.ctypes.data == a2.ctypes.data
class TestPoint2:
def test_round_trip(self):
p = Point2(x=1.5, y=-2.5)
restored = Point2.from_cdr(p.to_bytes())
assert restored.x == 1.5
assert restored.y == -2.5
class TestColor:
def test_round_trip(self):
c = Color(r=1.0, g=0.5, b=0.25, a=1.0)
restored = Color.from_cdr(c.to_bytes())
assert restored.r == 1.0
assert restored.g == 0.5
assert restored.b == 0.25
assert restored.a == 1.0
@pytest.mark.parametrize(
"rgba",
[
(0.0, 0.0, 0.0, 0.0),
(1.0, 1.0, 1.0, 1.0),
(0.123456789, 0.987654321, 0.5, 0.75),
],
)
def test_f64_precision(self, rgba):
c = Color(*rgba)
restored = Color.from_cdr(c.to_bytes())
assert (restored.r, restored.g, restored.b, restored.a) == rgba
from edgefirst.schemas.foxglove_msgs import CircleAnnotations
class TestCircleAnnotations:
def test_round_trip(self):
ca = CircleAnnotations(
timestamp=Time(1, 0),
position=Point2(100.0, 200.0),
diameter=50.0,
thickness=2.0,
fill_color=Color(1.0, 0.0, 0.0, 1.0),
outline_color=Color(0.0, 1.0, 0.0, 1.0),
)
restored = CircleAnnotations.from_cdr(ca.to_bytes())
assert restored.timestamp.sec == 1
assert restored.position.x == 100.0
assert restored.diameter == 50.0
assert restored.fill_color.r == 1.0
def test_defaults(self):
ca = CircleAnnotations()
assert ca.diameter == 0.0
from edgefirst.schemas.foxglove_msgs import TextAnnotation
class TestTextAnnotation:
def test_round_trip(self):
ta = TextAnnotation(
timestamp=Time(1, 0),
position=Point2(10.0, 20.0),
text="Hello, world!",
font_size=14.0,
text_color=Color(1.0, 1.0, 1.0, 1.0),
)
restored = TextAnnotation.from_cdr(ta.to_bytes())
assert restored.text == "Hello, world!"
assert restored.font_size == 14.0
assert restored.timestamp.sec == 1
def test_empty_text(self):
ta = TextAnnotation()
restored = TextAnnotation.from_cdr(ta.to_bytes())
assert restored.text == ""
from edgefirst.schemas.foxglove_msgs import PointAnnotation
class TestPointAnnotation:
def test_round_trip(self):
pa = PointAnnotation(
timestamp=Time(2, 0),
type_=1,
points=[Point2(0.0, 0.0), Point2(100.0, 100.0)],
outline_color=Color(0.0, 1.0, 0.0, 1.0),
thickness=3.0,
)
restored = PointAnnotation.from_cdr(pa.to_bytes())
assert restored.type_ == 1
assert len(restored.points) == 2
assert restored.points[1].x == 100.0
assert restored.thickness == 3.0
from edgefirst.schemas.foxglove_msgs import ImageAnnotation
class TestImageAnnotation:
def test_round_trip_empty(self):
ia = ImageAnnotation()
restored = ImageAnnotation.from_cdr(ia.to_bytes())
assert len(restored.circles) == 0
assert len(restored.points) == 0
assert len(restored.texts) == 0
def test_round_trip_with_annotations(self):
ca = CircleAnnotations(
timestamp=Time(1, 0),
position=Point2(50.0, 50.0),
diameter=20.0,
)
ta = TextAnnotation(
timestamp=Time(1, 0),
text="label",
font_size=12.0,
)
ia = ImageAnnotation(circles=[ca], texts=[ta])
restored = ImageAnnotation.from_cdr(ia.to_bytes())
assert len(restored.circles) == 1
assert restored.circles[0].diameter == 20.0
assert len(restored.texts) == 1
assert restored.texts[0].text == "label"