Skip to main content

Hex Flow Node for Data Recording and Replaying

Project description

HEX FLOW NODE DATA

      


📖 Overview

What is hex_flow_node_data

hex_flow_node_data provides hex-flow nodes for recording and replaying robot data. It currently supports two operations: recording — subscribing to robot state, camera color, and camera depth topics, and writing them to Foxglove MCAP files via hex_util_data; and replay — reading MCAP files and publishing recorded data back onto the network. The record node is toggle-controlled by a boolean message on the record topic, enabling episode-based data collection.

What problem it solves

  • Episode-based data collection: Supports multiple recording episodes, each written as a separate episode_NNNNNN.mcap file, making it easy to organize training data for imitation learning or model-based RL.
  • Dynamic topic discovery: Automatically classifies topics by suffix (*state, *color, *depth) from the HEX_FLOW_REMAP JSON configuration, so the same binary works with any robot configuration — no code changes needed.
  • Foxglove-native format: Writes MCAP files compatible with Foxglove Studio for visualization and analysis.
  • Flexible recording control: Start/stop recording via a dedicated record topic; integrates with keyboard teleoperation or any other trigger source.
  • Integrated testing: Ships with a test node that publishes predefined control commands and toggles recording on the S key — no additional tools needed.
  • Simulation & real-robot support: Example launch configurations demonstrate integration with both MuJoCo simulation and real Archer Y6 robots with cameras.

Target users

  • Engineers collecting demonstration data from HEXFELLOW robot systems for imitation learning or behavior cloning.
  • Researchers running data acquisition pipelines (teleoperation → recording) before training policies.
  • Developers building on the hex-flow framework who need a working data recording and replay layer.

Nodes

Node Description Publishes Subscribes
hex-flow-data-record Records robot state and camera data to MCAP {side}_arm_state, {side}_grip_state, obj_pose, {cam}_color, {cam}_depth, record
hex-flow-data-record-test Terminal-based test control for recording {side}_arm_ctrl, {side}_grip_ctrl, record keys
hex-flow-data-replay Replays MCAP data back onto the network {side}_arm_state, {side}_grip_state, obj_pose, {cam}_color, {cam}_depth

📦 Installation

Requirements

  • Python >= 3.10
  • OS: Ubuntu (or other Linux)
  • Core dependencies:
    • hex_flow_core >= 0.0.0, < 0.1.0
    • hex_util_data >= 0.0.0, < 0.1.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-data from PyPI

pip install hex_flow_node_data

Install hex-flow-node-data 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 venv.sh to create a virtual environment with all dependencies installed:

git clone https://github.com/hexfellow/hex_flow_node_data.git
cd hex_flow_node_data
./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_data import (
    default_data_record_node,
    default_data_record_test_node,
    default_data_replay_node,
)

default_data_record_node

Parameter Type Default Description
name str "data_record" Node name
record_path str "./hex_record_data" Directory path for MCAP file output
foxglove_host str "127.0.0.1" Foxglove WebSocket server host
foxglove_port int 8765 Foxglove WebSocket server port
start_cnt int 0 Starting episode count for file naming
required bool True Required for launch
hidden bool False Hidden from TUI display
remap_dict dict None Custom remap; auto-generated if None
sensor_source str "mujoco_e3_desktop" Sensor node name for auto-remap topic prefix

default_data_record_test_node

Parameter Type Default Description
name str "data_record_test" Node name
rate_hz float 10.0 Control command publish rate (Hz)
arm_ctrl_mode str "pos" Arm control mode ("mit", "pos")
grip_ctrl_mode str "pos" Gripper control mode ("mit", "pos")
required bool False Required for launch
hidden bool False Hidden from TUI display
remap_dict dict None Custom remap; auto-generated if None
sensor_source str "mujoco_e3_desktop" Sensor node name for auto-remap of control topics
keys_source str "teleop_keyboard" Keyboard node name for auto-remap of keys topic

default_data_replay_node

Parameter Type Default Description
name str "data_replay" Node name
mcap_path str "~/hex_record_data" Path to MCAP file or directory
enable_color bool False Enable color image replay
enable_depth bool False Enable depth image replay
color_encoding str "bgr8" Color image encoding
depth_encoding str "mono16" Depth image encoding
rate_hz float 500.0 Replay publish rate (Hz)
state_topics list ["left_arm_state", "right_arm_state", "left_grip_state", "right_grip_state", "obj_pose"] State topic names to replay
color_topics list ["head_color"] Color image topic names to replay
depth_topics list ["head_depth"] Depth image topic names to replay
required bool True Required for launch
hidden bool False Hidden from TUI display
remap_dict dict None Custom remap; auto-generated if None

💡 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:

Simulation-based recording (E3 Desktop)

# Records robot state and camera data from a simulated E3 Desktop
# Toggle recording with the S key (keyboard teleoperation)
hexflow run example/sim_record_test.launch.py

Real-robot recording (Dual Archer Y6)

# Records robot state and camera data from real Archer Y6 arms
# with Berxel depth camera and USB cameras
hexflow run example/real_record_test.launch.py

YAML Examples

Simulated recording (E3 Desktop)

