Skip to main content

Hex Flow Node for Camera (USB, Dummy, RealSense, Berxel)

Project description

HEX FLOW NODE CAMERA

      


📖 Overview

What is hex_flow_node_camera

hex_flow_node_camera provides hex-flow nodes for reading camera streams from USB (V4L2), RealSense, Berxel, and dummy (simulated) cameras. Each node captures frames from the hardware via hex_driver_camera, serializes them into FlatBuffer messages using hex_util_robot, and publishes at the configured rate (default 500 Hz) over Zenoh via hex_flow_core.

What problem it solves

  • Hardware abstraction: Abstracts different camera backends (V4L2 USB, Intel RealSense, Berxel ToF) into structured, rate-controlled image topics over Zenoh.
  • Unified interface: All camera types share the same topic and message schema for color images, making it easy to swap cameras without changing downstream consumer code.
  • Depth support: RealSense and Berxel nodes additionally publish depth streams alongside color, with automatic colormap conversion in test/viewer nodes.
  • Simulation friendly: The dummy camera node generates test pattern frames without any hardware, enabling offline development and integration testing.
  • Flexible deployment: Supports device auto-detection (serial number), topic remapping, and environment variable configuration — no code changes needed for different hardware setups.

Target users

  • Engineers integrating USB cameras (V4L2), Intel RealSense, or Berxel depth cameras into HEXFELLOW robot systems.
  • Researchers requiring synchronized color + depth streams for perception and mapping.
  • Developers building on the hex-flow framework who need a working camera input layer.
  • Teams wanting a simulated camera source for testing vision pipelines offline.

Nodes

Node Description Publishes Subscribes
hex-flow-cam-usb USB V4L2 camera color stream reader color -
hex-flow-cam-dummy Simulated camera (test pattern generator) color -
hex-flow-cam-realsense Intel RealSense color & depth stream reader color, depth -
hex-flow-cam-berxel Berxel ToF color & depth stream reader color, depth -
hex-flow-cam-test-usb OpenCV viewer for USB camera - color
hex-flow-cam-test-dummy OpenCV viewer for dummy camera - color
hex-flow-cam-test-realsense OpenCV viewer for RealSense (color + depth) - color, depth
hex-flow-cam-test-berxel OpenCV viewer for Berxel (color + depth) - color, depth

Prerequisites

USB camera nodes require read/write access to /dev/video*. Ensure your user is in the video group:

sudo usermod -aG video $USER
# Log out and back in for the change to take effect

For RealSense cameras, the librealsense2 runtime must be installed. For Berxel cameras, the vendor SDK must be available (see berxel_py_wrapper documentation).

📦 Installation

Requirements

  • Python >= 3.10
  • OS: Ubuntu (or other Linux)
  • Core dependencies:
    • hex_flow_core >= 0.0.0, < 0.1.0
    • hex_driver_camera >= 0.1.0, < 0.2.0
    • hex_util_msg >= 0.0.0, < 0.1.0
    • hex_util_runtime >= 0.0.0, < 0.1.0
    • hex_util_robot >= 0.0.0, < 0.1.0

Install hex-flow-cli

For Ubuntu or any Debian-based system, install Zenoh and hex-flow CLI:

sudo apt update
sudo apt install -y curl gpg

curl -L https://download.eclipse.org/zenoh/debian-repo/zenoh-public-key | sudo gpg --dearmor --yes --output /etc/apt/keyrings/zenoh-public-key.gpg
echo "deb [signed-by=/etc/apt/keyrings/zenoh-public-key.gpg] https://download.eclipse.org/zenoh/debian-repo/ /" | sudo tee -a /etc/apt/sources.list > /dev/null
sudo apt update
sudo apt install zenoh curl

curl -fsSL https://raw.githubusercontent.com/hexfellow/hex-flow/main/install.sh | sh

For other systems, please install zenohd yourself, then run the install script.

Install hex-flow-node-camera from PyPI

# Base install (USB + Dummy cameras)
pip install hex_flow_node_camera

# With RealSense support
pip install hex_flow_node_camera[realsense]

# With Berxel support
pip install hex_flow_node_camera[berxel]

# With all camera backends
pip install hex_flow_node_camera[all]

Install hex-flow-node-camera from source

We provide a venv.sh script to create a virtual environment with all dependencies installed. However, you need to install uv first. For uv installation, please refer to uv official installation guide.

curl -LsSf https://astral.sh/uv/install.sh | sh

Then you can use our venv.sh to create a virtual environment with all dependencies installed:

git clone https://github.com/hexfellow/hex_flow_node_camera.git
cd hex_flow_node_camera
./venv.sh

