Files
dora-zed/AGENTS.md
T
cesarandClaude Opus 5 ee48948de9 add a dora-node.yml manifest and a dora validate CI gate
No source package is shared between node repositories, so the manifest and its
type URNs are the only contract a consumer has. Declaring them makes a wiring
mistake fail at validate time with the producer and consumer URNs, instead of
at runtime.

Every payload this node sends is a raw buffer whose shape and dtype live in the
metadata rather than an Arrow struct, so the URNs name the element type:
UInt8 for image_bgr, Float32 for depth, camera_info and point_cloud, String for
camera_state. tick is UInt64, matching how dora types timer inputs.

dataflow.yml now builds the node from the checkout with path: + build:. A
git:-sourced node does not pick up an adjacent manifest, so validating the
previous form checked nothing; with path: the CLI reports "injected 6 contract
type(s)" and a deliberately mismatched annotation exits non-zero under
strict_types. The README keeps the tag: form for consumers.

The workflow needs no camera and no ZED SDK, since validation never runs the
node. Also ignores the git/ and out/ working directories dora build creates,
and drops the ignore rules for the deleted test assets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7g2cBJ5e3r15ZbJ9WZn8c
2026-09-08 09:34:12 -03:00

6.2 KiB

AGENTS.md

This file provides guidance to AI coding assistants when working with code in this repository.

What this is

A dora-rs C++ node that interfaces with ZED stereo cameras. On each tick it grabs a frame and publishes it over the dora dataflow: a BGR image, an XYZRGBA point cloud and camera intrinsics. Camera management lives in src/zed/ and the dora event loop in src/main.cc.

The node is a camera source only. It ran inference in-process through v0.1.0, under src/engines/; that was removed so the node has no inference dependency and builds on any platform the ZED SDK supports. The removed code remains reachable at tag v0.1.0.

Build

scripts/build.sh

The binary is installed to bin/dora_zed relative to the repo root. The script is also the dataflow's build: command: dora 1.0 executes build commands directly rather than through a shell, so cd, && and command substitution do not work there.

Requirements: dora 1.0+ (verified with dora-cli 1.0.1), CMake 3.21+, ZED SDK 5.x (at /usr/local/zed), CUDA Toolkit, Rust stable toolchain (for dora-rs C++ bindings).

The first build clones dora-rs from GitHub and compiles dora-node-api-cxx via Cargo. This takes a while. Subsequent builds are incremental. If DORA_ROOT_DIR is set to a local dora checkout, it builds against that instead.

For a build without installing the SDK stack on the host, see the Dockerfile (Ubuntu 24.04 — the newest release with a ZED SDK; there is no Stereolabs build for 26.04). Run the compile with --gpus all.

Run

dora up
dora start dataflow.yml

Camera behavior is configured entirely through environment variables (see README.md for the full list: ZED_RESOLUTION, ZED_FPS, ZED_DEPTH_MODE, etc.).

Architecture

  • src/util/env.h — Shared inline env-variable parsing helpers (get_env_int, get_env_str, get_env_bool, get_env_float).
  • src/zed/camera.h — zed::Config, zed::Calibration, and zed::Camera class. Camera wraps the ZED SDK lifecycle: open() (one attempt, returns success), warmup, grab (image + depth + point cloud), calibration, device timestamp, blank-frame check, close() and reset() (close plus sl::Camera::reboot() where the model allows it). Exposes handle() for engine access.
  • src/zed/camera.cc — Implementation. SDK enum parsers live in an anonymous namespace. parse_depth_mode runs in Config::from_env(), not in the constructor, so an unrecognised ZED_DEPTH_MODE exits before the node joins the dataflow rather than falling back to a default.
  • src/main.cc — Dora event loop. Parses ZED_PC_MODE (FULL/HALF) once before the loop. On any input event (intended to be driven by a tick timer; the id is not inspected): calls camera.grab(), then sends image_bgr and depth, plus point_cloud when ZED_POINT_CLOUD is on and camera_info on the first frame of a camera session (camera_info_pending, re-armed on reconnection). pack_depth copies the depth map into a tightly packed [H, W] float buffer (sl::Mat rows can be padded) and clears inf/nan to 0. set_intrinsics and set_frame_stamps stamp every output of a frame with the same intrinsics, frame_id and the two timestamps (device_timestamp_ns, host_timestamp_ns; both Unix-epoch nanoseconds). Point cloud output varies by mode: FULL sends the raw sl::Mat pointer (no copy); HALF downsamples by 2 in each dimension. Recovery is a state machine over ticks rather than a blocking retry: the camera is opened from inside the loop, begin_recovery closes (first attempt) or resets (later ones) and sets a backoff deadline, and camera_state is published on each transition. Nothing sleeps, so Stop is honoured while the camera is down.
  • DoraTargets.cmake — Handles building or fetching dora-rs and generating the CXX bridge files. Two paths: local (DORA_ROOT_DIR) or git clone. Produces dora_node_api_cxx library and the node_bridge.cc glue.
  • scripts/build.sh — Configure/compile/install in one shell-free-callable step. Referenced by dataflow.yml, the Dockerfile and the README.
  • dora-node.yml — Node manifest (apiVersion: 1): typed input/output contract, entrypoint, build command. dora validate injects these types into any dataflow that reaches the node by path:; a git:-sourced node does not pick it up, which is why dataflow.yml builds from the checkout. Type URNs name the element type (std/core/v1/UInt8, .../Float32, .../String) because every payload is a raw buffer described by its metadata, not an Arrow struct.
  • dataflow.yml — Example dora dataflow, built from this checkout with path: + build: and strict_types: true. A consumer wires the node from a tag instead (see README) — dora 1.0 pins a source with the mutually exclusive tag:, rev: or branch:.
  • .gitea/workflows/validate.yml — CI gate running dora validate dataflow.yml on push and pull request. Needs no camera and no ZED SDK.
  • Dockerfile — Ubuntu 24.04 x86-64 build environment (CUDA 12.8, ZED SDK 5.2, Rust). No ARM64/Jetson image; build natively there. No camera needed; run the compile with --gpus all. Sets NVIDIA_DRIVER_CAPABILITIES=compute,utility,video — the video capability is what makes the container runtime mount NVDEC/NVENC, which libsl_zed.so links against. Rust lives at /usr/local/{rustup,cargo} rather than /root so the build can run as the invoking user. docker build -t dora-zed-build . && docker run --rm --gpus all --user "$(id -u):$(id -g)" -v "$PWD:/src" -v dora-zed-cargo:/usr/local/cargo/registry dora-zed-build.

Key APIs

  • dora C++ API (<dora-node-api.h>): init_dora_node(), dora_node.events->next(), event_type(), send_output_with_metadata(), new_metadata().
  • ZED SDK (<sl/Camera.hpp>): sl::Camera, sl::InitParameters, sl::RuntimeParameters, sl::Mat.
  • Output data is sent as raw byte slices (rust::Slice<const uint8_t>) with typed metadata (shape, dtype, encoding).

Tools

  • Issue tracker: Gitea. Use the Gitea MCP tools (mcp__gitea__*) to read and manage issues, pull requests, and other repository operations.

Rules

  • Do not mention AI tools in commit messages or documentation.