nodes:
  - name: data_record
    build: pip install hex_flow_node_data
    run: hex-flow-data-record
    required: false
    hidden: true
    remap:
      left_arm_state: mujoco_e3_desktop/left_arm_state
      right_arm_state: mujoco_e3_desktop/right_arm_state
      left_grip_state: mujoco_e3_desktop/left_grip_state
      right_grip_state: mujoco_e3_desktop/right_grip_state
      head_color: mujoco_e3_desktop/head_color
      left_color: mujoco_e3_desktop/left_color
      right_color: mujoco_e3_desktop/right_color
      head_depth: mujoco_e3_desktop/head_depth
      left_depth: mujoco_e3_desktop/left_depth
      right_depth: mujoco_e3_desktop/right_depth
      record: data_record_test/record
    env:
      RECORD_PATH: "./record_data"
      FOXGLOVE_HOST: "127.0.0.1"
      FOXGLOVE_PORT: "8765"
      START_CNT: "0"

  - name: data_record_test
    build: pip install hex_flow_node_data
    run: hex-flow-data-record-test
    required: true
    hidden: true
    remap:
      left_arm_ctrl: mujoco_e3_desktop/left_arm_ctrl
      right_arm_ctrl: mujoco_e3_desktop/right_arm_ctrl
      left_grip_ctrl: mujoco_e3_desktop/left_grip_ctrl
      right_grip_ctrl: mujoco_e3_desktop/right_grip_ctrl
      record: data_record_test/record
      keys: teleop_keyboard/teleop_keyboard
    env:
      RATE_HZ: "100"
      ARM_CTRL_MODE: "pos"
      GRIP_CTRL_MODE: "pos"

Real-robot recording (Dual Archer Y6)

nodes:
  - name: data_record
    build: pip install hex_flow_node_data
    run: hex-flow-data-record
    required: false
    hidden: true
    remap:
      left_arm_state: left_archer_y6/arm_state
      right_arm_state: right_archer_y6/arm_state
      left_grip_state: left_archer_y6/grip_state
      right_grip_state: right_archer_y6/grip_state
      head_color: head_berxel/color
      head_depth: head_berxel/depth
      left_color: left_cam_usb/color
      record: data_record_test/record
    env:
      RECORD_PATH: "./record_data"
      FOXGLOVE_HOST: "127.0.0.1"
      FOXGLOVE_PORT: "8765"
      START_CNT: "0"

  - name: data_record_test
    build: pip install hex_flow_node_data
    run: hex-flow-data-record-test
    required: true
    hidden: true
    remap:
      left_arm_ctrl: left_archer_y6/arm_ctrl
      right_arm_ctrl: right_archer_y6/arm_ctrl
      left_grip_ctrl: left_archer_y6/grip_ctrl
      right_grip_ctrl: right_archer_y6/grip_ctrl
      record: data_record_test/record
      keys: teleop_keyboard/teleop_keyboard
    env:
      RATE_HZ: "100"
      ARM_CTRL_MODE: "pos"
      GRIP_CTRL_MODE: "pos"

Topics

Record Node — Subscribed Topics

The record node discovers topics dynamically from the HEX_FLOW_REMAP JSON env var, classifying by suffix:

Suffix Message Type Description
*state HexArmState / HexGripState / HexPoseState Robot joint/pose state
*color HexImgSimple (encoding bgr8) Color camera frames
*depth HexImgSimple (encoding mono16) Depth camera frames
record raw bytes (1-byte boolean) Start/stop recording (non-zero = start)

State topics — HexArmState

Field Type Description
ts_ns int64 Timestamp in nanoseconds
jnt_pos [float64] Joint position array
jnt_vel [float64] Joint velocity array
jnt_eff [float64] Joint effort/torque array
pose_pos [float64] End-effector position (x, y, z)
pose_quat [float64] End-effector orientation (w, x, y, z)

Schema: msgs/msg_robot/arm_state.fbs

State topics — HexGripState

Field Type Description
ts_ns int64 Timestamp in nanoseconds
jnt_pos [float64] Gripper joint position
jnt_vel [float64] Gripper joint velocity
jnt_eff [float64] Gripper joint effort

Schema: msgs/msg_robot/grip_state.fbs

State topics — HexPoseState

Field Type Description
ts_ns int64 Timestamp in nanoseconds
pose_pos [float64] Object position (x, y, z)
pose_quat [float64] Object orientation (w, x, y, z)

Schema: msgs/msg_robot/pose_state.fbs

Camera topics — HexImgSimple

Field Type Description
ts_ns int64 Timestamp in nanoseconds
encoding HexImgEncoding Image encoding (bgr8 or mono16)
width uint16 Image width
height uint16 Image height
data [uint8] Raw image pixel data (flattened)

Schema: msgs/msg_image/img_simple.fbs

Record Test Node — Published Topics

Topic Message Type Description
{side}_arm_ctrl HexArmCtrl Arm control command
{side}_grip_ctrl HexGripCtrl Gripper control command
record raw bytes (1-byte boolean) Start/stop recording command

{side}_arm_ctrlHexArmCtrl

