A deterministic, testable B-Mode ultrasound pipeline targeting the NVIDIA Jetson Orin Nano — synthetic channel data, delay-and-sum beamforming (CPU & CUDA), calibrated image reconstruction, and live display across Pipeline, Core, ROS Nodes, and Holoscan Operators with native iOS & macOS DDS viewport applications.
End-to-End B-Mode ultrasound: synthetic channel data → DAS beamforming → live HolovizOp display → DDS viewport
Sitka is a research and engineering scaffold for the core computational stages of a B-Mode ultrasound imaging pipeline. It is not a clinical system; it is a deterministically testable platform for validating beamforming algorithms, exercising production-shaped data contracts, and demonstrating real-time image display on embedded GPU hardware.
The primary acquisition source is acoustic-data-generator, a Python probe simulator
modelling a 2D linear array with single-element synthetic-aperture transmit. A forward acoustic
model produces RF or IQ channel data from configurable point-scatterer phantoms, emitting flat
binary payloads with standalone JSON sidecar metadata. The C++ processing core (us_core)
is middleware-neutral — the same library runs from a CLI tool, a ROS 2 node graph, or a Holoscan
operator graph, producing identical numerical output in all three.
Every reconstructed B-Mode frame carries a RegionCalibration record mapping display
pixels to calibrated physical distances (cm/px), derived directly from the imaging grid geometry.
When depth changes via the ImGui slider or the /us/parameters DDS topic, the
calibration updates live — no restart, no hardcoded values.
us_core and reconstructing B-Mode images. This was used to validate basic beamformer
capability against an outside, independently-generated source rather than data synthesized by
acoustic-data-generator.
B-Mode frame reconstructed by us_core from a sharded NV-Raw2Insights-US IQ sample.
Data: Simson & Huver (2026), NVIDIA Corporation, CC BY 4.0.
| Component | Package / Binary | Role |
|---|---|---|
| Acoustic Data Generator | acoustic-data-generator | Python Synthetic Aperature forward model based on linear array geometry. Produces deterministic RF/IQ fixtures (.bin + _meta.json) |
| Core | us_core (C++17) | FixtureLoader · TableBuilder · DAS Beamformer (CPU + CUDA) · ImageReconstructor · PostProcessor · RegionCalibration · PngWriter. This is a middleware-neutral static library. |
| Pipeline | usbeam_cli | Batch file-in / file-out; full pipeline to PNG; golden reference comparison; CI validation; no live display |
| ROS Nodes | us_nodes + acoustic_generator_node.py | ROS 2 Humble adapter nodes with file-backed FrameRef transport; live B-Mode on depth-change demand (~1.4 s/frame) |
| Holoscan | usbeam_holoscan | Holoscan 4.2.0 operator graph. Contains RF B-Mode and IQ coherent compounding paths. Has switchable CPU/CUDA beamforming (--cpu-das) |
| Live Display | us_display | FrameSubscriberOp → HolovizOp; ImGui depth slider; DepthParameterPublisherOp; Holoscan + rclcpp on Jetson |
| Viewports | Viewports | These are iOS and macOS SwiftUI, Metal B-Mode viewers with a depth slider. Based on FastDDS 3.5.0 bridge but has no direct ROS2 dependency |
As the puzzle pieces settle in, a side objective is having a platform in place to revise and refine guided by past classical algorithm experience on imaging pipelines yet approaching with modern machine learning techniques where it makes sense. Take note below at the Core versus Holoscan and related components at CPU and GPU intersection.
| Connection | Carries | Transport |
|---|---|---|
| Acoustic Data Generator → Core | RF/IQ channel data | .bin float32 [tx, samples, rx] + _meta.json |
| Core → Pipeline | B-Mode PNG + bmode_meta.json with RegionCalibration | Filesystem |
| Core → ROS Nodes | Frames + calibration metadata | File-backed frame reference URIs that uniquely conveys one of RF, IQ, Envelope then exiting as B-Mode - never a mixture of type/format |
| Core → Holoscan | Beamformed frames | DLPack CPU / GPU tensors |
| ROS Nodes → Live Display | B-Mode stream | /us/frame — sensor_msgs/Image mono8 |
| Holoscan → Live Display | B-Mode stream | /us/frame — sensor_msgs/Image mono8 |
| Live Display → Viewports | B-Mode stream | DDS rt/us/frame [FastDDS 3.5.0] |
| Viewports → Live Display | Depth command, e.g. | DDS rt/us/parameters [FastDDS 3.5.0] |
us_core is the same static library across all three execution paths.
Output is bit-identical between (manual) command line and Holoscan (compare_holoscan_output.py; max|Δ|=0).
The command line path currently driving the pipeline and core is for batch validation and does not connect to Live Display - yet, anyway. As a side point, DLPack tensor approach is thea zero-copy memory handoff standard that keeps beamformed frames GPU-resident between pipeline stages.
Every B-Mode frame produced by us_core carries a RegionCalibration
record mapping pixels to physical space, derived at reconstruction time from the actual
BeamformGrid geometry:
physical_delta_x = (x_max_m − x_min_m) / width_px × 100 [cm/px] physical_delta_y = (z_max_m − z_min_m) / height_px × 100 [cm/px] z_min_m = 0.0 (probe face) z_max_m = depth_m (from AcquisitionParameters) x_min_m = element_x_m[0] − pitch_m / 2 x_max_m = element_x_m[N−1] + pitch_m / 2
A depth change via the ImGui slider or /us/parameters DDS topic propagates
automatically to a fresh RegionCalibration in every output frame.
The bmode_meta.json sidecar records calibration alongside acquisition parameters
for every output PNG.
| Stage | CPU | GPU |
|---|---|---|
| DAS — 16-el / 1-TX, 256×512 | 19.7 ms | 5.9 ms |
| DAS + Envelope - NVIDIA edge device-resident | — | 5.0 ms |
| IQ Compound — 180-el / 180-TX, 256×512 | — | 530 ms (target ≤ 150 ms) |
| PNG write, 256×512 | ~20 ms | ~20 ms |
[tx,ax,rx] → [tx,rx,ax] layout transposition (IQTransposeGPU).
Next: warp-level reduction or frequency-domain compounding.
Four topics under /us/ govern all inter-process communication.
The same namespace is mirrored by namespace us in the C++ core headers.
| Topic | Direction | Content | Status |
|---|---|---|---|
/us/frame | Generator → Display | sensor_msgs/Image mono8; one B-Mode frame per publish | Functional |
/us/parameters | Display → Generator | Float64 depth in SI meters; future: full AcquisitionParameters | Functional |
/us/context | Generator → Display | Confirmed params + MI/TI safety indices; always broadcast | Under Construction |
/us/command | Controller → All | CQRS command bus: Freeze · CaptureStart · CaptureStop · ModeChange · SystemFault | Under Construction |
The Viewports application(s) subscribe to FastDDS wire-level topics rt/us/frame and
rt/us/parameters (ROS 2 wire-name prefix rt/). No ROS 2 dependency on the companion side.
/opt/ros/humble on Jetson