📑 Python Config API

The package provides helper functions that return NodeConfig objects for easy integration into your LaunchConfig.

from hex_flow_core import LaunchConfig
from hex_flow_node_camera import (
    default_cam_usb_node,
    default_cam_usb_test_node,
    default_cam_realsense_node,
    default_cam_realsense_test_node,
)

config = LaunchConfig(
    local_only=True,
    enable_tui=True,
    log_to_file=True,
    save_path="/tmp/cam_test.yml",
)

nodes = {
    "cam_usb": default_cam_usb_node(
        name="cam_usb",
        cam_path="/dev/video2",
        width=640,
        height=480,
        frame_rate=30,
        rate_hz=500.0,
        required=True,
        remap_dict={"color": "cam_usb/color"},
    ),
    "test_cam_usb": default_cam_usb_test_node(
        name="test_cam_usb",
        rate_hz=30.0,
        required=False,
        remap_dict={"color": "cam_usb/color"},
    ),
}

config.set_nodes(nodes)
print(config.export())

default_cam_usb_node

Parameter Type Default Description
name str "cam_usb" Node name and remap prefix
frame_rate int 30 Camera sensor frame rate
height int 480 Image height in pixels
width int 640 Image width in pixels
cam_buffer_size int 8 Internal camera driver buffer size
sens_ts bool True Use sensor timestamp when available
cam_path str "/dev/video0" V4L2 device path
exposure int 100 Exposure value
temperature int 4000 White balance temperature
color_encoding str "bgr8" Color image encoding (e.g. "bgr8", "rgb8")
rate_hz float 500.0 Publishing rate in Hz
required bool True Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {name}/color

default_cam_usb_test_node

Parameter Type Default Description
name str "test_cam_usb" Node name
rate_hz float 30.0 Display refresh rate in Hz
required bool False Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {cam_name}/color
cam_name str "cam_usb" Camera node to subscribe to

default_cam_dummy_node

Parameter Type Default Description
name str "cam_dummy" Node name and remap prefix
frame_rate int 30 Camera sensor frame rate
height int 480 Image height in pixels
width int 640 Image width in pixels
cam_buffer_size int 8 Internal camera driver buffer size
sens_ts bool True Use sensor timestamp when available
color_encoding str "bgr8" Color image encoding
rate_hz float 500.0 Publishing rate in Hz
required bool True Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {name}/color

default_cam_dummy_test_node

Parameter Type Default Description
name str "test_cam_dummy" Node name
rate_hz float 30.0 Display refresh rate in Hz
show_color_ts bool False Overlay timestamp text on the displayed image
required bool False Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {cam_name}/color
cam_name str "cam_dummy" Camera node to subscribe to

default_cam_realsense_node

Parameter Type Default Description
name str "cam_realsense" Node name and remap prefix
frame_rate int 30 Camera sensor frame rate
height int 480 Image height in pixels
width int 640 Image width in pixels
cam_buffer_size int 8 Internal camera driver buffer size
sens_ts bool True Use sensor timestamp when available
serial_number str "b0" RealSense device serial number
color_encoding str "bgr8" Color image encoding
depth_encoding str "mono16" Depth image encoding
rate_hz float 500.0 Publishing rate in Hz
required bool True Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {name}/color, {name}/depth

default_cam_realsense_test_node

Parameter Type Default Description
name str "test_cam_realsense" Node name
rate_hz float 30.0 Display refresh rate in Hz
required bool False Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {cam_name}/color, {cam_name}/depth
cam_name str "cam_realsense" Camera node to subscribe to

default_cam_berxel_node

Parameter Type Default Description
name str "cam_berxel" Node name and remap prefix
frame_rate int 30 Camera sensor frame rate
height int 400 Image height in pixels
width int 640 Image width in pixels
cam_buffer_size int 8 Internal camera driver buffer size
sens_ts bool True Use sensor timestamp when available
serial_number str "b0" Berxel device serial number
exposure int 10000 Exposure value
gain int 100 Gain value
color_encoding str "bgr8" Color image encoding
depth_encoding str "mono16" Depth image encoding
rate_hz float 500.0 Publishing rate in Hz
required bool True Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {name}/color, {name}/depth

default_cam_berxel_test_node

Parameter Type Default Description
name str "test_cam_berxel" Node name
rate_hz float 30.0 Display refresh rate in Hz
required bool False Required for launch
hidden bool False Hidden from TUI
remap_dict dict None Custom remap; defaults to {cam_name}/color, {cam_name}/depth
cam_name str "cam_berxel" Camera node to subscribe to