Field Type Description
ts_ns int64 Timestamp in nanoseconds
ctrl_mode HexArmCtrlMode Control mode enum (mit=0, pos=2)
jnt_pos [float64] Joint position target
jnt_vel [float64] Joint velocity target
jnt_eff [float64] Joint effort target
mit_tau [float64] MIT mode torque feedforward
mit_kp [float64] MIT mode stiffness gains
mit_kd [float64] MIT mode damping gains
lim_err [float64] Position error limit for safety

Schema: msgs/msg_robot/arm_ctrl.fbs

{side}_grip_ctrlHexGripCtrl

Field Type Description
ts_ns int64 Timestamp in nanoseconds
ctrl_mode HexGripCtrlMode Control mode enum (mit=0, pos=2)
jnt_pos [float64] Gripper joint position target
jnt_vel [float64] Gripper joint velocity target
jnt_eff [float64] Gripper joint effort target
mit_tau [float64] MIT mode torque feedforward
mit_kp [float64] MIT mode stiffness gains
mit_kd [float64] MIT mode damping gains
lim_err [float64] Position error limit for safety

Schema: msgs/msg_robot/grip_ctrl.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

Record Node (hex-flow-data-record)

Variable Type Default Description
RECORD_PATH str "../hex_record_data" Directory path for MCAP file output
FOXGLOVE_HOST str "127.0.0.1" Foxglove WebSocket server host
FOXGLOVE_PORT int 8765 Foxglove WebSocket server port
START_CNT int 0 Starting episode count for file naming

Record Test Node (hex-flow-data-record-test)

Variable Type Default Description
RATE_HZ float 10.0 Control command publish rate (Hz)
ARM_CTRL_MODE str "pos" Arm control mode ("mit", "pos")
GRIP_CTRL_MODE str "pos" Gripper control mode ("mit", "pos")

Replay Node (hex-flow-data-replay)

Variable Type Default Description
MCAP_PATH str "~/hex_record_data" Path to MCAP file or directory
ENABLE_COLOR bool false Enable color image replay
ENABLE_DEPTH bool false Enable depth image replay
COLOR_ENCODING str "bgr8" Color image encoding
DEPTH_ENCODING str "mono16" Depth image encoding
RATE_HZ float 500.0 Replay publish rate (Hz)

Architecture

The data recording pipeline follows a modular, decoupled design:

  1. Dynamic topic discovery — The record node reads the HEX_FLOW_REMAP JSON environment variable at startup and classifies all remapped topics by their suffix: *state topics (arm/gripper/pose states), *color topics (color camera images), and *depth topics (depth camera images). This allows the same binary to work with any robot configuration.

  2. Type-specific callbacks — For each discovered topic, the node creates a dedicated callback that subscribes via hex_flow_core.Node.create_sub(). State topics are parsed using parse_hex_arm_state, parse_hex_grip_state, or parse_hex_pose_state; image topics use parse_color_msg and parse_depth_msg. All parsed data is forwarded to a HexMcapWriter instance connected to a Foxglove WebSocket server.

  3. Episode-based recording — The node listens on the record topic for a single-byte boolean payload. On a rising edge (non-zero byte), it starts a new recording episode — incrementing the episode counter and creating a new episode_NNNNNN.mcap file at the configured RECORD_PATH. On a falling edge (zero byte), it stops the current episode. This enables seamless episode-level data collection.

  4. MCAP output format — Data is written to Foxglove MCAP files, a standard robotics binary log format that supports schemas, multiple topics, and efficient streaming. MCAP files can be visualized directly in Foxglove Studio for inspection and analysis.

  5. Decoupled test node — The hex-flow-data-record-test node is an independent process that publishes constant arm and gripper control commands at a configurable rate. It also listens for keyboard events and toggles the record topic when the S key is pressed (with rising-edge detection to avoid double-toggle). This provides a complete recording pipeline that works with both simulation (sim_record_test.launch.py) and real hardware (real_record_test.launch.py).

This decoupling allows the high-frequency control loop to run independently from the recording system, ensuring that data collection does not interfere with real-time control.

📄 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_data-0.0.2.tar.gz (20.1 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_data-0.0.2-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file hex_flow_node_data-0.0.2.tar.gz.

File metadata

  • Download URL: hex_flow_node_data-0.0.2.tar.gz
  • Upload date:
  • Size: 20.1 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_data-0.0.2.tar.gz
Algorithm Hash digest
SHA256 110d434c2e48f7b2a7f5cdf70b4f05e0f3e407ad115784e79263480db78716f2
MD5 2bf4c001d20ad12381d037c4ba91940f
BLAKE2b-256 7f26de096f34fbd8e59362b47a06c5b42f9131bbcdbf34944664ebf4c0ac61fb

See more details on using hashes here.

File details

Details for the file hex_flow_node_data-0.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for hex_flow_node_data-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 075149db72de4aefc32071b127d0144bd6a4196106f6a3b257a76f5e7fda5955
MD5 0da41ed3c1ccfe06500b706d55345310
BLAKE2b-256 399dcfcb4fe5045a646b5ebd13a846f52262842b6d1e7d89cbf5d769dccb257d

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