mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-24 18:26:11 +00:00
chore(foxglove depth): make it simple, and make it work.
This commit is contained in:
@@ -186,28 +186,20 @@ def _log_foxglove_image(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Log an image on a cached per-topic channel.
|
"""Log an image on a cached per-topic channel.
|
||||||
|
|
||||||
Encoding is chosen from the frame's channel count and dtype:
|
Frames are cast to ``uint8`` and the encoding is chosen from the channel count: 1 => ``mono8``,
|
||||||
|
3 => ``rgb8`` (float input assumed in [0, 1]), 4 => ``rgba8``; other counts are skipped with a
|
||||||
- Single channel => depth map, logged uncompressed as ``16UC1`` (integer) or ``32FC1`` (float).
|
warning. When ``compress_images`` is set, ``mono8`` and ``rgb8`` are JPEG-encoded instead.
|
||||||
Plain ``uint8`` grayscale (with no ``depth_range``) is the exception and is sent as ``mono8``.
|
|
||||||
- Three channels => ``rgb8``.
|
|
||||||
- Four channels => ``rgba8``.
|
|
||||||
|
|
||||||
When ``compress_images`` is set, ``mono8`` and ``rgb8`` frames are JPEG-encoded instead; depth
|
|
||||||
and ``rgba8`` frames are always sent raw.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
topic: Foxglove topic to log on.
|
topic: Foxglove topic to log on.
|
||||||
frame_id: Frame id stamped on the message.
|
frame_id: Frame id stamped on the message.
|
||||||
arr: Image as HWC or CHW (CHW is transposed to HWC), any dtype. Non-depth floating-point
|
arr: Image as HWC or CHW (CHW is transposed to HWC), any dtype.
|
||||||
images are assumed normalized to [0, 1] and scaled to uint8.
|
compress_images: JPEG-encode ``mono8`` and ``rgb8`` frames; ignored for ``rgba8``.
|
||||||
compress_images: JPEG-encode ``mono8`` and ``rgb8`` frames; ignored for depth and ``rgba8``.
|
|
||||||
channels: Per-topic channel cache to reuse (see :func:`_log_foxglove_scalars`).
|
channels: Per-topic channel cache to reuse (see :func:`_log_foxglove_scalars`).
|
||||||
log_time: Message time in nanoseconds, also written to the header timestamp; when ``None``
|
log_time: Message time in nanoseconds, also written to the header timestamp; when ``None``
|
||||||
the server's receive time is used.
|
the server's receive time is used.
|
||||||
depth_range: ``(lo, hi)`` bounds that normalize depth to ``[0, 1]`` ``32FC1`` so Foxglove's
|
depth_range: ``(lo, hi)`` bounds used to clip a single-channel frame before it is encoded as
|
||||||
default panel scaling matches rerun's ``depth_range`` contrast (a ``RawImage`` carries
|
a regular image.
|
||||||
no value range itself).
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from foxglove.channels import CompressedImageChannel, RawImageChannel
|
from foxglove.channels import CompressedImageChannel, RawImageChannel
|
||||||
@@ -225,39 +217,12 @@ def _log_foxglove_image(
|
|||||||
height, width = arr.shape[0], arr.shape[1]
|
height, width = arr.shape[0], arr.shape[1]
|
||||||
n_channels = 1 if arr.ndim == 2 else arr.shape[2]
|
n_channels = 1 if arr.ndim == 2 else arr.shape[2]
|
||||||
|
|
||||||
# Single-channel => depth, unless it's plain uint8 grayscale (kept as mono8 below). Foxglove
|
# Apply depth range clipping to single channel depth maps.
|
||||||
# renders both 16UC1 (uint16) and 32FC1 (float32) depth with a colormap.
|
if depth_range is not None and n_channels == 1:
|
||||||
if n_channels == 1 and (depth_range is not None or arr.dtype != np.uint8):
|
lo, hi = depth_range
|
||||||
depth = arr if arr.ndim == 2 else arr[..., 0]
|
arr = arr.clip(lo, hi)
|
||||||
if depth_range is not None:
|
|
||||||
lo, hi = depth_range
|
|
||||||
depth = depth.astype(np.float32)
|
|
||||||
depth = np.clip((depth - lo) / (hi - lo), 0.0, 1.0) if hi > lo else np.zeros_like(depth)
|
|
||||||
encoding, step = "32FC1", width * 4
|
|
||||||
elif np.issubdtype(depth.dtype, np.floating):
|
|
||||||
encoding, step = "32FC1", width * 4
|
|
||||||
else:
|
|
||||||
depth = np.clip(np.rint(depth), 0, 65535).astype("<u2")
|
|
||||||
encoding, step = "16UC1", width * 2
|
|
||||||
depth = np.ascontiguousarray(depth, dtype="<f4" if encoding == "32FC1" else "<u2")
|
|
||||||
channel = channels.get(topic)
|
|
||||||
if channel is None:
|
|
||||||
channel = channels[topic] = RawImageChannel(topic=topic)
|
|
||||||
channel.log(
|
|
||||||
RawImage(
|
|
||||||
timestamp=timestamp,
|
|
||||||
frame_id=frame_id,
|
|
||||||
width=width,
|
|
||||||
height=height,
|
|
||||||
encoding=encoding,
|
|
||||||
step=step,
|
|
||||||
data=depth.tobytes(),
|
|
||||||
),
|
|
||||||
**log_kwargs,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
if np.issubdtype(arr.dtype, np.floating):
|
if n_channels == 3 and np.issubdtype(arr.dtype, np.floating):
|
||||||
arr = (arr * 255.0).clip(0, 255)
|
arr = (arr * 255.0).clip(0, 255)
|
||||||
arr = np.ascontiguousarray(arr, dtype=np.uint8)
|
arr = np.ascontiguousarray(arr, dtype=np.uint8)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user