💡 Examples

Ready-to-run config scripts are provided in the example/ directory. Each script prints a launch YAML to stdout, intended for use with hexflow run:

USB Camera

# /dev/video2, 640x480, 30 FPS sensor, 500 Hz publish, 30 Hz test display
hexflow run example/usb_test.launch.py

Dummy Camera (simulated)

# No hardware needed, generates test patterns
hexflow run example/dummy_test.launch.py

RealSense

# Color + depth, 500 Hz publish, 30 Hz test display
hexflow run example/realsense_test.launch.py

Berxel

# Color + depth, 500 Hz publish, 30 Hz test display
hexflow run example/berxel_test.launch.py

YAML Examples

USB Camera (500 Hz)

nodes:
  - name: cam_usb
    build: pip install hex_flow_node_camera
    run: hex-flow-cam-usb
    required: true
    remap:
      color: cam_usb/color
    env:
      FRAME_RATE: "30"
      HEIGHT: "480"
      WIDTH: "640"
      CAM_BUFFER_SIZE: "8"
      SEN_TS: "True"
      CAM_PATH: "/dev/video2"
      EXPOSURE: "100"
      TEMPERATURE: "4000"
      COLOR_ENCODING: "bgr8"
      RATE_HZ: "500"

  - name: test_cam_usb
    build: pip install hex_flow_node_camera
    run: hex-flow-cam-test-usb
    required: false
    remap:
      color: cam_usb/color
    env:
      RATE_HZ: "30"

Dummy Camera (500 Hz)

nodes:
  - name: cam_dummy
    build: pip install hex_flow_node_camera
    run: hex-flow-cam-dummy
    required: true
    remap:
      color: cam_dummy/color
    env:
      FRAME_RATE: "30"
      HEIGHT: "480"
      WIDTH: "640"
      CAM_BUFFER_SIZE: "8"
      SEN_TS: "True"
      COLOR_ENCODING: "bgr8"
      RATE_HZ: "500"

  - name: test_cam_dummy
    build: pip install hex_flow_node_camera
    run: hex-flow-cam-test-dummy
    required: false
    remap:
      color: cam_dummy/color
    env:
      RATE_HZ: "30"
      SHOW_COLOR_TS: "False"

RealSense (500 Hz)

nodes:
  - name: cam_realsense
    build: pip install hex_flow_node_camera[realsense]
    run: hex-flow-cam-realsense
    required: true
    remap:
      color: cam_realsense/color
      depth: cam_realsense/depth
    env:
      FRAME_RATE: "30"
      HEIGHT: "480"
      WIDTH: "640"
      CAM_BUFFER_SIZE: "8"
      SEN_TS: "True"
      SERIAL_NUMBER: "0"
      COLOR_ENCODING: "bgr8"
      DEPTH_ENCODING: "mono16"
      RATE_HZ: "500"

  - name: test_cam_realsense
    build: pip install hex_flow_node_camera
    run: hex-flow-cam-test-realsense
    required: false
    remap:
      color: cam_realsense/color
      depth: cam_realsense/depth
    env:
      RATE_HZ: "30"

Berxel (500 Hz)

nodes:
  - name: cam_berxel
    build: pip install hex_flow_node_camera[berxel]
    run: hex-flow-cam-berxel
    required: true
    remap:
      color: cam_berxel/color
      depth: cam_berxel/depth
    env:
      FRAME_RATE: "30"
      HEIGHT: "400"
      WIDTH: "640"
      CAM_BUFFER_SIZE: "8"
      SEN_TS: "True"
      SERIAL_NUMBER: "b0"
      EXPOSURE: "10000"
      GAIN: "100"
      COLOR_ENCODING: "bgr8"
      DEPTH_ENCODING: "mono16"
      RATE_HZ: "500"

  - name: test_cam_berxel
    build: pip install hex_flow_node_camera
    run: hex-flow-cam-test-berxel
    required: false
    remap:
      color: cam_berxel/color
      depth: cam_berxel/depth
    env:
      RATE_HZ: "30"

Message Types (FlatBuffer)

All topics use FlatBuffer messages from hex_util_msg.

colorHexCamColor

Field Type Description
ts_ns int64 Timestamp in nanoseconds
data [uint8] Raw image data (encoded per encoding)
height int32 Image height in pixels
width int32 Image width in pixels
encoding string Image encoding string (e.g. "bgr8")

Schema: msgs/msg_cam/color_image.fbs

depthHexCamDepth

Field Type Description
ts_ns int64 Timestamp in nanoseconds
data [uint8] Raw depth image data
height int32 Depth image height in pixels
width int32 Depth image width in pixels
encoding string Depth encoding string (e.g. "mono16")

