10 Commits
Author SHA1 Message Date
cristhian c1a7d70ba6 add typed Arrow payloads and a dora-image-view dataflow
dora-image-view takes std/media/v1/Image, and dora's compatibility graph
has no edge from std/core/v1/UInt8 to it, so wiring the two failed
`dora validate` whatever the node actually sent. Its flat-buffer fallback
would not have decoded these frames either: it reads width/height
metadata, and this node only published shape.

image and depth now go out as the Image struct, camera_info and
point_cloud as Float32 arrays and camera_state as a string, all built
against the Arrow C data interface in src/arrow so the node still links
no Arrow C++. Shape, dtype and encoding metadata are dropped where the
payload describes itself; intrinsics, frame_id and both timestamps are
unchanged. tests/run.sh covers the packing without a camera or the SDK,
round-tripping each array through pyarrow and rebuilding it under the
sanitizers.

Breaking: image_bgr is renamed to image and every payload changes shape.
dataflow_plot.yml is replaced by dataflow_view.yml, which wires the
viewer from a tag and repeats its contract in input_types so validate
checks both sides of the wiring.
2026-09-15 10:52:08 -05:00
cesarandClaude Opus 5 483da05a98 refactor: split the opencv-plot viewer into its own dataflow
validate / validate (push) Successful in 59m2s
validate / validate (pull_request) Successful in 59m0s
dataflow.yml is now the camera alone, so running it no longer pulls
dora-hub over pip or needs a display. dataflow_plot.yml adds the viewer
on image_bgr for when the stream should be looked at.

dora 1.0 resolves an input's source only within the same descriptor, so
the camera node is declared in both files rather than shared, and the two
are run one at a time. CI validates both, which is what catches an output
rename that breaks only the viewer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A65jaxrPXMN9EhBDMmMWb2
2026-09-08 14:11:25 -03:00
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
cesarandClaude Opus 5 d8956f269d fix camera recovery blocking the dora event loop
Camera::open() retried forever inside a fixed sleep, so a camera that did not
come back left the node stuck there: it stopped reading dora events and no
longer honoured Stop or AllInputsClosed.

Recovery is now a state machine over ticks. open() makes one attempt and
returns; the loop decides when to try again from a 1/2/5/10 s backoff deadline,
and nothing sleeps, so events keep being read while the camera is down. The
first attempt closes the handle; past that the device is wedged and the node
escalates to sl::Camera::reboot(), guarded to the ZED 2 and newer since it does
nothing on the ZED and ZED Mini. Reopening pins the serial so recovery gets the
same physical camera back.

Set async_grab_camera_recovery so a link hiccup returns CAMERA_REBOOTING
immediately instead of blocking the grab for ~17 s, and enable_image_validity_
check so the SDK flags frames a stalled camera hands back looking valid. Those
transient errors no longer drop the handle, since the SDK is already
reconnecting it.

An all-black frame now counts as a failed grab rather than being published, and
a camera delivering nothing usable for 5 s (30 s while the SDK reports it is
reconnecting) triggers recovery. A new camera_state output publishes
opening/streaming/recovering so a downstream node can tell "no frame yet" from
"camera lost".

ZED_RETRY_INTERVAL_SECONDS is replaced by the backoff.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7g2cBJ5e3r15ZbJ9WZn8c
2026-09-08 09:26:17 -03:00
cesarandClaude Opus 5 15134dc12e add a depth output
Publish sl::MEASURE::DEPTH as float32 [H, W] millimetres on every frame that
carries image_bgr, with the intrinsics, frame_id and timestamps the other
outputs carry.

The map is copied out rather than published in place: sl::Mat rows can be
padded, so the buffer is not necessarily H * W floats. inf and nan are cleared
to 0 in the same pass, matching the reference driver — a hole is meaningful and
a consumer cannot back-project a non-finite value.

Consumers that need 3D can now back-project depth with the published
intrinsics instead of receiving a point cloud.

Also drops the stale objects entry from the dataflow outputs, missed when
detection was removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7g2cBJ5e3r15ZbJ9WZn8c
2026-09-08 09:17:36 -03:00
cesarandClaude Opus 5 a734692b60 update the build to dora 1.0 and a shell-free build command
dora 1.0 runs a node's build command directly rather than through a shell, so
the mkdir/cd/&& sequence in dataflow.yml could not work. Move it to
scripts/build.sh and invoke that instead.

Default CMAKE_BUILD_TYPE to Release so DoraTargets.cmake picks the release
cargo profile and the binary does not link debug dora bindings.

Pin the dataflow source with tag: — 1.0 replaced git_checkout with the
mutually exclusive tag/rev/branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7g2cBJ5e3r15ZbJ9WZn8c
2026-09-08 09:10:53 -03:00
cristhian aguilera 44eec29b83 refactor open_vocab into yolo_onnx and yoloworld_onnx engines
Split the monolithic open_vocab engine into two focused engines:
yolo_onnx (closed-vocabulary, any single-input YOLO ONNX) and
yoloworld_onnx (open-vocabulary YOLO-World with CLIP encoder).
Shared NMS/letterbox/fuse helpers extracted to yolo_helpers.h.
Add export_yolo.py script and separate test binaries for each engine.
2026-03-30 04:44:25 -03:00
cristhian aguilera 2d10a68527 add update_vocabulary dora input for runtime label changes
The open_vocab engine now accepts an update_vocabulary input event
carrying a UTF-8 comma-separated label string. Labels are re-encoded
immediately via the CLIP text encoder; the next tick uses the new
vocabulary. ZedNative ignores the input via a no-op base class method.
2026-03-28 11:03:18 -03:00
cristhian aguilera 6e6dc8ef27 add native 3D object detection using ZED SDK optimized models
Add engines::ZedNative class wrapping ZED SDK's TensorRT-optimized
object detection. On every frame grab, detected objects (label,
confidence, 3D position, 2D/3D bounding boxes) are serialized as a
flat float32 array and sent as a new "objects" dora output with
frame_id correlation to image_bgr.

Extract shared env-var helpers into src/util/env.h and expose
sl::Camera& via Camera::handle() for engine access.

Closes #3
2026-03-26 10:53:38 -03:00
cristhian aguilera 9ac14c07e2 add dora C++ node for ZED stereo camera capture
Implements a dora-rs node that captures frames from ZED cameras
and publishes BGR images, XYZRGBA point clouds, and camera
intrinsics. Includes CMake build system with automatic dora-rs
C++ bindings, dataflow definition, and documentation.
2026-03-25 08:42:26 -03:00