Schema: msgs/msg_cam/depth_image.fbs

Environment Variables

All Nodes

Variable Type Default Description
HEX_FLOW_NODE_NAME str constructor arg Overrides node name (handled by hex_flow_core)
HEX_FLOW_REMAP str {} JSON dict for topic remapping (handled by hex_flow_core)
RUST_LOG str info Log level for envlog

Camera Nodes (USB / Dummy / RealSense / Berxel)

Variable Type Default Description
FRAME_RATE int 30 Camera sensor frame rate
HEIGHT int 480 (Berxel: 400) Image height in pixels
WIDTH int 640 Image width in pixels
CAM_BUFFER_SIZE int 8 Internal camera driver buffer size
SEN_TS bool True Use sensor timestamp when available
COLOR_ENCODING str "bgr8" Color image encoding
RATE_HZ float 500.0 Publishing rate in Hz

USB-specific

Variable Type Default Description
CAM_PATH str "/dev/video0" V4L2 device path
EXPOSURE int 100 Exposure value
TEMPERATURE int 4000 White balance temperature

RealSense-specific

Variable Type Default Description
SERIAL_NUMBER str "0" RealSense device serial number
DEPTH_ENCODING str "mono16" Depth image encoding

Berxel-specific

Variable Type Default Description
SERIAL_NUMBER str "b0" Berxel device serial number
EXPOSURE int 10000 Exposure value
GAIN int 100 Gain value
DEPTH_ENCODING str "mono16" Depth image encoding

Test Nodes

Variable Type Default Description
RATE_HZ float 30.0 Display refresh rate in Hz
SHOW_COLOR_TS bool False Overlay timestamp on image (dummy only)

Architecture

All camera nodes follow the same pattern:

  1. Camera initialization — creates a camera driver instance (HexCamUsbCallback, HexCamDummyCallback, HexCamRealsenseCallback, or HexCamBerxelCallback) from hex_driver_camera, configured with params such as resolution, frame rate, and device path/serial number.

  2. Callback registration — user-provided callback functions are registered with the driver. Each callback receives a state dict {"ts_ns": int, "data": numpy.ndarray} when a new frame arrives from the camera hardware.

  3. FlatBuffer serialization — within each callback, the frame data and timestamp are serialized into a FlatBuffer message (HexCamColor or HexCamDepth) using helpers from hex_util_robot (build_color_msg(), build_depth_msg()). The binary payload is then published via hex_flow_core.Node.pub().

  4. Rate-controlled publish loop — using HexRate from hex_util_runtime, the node publishes at the configured rate (default 500 Hz) while the camera driver's capture thread feeds frames asynchronously into the callbacks.

Test nodes subscribe via hex_flow_core.Node.create_sub() and poll with Node.get(topic, latest=True) at a lower rate (default 30 Hz), deserializing the FlatBuffer and displaying frames with OpenCV (cv2.imshow()). For depth-capable cameras (RealSense, Berxel), test nodes also display a color-mapped depth visualization using depth_to_cmap().

This architecture decouples the variable-rate hardware frame capture from the fixed-rate publish output, ensuring consistent state updates regardless of actual camera frame rate.

📄 License

Apache License 2.0. See LICENSE.

🌟 Star History

Star History Chart

👥 Contributors

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hex_flow_node_camera-0.0.1.tar.gz (20.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hex_flow_node_camera-0.0.1-py3-none-any.whl (21.5 kB view details)

Uploaded Python 3

File details

Details for the file hex_flow_node_camera-0.0.1.tar.gz.

File metadata

  • Download URL: hex_flow_node_camera-0.0.1.tar.gz
  • Upload date:
  • Size: 20.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for hex_flow_node_camera-0.0.1.tar.gz
Algorithm Hash digest
SHA256 eee88d33c7f6ecd79e1f9e18d6dd353903b7045e6b01ca3b8654abdce5d709cb
MD5 d001875195fe6b62576adc86ff1da414
BLAKE2b-256 19bc7c33b00841def93ca0d4c3c801277123b7f324df2875f636f9cbb9a0c9c4

See more details on using hashes here.

File details

Details for the file hex_flow_node_camera-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for hex_flow_node_camera-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 92a60f8f5706ceb557d0872468d48e311ecf89ea013af7fd6288595c3a9a782f
MD5 21067f2bf4ee530d05de03ea1f8157f1
BLAKE2b-256 c4aded2b6a3d5013bdf95eee663131fc695eafd0d700f56818f393bf1457f53e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page